• 締切済み

C言語 この記述のどこが間違っているのでしょうか?

最大10文字の文字列入力を受け付け、 10回入力するか、「OK」が入力された時に 文字列を出力するプログラムを作ろうと思い、 その中で、1回目に『OK』が入力された時には、エラーメッセージを表示して終了するようにしたいのですが、 以下を入力したところ、うまく動作しませんでした。(見づらいのはご容赦ください) 制御文と配列を使って動作させるには、どう修正するべきでしょうか。 初心者ですが、ご教授お願い致します。 #include <stdio.h> #define MAX_INP 10 /* 入力最大回数 */ #define MAX_LGTH 5 /* 入力可能最大文字数 */ int main(void) { char str[MAX_INP][MAX_LGTH]; int cnt; /* 入力用カウンタ */ printf("\n"); for(cnt = 0 ; cnt < MAX_INP ; cnt++) /* 入力ループ */ { printf("Input String. -> "); /* 文字列入力メッセージ */ scanf("%s",&str[cnt][0]); /* 文字列入力 */ if(str[cnt][0]=='O' && str[cnt][1]=='K' && str[cnt][2]=='\0') { /* OKと入力された場合 */ break; /* ループから抜ける */ } if(cnt == 0) /*「OK」入力が1回目の場合 */ { printf("Error."); /* エラーメッセージ */ return 0; } } printf("\n"); for(cnt = 0 ; cnt < MAX_INPUT ; cnt++) /* 出力ループ */ { printf("%s\n",&str[cnt][0]); /* 文字列出力 */ } printf("\n"); return 0; } 【動作結果1】 Input string. -> abc Error. > 【動作結果2】 Input string. -> OK OK Uウ@ @ ■p 『 『 >

みんなの回答

回答No.7

if(str[cnt][0]=='O' && str[cnt][1]=='K' && str[cnt][2]=='\0') { /* OKと入力された場合 */  break; /* ループから抜ける */ } if(cnt == 0) /*「OK」入力が1回目の場合 */ {  printf("Error."); /* エラーメッセージ */  return 0; } の部分を if(str[cnt][0]=='O' && str[cnt][1]=='K' && str[cnt][2]=='\0') { /* OKと入力された場合 */  if(cnt == 0)  /*「OK」入力が1回目の場合 */  {   printf("Error."); /* エラーメッセージ */   return 0;  }  break; /* ループから抜ける */ } に修正すればいいですよ。

  • mac_res
  • ベストアンサー率36% (568/1571)
回答No.6

まず、"OK"で入力を終了する仕様は、OKという文字列を入力できない欠点があります。Cntl-Dで終端したほうが良いでしょう。 入力においては、10文字までと規定しても、10文字以上の文字が入力される危険性を考える必要があります。 また、使用には空白文字を含む文字列が入力された場合が考慮されていません。 コメントは時としてデバッグの妨げになります。コーディング内容と、コメントが一致していないとき、人はコメントに基づいて考察してしまうからです。コメントは必要十分、過剰にならないように入れましょう。コメントを入れるよりコード自身の可読性を向上させるべきです。 -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- #include <stdio.h> #include <string.h> #define MAX_INP 10 /* 入力最大回数 */ #define MAX_LGTH 10 /* 入力可能最大文字数 */ int main(void) { char *str[MAX_INP]; int i, cnt, len; char buf[BUFSIZ]; for (cnt = 0; cnt < MAX_INP; cnt++) { printf("Input String. -> "); if(fgets(buf, BUFSIZ, stdin) == NULL) { break; } len = strlen(buf); if (len < MAX_LGTH + 1) { buf[strlen(buf) - 1] = 0; } else { buf[MAX_LGTH] = 0; } str[cnt] = strdup(buf); } if (cnt == 0) { printf("Error.\n"); return 0; } printf("\n"); for (i = 0; i < cnt; i++) { printf("%s\n", str[i]); } return 0; }

回答No.5

細かいところが気になったので…… #define MAX_LGTH 5 /* 入力可能最大文字数 */ 10文字受け付けるなら #define MAX_LGTH 10 よね? char str[MAX_INP][MAX_LGTH]; 文字列には最後に'\0'が入るので char str[MAX_INP][MAX_LGTH +1]; あとは#04の方が仰るように string.h を使えばよいと思います

  • Sombart
  • ベストアンサー率16% (45/267)
