プロが教えるわが家の防犯対策術!

タイトルのようなプログラムをCで作ろうとしています。ちなみに初学者です。
たとえば 32356695 と入力すると
'0' appeared 0 times.
'1' appeared 0 times.
'2' appeared 1 times.
'3' appeared 2 times.
'4' appeared 0 times.
'5' appeared 2 times.
'6' appeared 2 times.
'7' appeared 0 times.
'8' appeared 0 times.
'9' appeared 1 times.
と表示されるようにしたいです。そこで以下のようなプログラムを組みましたが
コンパイルは成功するもexeを実行すると数字入力後エラーメッセージが出ます。
*************************************************
#include<stdio.h>
#include<string.h>
#include<stdlib.h>


int main(void)
{
int i;
int count[10]={0};
int length;
int digit;
char str[100];

printf("Please input number:");
gets(str);

length = strlen(str);

for(i=0;i<length;i++){

if(str[i]>='0' && str[i]<='9'){
digit = atoi(&str[i]);
count[digit]++;
}
}

for(i=0;i<=9;i++){
printf("'%d' appeared %d times.\n",i,count[i]);

}

return(0);
}
******************************************************
よくわからないのですが何故か文字列の長さを収納する変数lengthが1になているようです。
どうかお力添えください。お願いいたします。
コンパイラはbcc32、OSはWindowsXPです。

A 回答 (5件)

がるです。



> しかし何故digit = atoi(&str[i]);はダメで、がるさんの言うように
> 別の配列に入れなおすとうまく行くのでしょうか。
うい。ではちょっと詳細に。

例えば、strに
0123
と入ってるとします。正確には文字の後ろに¥0が入っているので、¥0をnで表現するとして
0123n
となります。
今回取得したいのは、0であったり1であったりといった「数字一桁」になります。
では、i=0の場合の&str[i]を考えて見ます。
str[i]は今回str[0]になるので、文字の先頭は0になります。ただ、atoiは「char *」を引数として期待しているため、当然のように「¥0があるところまで」を数字として取ってきます。
0123n
あれ?
これでは、取りたい数字になりません。
# このあたり、元のソースで、atoiの直後に、printfでdigitの値をprintするとわかります。

で。そのために「一文字だけを格納した別領域」を用意してやります。
それがcwk文字配列になります。

ちなみに、cwkは「char work」の略です(笑
ええあまり推奨できるネーミングではありませんが…便利なので、局所に限ってはたまに使います。特にテスト用のコードの場合。

こんなんで説明になりますでしょうか?

あと。#3さんのおっしゃるようなやり方もありです。ただしそれはASCIIコードなどに依存するので、一応コメントにそんな風に書いておいたほうがよいです(0-9が不連続にマッピングされているコード体系も存在するので)。
    • good
    • 0

#include <stdio.h>



int main(void){
int i;
int count[10]={0};
char str[100];

printf("Please input number:");
gets(str);

for(i=0;str[i];i++)
if('0' <= str[i] && str[i] <= '9')
count[str[i]-'0']++;

for(i=0;i<=9;i++)
printf("'%d' appeared %d times.\n",i,count[i]);

return(0);
}
    • good
    • 2

たいていの場合 '0'~'9' は (文字コード上で) この順に並んでいるので, atoi なんか使わなくても 0~9 に変換でき

    • good
    • 0

このような場合、実行時に出力されるというエラーを併せて書いていただくといいと思います。


とても重要な情報なのですが。

あと、たとえば、エラーが出る場合に、入力を

0
1
2

とか、やってみるといろいろヒントがつかめるものです。

さて、atoi() は、「文字列を数値に」直す関数です。
ですから、

1234567890

と入力した場合、最初の digit の値は、(整数としての)1234567890 になります。
ここで、count[1234567890] をインクリメントしようとして、(設定によっては)エラーが表示されることになります。

あと、length が 1 になる要素はなさそうだと思いますが、そのあたりも、どのように確認したのかがあると、いろいろわかると思います。
    • good
    • 0
この回答へのお礼

うーん、よくわからないのですが、
つまりatoiは文字列のうちの1個のstr[i]を数値にするのではなく
文字列str全体を数値にすることしか出来ないということでしょうか?
つまり
digit=atoi(&str[i]);はatoiの使い方が間違っていて
digit=atoi(str)という書き方しかできない、ということでしょうか?

あとlengthが1になるというのは正直ちょっと違う状況、、、
実は文字を読み込むときgets(str)かscanf("%c",str)なのかわからず
両方試したんですが、後者の時にprintf("%d",length)とすると
1と表示されたのです。なのでgetsのときでは無かったです。
申し訳ありません。

お礼日時:2006/05/12 19:29

がると申します。

何点か。

1.ループについて
単純に
for(; str[i] != '\0'; i++) {
でも良いと思うのですがどうでしょうか?

2.
できればgetsではなくてfgetsを使うとよいです。

3.
データ取得のところですが。
digit = atoi(&str[i]);
だとうまくいかないです。
char cwk[4];
を宣言した後に
cwk[1] = '\0';
if(str[i]>='0' && str[i]<='9'){
cwk[0] = str[i];
digit = atoi(cwk);

という感じでもっていくと、うまくいきます。
# ここがうまくいかない理由が直接的にカウントがうまくいっていない理由です。

参考になれば幸いです。
    • good
    • 0
この回答へのお礼

・・・うまくいきました!!!
おっしゃるとおり3のところが問題だったようです。
しかし何故digit = atoi(&str[i]);はダメで、がるさんの言うように
別の配列に入れなおすとうまく行くのでしょうか。
正直考えてもさっぱりで、願わくばご教授いただきたいです。
あとcwkって何の略なのでしょう。妙に気になります笑。

とにもかくにも、ほんとうにありがとうございます!

お礼日時:2006/05/12 19:22

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!