• ベストアンサー

C言語の初歩的な問題です。

現在C言語の入力の部分を勉強しているのですが 数字の入力をもらってから、それが数字じゃない場合 もう一度入力を受けるようなものを作りたいのですが、 うまく数字なのか文字なのかが判定できなくてこまっています。 どうすればいいのでしょうか? int n; int flag = 0; do{ printf("value:"); scanf("%d",&n); if(入力された値が数字であった場合) { flag = 1; } }while(flag == 0);

質問者が選んだベストアンサー

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.4

★最初に『数字文字判定』は『isdigit』があります。 ・この関数<ctype.h>を利用すれば数字文字の判定が可能です。  あと『scanf』を使うのならば『%s』で文字列で受け取って、その文字列に数字文字が  含まれない場合は再入力を促す仕組みにすればいいでしょう。 ・他にも『getche()』という1文字入力されると直ぐに文字を返す関数もあります。  関連関数として『getch()』、『getc()』、『getchar()』などありますが、後ろの2つは  バッファリング機能により、リターンキーが押されないと制御を戻します。  『getche()』、『getch()』関数は1文字入力されると直ぐに読み取った文字を返します。  下にサンプルを3つ載せます。どれでもどうぞ。 サンプル1: char buff[ 256 ]; int flag = 1; int i; while ( flag ){  printf( "value:" );  scanf( " %s", &buff ); ←文字列を取得    for ( i = 0 ; buff[i] != '\0' ; i++ ){   if ( buff[i] == '\n' ){    flag = 0;    break;   }   if ( !isdigit(buff[i]) ){    flag = 0;    break;   }  } } サンプル2: 上記のサンプル1の『scanf』の部分を『fgets(buff,sizeof(buff),stdin);』の1行に置き換える。 あとは同じです。 サンプル3: #include <conio.h> ←忘れずに! char buff[ 256 ]; int i, ch; do {  printf( "\nvalue:" );    for ( i = 0 ; isdigit(ch = getche()) ; i++ ){   buff[ i ] = (char)ch;  }  buff[ i ] = '\0'; } while ( (ch != '\r') && (ch != '\n') ); 最後に: ・サンプル3は1文字押されるごとに『buff』に文字を格納していきます。  そして、リターンキーや数字キー以外が押されると『for』文を抜けます。  さらに、『do-while』文の判定で抜け出た文字コードが『\r』か『\n』以外ならば  つまり英字や記号ならば『do-while』文を繰り返します。→これにより再入力となります。 ・以上。おわり。→<ctype.h>や<conio.h>をインクルードして下さい。 関連質問: ・http://oshiete1.goo.ne.jp/kotaeru.php3?q=2006690→『<conio.h>getche() → <curse.h>getc() = segmentation fault』

参考URL:
http://www9.plala.or.jp/sgwr-t/c/sec05.html,http://www5c.biglobe.ne.jp/~ecb/c/02_04.html

その他の回答 (5)

  • DT200
  • ベストアンサー率38% (63/164)
回答No.6

#include <stdio.h> #include <stdlib.h> #include <string.h> main() { char inbuf[ 32 ]; int n; char *p; int flag = 0; do{ printf( "Value: " ); if( fgets( inbuf, sizeof( inbuf ), stdin ) != NULL ){ /* * '\n'が付加さるので'\0'に置き換える */ p = strchr( inbuf, '\n' ); if( p != NULL ){ *p = '\0'; } /* * 10進表記のみ受付けると仮定して、'0'~'9'以外の文字なら * *pは不正な文字を指す。全てOKなら*pは'\0'を指す。 * もし、16進表記にしたいのなら、第3パラメータを16にする。 */ n = strtol( inbuf, ( char**)&p, 10 ); if( *p == '\0' ){ flag = 1; } } } while( flag == 0 ); printf( "n = %d\n", n ); }

  • tea_sheep
  • ベストアンサー率53% (8/15)
回答No.5

