- ベストアンサー
C言語の初歩的な問題です。
現在C言語の入力の部分を勉強しているのですが 数字の入力をもらってから、それが数字じゃない場合 もう一度入力を受けるようなものを作りたいのですが、 うまく数字なのか文字なのかが判定できなくてこまっています。 どうすればいいのでしょうか? int n; int flag = 0; do{ printf("value:"); scanf("%d",&n); if(入力された値が数字であった場合) { flag = 1; } }while(flag == 0);
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
★最初に『数字文字判定』は『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』
その他の回答 (5)
- DT200
- ベストアンサー率38% (63/164)
#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)
エラー入力時の処理を考えると、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になることを 利用しています。
- yaemon_2006
- ベストアンサー率22% (50/220)
#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)
入力されるデータによります。 この質問だけでは条件が足りないと思うので入力形式を確認してください。 質問では入力データを「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% (4900/10358)
参考書が悪いようです。 ・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);