コース一覧
    C言語中級 文字列・構造体
    つくる 名前入力の安全化

    C言語中級 文字列・構造体

    C言語の文字列と構造体を学び、複数のデータを整理して扱うコースです。

    1
    文字列処理の実践
    01. strlenを自作する15分
    02. strcpyを自作する15分
    03. バッファオーバーフロー体験15分
    04. 文字列を分解する15分
    05. 動的な文字列15分
    06. つくる 名前入力の安全化15分
    07. 第3章クイズ10分
    2
    構造体とポインタ
    01. 構造体ポインタと->15分
    02. 構造体の動的確保15分
    03. 動的な構造体配列15分
    04. 関数ポインタ15分
    05. qsortで並べ替える15分
    06. つくる 動的Student完成15分
    07. 第4章クイズ10分

    つくる 名前入力の安全化

    章の道具を1本の入力処理にまとめる

    第3章でやってきたことを並べ直します。終端まで数える my_strlen、1バイトずつ写す my_strcpy、器の広さを渡してあふれさせない safe_copy、カンマで切る分解、長さぶんだけ確保する my_strdup。この5つは、実はどれも「外から来た1行を安全に取り込む」という1つの仕事の部品です。今回はそれを組み上げます。

    入力は 名前,点数 の行です。外から来るものなので、次のどれが来ても壊れてはいけません。

    • 想定より長い名前
    • カンマが無い行
    • 空行

    切り詰めてから確保する順序

    今回の要点は、safe_copy と my_strdup を この順番で 使うところです。

    c

    char fixed[NAME_MAX + 1];
    cut[n] = safe_copy(fixed, NAME_MAX + 1, line);
    names[n] = dup_name(fixed);

    まず幅の決まった一時置き場 fixed に、あふれない形で受けます。ここで長さの上限が確定します。そのあと、確定した長さぶんだけヒープに確保して写します。順番が逆だと意味がありません。長さ制限をかける前に確保してしまうと、いくらでも長い名前をそのまま受け入れることになり、上限を設けた意味が消えます。

    一時置き場が固定長でよいのは、そこには決して上限を超えて書き込まないからです。固定長そのものが悪いのではなく、広さを見ずに書き込むことが悪い、という区別がここではっきりします。

    捨てた情報を黙って捨てない

    safe_copy は切り詰めたかどうかを返します。この戻り値を捨ててしまうと、Yamamotokurosawa が Yamamoto になったことを誰も知らないまま一覧に載ります。あとから別人と区別が付かなくなっても、原因を追う手掛かりが残りません。今回は切り詰めた行に印を出して、データが加工されたことを表に出します。

    壊れた行は読み飛ばす

    カンマが無い行や空行が来たときに落ちる作りだと、ファイル1行の乱れでプログラム全体が止まります。分解の前に line[pos] が '\0' かどうかを見て、区切りが見つからなければその行は数えずに次へ進みます。人数 n を増やさないので、平均の計算にも影響しません。

    最後に、確保した回数と解放した回数を出して、数が合っていることを確かめます。第2章で覚えた数え方が、そのまま今回の検算になります。読み飛ばした行では dup_name を呼んでいないので、確保の回数は一覧に出た人数と一致するはずです。ここがずれたら、読み飛ばしの位置か人数の数え方のどちらかが間違っています。

    平均の割り算

    人数で割るときは、整数どうしの割り算にならないよう気をつけます。total / n はどちらも int なので小数が切り捨てられます。(double)total / n と片方を実数にしてから割り、%.1f で桁を決めて出します。入門でやった話ですが、動的メモリの処理に気を取られていると落としやすいところです。

    では、第3章の総まとめとして、あふれない名前入力を書き上げましょう。

    要件

    1. fgets で1行ずつ読み、行末の改行を取り除く
    2. 空行と、カンマが無い行は読み飛ばして人数に数えない
    3. 名前は safe_copy で8文字までに受けてから、dup_name で必要な長さだけ確保して保持する
    4. 一覧は Tanaka 85点 の形。切り詰めた行だけ Yamamoto 70点 切り詰め の形にする
    5. 続けて 3人 平均81.7点 の形で、平均を小数第1位まで表示する
    6. 最後に全部 free して 確保3回 解放3回 の形で表示する

    ヒント

    safe_copy に渡す広さは NAME_MAX + 1 です。+1 は終端のぶんです

    切り詰めたかどうかは safe_copy の戻り値で分かります。行ごとに配列へ覚えておきます

    平均は整数どうしの割り算にならないよう (double)total / n にして %.1f で出します

    生田 陸人
    監修生田 陸人
    ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
    編集 ゆめさく編集部·公開 2026/08/07

    関連レッスン

    • 第3章クイズ

      文字列の内部構造と安全な扱い方の理解を確認します。

    • 構造体ポインタと->

      アロー演算子でメンバを読み書きできるようになります。

    • 動的な文字列

      長さに合わせて必要なぶんだけ確保できるようになります。

    • 文字列を分解する

      区切り文字で分ける処理を書けるようになります。

    このレッスンに出てくる用語

    意味があいまいなまま進んだ語は、ここから読み直せます。

    • 処理計算や代入を表す長方形
    • ヒープ親が子より常に大きい(最大ヒープ)または小さい(最小ヒープ)木構造。
    • 戻り値呼び出し元への返答を表す点線矢印
    • メモリプログラムとデータを一時保持する高速領域
    main.c
    エディタを読み込んでいます

    メモ

    つくる 名前入力の安全化

    ⌘S で保存