トラック9・🔤文字列

文字の判定と変換(ctype.h)

読む目安 約11分・ゴール:ctype.hの判定・変換関数を使って、文字の種類を調べたり大文字小文字を変換できる

アプリでこのトピックを学ぶ(無料・登録不要)

このトピックの要点

「この文字は数字か」「アルファベットか」「大文字に変えたい」——こうした1文字ごとの処理をまとめた道具箱が ctype.h です。

関数調べること
isdigit数字('0'〜'9')か
isalphaアルファベットか
isspace空白・タブ・改行か
isupper / islower大文字か / 小文字か
toupper / tolower大文字に変換 / 小文字に変換

判定関数は「その通りなら0以外、違えば0」を返します。真偽値ではなく int を返す点に注意しつつ、if の条件にはそのまま書けます。

#include <stdio.h>
#include <ctype.h>

int main(void)
{
    char s[] = "a1b2c3!";
    int digits = 0, letters = 0;

    for (int i = 0; s[i] != '\0'; i++) {
        if (isdigit(s[i])) {
            digits++;
        } else if (isalpha(s[i])) {
            letters++;
        }
    }
    printf("数字 %d 個 / 英字 %d 個\n", digits, letters);   // 数字 3 個 / 英字 3 個
    return 0;
}

大文字・小文字の変換

#include <stdio.h>
#include <ctype.h>

int main(void)
{
    char s[] = "Hello, C!";

    for (int i = 0; s[i] != '\0'; i++) {
        s[i] = toupper(s[i]);       // 1文字ずつ大文字に
    }
    printf("%s\n", s);              // HELLO, C!
    return 0;
}

toupper は、アルファベット以外の文字(, や !)をそのまま返してくれます。だから条件分岐なしで全文字に適用できます。「変換できないものは素通し」という設計は、使う側にとってとても親切です。

ここで使っている s[i] != '\0' というfor文の条件は、文字列処理の基本形です(t09-08で詳しく扱います)。判定関数で選び、変換関数で書き換える。この2つを組み合わせるだけで、「英数字だけ残す」「小文字にそろえる」といった処理が書けるようになります。

そもそも何に使うのか

いちばんの用途は入力チェックです。ユーザーが入力した文字列が本当に数字だけでできているかを isdigit で1文字ずつ確かめてから、数値に変換する。この一手間があるかどうかで、プログラムの堅さがまったく変わります。想定外の入力で落ちないプログラムは、たいていこうした地味な確認を積み重ねています。

自分で書かずに標準関数を使う

if (c >= '0' && c <= '9') と自分で書いても同じ判定はできます。実際そのとおりに動きますし、仕組みを理解するうえでは書いてみる価値もあります。それでも実務では isdigit を使ってください。意図が一目で伝わり、書き間違いも起きないからです。

罠・注意

ビット判定は is〜、変換は to〜。名前が素直だから、思い出しやすいよ

まとめ: 文字の種類を調べるのは is〜、変換は to〜。自作の条件式より、意図の伝わる標準関数を選びましょう。

アプリでこのトピックを学ぶ(無料・登録不要)

確認問題

確認問題 1

文字列を1文字ずつ大文字に変換します。空欄に入るものを選んでください。

for (int i = 0; s[i] != '\0'; i++) {
    ____;
}
  1. s[i] = toupper(s[i])
  2. toupper(s[i])
  3. s[i] = isupper(s[i])
  4. s = toupper(s)
答えを見る

正解:A(s[i] = toupper(s[i]))

toupper は変換した値を返すだけで、元の文字を書き換えません。戻り値を s[i] に代入する必要があります。isupper は「大文字かどうか」の判定関数なので用途が違います。

確認問題 2

次のプログラムの出力はどれですか。

#include <stdio.h>
#include <ctype.h>

int main(void)
{
    char s[] = "a1b2c3!";
    int n = 0;

    for (int i = 0; s[i] != '\0'; i++) {
        if (isdigit(s[i])) {
            n++;
        }
    }
    printf("%d\n", n);
    return 0;
}
  1. 3
  2. 6
  3. 7
  4. 4
答えを見る

正解:A(3)

isdigit が真になるのは '1' '2' '3' の3文字です。英字と '!' は数えません。ループ条件が s[i] != '\0' なので、文字数を知らなくても末尾まで走査できます。

「文字列」の目次

  1. 文字列とはchar配列である
  2. ヌル終端 '\0' の掟
  3. 文字列リテラルと初期化
  4. string.h の主要関数
  5. 安全な文字列操作——バッファサイズの意識
  6. 文字の判定と変換(ctype.h)
  7. 文字コードの基礎——ASCIIとUTF-8
  8. 文字列処理の定石パターン

もっと先へ:ポインタ・メモリ・ファイル入出力・セキュアコーディングを含む全26トラックと、段位検定・模試のフルセットは完全版に収録しています。

完全版の販売ページは準備中です。

ほかのトラック

📚 姉妹教材:手を動かして覚える Linux 教材 — Linuxとインフラの仕組みを地図で学ぶ

Web版