25 標準入力2(getchar・putchar・文字処理)

scanf / printf 以外の入出力関数と、文字処理ライブラリを学ぶ。


25-1 getchar() と putchar()

1文字単位で入出力する関数。printf / scanf と同じく、stdio.h で宣言されている

関数正式な形動作
getchar()int getchar(void);標準入力(キーボード)から1文字読み込み、その文字を返す。
読み込む文字がもう無いときは EOF を返す
putchar(c)int putchar(int c);文字 c を標準出力(画面)へ1文字出力する。
出力した文字を返す(失敗時は EOF
getchar() の戻り値が char ではなく int なのは、どの文字とも重ならない特別な値 EOF(入力終了)を返せるようにするため。
getchar() の結果を受け取る変数は int で宣言するのが正しい作法。
✅ 試験ポイント:getchar / putcharstdio.h で宣言。toupper / isalpha など(25-2)は ctype.h で宣言。
「標準入力から1文字入力する関数はどれか」「どのヘッダファイルで宣言されているか」は本試験で繰り返し問われている。
25_01_echoChar.c
#include <stdio.h>

int main(void)
{
    int c;
    printf("1文字入力してください: ");
    c = getchar();
    printf("入力された文字: ");
    putchar(c);
    printf("¥n");
    return 0;
}
1文字入力してください: A
入力された文字: A

EOF(入力の終わり)と定番ループ

EOF(End Of File)は stdio.h で定義されているマクロで、
ファイルの終わり=ストリームにこれ以上の入力がない」ことを示す(多くの環境で値は -1)。

getchar()EOF を返すまで読み続けるループは、C言語の定番パターン。

25_01b_echoAll.c
#include <stdio.h>

int main(void)
{
    int c;

    /* 入力が終わる(EOF になる)まで、1文字ずつ読んでそのまま出力 */
    while ((c = getchar()) != EOF) {
        putchar(c);
    }
    return 0;
}
hello
hello
abc
abc
^Z
(Windows では Ctrl+Z → Enter で入力終了=EOF)
(c = getchar()) != EOF は「c に1文字読み込み、それが EOF でない間くり返す」という意味。
比較(!=)の方が代入(=)より優先順位が高いので、c = getchar()必ずカッコで囲む
キーボードからの EOF は、Windows は Ctrl+Z → Enter、macOS/Linux は Ctrl+D
⚠ 「改行まで」を処理したいときは比較先を変えて while ((c = getchar()) != '¥n') とする。
また、scanf("%d", ...) の直後に getchar() を使うと、入力バッファに残った Enter('¥n')を先に読んでしまうことがあるので注意。

25-2 ctype.h:文字の判定・変換

#include <ctype.h> で使える文字処理関数。

関数意味真になる例
isalpha(c)英字かどうか'A', 'z'
isdigit(c)数字(0〜9)かどうか'0', '9'
isalnum(c)英字または数字かどうか'A', '3'
islower(c)小文字かどうか'a', 'z'
isupper(c)大文字かどうか'A', 'Z'
isspace(c)空白文字かどうか' ', '¥t', '¥n'
ispunct(c)記号かどうか(英数字・空白以外の表示文字)'!', '.'
isgraph(c)表示可能文字かどうか(空白は含まない)'A', '!'
isprint(c)表示可能文字かどうか(空白も含む)' ', 'A'
iscntrl(c)制御文字かどうか'¥n', '¥t'
isxdigit(c)16進数で使える文字かどうか'0'〜'9', 'a'〜'f', 'A'〜'F'
toupper(c)小文字 → 大文字に変換'a' → 'A'
tolower(c)大文字 → 小文字に変換'A' → 'a'
✅ 関数名の語源・覚え方・紛らわしいペア(isgraph と isprint など)は 27-4 で整理している。
25_02_charCheck.c
#include <stdio.h>
#include <ctype.h>

int main(void)
{
    int c;
    printf("1文字入力してください: ");
    c = getchar();

    if (isalpha(c)) {
        printf("英字です。大文字変換: %c¥n", toupper(c));
    } else if (isdigit(c)) {
        printf("数字です。¥n");
    } else {
        printf("その他の文字です。¥n");
    }
    return 0;
}
1文字入力してください: a
英字です。大文字変換: A

25-3 string.h:文字列操作

#include <string.h> で使える文字列処理関数。

関数意味使い方
strlen(s)文字列の長さを返すstrlen("hello") → 5
strcpy(dst, src)文字列をコピーstrcpy(buf, "abc")
strcat(dst, src)文字列を末尾に連結strcat(a, b)
strcmp(s1, s2)文字列を比較(0なら一致)strcmp(a, b) == 0
25_03_stringOps.c
#include <stdio.h>
#include <string.h>

int main(void)
{
    char a[50] = "Hello";
    char b[50] = "World";

    printf("長さ: %d¥n", (int)strlen(a));

    strcat(a, b);   /* a の末尾に b を連結 */
    printf("連結後: %s¥n", a);

    if (strcmp(a, "HelloWorld") == 0) {
        printf("一致しました¥n");
    }
    return 0;
}
長さ: 5
連結後: HelloWorld
一致しました
strcat は dst の配列サイズに余裕がないとバッファオーバーフローになる。
連結後の長さが dst の要素数を超えないよう注意する。

25-4 fgets():スペースを含む文字列の入力

scanf("%s", ...) はスペースの手前で止まる。
スペースを含む文字列を読み込むには fgets() を使う。

fgets(配列名, サイズ, stdin);
25_04_fgets.c
#include <stdio.h>
#include <string.h>

int main(void)
{
    char name[50];
    printf("名前を入力してください(スペースOK): ");
    fgets(name, sizeof(name), stdin);

    /* fgets は末尾に ¥n を含む場合があるので除去 */
    name[strcspn(name, "¥n")] = '¥0';

    printf("こんにちは、%s さん!¥n", name);
    return 0;
}
名前を入力してください(スペースOK): Yamada Taro
こんにちは、Yamada Taro さん!
strcspn(name, "¥n") は文字列中の ¥n の位置を返す。
その位置に '¥0'(文字列終端)を代入することで改行を除去できる。

25-5 演習

📝 演習① 大文字・小文字を変換する

英字1文字を入力し、小文字なら大文字に、大文字なら小文字に変換して表示せよ。

25_05_caseConvert.c
#include <stdio.h>
#include <ctype.h>

int main(void)
{
    int c;
    printf("英字を1文字入力してください: ");
    c = getchar();

    /* ここに変換処理を書く */

    return 0;
}
答えの例を表示
    if (islower(c)) {
        printf("大文字: %c¥n", toupper(c));
    } else if (isupper(c)) {
        printf("小文字: %c¥n", tolower(c));
    } else {
        printf("英字ではありません¥n");
    }
📝 演習② 文字列の長さを数える

文字列を入力し、長さを表示するプログラムを作れ。strlen を使うこと。

25_06_strLen.c
#include <stdio.h>
#include <string.h>

int main(void)
{
    char str[100];
    printf("文字列を入力してください: ");
    fgets(str, sizeof(str), stdin);
    str[strcspn(str, "¥n")] = '¥0';   /* 改行除去 */

    /* ここに長さ表示を書く */

    return 0;
}
答えの例を表示
    printf("文字数: %d¥n", (int)strlen(str));

25-6 理解度チェック

Q1. getchar() の説明として正しいものはどれか。

解説を表示

正解:イ

getchar() は標準入力から1文字読み込む関数。戻り値は int 型。

Q2. isdigit('7') の戻り値はどれか。

解説を表示

正解:イ

'7' は数字文字なので isdigit は真(0以外)を返す。

Q3. strcmp(a, b) が 0 を返すとき何を意味するか。

解説を表示

正解:ア

strcmp は a==b なら 0、a<b なら負、a>b なら正を返す。

Q4. scanf("%s", name)fgets(name, ...) の違いとして正しいものはどれか。

解説を表示

正解:イ

scanf の %s はスペースを区切り文字として扱うため途中で止まる。fgets は改行まで(またはサイズ上限まで)を読み込む。

Q5. マクロ EOF の説明として正しいものはどれか。

解説を表示

正解:ウ

EOF(End Of File)は stdio.h で定義されているマクロで、「ファイルの終わり=これ以上入力がない」ことを示す。文字列の終わりは '¥0'(ヌル文字)なので混同しないこと。本試験の正誤問題でそのまま出題されている。

Q6. putchar が宣言されているヘッダファイルはどれか。

解説を表示

正解:エ

getchar / putchar / printf / scanf は stdio.h。toupper / isalpha などの文字判定・変換は ctype.h。「toupper は stdio.h で宣言されている(→誤り)」のような正誤問題が本試験で出題されている。