エラー入力時の処理を考えると、scanfではなく「fgets(buff,sizeof(buff),stdin)」 で入力した後で sscanf で値取得&書式チェックをするのが良いかと思います。 int main(void) {  int num;  char buff[256], dummy[2];  while (1) {   printf("Input Value: ");   if (fgets(buff, sizeof(buff), stdin) == NULL)    return 0;      // 正常(整数1個のみ)入力時はループを抜ける   if (sscanf(buff, "%d%1s", &num, dummy) == 1)    break;   printf("Format error. ");  }  printf("Input Value = %d\n", num);  return 0; } sscanf の戻り値が「正常に取得されたデータ数」になることを利用しています。 最初が数値でない文字列「ABC12」などを渡した場合には戻り値がEOFになり、 正しい数値「10」などの場合には戻り値が1になり、数値の後に他の文字が続く 「10XY」などの場合は1文字目「X」がdummyに格納されて戻り値が2になることを 利用しています。

回答No.3

  #include <stdio.h> int main(void) { int num, flag = 1; do{ if(!flag) while(getchar() != '\n') ; printf("Value:"); flag = scanf("%d", &num); }while(!flag); printf("%d", num); return 0; }  

  • noring
  • ベストアンサー率0% (0/3)
回答No.2

入力されるデータによります。 この質問だけでは条件が足りないと思うので入力形式を確認してください。 質問では入力データを「int n」で受けようとしていますが、「int」は4バイトです。 この4バイトを  1.文字列(半角1文字)の場合、「"1"」なら「0x0100」('1'+null)  2.文字(半角1文字)の場合、「'1'」なら「0x01」頭の2バイトだけで済んでしまう。  3.数字データの場合、数字の「1」なら「0x0001」) です。 コンピュータの世界では、文字や文字列は全て数字に置き換えることが可能なので、 例えば4バイトで受けた場合の文字列の「"1"」(0x0100)と数値の「256」(16進で0x0100)は同じ値になってしまいます。 従って質問の条件だけでは判定できません。 しかし、入力されるバイト数や形式が限定されていれば判断要素が増えるので判断は可能になるかもしれません。 ご理解いただけたでしょうか?

  • notnot
  • ベストアンサー率47% (4848/10262)
回答No.1

参考書が悪いようです。 ・printfのあとfflushが無い ・scanfで入力している 他の参考書を探しましょう。 int n; int flag=0; char buf[100]; do { fprintf(stderr,"value:"); if(!fgets(buf,100,stdin)) { fprintf(stderr,"EOFが入力された\n"); exit(1); } if(sscanf(buf,"%d",&n)==1) flag=1; } while(flag==0);

関連するQ&A

  • C言語!教えてください!

    /* キーボードから4桁の数字を読み込み、3で割った余りが0ならばそのまま  表示する。1ならば数字と並びを逆に表示する。  2ならばその数字と逆に並べた数字の差の絶対値を表示。その際に差が0  であるなら入力した数字をそのまま表示するプログラム。 */ #include <stdio.h> int main(void) { int no; printf("4桁の数字を入力してください:"); scanf("%d",&no); if(no % 3 ==0) printf("%d \n" , no); else if(no % 3 ==1) do{ printf("%d",no%10); no = no / 10; }while (no > 0 ); else ここから絶対値を考えようとしたのですが 逆にした値が文字で置かれていないのでやりようがありません。 逆にした値は文字で置けるものなんですか? それともこの文ではできませんか? よろしくお願いします。

  • C言語 繰り返しの問題

    C言語の初心者です。 キーボードから値を入力して、1から入力された値までの奇数の和を求めて出力するプログラムを作成します。以下のように組んでみましたが、全然うまくいきません。誰か教えていただけませんか? #include<stdio.h> int main(void) { int i,n,sum; sum=0; printf("入力値:",n); scanf("%d",&n); if(n<=0) { printf("\n合計値:0\n"); } else { printf("入力値:\n",n); for(i= 1; i<= n; i=i+2) { if(n%2=1) { sum=sum+i; } } } printf("\n合計値\n",sum); }

  • C言語について。

    今、C言語に関する問題をやっているんですが、いまいちわかりません。 その問題というのは↓ ≪問題5 (繰り返し) 例題をもとに、次のような九九の表を出力するプログラムを作成しなさい。  1 2 3 4  5  6  7  8  9  2 4 6 8 10 12 14 16 18  ~(略)                                               ≫ という問題です。それで、その例題というのは↓ ≪例題4 (for文、do while文)  次のプログラムは、入力された整数を一辺とする正方形を出力するプログラムである。動作確認をしなさい。  4       (←入力)  ****  (←出力)  ****  ****  **** /* 正方形 */ #include <stdio.h> void main() {     int hen, i, j;     do{        printf("数字(2~9)を入力してください : ");        scanf("%d", &hen);        if( hen < 2 || hen > 9 )           printf("入力エラーです!\n");     }while( hen < 2 || hen > 9);     for( i = 1 ; i <= hen ; i++)     {         for( j = 1 ; j <= hen ; j++)           printf("*");         putchar('\n');    } }  ≫ ≪例題5 (for文、do while文) 次のプログラムは、入力された整数を一辺とする二等辺三角形を出力するプログラムである。動作確認しなさい。  4      (←入力)  *     (←出力)  **  ***  **** /* 二等辺三角形 */ #include <stdio.h> void main() {     int hen, i, j;     do{        printf("数字(2~9)を入力してください : ");        scanf("%d", &hen);        if( hen < 2 || hen > 9 )           printf("入力エラーです!\n");     }while( hen < 2 || hen > 9 );     for( i = 1 ; i <= hen ; i++ )     {            for( j = 1 ; j <= i ; j++ )              printf("*");          putchar('\n');     } }  ≫ 以上の二つが例題です。 わかりづらかったらすみませんm(_ _)m わかる方(問題5を)教えてくださるとありがたいです。

  • C言語について

    問題文が表示され、その解答を数字で入力すると正解の場合は「大正解」、不正解の場合は「はずれ」と表示されるプログラムなのですが、?部分がどうしても分りません・・・ 正しいと思えば0、間違ってると思うなら1と入力するプログラムです。 どなたかご教授いただけるとありがたいです>< main() { int i,k; i=0; while(i<5){ printf("次の文章が正しければ0、間違っていれば1を入力してください。\n"); printf("%s",q[i]); scanf("%d",&k); if(a[?]==?) {printf("大正解\n");} else {printf("はずれ\n");} i????; } printf("おしまい\n"); }

  • C言語について

    次のような問題です。 問 自然数nを入力し、nを3で割って割り切れるかどうかを判定し結果を表示する。「割り切れる」、「1余る」、「「2余る」のいずれかが入るものとする。 このようなものをつくりました。 #include<stdio.h> int main(void) { int n; printf("自然数:"); scanf("%d",&n); if(n==0){ printf("割り切れる\n"); }else if(n==1){ printf("1余る\n"); }else{ printf("2余る"); } return(0); } これで合っているかよろしくお願いします。

  • C言語の問題でわからないところがあります

    先ほども似たような内容で質問させて頂いたのですが、もう一度質問させてください。 最近C言語を勉強し始めたのですが、わからないところがあります。 二つの整数値を読み込んで、小さい方の数以上で大きい方の数以下の整数を全て加えた値を表示するプログラムを作成するものなのですが、うまくいかなく困っています。 他の書き方でやれば普通にいけると思うのですが、これだとできない理由がわからないと、もやもやしてしまうので・・・・ プログラムは以下の通りです #include <stdio.h> int main(void) { int n1,n2,n3,n4; puts("二つの整数を入力してください"); printf("整数1:"); scanf("%d",&n1); printf("整数2:"); scanf("%d",&n2); n3=(n1>n2) ? n2 : n1; n4=(n1>n2) ? n1 : n2; printf("%d以上%d以下の全整数の和は", n3,n4); int num=n3; /* numの最初の値は小さい方の値 */ int wa=0; /* n3が小さい方の数、n4は大きい方の数 */ do{ if (n1>n2) { wa=n4+num; /* 大きいほうの数(num)にsub(小さい方の数+0,2,3,4・・・)を足していく */ num=num+1;/* ここを通るたびにsubに+1 */ printf("%d",wa);} else { wa=n4+num; num=num+1; printf("%d",wa);} }while(num<n4); /* num<n4を満たさない=numが大きいほうの数よりも大きくなったらループを終了 */ printf ("です\n"); /* ですっす */ return 0; } これで大きい方に37、小さいほうに28と入力すると656667686970717273ととても大きな数値になってしまいます。 ループが間違っているのでしょうか? whileは whileの後の()の中身の条件を満たしているとにループする、と認識しているので、numが大きい方の数値より大きくなったとき、ループを終了するようにしているつもりです。 ここがどこか間違っているのでしょうか・・・? それから、初期化というのもいまいち理解していないのですが、intで宣言するときに、中に数値を格納しておく、という物だと思っています。 宣言の後にprintf("%d",num);などで確認すると、代入できているようなので、これは間違っていないと思うのですが・・・・、 間違っているところがざっとみて解りましたら、回答頂けるとありがたいです。 C言語を始めたばかりなので、できれば簡単に説明して頂けるとありがたいです。

  • C++言語について。構文エラー

    ジャンケンゲームを作ってたんですが サイトを参考にしながらやってたんですが、どこかでミスったみたいで。 コピーしてやるのはイヤなので、自分で打ちたいんです。   どうか間違いを指摘してもらえないでしょうか?            #include <stdio.h> #include <stdlib.h> int main() { int n; int p;//player int c;//computer srand(0);//乱数の初期化 do { //プレイヤーの手 printf("あなたの手を入力してください\n(グー:1、チョキ:2、パー:3\n"); scanf("%d", &p); //コンピュータの手 c = rand() % 3 + 1; //勝ち負け判定 if(p == c){ printf("draw\n"); }else if(p == 1 && c == 2){ printf("WIN!!\n"); }else if(p == 2 && c == 3){ printf("WIN!!\n"); }else if(p == 3 && c == 2){ printf("WIN!!\n"); }else{ printf("lose...\n"); } //続けるかどうかの判定 printf("try agin?\nNO(0を入力)---"); scanf("%d", &n); //nが0以外だったら続ける }while(n != 0); return 0; }        で、エラーが構文エラー : ';' が 'return' の前にありません。 というものでした。   よろしくおねがいします。

  • C言語の簡単なプログラム

    簡単な足し算のみの電卓をC言語で作っています。 /が入力されるまで足し算を繰り返すものです。 コンパイルをして、足し算を繰り返すところまでは上手くいったのですが、 /を入力してのループの抜け方がわかりません。 #include<stdio.h> int main(void) { int x=0,z; printf("数値を入力\n"); printf("終了は/を入力\n"); printf("\n結果 %d\n",x); while(1){ scanf("%d",&z); x=x+z; /* 足し算の計算 */ printf("結果 %d\n",x); /* 現在の計算結果を表示 */ } printf("終了 結果: %d\n",x); /* 計算の終了、合計値の表示 */ return 0; } while文のなかにifでいれればいいのでしょうか? その場合、 if(z=='/') break; でいいんでしょうか? if文以外のやり方がある場合も教えていただけたらと思います。 よろしくお願いします。

  • C言語の問題

    自分の生まれた日から、今日までの生存日数を求めよ。(但し、うるう年なども計算するプログラム)という問題を提示されたのですが、ぜんぜんわかりません。どなたか上記プログラムがわかる方、ご教授お願いいたします。 #include<stdio.h> int main(void) { int table1[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; int table2[13]={0,31,29,31,30,31,30,31,31,30,31,30,31}; int mm,dd,i,day=0; /*(1)指定月日までの日数計算*/ do { printf("月>"); scanf("%d",&mm); if(mm>=1 && mm<=12)break; printf("月(%d)は誤りです。\n",mm); }while(1); do { printf("日>"); scanf("%d",&dd); if(dd>=1 && dd<=table1[mm])break; printf("日(%d)は誤りです。\n",dd); }while(1); for(i=1;i<mm;i++) day += table1[i]; day += dd; printf("1/1から%d/%d迄の日数は%d日です。\n",mm,dd,day); return 0; } ↑参考までにこんなプログラムでやっています。

  • 続・C言語について

    http://okwave.jp/qa5241461.html 先ほど、このような質問をして、いただいた回答を参考に下記のようなプログラムを作ってみたのですが、実行結果は、数値の入力と最後の"\n"しか反映していません…。 このプログラムのどの部分がマズイのか、お教えいただけたら幸いです。 よろしくお願いいたします。 #include <stdio.h> void draw_even(int, int); void draw_odd(int, int); int main(void) { int kazu; int gyou=1; printf("数字2~9を入力してください:"); scanf("%d", &kazu); while(kazu < 2 || kazu >9) { printf("※入力エラー!! 2~9を入力してください:"); scanf("%d", &kazu); } while(gyou <= kazu) { if(kazu = 2*(kazu/2)) { gyou = kazu+1; draw_even(kazu, gyou); } else { gyou = kazu; draw_odd(kazu, gyou); } gyou++; } } void draw_even(int kazu, int gyou) { int keta = 1; if(kazu!=(gyou+1)/2) { while(keta==kazu && keta==(gyou+1)/2 && keta==gyou-(kazu-1)) { printf("*"); } } else { for(keta=1; keta<=gyou; keta++) { if(keta!=(gyou+1)/2) { printf("*"); } else { printf(" "); } } } printf("\n"); } void draw_odd(int kazu, int gyou) { int keta = 1; if(kazu!=(gyou+1)/2) { while(keta==kazu && keta==(gyou+1)/2 && keta==gyou-(kazu-1)) { printf("*"); } } else { for(keta=1; keta<=gyou; keta++) { printf("*"); } } printf("\n"); }

専門家に質問してみよう