C 言語の変数命名規則と入出力処理の実装

変数命名規則

C 言語では、変数の機能や用途を明確に伝える命名が推奨されます。意味の通りに読める名前を採用することで、コードの保守性と可読性が大幅に向上します。

主な命名スタイル

  • 小文字キャメルケース(Lower Camel Case)
    最初の単語を小文字、その後の単語の先頭を大文字にします。ローカル変数や関数内変数に適しています。
    int totalScore;char userName[32];
  • スネークケース(Snake Case)
    単語間にアンダースコア(_)を用いるスタイルで、C 言語標準ライブラリや Linux カーネルコードで広く使われています。
    int item_count;float average_value;

命名例

int digits[4];              // 各桁を保持
int thousand, hundred, ten, unit;
char separator = '_';        // 区切り文字の格納変数
unsigned long timestamp_ms;  // ミリ秒単位タイムスタンプ

C 言語における文の分類

C の実行単位である「文」は、目的に応じて以下の 5 種類に整理できます。

種別特徴具体例
制御文分岐・繰り返し・ジャンプ処理を制御if (x > 0) { ... }, while (ptr != NULL)
関数呼び出し文定義済み関数を呼び出し、処理を委譲printf("result:%d\n", res);, fflush(stdout);
式文計算・代入・演算を実行する式+セミコロンresult = a * b + c;, ++counter;
空文セミコロンのみで構成。wait やループの本体として利用for (int i = 0; i < N; i++);
複合文(ブロック)ブレースで囲んだ複数文を単一文として扱う{ int tmp = x; x = y; y = tmp; }

標準入出力の仕組み

C 言語は言語仕様として入出力機能を含まず、すべて標準入出力ライブラリ <stdio.h> に依存しています。入出力は、

外部デバイス ←→ バッファ ←→ メモリ ←→ CPU

という流れで処理されます。

文字単位の入出力

1 つの文字を読み込む:getchar()

  • 関数外形:int getchar(void);
  • 機能:標準入力スタンドアローンから 1 字読み込み
  • 戻り値:
    • 成功時:読み込んだ文字の ASCII コード値(unsigned char として符号拡張なし)
    • 終端(EOF)またはエラー時:EOF(通常 -1
int c = getchar();  // 文字を 1 字読み込み
if (c != EOF) {
    // c に有効データが格納されている
}

1 文字を出力:putchar()

  • 関数外形:int putchar(int ch);
  • 機能:標準出力に 1 字書き込み
  • 戻り値:
    • 成功時:書き込んだ文字コード値
    • エラー時:EOF
putchar('X');      // 文字 X を出力
putchar('\n');     // 改行
putchar(c % 10 + '0');  // 整数 0〜9 を文字化して出力

フォーマット付き入出力

printf()stdio.h による柔軟な出力

  • 関数外形:int printf(const char *format, ...);
  • 機能:format に指定された書式で可変引数を出力
  • 戻り値:出力された文字数(失敗時:EOF
主なフォーマット指定子
指定子説明
signed int%d符号付き 10 進数
unsigned int%u符号なし 10 進数
16 進数%x / %X小文字/大文字で出力
8 進数%o0 で始まる 8 進表現
float%f固定小数点(デフォルト:6 桁)
double%e / %E指数表記(e/E 小文字/大文字)
char%c1 文字出力
char*%s文字列出力('\0' 終端前提)
装飾コンテキスト
  • %#x0x プレフィックスを付与
  • %5d:全体幅 5 文字(右詰め、空白補完)
  • %-8s:左詰め 8 文字幅
  • %.3f:小数点以下 3 桁まで表示
  • %.4s:最初の 4 文字のみ出力
  • %ld:long 型に対応
  • %lld:long long 型
使用例
int num = 42;
double val = 1.2345678;
long id = 9876543210L;

printf("hex:%#x, width:%06d\n", num, num);        // hex:0x2a, width:000042
printf("fixed:%.2f, exp:%E\n", val, val);        // fixed:1.23, exp:1.234568E+00
printf("long ID:%012ld\n", id);                  // long ID:9876543210 (左ゼロ埋め)

scanf():文字入力の高度な制御

  • 関数外形:int scanf(const char *format, ...);
  • 機能:format に従って入力ストリームからデータを読み込み、アドレス指定子で渡された変数に格納
  • 戻り値:正常に読み込まれたフィールド数(失敗:EOF
必須注意点
  1. アドレス渡しは必須
    示された変数のアドレスを渡す必要があります(例:&value)。誤って値を渡すと未定義動作・クラッシュの原因になります。
  2. 型の完全一致
    %ffloat
    %lfdouble
    %hdshort
    %hhdchar(符号付き)
  3. 空白文字の扱い
    • 空白類(スペース・タブ・改行)はデフォルトで無視されます
    \n を含める場合、次回入力までブロッキングします
  4. %cの特殊性
    • 空白構成文字も-read 対象
    • 空白飛ばしをしたい場合は明示的に空白入れる:" %c" で次回より開始
    • または %*c を使って明示除外
動作モードの説明

入力バッファへのデータ流入後、scanf() は左から右へ走査し、マッチする文字列を収集します。消費されなかった残余は、次回の入力処理で再利用されます。

char buf[10];
int val;

scanf("%d", &val);      // 入力: "123abc" ⇒ val = 123, 残余: "abc"
scanf("%c", &buf[0]);   // buf[0] = 'a'
scanf("%s", buf);       // buf = "abc"
実用的な使用例
char op;
double x, y;

printf("式を入力(例: 3.5 * 2):\n");
scanf("%lf %c %lf", &x, &op, &y);

switch (op) {
  case '+': printf("合計: %.2f\n", x + y); break;
  case '-': printf("差: %.2f\n", x - y); break;
  case '*': printf("積: %.2f\n", x * y); break;
  case '/': 
    if (y != 0.0) printf("商: %.2f\n", x / y);
    else puts("エラー: 0 除算");
    break;
}

入力バッファのクリア

不正な入力が残ると、次回の読取りに悪影響します。クリア方法として以下が phổ biến:

// バッファ内に残存文字が存在しなくなるまで読み捨てる
int c;
while ((c = getchar()) != '\n' && c != EOF) ;

代わりに fgets() + sscanf() を使った安全な入力処理も推奨されます。

タグ: scanf printf variable-naming STDIO hackers-grammar

6月22日 18:51 投稿