- ベストアンサー
入力する数字のサイズ制限について
よろしくお願いします。 C言語において、以下のようなコードで数字の入力を 行う場合、入力される数字がintのサイズを超えると問題があります。 int a; printf("数字を入力してください。"); scanf("%d",&a); 一般的に入力される数字のサイズが不明の場合、どのようなコードを書けばよいのでしょうか? ご存知の方お願いします。
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
>一般的に入力される数字のサイズが不明の場合、どのようなコードを書けばよいのでしょうか? int型変数に格納できない値が入力された場合にエラーとしたいのでしょうか? それでしたら、fgetsで入力データをバッファに格納してからチェックを行うことで可能となります。(もしくはチェックを行う関数を利用する。) longの場合でサンプルを作ってみました。 -------------------------------------------------- #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <limits.h> #define ERR_MSG(msg) {printf("%s\n", (#msg)); exit(1);} int main() { char buf[256]; long a; /*入力*/ printf("%s", "数字を入力してください:"); fgets(buf, sizeof(buf), stdin); buf[strlen(buf) - 1] = '\0'; /*改行削除*/ /*変換*/ if (strncmp(buf, "0", 2) != 0) { /*入力値 != 0*/ errno = 0; a = strtol(buf, NULL, 10); if (a == 0) { ERR_MSG(変換失敗) } if ((errno == ERANGE) && (a == LONG_MAX)) { ERR_MSG(レンジエラー : 入力値 > LONG_MAX) } else if ((errno == ERANGE) && (a == LONG_MIN)) { ERR_MSG(レンジエラー : 入力値 < LONG_MIN) } } else { /*入力値 == 0*/ a = 0; } /*出力*/ printf("入力値:%d\n", a); return 0; }
その他の回答 (6)
- gimmick
- ベストアンサー率49% (134/270)
#4です。 バッファサイズを256バイトとしたのは、long型変数で扱える桁数に対して十分なサイズだからです。つまり、256バイトのバッファに収まらない値はLONG_MAXを超えるので、残りの部分を切り捨ててしまおうということです。 #スペースを使われるとうまくいかないのはyoppiiさんのご指摘どおりです。あくまでサンプルなので...。 任意の桁数の入力を許可したい場合でしたら、ループの中でfgetsを使えば可能になります。ただし、入力値を利用する場合にそれ相応の工夫が必要になりますが...。 while(1) { char *p; p = fgets(buf, sizeof(buf), stdin); if (p == NULL) break; /*bufに対する処理*/ }
お礼
何度も回答ありがとうございました
#4 の補足に対してです。 > 結局この方法でも255桁以上には対応できない。 255 桁以上入力されても余分に入力された分がストリームに残るだけですから、 別にエラーで落ちたりはしません。 問題なしです。 スペースを 250 桁入れた後、数字を 10 桁入れたりすると、 誤動作する可能性は無くは無いですが。 それが心配なら、 if (strlen(buf) > 32) { puts("入力が長すぎる!"); return 0; } などとしておけばよいと思います。
お礼
大変良く分かり、非常に納得出来ました。 ありがとうございました。
- nubou
- ベストアンサー率22% (116/506)
#include <iostream> using namespace std; void main(void) { int a; while(true) { cout<<"数字を入力してください"; cin>>a; if(cin.good()==0) { cin.clear(); cin.seekg(0); cout<<"int型で収納できません"<<endl; break; } else cout<<"入力された数字は"<<a<<endl; } } なお int a; を __int a; に変えるとまだ__int a;を完全にはstreamが対応していないので動きません(無償borlandの場合) そのときには旧式のscanfを使うしか有りません
お礼
回答ありがとうございます。 何度も申しますが、貴殿の回答はC++だと思うのですが、私の希望はC言語です。 それとも、私が何か勘違いしてる???
- nubou
- ベストアンサー率22% (116/506)
失礼しました 質問をよく読まずに回答したので 数字の長さと思ってしまいました 数の大きさですね だと __int64 型の変数はどうでしょうか?
お礼
回答ありがとうございます
補足
最初の質問で書き忘れたのですが、 自分のプログラムに対して、ユーザーが大きすぎる値を入力しないように、 ”1億以下の数字を入力ください” といったコメントを出力してから、入力してもらえば問題ないと思いますが、そのようなコメントなしに自由に入力してもらい、プログラム上問題となる大きな数値を入力されたときに初めて、 ”数値が大きすぎます” といったコメントを出せるようなことは可能なのでしょうか? <補足> 自分でこれを書いていて、コメントは出せるが、プログラム上は明らかに問題ありという気がして来ました。
- nubou
- ベストアンサー率22% (116/506)
string型を使えば長さ制限はありません しかしOSの入力長制限が有るかもしれません (250前後、実験で確かめること) #include <string> #include <iostream> using namespace std; void main(void) { string str; int a; cout<<"数字を入力してください"; cin>>str; cout<<"入力された数字は文字列バージョンで"<<str<<endl; a=atoi(str.c_str()); cout<<"入力された数字は整数型バージョンで"<<a<<endl; } a=atoi(?) において?に数字を示す文字が無い場合にはaは0になります
- nubou
- ベストアンサー率22% (116/506)
string型を使えば長さ制限はありません しかしOSの長さ制限が有るかもしれません (250前後) #include <string> #include <iostream> using namespace std; void main(void) { string str; int a; cout<<"数字を入力してください"; cin>>str; cout<<"入力された数字は文字列バージョンで"<<str<<endl; cout<<"入力された数字は整数型バージョンで"<<atoi(str.c_str())<<endl; } atoi(?) において?に数字を示す文字が無い場合には0になります
お礼
回答ありがとうございます。 C++ではなくC言語を希望しています。
お礼
回答ありがとうございます。 >int型変数に格納できない値が入力された場合にエラーと>したいのでしょうか? そうです。
補足
回答いただいた内容が、私が期待していたものですが、 結局この方法でも255桁以上には対応できない。 また、256をどんなに大きくしても、それ以上の入力には対応できないので結局不可能なんだなと思っています。 但し、現実的には誰が255桁以上を入力するの?の世界なので問題ないのでしょうが・・・