回答No.4

 まず、キャラクタと文字列の扱いは違えた方が分かりやすいコードがかけます。言い換えれば、文字列なら文字列らしく扱った方が良いです。  というわけで、string.h を使うことをお勧めします。  また、考えた通りの道筋をコメントに書く方が、可読性は上がります。  なお、実行環境が今手元に無いので以下のコードの検証はできていません。ご確認ください。 #include <stdio.h> #include <string.h> #define MAX_INP 10 /* 入力最大回数 */ #define MAX_LGTH 5 /* 入力可能最大文字数 */ int main(void) { char str[MAX_INP][MAX_LGTH]; int cnt; /* 入力用カウンタ */ int cmp; /* 比較結果格納用 */ printf("\n"); /* 入力ループ */ for(cnt = 0 ; cnt < MAX_INP ; cnt++) { /* 文字列入力メッセージ */ printf("Input String. -> "); /* 文字列入力 */ scanf("%s",str[cnt]); cmp = strcmp(str[cnt],"OK"); /* OKと入力された場合で、かつ初回の場合 */ if(cmp == 0 && cnt == 0){ printf("Error.\n"); /* エラーメッセージ */ return 0; } /* OKと入力された場合で、初回ではない場合 */ if(cmp == 0){ break; /* ループから抜ける */ } } printf("\n"); for(cnt = 0 ; cnt < MAX_INPUT ; cnt++){ /* 出力ループ */ printf("%s\n",str[cnt]); /* 文字列出力 */ } printf("\n"); return 0; }

  • mac_res
  • ベストアンサー率36% (568/1571)
回答No.3

#include <stdio.h> #include <string.h> #define MAX_INP 10 /* 入力最大回数 */ #define MAX_LGTH 5 /* 入力可能最大文字数 */ int main(void) { char *str[MAX_INP]; int i, cnt; char buf[BUFSIZ]; printf("\n"); for (cnt = 0; cnt < MAX_INP; cnt++) /* * 入力ループ */ { printf("Input String. -> "); fgets(buf, MAX_LGTH + 1, stdin); buf[strlen(buf) - 1] = 0; if (strcmp(buf, "OK") == 0) { break; } str[cnt] = strdup(buf); } if (cnt == 0) { printf("Error.\n"); return 0; } printf("\n") for (i = 0; i < cnt; i++) { printf("%s\n", str[i]); } printf("\n"); return 0; }

  • yasuya
  • ベストアンサー率16% (35/216)
回答No.2

実行環境が無いので検証取れず確実では ありませんが・・・ 1.動作結果1のように1回目でErrorが出るのは んな感じでどうでしょう? if(str[cnt][0]=='O' && str[cnt][1]=='K' && str[cnt][2]=='\0') { /* OKと入力された場合 */  if(cnt == 0) {   /*「OK」入力が1回目の場合 */   printf("Error."); /* エラーメッセージ */  }  break; /* ループから抜ける */ } 2.動作結果2で文字化けが表示されるのは str[cnt][0] = 'O' str[cnt][1] = 'K' str[cnt][2] = '' <-- ここに\nが入っていない可能性があります。 scanfで入力文字を取得した後、\nを付け足せばよいかとおもいます。

crusader
質問者

お礼

御回答ありがとうございます。 文字化けの問題について、ご指摘された部分を確認してみましたが、 str[cnt][2] = " の後は「\0」だったと思います。

  • rentahero
  • ベストアンサー率53% (182/342)
回答No.1

if(str[cnt][0]=='O' && str[cnt][1]=='K' && str[cnt][2]=='\0') { /* OKと入力された場合 */ break; /* ループから抜ける */ } if(cnt == 0) /*「OK」入力が1回目の場合 */ { printf("Error."); /* エラーメッセージ */ return 0; } この部分がおかしい。 if(str[cnt][0]=='O' && str[cnt][1]=='K' && str[cnt][2]=='\0') { /* OKと入力された場合 */ if(cnt == 0) /*「OK」入力が1回目の場合 */ { printf("Error."); /* エラーメッセージ */ return 0; } else { break; /* ループから抜ける */ } } こうするべきだと思う。

crusader
質問者

お礼

御回答ありがとうございました。 早速この記述で試してみたところ、ご指摘の部分を正常に動かすことができました。