みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

atoiでの文字列以外のエラー処理(初心者)

超初心者の質問です
1~3の数値のみ入力してほしい場合

_getts(Word);
number = atoi(Word);
if( 1<= nunber && 11 >= nunber ){ brerk };

とするとnunberの中に1~11が入るはずですが
これを実行すると文字列を入力したときにヘンテコなエラーが出ます
ちなみに%dでとればいいのでしょうがscanfは変なエラーでるときが多いので
嫌いなので使いたくありません
悩んだ挙句こうしてみましたが

_getts(Word);
if( "1"<= nunber && "11" >= nunber ){
number = atoi(Word);
brerk;
};

これでもエラーが出ます

1文字1文字for文で回して数字かどうか判定してあげるしかないのでしょうか?
すっきりした書き方があればよろしくお願いします

投稿日時 - 2007-05-20 19:52:47

QNo.3016326

困ってます

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

★strtol() 関数を使ってみる。
・この関数ならば文字列を整数に変換する以外に数字文字列以外はエラーもチェックできます。
 下にサンプルを載せます。

サンプル:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

char buff[ 64 ];
char *check;
long number; ←ナンバーはnu[m]berです。

while ( fgets(buff,sizeof(buff),stdin) != NULL ){
 number = strtol( buff, &check, 10 );
 
 if ( errno == ERANGE ){
  puts( "number が長整数の範囲を超えました。" );
 }
 else if ( *check != '\0' ){
  puts( "数字文字列ではありません。" );
 }
 else if ( (number >= 1) && (number <= 3) ){
  printf( "入力した数は %d です。\n", number );
 }
}

解説:
・fgets() 関数で文字列を入力します。
 その後、strtol() 関数で文字列を整数に変換しています。→atoi() の代わり
 そして、グローバル変数の errno の値を調べます。この errno に ERANGE 定数が
 セットされていると long 値を越える大きい(小さい)数字文字列ですのでエラーと
 します。ERANGE 定数がセットされていない場合は check の位置が NULL 文字ならば
 すべて数字文字列であったと判定します。少しでも英字や記号が含まれていると NULL
 文字以外になるため、ここで数字文字列以外のエラーを表示します。
・上記のを踏まえてプログラミングの参考にして下さい。
・以上。おわり。→下の『参考URL』もどうぞ。

参考URL:http://www9.plala.or.jp/sgwr-t/lib/strtol.html

投稿日時 - 2007-05-20 21:30:08

お礼

まだまだ勉強不足でした
*check != '\0' これは文字列の後につく終端コードですよね
数字には入らないと考えてよろしいのでしょうか

やはり文字を1文字づつ回してあげるのがベストなようですね

勉強になるURLまでありがとうございました
----------------------------------------------------------------------
文字列 s を、baseで指定された基数でlong型に変換し返却します。このとき、文字列中に変換不可能な文字があった場合には、その文字列のポインタをendptrに格納します。
atol関数は、単に文字列を10進のlong型変数に変換するのみで、文字列中に変換不可能な文字があったときには対応できませんが、strtolを使うと、変換可能な部分についてはきちんと変換し、変換不可能な部分についても情報を得ることができます。更に、baseを指定することにより、好きな基数で変換することができます。

投稿日時 - 2007-05-20 22:24:08

このQ&Aは役に立ちましたか?

1人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.1

目的はこういうことでしょうか?

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
int n;
char buffer[32];

gets_s(buffer, sizeof(buffer));

n = atoi(buffer);
if(n >= 1 && n <= 3)
{
puts("1 - 3 です。");
}
else
{
puts("1 - 3 ではありません。");
}
}


> とするとnunberの中に1~11が入るはずですが
申し訳ありませんが意味がわかりません。プログラムだけみると1~11が入るとは思えませんのでそう思われる根拠はなんでしょうか。

> ちなみに%dでとればいいのでしょうがscanfは変なエラーでるときが多いので
適切に使用し、適切な処理を行えば変なエラーはでません。

> if( "1"<= nunber && "11" >= nunber ){
"1"は、コンスタントプール"1"のアドレスとnunberの値(初期化されていない値)を比較しています。
"11"にしても同様です。

"1"は文字列(キャラクタ配列)。'1'はキャラクタ。1は数値。
違いを理解されておりますでしょうか。

文字列はstrcmpとかで比較しましょう。

投稿日時 - 2007-05-20 20:24:48

お礼

>適切に使用し、適切な処理を行えば変なエラーはでません。
そうなのですか・・・
_tscanf_s(_T(""))でマルチコードにも対応するようにしたのですが
まだまだ勉強不足なので使えないものとばかり思ってました

"1"< <"11" はアスキーコードに変換して考えるといけるかなと思ったのですが
そもそもstrcpyって便利ですね覚えておきます
マルチコードだと_tcscpyですね

投稿日時 - 2007-05-20 22:13:46

あなたにオススメの質問