以下のプログラムの理解について、質問です。
入力した文字列に、0 ~ 9 の数字がそれぞれ何度含まれていたかをカウントするプログラムです。
(明解C言語 入門編 P219)
==========
プログラム
==========
#include <stdio.h>
void str_dcount(const char str[], int cnt[])
{
unsigned i = 0;
while(str[i]) { // str に '\0' が現れるまで繰り返し
if(str[i] >= '0' && str[i] <= '9')
cnt[str[i] - '0']++; // !!!! ココです !!!!
i++;
}
}
int main(void)
{
int i;
int dcnt[10] = {0};
char str[100];
printf("文字列を入力してください : " );
scanf("%s", str); // 文字列を str へ
str_dcount(str, dcnt); // 引数 str = 入力した文字列, dcnt = すべて '0'
puts("数字文字の出現回数 ");
for(i = 0; i < 10; i++)
printf("'%d' : %d\n", i, dcnt[i]);
return 0;
}
=========
実行結果
=========
文字列を入力してください : 3.14159
数字文字の出現回数
'0' : 0
'1' : 2
'2' : 0
'3' : 1
'4' : 1
'5' : 1
'6' : 0
'7' : 0
'8' : 0
'9' : 1
==========
質問内容
==========
関数 str_dcount 内の 『 cnt[str[i] - '0']++; 』 がどのような処理を行っているのか、理解ができません。
以下のように考えたのですが、それでは上手く動かないとの結論に至りました。
たとえば、i = 0 で、str[100] = 3.14159 であるとき、
/* ループ1回目 */
cnt[0] = str[0] - 0; /* 3 - 0 で cnt[0] には 3 が入る。 */
cnt[0++];
/* ループ2回目 */
cnt[1] = str[1] - 1; /* "." - 1 となる。 数字ではないので減算できずエラーになるのでは? */
cnt[1++];
/* ループ3回目 */
cnt[2] = str[2] - 2; /* 1 - 2 なので、なぜか負の数になってしまう。。 */
cnt[2++];
配列の添え字が、配列になっている cnt[str[i]] までは理解できますが、
以下の2点が解っていないために理解ができていないようです。
1) cnt[str[i] - '0']++ ;
の - '0' が何を行っているのか
配列には数字が入っており、そこから文字 '0' を減算しているのでしょうか?
数字から文字を減算できるのでしょうか?
2) ++
はどの値を増加させているのでしょうか?
宜しくお願いします。
No.1ベストアンサー
- 回答日時:
unsigned i = 0;
while(str[i]) { // str に '\0' が現れるまで繰り返し
if(str[i] >= '0' && str[i] <= '9')
cnt[str[i] - '0']++; // !!!! ココです !!!!
i++;
str[]に"3.14159"が入っていたとき、
str[0] == '3'であるから、if文の条件を満たします。
str[0] - '0'は、'3' - '0'ですから、3という数値です。
たいていの文字コードでは'0', '1, '2', ..., '9'の順に番号が振ってあるはずですから、
'0'を基準としていくつ離れているか('3' - '0'の式の部分)が、その数字に相当します。
cnt[3]++;は、配列の要素cnt[3]の値を1だけ増やします。
これで、"3.14159"の先頭文字である'3'の個数が1個増えたことになります。
i++;によって、次の文字'.'を対象とします。
これは、数字ではありませんので、if文をスルーします。
i++;によって、次の文字'1'を対象とします。
ここの処理は、先ほどの'3'の場合と同じです。cnt[1]を1増やします。
以下同様です。
No.4
- 回答日時:
数字の文字コードは連続していると仮定(念のため)
> /* ループ1回目 */
> cnt[0] = str[0] - 0; /* 3 - 0 で cnt[0] には 3 が入る。 */
> cnt[0++];
str[0]は'3'で、str[i]-'0'='3'-'0'=3です。この値がcntの添え字になります。
なので、cnt[3]++;が実行されます。++の位置も違いますね。
> /* ループ2回目 */
> cnt[1] = str[1] - 1; /* "." - 1 となる。 数字ではないので減算できずエラーになるのでは? */
> cnt[1++];
その前のif文で'.'は排除されています。
> /* ループ3回目 */
> cnt[2] = str[2] - 2; /* 1 - 2 なので、なぜか負の数になってしまう。。 */
> cnt[2++];
str[2]-'0'ですよね。なんで-2になってるんですか?
'2'-'0'=2なので、cnt[2]++;が実行されます。
ご回答有難うございました。おかげさまで理解が進みました。
ベストアンサーにすることができず恐縮ですが、皆様の
回答を読むことで理解度が高まり、感謝しております。
No.3
- 回答日時:
文字データは特定の数値で符号化されています.
ひとまず,ASCIIコード表と照らし合わせるのが分かりやすいでしょう.
1) - '0' が何を行っているのか
'0'はASCIIコードで48(十六進数で0x30)です.
'3'は同じく51(十六進数で0x33)です.
よって '3'-'0' は 51-48 を意味し,結果は数値の 3 です.
2) ++ はどの値を増加
上の例('3'-'0')なら,'3'の度数(cnt[3])を増やします.
/* ループ1回目 */
cnt[3]++; /* '3'-'0' = 51-48 = 3 より */
/* ループ2回目 */
/*
if(str[i] >= '0' && str[i] <= '9') は
if(str[i] >= 48 && str[i] <= 57) であり,
'.' == 46 なので 偽となる
*/
/* ループ3回目 */
cnt[1]++; /* '1'-'0' = 49-48 = 1 より */
以下同様.
ご回答有難うございました。おかげさまで理解が進みました。
ベストアンサーにすることができず恐縮ですが、皆様の
回答を読むことで理解度が高まり、感謝しております。
No.2
- 回答日時:
if(str[i] >= '0' && str[i] <= '9')
cnt[str[i] - '0']++; // !!!! ココです !!!!
これを
if(str[i] >= '0' && str[i] <= '9'){
printf("%d回目,str[i]=%d,str[i]-'0'=%d,before:cnt[%d]=%d",i,str[i],str[i]-'0',str[i]-'0',cnt[str[i] - '0']);
cnt[str[i] - '0']++; // !!!! ココです !!!!
printf(",after:cnt[%d]=%d\n",str[i]-'0',cnt[str[i] - '0']);
}
これに書き直して実行ささせてみなさい。
ご回答有難うございました。おかげさまで理解が進みました。
ベストアンサーにすることができず恐縮ですが、皆様の
回答を読むことで理解度が高まり、感謝しております。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# str[j++]の意味 2 2022/08/30 16:20
- C言語・C++・C# C#テキストボックスの文字を配列にいれてその後表示する 4 2022/07/17 04:47
- その他(プログラミング・Web制作) python質問 1 2023/08/14 11:54
- C言語・C++・C# C# 浮動小数の数値文字列化 1 2022/04/18 15:15
- C言語・C++・C# sprintf()の使い方について 1 2022/08/17 16:16
- Visual Basic(VBA) VBA ユーザーフォームからSubプロージャ―に値を引き渡す方法 3 2023/04/09 01:54
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
break文でループを一気に抜ける...
-
do-while文が禁止される理由
-
繰り返し文の利点について
-
入力した文字列から母音だけを...
-
for文while文の無限ループの違...
-
ループの特定入力終了
-
C言語forループが完結した場合...
-
if文を使わずに奇数・偶数を判断
-
階層型ニューラルネットに準ニ...
-
アルゴリズムです!四つの数字...
-
C言語のfor文です。 繰り返しの...
-
2÷3などの余りについて
-
信頼区間の1.96や1.65ってどこ...
-
Enterキーを押されたら次の処理...
-
*をユーザーが入力した数字の数...
-
fgetsなどのときのstdinのバッ...
-
C言語で%を使わない余りの出し方
-
C言語
-
プログラムでの数字につく”f”の...
-
マイナスからプラスへ転じた時...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
break文でループを一気に抜ける...
-
do-while文が禁止される理由
-
ループを途中で抜けたいのですが。
-
入力した数値を倍々するプログラム
-
入力した文字列から母音だけを...
-
if文の中にfor文なのか、for文...
-
C言語forループが完結した場合...
-
エクセルでC言語のfor文と同じ...
-
Excel VBAで年度をまたぐ期間の...
-
For文の終了値を関数にしても問...
-
エクセルVBAで Do While (1)って?
-
C言語、whileループを抜け出す...
-
PAD図の書き方
-
Cプログラムが終了しない
-
PIC のプログラムについて ど...
-
他言語で言うcontinue文
-
C言語のプログラムみてください...
-
ループの特定入力終了
-
COBOLのEVALUATE文
-
for文while文の無限ループの違...
おすすめ情報