
C言語基礎|数字文字の出現回数
数字は10種類だけ! 文字列を走査して「0〜9の出現回数」を一気に見える化しよう
文字列の中身を「数えて理解」してみよう
文字列って、見た目はただの文字の並びですが、よく観察するといろんな情報が詰まっています。
その中でも分かりやすくて実用的なのが、数字文字 0〜9 がそれぞれ何回出てきたかを数えることです。
ここでは、文字列を先頭から順に走査して、数字文字を見つけたらカウントする、という王道の考え方を身につけます。
配列と条件判定、そして文字コードの性質('0' を引くと 0〜9 になる)をまとめて復習できる、おいしい題材です。

全体のアイデア:数える箱を10個用意する
数字文字は 0〜9 の 10種類だけなので、カウント用の配列を 10 要素で作るのがピッタリです。
カウント用配列の対応
| 数字文字 | 添字 | カウント先 |
|---|---|---|
| '0' | 0 | cnt[0] |
| '1' | 1 | cnt[1] |
| '2' | 2 | cnt[2] |
| ... | ... | ... |
| '9' | 9 | cnt[9] |
表の説明
- 添字が 0〜9 なので、数字文字と一致させると管理が簡単です
- cnt[3] は「文字 '3' の出現回数」を入れる箱になります
なぜ cnt[s[i] - '0']++ で数えられるの?
C言語では文字は数値(文字コード)として扱われます。
そして '0','1',...,'9' は1つずつ増えていくことが保証されています。
文字から添字を作る仕組み
| 文字 | 計算 | 結果 |
|---|---|---|
| '0' | '0' - '0' | 0 |
| '3' | '3' - '0' | 3 |
| '9' | '9' - '0' | 9 |
表の説明
- '0' を基準に引き算すると、欲しい 0〜9 がそのまま出ます。
- これができるのは「数字文字が連続している」保証があるからです。
サンプルプログラム
読み込みを scanf ではなく fgets にして、空白を含む行でも扱えるようにしています。
プロジェクト名:chap9-9-1 ソースファイル名:chap9-9-1.c
// 文字列内の数字文字をカウントする(別例)
#include <stdio.h>
// 文字列 s 内の数字文字の出現回数を cnt[10] に加算
void str_dcount(const char s[], int cnt[])
{
int i = 0;
while (s[i]) {
if (s[i] >= '0' && s[i] <= '9')
cnt[s[i] - '0']++;
i++;
}
}
int main(void)
{
char line[128];
int dcnt[10] = {0};
printf("一行入力してください(例:ID=A12-39):");
fgets(line, sizeof(line), stdin);
str_dcount(line, dcnt);
puts("数字の出現回数まとめ");
for (int i = 0; i < 10; i++)
printf("%d : %d回\n", i, dcnt[i]);
return 0;
}実行例
一行入力してください(例:ID=A12-39):ID=Q12-39
数字の出現回数まとめ
0 : 0回
1 : 1回
2 : 1回
3 : 1回
4 : 0回
5 : 0回
6 : 0回
7 : 0回
8 : 0回
9 : 1回文字列を走査して数える流れ
走査とカウントの流れ(イメージ)

図の説明
- 先頭から1文字ずつ見ます。
- 数字なら cnt の該当箱を1増やします。
- \0(終端)に来たら走査終了です。
登場する命令の書式と「何をする命令か」
while の書式と役割
- 書式
while (条件式) 文; - 何をする?
条件式が真のあいだ、文を繰り返します。
今回は s[i] が 0(終端)になるまで文字を見続けます。
if の書式と役割
- 書式
if (条件式) 文; - 何をする?
条件式が真のときだけ文を実行します。
今回は s[i] が '0'〜'9' の範囲ならカウントします。
fgets の書式と役割
- 書式
char *fgets(char *s, int size, FILE *stream); - 何をする?
1行読み込んで配列 s に入れます(改行も入ることがあります)。
scanf の %s と違って、空白を含む入力も読み取れます。
puts の書式と役割
- 書式
int puts(const char *s); - 何をする?
文字列を表示して、最後に改行も付けます。見出し表示に便利です。
printf の書式と役割
- 書式
int printf(const char *format, ...); - 何をする?
書式に従って整形しながら表示します。今回は集計結果の表示に使います。
cnt 配列を 0 で初期化する意味
カウントは「足し算」で増えていくので、最初が 0 じゃないと正しく数えられません。
初期化の考え方
| 状態 | dcnt[10] の中身 | 結果 |
|---|---|---|
| 初期化あり | 全部 0 から開始 | 正しく数えられる |
| 初期化なし | ゴミ値の可能性 | いきなり変な回数になる |
表の説明
- int dcnt[10] = {0}; は「全要素を 0 にする」定番テクニックです
演習問題
演習9-8:文字列を後ろから表示する関数
文字列を後ろから逆に表示する関数を作成せよ。
void put_stringr(const char s[]);
解答例
プロジェクト名:chap9-9-2 ソースファイル名:chap9-9-2.c
Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。
#include <stdio.h>
int str_length(const char s[])
{
int len = 0;
while (s[len])
len++;
return len;
}
void put_stringr(const char s[])
{
int len = str_length(s);
for (int i = len - 1; i >= 0; i--)
putchar(s[i]);
}
int main(void)
{
char s[128];
printf("文字列:");
scanf("%127s", s);
put_stringr(s);
putchar('\n');
return 0;
}解説
- まず長さを調べて、末尾から添字を減らして表示します。
- \0 は表示しません(走査の終端として使うだけです)
演習9-9:文字列そのものを反転して更新する関数
文字列 s の並びを反転する関数を作成せよ。
void rev_string(char s[]);
解答例
プロジェクト名:chap9-9-3 ソースファイル名:chap9-9-3.c
Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。
#include <stdio.h>
int str_length(const char s[])
{
int len = 0;
while (s[len])
len++;
return len;
}
void rev_string(char s[])
{
int len = str_length(s);
for (int i = 0; i < len / 2; i++) {
char tmp = s[i];
s[i] = s[len - 1 - i];
s[len - 1 - i] = tmp;
}
}
int main(void)
{
char s[128];
printf("文字列:");
scanf("%127s", s);
rev_string(s);
printf("反転結果:%s\n", s);
return 0;
}解説
- 左端と右端を交換して、内側へ詰めていく方式です。
- len/2 回だけ交換すれば全部ひっくり返ります。
- 更新するので仮引数は const を付けません。
