
C言語基礎|再帰関数呼出し
「1文字ずつ読んで、1文字ずつ出す。たったそれだけで入出力の“基本形”が見えてくる」
文字の入出力は、プログラムの会話そのもの
多くのプログラムは、キーボードやファイル、通信などから文字を読み込み、何かの形で文字を出力しています。
その“最小単位”が 1文字の入出力 です。
C言語には、1文字を読む getchar と、1文字を出す putchar があります。
この2つを組み合わせると「入力をそのまま出力する(コピーする)」という、入出力の基本形を作れます。
この記事では、元の「入力を標準出力へコピー」例を、少し味付けして 入力を大文字にして出力する シンプルな例に置き換えます(表示文も別の日本語に変更)。
その上で、EOF、while の条件式、代入と判定が一体になった書き方の意味を、表と図で丁寧に追いますね。

サンプルプログラム
例:入力を大文字にして出力する(EOF で終了)
※英字以外はそのまま出力します。
プロジェクト名:chap8-10-1 ソースファイル名:chap8-10-1.c
#include <stdio.h>
int main(void)
{
int ch;
puts("文字を入力してください(終了は Ctrl+D または Ctrl+Z)。");
while ((ch = getchar()) != EOF) {
if ('a' <= ch && ch <= 'z')
ch = ch - ('a' - 'A'); // 小文字→大文字
putchar(ch);
}
return 0;
}実行例(イメージ)
文字を入力してください(終了は Ctrl+D または Ctrl+Z)。
Hello!
HELLO!
This is a pen.
THIS IS A PEN.getchar と putchar:1文字入出力の基本ペア
getchar / putchar の役割
| 関数 | 役割 | 入力/出力 | 返すもの |
|---|---|---|---|
| getchar | 1文字読む | 標準入力から入力 | 読んだ文字(int)または EOF |
| putchar | 1文字出す | 標準出力へ表示 | 出力した文字(int)または EOF |
表の説明
- getchar は「次の1文字」を取り出して返します。
- putchar は「指定した1文字」を表示します。
- どちらも戻り値は int です(ここが重要で、EOF を扱うためです)
書式:getchar / putchar はこう使う
getchar の書式
int getchar(void);
何をする?
標準入力から次の1文字を読み込み、その文字を返します。読み込めないときは EOF を返します。
putchar の書式
int putchar(int c);
何をする?
c で指定された1文字を標準出力へ書き込みます。失敗すると EOF を返すことがあります。
EOF とは何か:文字が尽きた合図(またはエラー)
EOF は End Of File の略で、「もう読み込む文字がない」または「読み込みエラー」を表す特別な値です。
EOF のイメージ
入力が続く → getchar は文字コードを返す(例:'H')
入力が終わる→ getchar は EOF を返す
EOF のポイント
| 項目 | 内容 |
|---|---|
| EOF の正体 | <stdio.h> で定義されたマクロ |
| 値 | 多くの処理系で負の値(例:-1) |
| 使いどころ | getchar の終了判定、ファイル読み込みの終了判定 |
| 注意 | char ではなく int で受けるのが安全 |
表の説明
EOF は「文字ではない値」なので、char 型に入れると判定に失敗する可能性があります。
だから int ch; が定番です。
重要:なぜ int ch; なの?
「1文字だから char でいいのでは?」となりがちですが、EOF を確実に扱うには int が安心です。
char ではなく int を使う理由
| 受け取り型 | EOF を安全に判定できる? | 理由 |
|---|---|---|
| char | 怪しいことがある | char が符号なしだと EOF(負数)が表せない場合がある。 |
| int | 安全 | EOF も通常の文字コードも両方表せる。 |
while の条件式が少し複雑に見える理由
この1行がこの記事のキモです。
while ((ch = getchar()) != EOF)
「代入」と「EOF 判定」を一体化しています。
制御式の分解(読み方)
(1) ch = getchar() まず1文字読む(結果を ch に代入)
(2) ch != EOF その結果が EOF かどうか調べる
(3) EOF でなければループ継続
説明
- 代入式 ch = getchar() は「代入した後の値」そのものが式の値になります
- その値を != EOF で比較して、続けるか止めるか決めています
代入と判定を分けて書くとどうなる?
同じ処理を、もっと素直に書くとこうなります。
while (1) {
ch = getchar();
if (ch == EOF)
break;
if ('a' <= ch && ch <= 'z')
ch = ch - ('a' - 'A');
putchar(ch);
}
一体型と分離型の比較
| 書き方 | 良いところ | 注意点 |
|---|---|---|
| while ((ch = getchar()) != EOF) | 短く書ける、入出力の定番形 | 初見だと読みにくい |
| 代入→if→break | 読みやすい、デバッグしやすい | 少し長くなる |
表の説明
慣れるまでは分離型で理解して、意味が分かったら一体型に戻すのがおすすめです。
小文字→大文字の変換が何をしているか
今回の例では、英字だけ大文字化しています。
if ('a' <= ch && ch <= 'z')
ch = ch - ('a' - 'A');
変換のイメージ(ASCII 前提)
'a' と 'A' の差だけ引くと小文字→大文字になる
例: 'c' → 'C'
図の説明
- ASCII では 'a'〜'z' と 'A'〜'Z' が一定の差で並んでいます
- その差 'a' - 'A' を使って変換しています
(より安全にやるなら ctype.h の toupper もありますが、今回は仕組みが見えやすい形にしています)
入力の終わらせ方(環境メモ)
- Windows のコンソールでは Ctrl+Z を入力して Enter のことが多いです
- UNIX/Linux/macOS の端末では Ctrl+D が一般的です
環境によって少し違いますが、「EOF を送る操作」だと思えばOKです。
登場する命令・構文の役割まとめ
while の書式
while (条件) {
文;
}
何をする?
条件が真の間、繰り返します。EOF が来るまで読み続ける定番の形に使われます。
if の書式
if (条件)
文;
何をする?
条件に当てはまるときだけ処理します。今回だと小文字判定に使っています。
break の書式
break;
何をする?
ループを強制終了します。EOF を分離型で書くときに使います。
まとめ:文字入出力の基本形を押さえると強い
- getchar は 1文字を読み、読めなければ EOF を返す。
- putchar は 1文字を出力する。
- ch は int で受けるのが安全(EOF を扱うため)
- while ((ch = getchar()) != EOF) は「読む→EOF 判定→繰り返す」の定番形
- 文字処理は「読みながら加工して出す」が基本パターン
