ページ 11

文字列中の各 文字の出現回数を数える

Posted: 2010年6月22日(火) 02:07
by porno
すいませんが質問に答えて下さい。

fgets() を使って50文字以下の文字列を入力し,文字列中の各
文字の出現回数を数えるプログラムを作成せよ。
という課題で 
例えば、
%
文字列は? abcdef,abb(ccc110)
a : 2
b : 3
c : 4
d : 1
e : 1
f : 1
, : 1
( : 1
1 : 2
0 : 1
) : 1
という感じに仕上げたいのですがどうしてもうまくいきません。
どうやって出現回数の数を数えることができるのか教えてもらえないでしょうか。

osはlinux、コンパイラはgccです。

一応作りかけのソースを載せておきます。

#include <stdio.h>

# define BUFFER_SIZE (256)

int main(void)
{
int i;
 int count[256];
char buf[BUFFER_SIZE];
printf("Please input :");
fgets(buf, BUFFER_SIZE, stdin);
for(i=0;buf;i++)
{
count[buf]++;
}
for(i=0;buf[i+1]!='\0';i++)
{
printf("'%c' appeared %d times.\n",buf,count[buf]);
}
return(0);
}

Re:文字列中の各 文字の出現回数を数える

Posted: 2010年6月22日(火) 02:54
by ookami
いろいろ気になるところはありますが、まずは、
int count[256];

int count[256]={0};
ですね。

現状の出力結果も回答の参考になるので、示してもらえるとよいと思いますよ。

Re:文字列中の各 文字の出現回数を数える

Posted: 2010年6月22日(火) 03:12
by porno
返答ありがとうございます。
ソースを直してから実行してみると
Please input number:ghfyug
'g' appeared 2 times.
'h' appeared 1 times.
'f' appeared 1 times.
'y' appeared 1 times.
'u' appeared 1 times.
'g' appeared 2 times.
となり、回数は正しくなりましたがgが二回表示されてしまいます。

また、
int count[256];

int count[256]={0};
なぜこのようにする必要があるのでしょうか。

Re:文字列中の各 文字の出現回数を数える

Posted: 2010年6月22日(火) 03:37
by ookami
デバッグの手法として「ステップ実行」はご存知でしょうか?活用を強くオススメします。gccが手元にないのでちょっと手順はわかりませんが…

とは言え、これくらいならってことで、
for(i=0;buf[i+1]!='\0';i++)
{
printf("'%c' appeared %d times.\n",buf,count[buf]);
}

for(i=0;i<256;i++)
{
if(count[buf]) printf("'%c' appeared %d times.\n",buf,count[buf]);
}
なぜこうなるのか、お分かりいただけるでしょうか?

> なぜこのようにする必要があるのでしょうか。

これは「c++ 配列 初期化」あたりで検索するとよいと思います。

Re:文字列中の各 文字の出現回数を数える

Posted: 2010年6月22日(火) 04:20
by porno
当たり前のことに気づいてなかったです..
0から数えるのだからすべてを0に初期化しないとだめということですね。

for(i=0;buf[i+1]!='\0';i++)
{
printf("'%c' appeared %d times.\n",buf,count[buf]);
}

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

これの意味がわかりません..
これに直してコンパイルし、実行したところ
おかしくなったのですが..

Re:文字列中の各 文字の出現回数を数える

Posted: 2010年6月22日(火) 04:44
by フリオ
 
 結果(count)を表示する際に入力した文字列(buf)を経由しているので、
その文字列に複数回出現する文字は、結果も複数回表示されます。
 
これは、入力した文字列(buf)を使わずに、結果(count)を表示すれば
回避できます。

Re:文字列中の各 文字の出現回数を数える

Posted: 2010年6月22日(火) 04:50
by フリオ
 
for(i=0;buf[i+1]!='\0';i++)
{
printf("'%c' appeared %d times.\n",buf,count[buf]);
}

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

 これだと、bufに格納されている文字列の終端を越えて意味のない場所まで参照してしまうので、
結果がおかしくなります。

Re:文字列中の各 文字の出現回数を数える

Posted: 2010年6月22日(火) 07:30
by ookami
うぅわすいません(汗
「なぜこうなるのか、お分かりいただけるでしょうか?」とか言って私が分かってないっていう… 本当にすみませんでした。

えぇと… その後うまくいきましたでしょうか。

Re:文字列中の各 文字の出現回数を数える

Posted: 2010年6月22日(火) 10:25
by porno
みなさんアドバイスありがとうございます。
一応このソースコードでうまくいったのですが、これであってますか?


#include <stdio.h>
# define BUFFER_SIZE (256)
int main(void)
{
int i;
int count[256]={0},sum[256]={0};
char buf[BUFFER_SIZE];
printf("Please input :");
fgets(buf, BUFFER_SIZE, stdin);
for(i=0;buf;i++)
{
count[buf]++;
}
for(i=0;buf[i+1]!='\0';i++)
{
if(sum[buf]==0)
{
printf("'%c' appeared %d times.\n",buf ,count[buf]);
sum[buf]++;
}
}
return(0);
}

Re:文字列中の各 文字の出現回数を数える

Posted: 2010年6月22日(火) 20:50
by mila
後ろの処理はこうした方がすっきりします。
for (i = 0; i < 256; i++) {
    if (count > 0) {
        printf("%c appeared %d times.\n", i, count);
    }
}

Re:文字列中の各 文字の出現回数を数える

Posted: 2010年6月22日(火) 21:59
by porno
こちらのほうがすっきりしますね。わかりました!
皆さんのおかげで完成することができました。

本当にありがとうございました!

Re:文字列中の各 文字の出現回数を数える

Posted: 2010年6月22日(火) 22:09
by KEYONN_
僕も自分なりに作ってみました。
作ったのはいいんですが、期待した動作と違っているような気がします。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define MAX_CODE 93
//93の由来は、ASCIIコード abs(0x21-0x7e)

int CountString(char *String)
{
static int Count[MAX_CODE]={0};
int StringTable[MAX_CODE]={0};

int i,j;

for(i=0;i<strlen(String);i++)
{
Count[String-0x21]++;
StringTable[String-0x21]=1;
}

{
for(i=0;i<MAX_CODE;i++)
{
if(StringTable==1 && Count!=0)
{
printf("%c:%d\n",i+0x21,Count);
}
}
}
}

#define BUFFERSIZE (256)
#define StringLen 50

int main(void)
{
char buf[StringLen];
printf("文字列は?");fgets(buf,BUFFERSIZE,stdin);

CountString(buf);

return 0;
}

Re:文字列中の各 文字の出現回数を数える

Posted: 2010年6月22日(火) 23:53
by porno
そのような方法もあるんですね!

ありがとうございます!!

Re:文字列中の各 文字の出現回数を数える

Posted: 2010年6月23日(水) 02:05
by フリオ
 
 charがsignedかunsignedかは処理系によるので、
char buf[BUFFER_SIZE];
は、
unsigned char buf[BUFFER_SIZE];
にしましょう。
 
先に、
>これは、入力した文字列(buf)を使わずに、結果(count)を表示すれば
>回避できます。
と回答しましたが、もし結果表示の順を文字コードではなく、
入力した文字列に依るのなら、
for(i = 0; buf && buf != '\n'; ++ i) 
    { 
        if(count[buf]) 
        { 
            printf("'%c' appeared %d times.\n", buf, count[buf]);  
            count[buf] = 0;
        }
    }

という方法もあります。
 

画像