• 締切済み

プログラム(ループの挙動

void kamoku_touroku(void) { int t; printf("**** 科目登録 ****\n\n" ~~~~~~~~~~~~~~~~~~~~      \n"); for(t=0;t<1000;t++) { printf("科目名:"); gets(kamoku_list[t].name); if(kamoku_list[t].name[0] == '\0') //エンターキーのみが押された { printf("a");//ループ確認のために入れた出力 } else { printf("\n%sの情報を入力してください\n",kamoku_list[t].name); printf("[1]必修\n" "[2]選択必修\n" "[3]選択\n" "[4]自由\n" "単位の種類:"); scanf("%d",&kamoku_list[t].tanni_type); ~~~~~~~~~~~~~~~~~~~~~~~~ } } } 以上のプログラムを実行すると「科目名:a科目名:」と出てしまい 「gets」が無視されているように思うのですが原因がわかりません。 後、エンターキーのみの入力を受付けるようにするには何かいい方法はないでしょうか? 波線は関係ないところを省略してあります。

みんなの回答

  • P-mann
  • ベストアンサー率62% (56/89)
回答No.2

いえ。 fgetsでstdinから読み込めばgetsと同じように標準入力から取得できます。 /* 格納先変数 */ char hoge[256]; /* stdinは標準入力を表す */ fgets(hoge, sizeof(hoge), stdin); この辺りに書かれています。 http://homepage3.nifty.com/mmgames/c_guide/22-01.html ただし、入力した文字数がfgetsの第2引数よりも長い場合、 最初の問題と同じように読み残しが生じます。 ですので、読み捨てる処理というのが必要になってきます。 具体的には、読み出した文字列の中に改行文字が入っていない場合に 改行文字が現れるまで何度も読み捨てるという処理になります。

ism1369
質問者

お礼

色々と調べましたところこの問題は解決できました 有益なアドバイスありがとうございました

全文を見る
すると、全ての回答が全文表示されます。
  • P-mann
  • ベストアンサー率62% (56/89)
回答No.1

原因は、scanfで改行文字を読み込まないせいです。 一回目の実行後、scanfにて数値を読み出していますが、その際に入力した改行文字を読み込んでいません。ですので、次のgetsでは必ず改行文字を読み込んでしまいます。 以下のページ内で「改行文字が残る」と検索すれば詳細が分かるかと思います。 http://www9.plala.or.jp/sgwr-t/c/sec05.html 回避方法も上記ページに書いてありますが、個人的にはscanfを使用しない実装に変更すべきであると考えます。 fgetsで取得し、それを数値に変換する方がいいと思われます。 また、getsは最大文字数を指定できないのでメモリ破壊の危険があります。fgetsの使用をお勧めします。

ism1369
質問者

お礼

返答ありがとうございます。 fgetsで取得するということは関数内でテキストファイルを 定義しないといけないと思うのですがその辺がいまいち よくわかりません。 ほかの関数内で定義しているテキストファイルを使用することは 可能なんでしょうか?

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • MacでC言語を勉強しています

    最近C言語に興味を持って 趣味程度に、ハーバート・シルトさん著の「独習C」を、 Xcodeを使ってCが使える感じにして、 プログラミングを打って、ビルドして、コンソールで結果を見て、ふむふむ、ってやっていたのですが、 第8章の総合理解度チェックの問題で、 「簡単な図書カードカタログプログラムを作成してください。 ~省略~ ユーザーが「1.入力」を選んだ場合には、書名、著者名、出版社を繰り返し入力させます。書名として空白行が入力されるまで、これを続けます。~~省略~~」 ということになっていまして、この入力を選んだ場合がうまくいきません・・・。作り途中のプログラムですが・・・ /*8の総合理解度チェック2test1「メニュー関数の完成」*/ #include <stdio.h> #include <string.h> #define MAX 100 void inputf(void); void name_sarch(void); void title_sarch(void); char names[MAX][80], titles[MAX][80], pubs[MAX][80]; int main(void) { int i; do { printf("図書カードカタログ:\n"); printf(" 1.入力\n"); printf(" 2.著者名による検索\n"); printf(" 3.書名による検索\n"); printf(" 4.終了\n"); printf("いずれかを選択してください:"); scanf("%d", &i); switch (i) { case 1: inputf(); break; case 2: name_sarch(); break; case 3: title_sarch(); break; case 4: break; default: printf("メニューにありません\n"); break; } } while (i != 4); printf("正常に終了します"); return 0; } /*インプット部分*/ void inputf(void) { int i; for (i = 0; i < MAX; i++){ printf("書名を入力してください:"); gets(titles[i]); if (! *titles[i]) break; printf("著者名を入力してください:"); gets(names[i]); printf("出版社を入力してください:"); gets(pubs[i]); } if (i == MAX) printf("これ以上は入力出来ません\n"); } /*著者名による検索*/ void name_sarch(void) { int i; printf("臨時テスト関数です\n書名の配列番号を入力してください"); scanf("%d", &i); printf("%s", titles[i]); } /*書名検索*/ void title_sarch(void) { printf("書名検索関数\n"); } と作りまして、これをコンパイルしてコンソールで見ると、 『 [Session started at 2008-03-18 21:30:34 +0900.] 図書カードカタログ: 1.入力 2.著者名による検索 3.書名による検索 4.終了 いずれかを選択してください:1     (←僕はここで1を押して、enterキーを押しました) warning: this program uses gets(), which is unsafe. 書名を入力してください:図書カードカタログ: 1.入力 2.著者名による検索 3.書名による検索 4.終了 いずれかを選択してください: 』 と言うふうに勝手に、書名の部分をエンターでか、終わらせて、メニューに帰ってきてしまいます。 これは一体どういう事で、どうすれば解決できるんでしょうか、是非教えてください。

    • ベストアンサー
    • Mac
  • getsの部分がとばされてしまう

    #include<stdio.h> typedef struct Car{ char name[20]; int num; double gas; }Car; int main(void) { Car car[3]; int i; for(i=0;i<3;i++){ printf("ナンバーを入力してください。\n"); scanf("%d",&car[i].num); printf("車の名前を入力してください。\n"); gets(car[i].name); printf("ガソリン量を入力してください。\n"); scanf("%lf",&car[i].gas); } printf("name\tnumber\tfuel\n"); for(i=0;i<3;i++){ printf("%s\t%d\t%f\n",car[i].name,car[i].num,car[i].gas); } return 0; } …上記のようなプログラムを書いたのですが、実行すると、gets(car[i].name);の部分の処理が飛ばされてしまい、入力することができません。 どのようにしたらよいか、教えていただけませんでしょうか。 よろしくお願いいたします。

  • 助けてください! c言語のプログラムです。

    #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #define KAMOKU_SUU 5 #define AVE_INDEX KAMOKU_SUU typedef struct { char name[32]; int scor[KAMOKU_SUU]; int mean; } STUDENT; int round(double d) { if (d < 0) return (int)(d-0.5); else return (int)(d+0.5); } #define ARRAY_OF(a) (sizeof (a) / sizeof (a[0])) int main(int argc,char* argv[]) { int i, j,k, n; int nStudets; double avrg[KAMOKU_SUU + 1]; double stdv[KAMOKU_SUU + 1]; STUDENT *mem; char buff[80]; if (argc < 2) { printf("!パラメータ不足\n"); return 1; } nStudets = atoi(argv[1]); mem = (STUDENT*)malloc(sizeof (STUDENT) * nStudets); if (mem == NULL) { printf("!アロケーション\n"); return 2; } memset(avrg, 0, sizeof (avrg)); memset(stdv, 0, sizeof (stdv)); printf("生徒 %d 名分の成績を入力してください:\n", nStudets); for (k = 0; k < nStudets; k++) { printf("%d 人目の点数と名前 > ", k + 1); gets(buff); strcpy(mem[k].name, strtok(buff," ")); mem[k].mean = 0; for (j = 0; j < KAMOKU_SUU; j++) { int i = mem[k].scor[j] = atoi(strtok(NULL," \n")); mem[k].mean += i; avrg[j] += i; stdv[j] += i * i; } mem[k].mean = round(mem[k].mean * 1.0 / KAMOKU_SUU); } for(j = 0; j < KAMOKU_SUU; j++) { avrg[AVE_INDEX] += avrg[j]; stdv[AVE_INDEX] += stdv[j]; avrg[j] = avrg[j] / nStudets; stdv[j] = sqrt(stdv[j] / nStudets - avrg[j] * avrg[j]); } n = nStudets * KAMOKU_SUU; avrg[AVE_INDEX] = avrg[AVE_INDEX]/ n; stdv[AVE_INDEX] = sqrt(stdv[AVE_INDEX] / n) - (avrg[AVE_INDEX] * avrg[AVE_INDEX]); printf("\n成績表\n"); printf("# NAME"); for (i = 1; i <= KAMOKU_SUU; ++i) printf(" #%d ", i); printf("MEAN\n"); for (k = 0; k< nStudets; k++) { printf("%d %10s",k+1,mem[k].name); for (j = 0; j < KAMOKU_SUU; j++) { printf(" %3d",mem[k].scor[j]); } printf(" %3d\n",mem[AVE_INDEX].mean); } printf("------------------------------------\n"); printf(" %10s","average"); for(j = 0; j < ARRAY_OF (avrg);j++) { printf(" %3.0f",avrg[j]); } printf("\n"); printf(" %10s","st.dev."); for ( j = 0; j < ARRAY_OF (stdv); j++) { printf(" %3.0f",stdv[j]); } printf("\n"); printf("正常終了\n"); return 0; }  実行してもできません。原因が全く分かりません。 お願いします。 修正してくださるとありがたいです。

  • C++でfscanf関数・fprintf関数を利用した成績処理のプログ

    C++でfscanf関数・fprintf関数を利用した成績処理のプログラムを作成しています。 #include "stdafx.h" void input(void); void calc(void); void edit(void); int gakusei=10,kamoku=5; /*学生数、科目数*/ char kamokumei[5][40]; /*科目名*/ char shimei[10][40]; /*氏名*/ int tennsuu[10][5]; /*点数*/ float heikin[10]; /*平均点*/ void main() /*メイン関数*/ { input(); calc (); edit (); } void input(void) /*データ入力(infile.d.txtから読み込む)*/ { FILE *fp; int n,k; fp=fopen("infile.d.txt","r"); if(fp==NULL) { printf("infile.d.txtが開けません\n"); } printf("infile.d.txt\n\n"); fscanf(fp,"%d %d",&gakusei,&kamoku); printf("%d %d\n",gakusei,kamoku); fscanf(fp,"%s",kamokumei); printf("%s\n",kamokumei); fscanf(fp,"%s",shimei); printf("%s\n",shimei); while(fscanf(fp,"%s",tennsuu)!=EOF) { printf("%s\n",tennsuu); } printf("\n\n"); fclose(fp); } void calc(void) /*各学生の平均点を計算、平均点の優秀者(80点以上)及び不合格者(60点未満)を摘出*/ { int n,k; float sum; for(n=0; n<gakusei; n++) { sum=0; for(k=0; k<kamoku; k++) { sum+=(float)tennsuu[n][k]; } heikin[n]=sum/kamoku; } } void edit(void) /*平均点、優秀者及び不合格者の氏名を付加した成績表を出力(outfile.d.txtに書き込み)*/ { int n; FILE *seiseki; seiseki=fopen("outfile.d.txt","w"); printf("outfile.d.txt\n\n"); fprintf(seiseki,"氏名 %s 平均\n",kamokumei); printf("氏名 %s 平均\n",kamokumei); fprintf(seiseki,"%s\n",shimei); printf("%s\n",shimei); for(n=0; n<gakusei; n++) { fprintf(seiseki,"%s",tennsuu); printf("%s\n",tennsuu); } printf("\n"); fprintf(seiseki,"平均点優秀者\n"); printf("平均点優秀者\n"); fprintf(seiseki,"平均点不合格者"); printf("平均点不合格者\n"); fclose(seiseki); } 添付した画像のoutfile.d.txtのようなフォーマットで出力したいのですが、氏名がうまく出力できません。また、点数もinfile.d.txtの最後の行しか読み込んでくれません。 どのように書き換えればよいのでしょうか? よろしくお願いします。 *infile.d.txtについて 10 5 ⇒学生数と科目数 材料力学 熱力学 ・・・ ⇒科目名 石川 川上 佐藤 ・・・ ⇒学生の氏名 78 95 75 86 ・・・ ⇒各科目の点数(1行につき5科目×2人分の点数が書き込まれています。)

  • リストの削除について(構造体)

    リストの削除のプログラムを実行して行ってみると、リストの削除処理中にプログラムが終わって変更後処理がうまく表示されません。どこが間違っているかが分からないしだいです。返答のほどよろしくお願いいたします。 #include<stdio.h> #include<malloc.h> #include<string.h> struct list{ char name[20]; int age; struct list *next; }; void main(void) { struct list *head, *p, *n, *old; char key[20]; /*ダミーノード作成*/ head = (struct list*)malloc(sizeof(struct list)); old = head; while(p = (struct list*)malloc(sizeof(struct list)), printf("name age入力\n"), scanf("%s %d", p -> name, &p -> age) != EOF){ old -> next = p; old = p; } free(p); old -> next = NULL; p = head -> next; printf("変更前リスト\n"); while(p != NULL){ printf("name:%s age:%d\n",p -> name, p -> age); p = p -> next; } printf("削除key入力(name)\n"); gets(key); n = head; while(n != NULL){ old = n; n = n -> next; //printf("n -> name %s\n", n -> name); if(strcmp(n -> name, key) == 0){ printf("%s削除\n", key); //printf("n -> name %s old -> name %s\n", n -> name, old -> name); old -> next = n -> next; } } p = head -> next; printf("変更後リスト\n"); while(p != NULL){ printf("name:%s age:%d\n", p -> name, p -> age); p = p -> next; } }

  • ループ

    #include<stdio.h> int main(void) { int i=1,sum=0; int num=1; while(num>0) { printf("整数を入力してください。(マイナスの値で終了)\n"); scanf("%d",&num); printf("%dが入力されました。(%d番目の繰り返しです)\n",num,i); sum+=i; printf("1から%dまでをたすと%dです。\n",i,sum); i++; } printf("繰り返しが終わりました。\n"); printf("加算値は%dです。\n",sum); printf("%d回繰り返しました。\n",i); return 0; } このプログラムで101以上の数値は加算しないようにするにはどうすればいいですか。

  • Cプログラムがどうしても動きません

    Cを勉強中です。 年齢に-1が入力されるまで、名前、年齢、性別を聞くプログラムを作っているのですが、どうしてもうまく動きません。 具体的には、年齢を聞かれず、年齢?性別?_とまとめて表示されてしまいます。 ぜひともどこが間違っているか教えてください。お願いしますm(_ _)m #include<stdio.h> typedef struct{ char name[20]; int year; char sex[6]; }student; void read_data(int,student*); void write_data(int,student*); int main(void){ student data[10]; int i=0,j=0; do{ read_data(i,data); i++; }while(data[i-1].year!=-1); for(j=0;j<=i-1;j++){ write_data(j,data); } return 0; } void read_data(int i,student *data){ printf("%d人目\n",i); printf("名前?\n",i); scanf("%s\n",&(data[i].name)); printf("年齢?\n",i); scanf("%d\n",&(data[i].year)); printf("性別?\n",i); scanf("%s\n",&(data[i].sex)); return; } void write_data(int j,student *data){ printf("%d人目\t",j+1); printf("名前:%s",data[j].name); printf("年:%d",data[j].year); printf("性:%s",data[j].sex); return; }

  • プログラムの添削

    以下のようなプログラムを作りました.よりよい書き方,アドバイスなどお願いします. /*文字列の入力を繰り返し受け取るプログラムを作成しなさい.*/ #include<stdio.h> #include<string.h> int main(void) { char bigstr[101],str[31]; printf("文字列の入力を繰り返し受け取るプログラムです.\n"); strcpy(str,""); strcpy(bigstr,""); for(;;) { printf("文字列を入力してください.\n"); gets(str); if(strlen(str)>30) { printf("入力できる文字数の上限(20字)を超えました.\n"); return 0; } else if(strcmp(str,"quit")) { strcat(bigstr,str); if(strlen(bigstr)>100) { printf("入力できる文字数の上限(合計100字)を超えました.\n"); return 0; } } else break; } printf("%s\n",bigstr); return 0; }

  • プログラムについてです。

    クラスの身体計測簿をつくるプログラムを作成したいのですが、 以下のプログラムの修正点を指摘願います。 項目は、氏名 身長 体重です。 #include <stdio.h> #define MAX_氏名 50 /*maximum length of name */ #define MAX_身長 200 /*maximum length of height code */ #define MAX_体重 120 /*maximum length of weight */ struct person{ char 氏名[MAX_氏名+1]; char 身長[MAX_身長+1]; char 体重[MAX_体重+1]; }; main() { struct person Book; printf("氏名を入力してください.\n"); gets(Book.氏名); printf("身長を入力してください.\n"); gets(Book.身長); printf("体重を入力してください.\n"); gets(Book.体重); puts(Book.氏名); puts(Book.身長); puts(Book.体重); } こんなんでよろしいのでしょうか?? あと、身長順に並び変えたりするにはどのようなプログラムを用いたらよいのでしょうか??

  • ジャンケンプログラム作ったんですが動作しません。

    Borland C++とVisualC++の両方でEXEまで出来るのですが、起動させてグーチョキパーの手の選択をしてリターンキーを押すと、エラーウィンドが出てしまいます。 いろいろ考えて見たのですが理由が分かりません。 どうか、バグの原因を教えてください。 #include <stdio.h> #include <stdlib.h> #include <time.h> void show_title(void); void match(void); void comp_match(void); void judge(void); void p_memory(void); int playerhand=1; //プレイヤーの手 int computerhand=0;//コンピューターの手 int win=0;//勝利数 int lost=0;//負け数 int draw=0;//引き分け数 int main(void) { while(playerhand!=0) { show_title(); match(); comp_match(); judge(); p_memory(); } return 0; } void show_title(void) { printf("ジャンケンゲームver0.1\n"); printf("製作 ForceFeed 2009/4.13\n"); } void judge(void) { if(playerhand==computerhand){ printf("引き分けですね"); draw++;//引き分けのカウント }else if(playerhand==1 && computerhand==2){ printf("あなたの勝ちです\n"); win++;//勝ちのカウント }else if(playerhand==2 && computerhand==3){ printf("あなたの勝ちです\n"); win++;//勝ちのカウント }else if(playerhand==3 && computerhand==1){ printf("あなたの勝ちです\n"); win++;//勝ちのカウント }else{ printf("あなたの負けです\n"); lost++;//負けのカウント } } void match(void) { printf("1:グー 2:チョキ  3:パー 0:終了 半角数字で入力してください>"); scanf("%d",playerhand); switch(playerhand) { case 1: printf("あなたの手 :グー\n"); break; case 2: printf("あなたの手 :チョキ\n"); break; case 3: printf("あなたの手 :パー\n"); break; case 0: printf("終了します。\n"); exit(0); default: printf("0、1,2,3以外の入力がありました"); break; } } void comp_match(void)//コンピューターの手 { srand((unsigned)time(NULL));//乱数の種 computerhand=rand()%3+1; switch(computerhand) { case 1: printf("コンピューターの手 :グー\n"); break; case 2: printf("コンピューターの手 :チョキ\n"); break; case 3: printf("コンピューターの手 :パー\n"); break; default: printf("1,2,3以外の入力がありました\n"); break; } } void p_memory(void) //記録表示 { printf("勝ち数 %d\n",win); printf("勝ち数 %d\n",lost); printf("勝ち数 %d\n",draw); }