No.18171![]() |
10件の文章を2次元配列に格納し、表示する 投稿者---ΔΓβ(2004/11/16 21:11:36) |
||
はじめまして。ちょっとした知人の出したプログラムをといているのですが、行き詰ってしまいました。 2次元配列に文章を格納するプログラムなのですが、以下の仕様を満たすことが出来ません。 ・文章の長さは10文字以下、11文字以上入力されたときは先頭から10文字までを有効とし、以降は無視 ・文章の最大件数は10件 ・10件目の入力が完了するか、文章の1文字目に0が入力された場合は入力を終了し、それまでのデータを表示 ・改行のみの入力の場合、エラーメッセージを表示し再入力 現在まで出来ているソースは下のようになりますが #include <stdio.h> int main() { char name[10][10]; int i; for (i = 0; i < 10; i++) { printf("name[%d]:", i); scanf("%s", name[i]); printf("現在%d件目\n", i+1); } for (i = 0; i < 10; i++) { printf("name[%d] = %s\n", i, name[i]); } return(0); } 満たしているのは10件までというものだけなのですが、これ以上は思いつきません。 どなたか教えていただけると幸いです。 |
No.18176![]() |
Re:10件の文章を2次元配列に格納し、表示する 投稿者---KING・王(2004/11/17 00:56:21) |
||
> char name[10][10]; このままでは、10文字の文字列を入力すると、オーバフローが発生します。 > scanf("%s", name[i]); scanf()では、入力される文字の制限ができないので、10文字以上のデータを入力された場合、 name[i]に10文字以上のデータが格納され、オーバフローを起こします。 >・文章の長さは10文字以下、11文字以上入力されたときは先頭から10文字までを有効とし、以降は無視 私ならとりあえず以下のようにします。 #255文字以上のデータを入力されるとオーバーフローします。 char name[10][11]; char buf[256];// 入力データ用バッファ scanf("%d", buf );//一旦バッファにデータを格納する strncpy( name[i], buf, 10 );// 入力バッファより10文字分コピーする name[i][11] = '\0';//10文字以上の場合のために、末端のNULLを付加しておく。 >・10件目の入力が完了するか、文章の1文字目に0が入力された場合は入力を終了し、それまでのデータを表示 if( name[i][0] == '0' ){//入力の先頭の文字が'0'かチェックする break;//ループを抜ける } #先の例を用いてる場合、name[i][0]の部分はbuf[0]でも可 >・改行のみの入力の場合、エラーメッセージを表示し再入力 改行のみの入力の判定に関しては、scanf()の使い方と動作にいまいち自信がないので、 他の識者の方におまかせるとして、エラーメッセージの表示と再入力に関しては、 次のような形はどうでしょうか? if( /*改行のみの入力と判定*/ ){ printf( "正しくデータを入力して下さい\n" ); i--;//ループで同じiの値を繰り返すために、iの値を //デクリメントしておく。 continue; } scanf()系の動作に関しては、いまいち自信がありませんので、 識者の方々、フォローをお願いします。 |
No.18189![]() |
Re:10件の文章を2次元配列に格納し、表示する 投稿者---ΔΓβ(2004/11/17 12:39:18) |
||
色々考えた結果、scanfではなくgetcharを使用することにしたのですが……改行の際に再入力がどうしても出来ません。 下にソースを張ります。 <pre>#include <stdio.h> #define MAXCHAR 10 main() { char name[10][11] = {0}; int c = 0, i, j; int count = 0, che1 = 0, che2 = 0; for (i = 0; i < 10; i++) { printf("氏名%d入力:", i + 1); j = 0; che1 = 0; while ((c= getchar()) != '\n' && j < MAXCHAR) { name[i][j++] = c; if (che1 == 0 && c == '0') { che2 = 1; } if (che1 == 0 && c == '\n') { i = i - 1; printf("再入力"); break; } che1 = 1; } fflush(stdin); name[i][MAXCHAR + 1] = '\0'; count = count + 1; printf("累計件数:%d\n", count); if (che2 == 1) { break; } } for (i = 0; i < count -1; i++) { printf("%d件目:", i+1); for (j = 0; j < 10; j++) { printf("%c", name[i][j]); } putchar('\n'); } } どなたかご教授をお願いいたします。 |
No.18193![]() |
Re:10件の文章を2次元配列に格納し、表示する 投稿者---あかま(2004/11/17 13:38:26) |
||
>色々考えた結果、scanfではなくgetcharを使用することにしたのですが……改行の際に再入力がどうしても出来ません。 一文字目が改行だったらループあたりでやり直せばいいです。 >下にソースを張ります。 文字化け。これだとコピペで使えないです。 確認画面があるのですから、しっかり確認してから投稿してください。 それでも投稿しちゃったなら投稿しなおしがよいかと。 |
No.18194![]() |
Re:10件の文章を2次元配列に格納し、表示する 投稿者---ΔΓβ(2004/11/17 14:21:43) |
||
すいません、よく確認せず貼り付けてしまいました。 まだ改行のみの入力の場合、再入力は出来ていませんが……。 #include <stdio.h> #define MAXCHAR 10 main() { int c1 = 0, check = 0, check2 = 0, i, j, count = 0; char str[11][MAXCHAR + 1] = {0}; for (j = 0; j < 10; j++){ printf("文字列%dを入力:", j + 1); i = 0; check = 0; /*改行、あるいはMaccharを超えるまで文字を入力*/ while ((c1 = getchar()) != '\n' && i < MAXCHAR) { str[j][i++] = c1; if (check == 0 && c1 == '0'){ check2 = 1; } else if (check == 0 && c1 == '1'){ j = j - 1; count = count - 1; printf("再入力:\n"); break; } check = 1; } fflush( stdin ); str[j][MAXCHAR + 1] = '\0'; count = count + 1; printf("累積レコード数:%d\n", count); if (check2 == 1){ printf("終了\n"); break; } } for(j = 0;j < count; j++){ printf("%d件目:", j + 1); for(i = 0; i < 10; i++){ printf("%c", str[j][i]); } putchar('\n'); } } こちらがソースになります。 以前の投稿は消させていただきますのでお願いいたします。 |
No.18195![]() |
Re:10件の文章を2次元配列に格納し、表示する 投稿者---ΔΓβ(2004/11/17 14:27:47) |
||
>こちらがソースになります。 >以前の投稿は消させていただきますのでお願いいたします。 すいません、以前の投稿はパスワードを失念してしまい消すことが出来ませんでした。 |
No.18204![]() |
Re:10件の文章を2次元配列に格納し、表示する 投稿者---あかま(2004/11/17 18:43:09) |
||
>すいません、よく確認せず貼り付けてしまいました。 >まだ改行のみの入力の場合、再入力は出来ていませんが……。 内側のwhile内で if(i==0 && c1 == '\n') エラー表示&どこぞへ飛ぶ みたいのを入れればいいのではないでしょうかね。 |
No.18205![]() |
Re:10件の文章を2次元配列に格納し、表示する 投稿者---ΔΓβ(2004/11/17 19:29:37) |
||
>内側のwhile内で > >if(i==0 && c1 == '\n') エラー表示&どこぞへ飛ぶ > >みたいのを入れればいいのではないでしょうかね。 やってみたのですが、どうしても「\n」では反応しないのです。 数値の「1」や文字「a」などでは反応があるのですが……。 |
No.18207![]() |
Re:10件の文章を2次元配列に格納し、表示する 投稿者---かずま(2004/11/17 21:06:21) |
||
>>内側のwhile内で >> >>if(i==0 && c1 == '\n') エラー表示&どこぞへ飛ぶ >> >>みたいのを入れればいいのではないでしょうかね。 > > やってみたのですが、どうしても「\n」では反応しないのです。 > 数値の「1」や文字「a」などでは反応があるのですが……。 どんなコードを書かれたのかわかりませんが、c1 が '\n' でなかったら while 内に入るわけですから、while 内で if (... c1 == '\n') とやっても 無意味です。 それから、11文字以上の入力を捨てるために fflush(stdin) を実行して いますが、これは VC++ や BC++ では思ったとおり動きますが、gcc では 何もしてくれません。C の規格では、出力ストリームにのみはたらくことが 規定させていて、入力ストリームに対しては未定義となっています。 |
No.18206![]() |
Re:10件の文章を2次元配列に格納し、表示する 投稿者---かずま(2004/11/17 20:58:53) |
||
> 私ならとりあえず以下のようにします。 > #255文字以上のデータを入力されるとオーバーフローします。 > char name[10][11]; > char buf[256];// 入力データ用バッファ > > scanf("%d", buf );//一旦バッファにデータを格納する > strncpy( name[i], buf, 10 );// 入力バッファより10文字分コピーする > name[i][11] = '\0';//10文字以上の場合のために、末端のNULLを付加しておく。 255文字ではオーバーフローしません。 "%d" は、文字列を読み込むのに使いません。 "%255s" にすると、バッファーオーバーフローによるプログラムの破壊は 防げますが、実行結果が思ったとおりになるとは限りません。 name[i][11] は参照してはいけません。name[i][10] の間違いでしょう。 '\0' のことを NULL というのは不適切です。 |
No.18211![]() |
Re:10件の文章を2次元配列に格納し、表示する 投稿者---KING・王(2004/11/17 23:27:28) |
||
ご指摘ありがとうございます。 なんか、細かいミスばかりでぼろぼろ。。。 それぞれ、以下の間違いです。 > scanf("%d", buf );//一旦バッファにデータを格納する => scanf("%s", buf ); > name[i][11] = '\0';//10文字以上の場合のために、末端のNULLを付加しておく。 =>name[i][10] = '\0'; |
No.18209![]() |
Re:10件の文章を2次元配列に格納し、表示する 投稿者---かずま(2004/11/17 21:52:26) |
||
参考となるプログラムですが、このプログラムは未完成です。 EOF の処理が抜けているので、とんでもないことになる可能性があります。 #include <stdio.h> #define MAXCHAR 10 #define MAXSTR 10 int main(void) { int i, n, c; char str[MAXSTR][MAXCHAR + 1]; for (n = 0; n < MAXSTR; ) { printf("文字列%dを入力:", n + 1); for (i = 0; (c = getchar()) != '\n'; ) if (i < MAXCHAR) str[n][i++] = c; str[n][i] = '\0'; if (str[n][0] == '0') break; if (str[n][0] == '\0') printf("再入力:\n"); else printf("累積レコード数:%d\n", ++n); } for (i = 0; i < n; i++) printf("%d件目:%s\n", i + 1, str[i]); return 0; } |