- ベストアンサー
配列をいれても表示がおかしい
data.txtから英文を読み込んで配列にいれ、それをさらに英単語に分類して配列に入れるプログラムを作っています。動作確認のために画面表示させているのですが、表示に変な文字が入ってしまい、わけがわからなくなっています。 どこか、おかしい点があれば指摘をお願いします<(_ _)> //tango1から英単語を取り出し、tango2に入れる。------------------------------- fp=fopen("data.txt","r"); /*つぎにtango1の中にある英文を空白、改行ごとに*/ n=0;s=1; /*一つの英単語とみなしてtango2に入力する。*/ while((c=fgetc(fp))!=EOF){ if (c==' '){ /*上記の前に空白、改行をpointに入れて*/ point[s]=n;s++; /*pointとpointの間が英単語であることを認識させる。*/ } else if(c=='\n'){ point[s]=n;s++; } n++; } fclose(fp); s=1; while(s<20){ for(h=0,i=point[s];i<point[s+1];h++,i++){ tango2[j][h]=tango1[i]; } s++; printf("tango2[%d]は%sです。\n",j,tango2[j]); j++; } }
- みんなの回答 (8)
- 専門家の回答
質問者が選んだベストアンサー
No1, No3, No5です 2行以上でも正常に読み込むには…… ・1行読み込むごとに単語に分ける ・前にtango1に格納した範囲を記憶しておき、次の行は続きに格納する ・tango1を2次元配列にして、行ごとに読み込む などの方法があります(他にもあると思いますが……)。 なお、No6のtaka_tetsuさんが回答されているように、C言語の文字列は'\0'で終わることになっているので、これを忘れないように付け足す必要があります。
その他の回答 (7)
- tsukasa-12r
- ベストアンサー率65% (358/549)
私は、最初のソースコードを見た時点では、 buf の長さ>1行の長さ(改行までの長さ) の場合に、単語の途中で切れる可能性があるので、それが嫌で fgets を使用していないのかと勝手に推測していたんですが、#3 の補足を見ましたが、fgets 使用してるんですね。 単語が途中で切れる場合があることを考慮しなければなりませんが、fgets を使用するんでしたら strtok() 関数で単語を切り出せばいいと思います。
- taka_tetsu
- ベストアンサー率65% (1020/1553)
//for(i=0;buf[i]!=0;i++){ //tango1[i]=buf[i]; //printf("%c",tango1[i]); /*ここで、data.txtの中身を画面に表示する。*/ ///*つまり、tango1にdata.txtの中身が入っている事が証明される。*/ //} 証明されません。 buf[i] の値が'\0'だったときに格納されていません。 つまり、tango1は'\0'で終了していません。
- winterofmeei
- ベストアンサー率22% (20/88)
たとえばdataファイルが以下のようなものだとします ------ abc def ghi jkl mn opq rst ------ この場合、『//data.txtの中身をtango1に入れる』のwhile内で fgets(buf,100,fp)が(2行あるので)2回実行されます。 1回目でbufの内容は「abc def ghi jkl」となりこれがtango1にコピーされ、 2回目でbufの内容は「mn opq rst」となりこれがtango1に上書きされます。 つまり、最後に読み込んだ行の内容がtango1の内容となり、他の行は無視されます。
補足
なるほど!だから表示の時に最後の行のやつだけ表示されていたんですね。 上書きされないためにはどこを変更すればいいですか?
- winterofmeei
- ベストアンサー率22% (20/88)
以下の条件で「変な文字」が出力されるのでは? ・単語数が20未満しかない ・2行以上にわたってファイルに文章が書かれている ・ファイルの文字数が100文字以上ある 改行も単語の区切りとしたい、というわけですが このプログラムはそもそも2行以上の入力は読めません。 なぜなら、次の行を読み込むとき、前の行を読み込んだ部分に上書きしているからです。
補足
・単語数が20未満しかない ・ファイルの文字数が100文字以上ある この2つの意味は分かったのですが、 ・2行以上にわたってファイルに文章が書かれている の意味がわかりません。 「data.txtの文章が2行以上だとおかしくなる」という意味ですか?
- winterofmeei
- ベストアンサー率22% (20/88)
No1です。 文字列の最後に'\0'が入力されていなかったので、入力すれば解決するかもとおもったのです。 これで解決しないなら、どこに原因があるのか分かりません。どのように表示されているかが分かれば、どこにバグがあるか指摘できるかも知れませんが。。。
補足
これが全文です。文字列の最後に'\0'もいれておきました。 #include<stdio.h> #include<stdlib.h> #include<string.h> main(){ FILE *fp; char c,d,buf[100]; char tango1[100]; char tango2[30][50]; /*英単語を配列に入れる*/ char tango3[30]; int point[1000]; int kuhaku[1000]; /*スペース*/ int h,i,j=0,m,n,s; //data.txtの中身をtango1に入れる。------------------------------------------- fp=fopen("data2.txt","r"); while( fgets(buf,100,fp)!=NULL){ for(i=0;buf[i]!=0;i++){ tango1[i]=buf[i]; printf("%c",tango1[i]); /*ここで、data.txtの中身を画面に表示する。*/ /*つまり、tango1にdata.txtの中身が入っている事が証明される。*/ } } fclose(fp); printf("\n\n"); //tango1から英単語を取り出し、tango2に入れる。------------------------------- fp=fopen("data2.txt","r"); /*つぎにtango1の中にある英文を空白、改行ごとに*/ n=0;s=1; /*一つの英単語とみなしてtango2に入力する。*/ while((c=fgetc(fp))!=EOF){ if (c==' '){ /*上記の前に空白、改行をpointに入れて*/ point[s]=n;s++; /*pointとpointの間が英単語であることを認識させる。*/ } else if(c=='\n'){ point[s]=n;s++; } n++; } fclose(fp); s=1; while(s<20){ for(h=0,i=point[s];i<point[s+1];h++,i++){ tango2[j][h]=tango1[i]; } tango2[j][h] = '\0'; s++; printf("tango2[%d]は%sです。\n",j,tango2[j]); j++; } }
- tsukasa-12r
- ベストアンサー率65% (358/549)
while((c=fgetc(fp))!=EOF){ ... } のループの中では、ファイルから読み取った c を tango1 にも tango2 にも格納してませんよね? tango1 も tango2 もどこでどう宣言されているのかわかりませんし、ちゃんと単語の長さ分だけ確保されているのかわかりません。このへんは大丈夫なんでしょうか? ちょっとやってみました。参考にしてみてください。 #include <stdio.h> #include <string.h> #include <malloc.h> char buffer[100]; #defin WORD_MAX 100 char *pWord[WORD_MAX]; int main(void) { FILE *fp; char *p; char c; int iCount; int i; int blnDelimiter; fp = fopen("data.txt","r"); if( fp == NULL ) { return( 0 ); } p = buffer; iCount = 0; blnDelimiter = 0; do { c = fgetc(fp); switch( c ) { case ' ': case '\n': case EOF: if( blnDelimiter == 0 ) { // 空白などが連続する場合は、そのまま読み飛ばす。 blnDelimiter = 1; *p = '\0'; pWord[iCount] = (char *)malloc( sizeof(char) * ( strlen(buffer) + 1 ) ); if( pWord != NULL ) { strcpy( pWord[iCount], buffer ); puts( pWord[iCount] ); iCount++; } p = buffer; } break; default: if( blnDelimiter == 1 ) { blnDelimiter = 0; } *p = c; p++; } if( iCount >= WORD_MAX ) { break; } } while( c != EOF ); fclose(fp); // ここで、何らかの処理を行う。 // 使用済みメモリ開放 i = 0; while( pWord[i] ) { free( pWord[i] ); i++; if( i >= WORD_MAX ) { break; } } return( iCount ); }
補足
すみません。プログラム全体載せようと思ったのですが、800文字以上は書き込めないらしくて。主要部分を書きました。 プログラムを全部作っていただいてありがとうございます。この中で重要だと思われるプログラムがあれば教えていただきたいのですが・・
- winterofmeei
- ベストアンサー率22% (20/88)
他にも色々と疑問な点がありますが…… 以下の方法で解決できないでしょうか? for(h=0,i=point[s];i<point[s+1];h++,i++){ tango2[j][h]=tango1[i]; } // ここに tango2[j][h] = '\0'; を追加 s++; printf("tango2[%d]は%sです。\n",j,tango2[j]); j++;
補足
返答ありがとうございます。tango2[j][h] = '\0'; を追加して実行してみたのですが、表示結果はかわりませんでした。ちなみにこれはどういう意味なのでしょうか?
補足
・tango1を2次元配列にして、行ごとに読み込む これでやってみようと思います。アドバイスありがとうございます。