数値入力の例外処理について。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
いちこ
記事: 62
登録日時: 7年前
連絡を取る:

数値入力の例外処理について。

#1

投稿記事 by いちこ » 6年前

こんばんは、いつもお世話になっております。
よろしくおねがいします。

キーボードから入力された0から5までの整数値を受け取り処理を行いたいです。
はじめは、scanf関数で受け取っていましたが、これでは誤って文字入力がなされたときに無限ループになってしまいました。
そこで、getsやgetcharなどの関数を使って例外処理を行おうと思ったのですが、なかなかうまくいきません。

とりあえず、0から9までの整数値と、一文字の文字が入力されるかもしれないと考えて、例外処理を作成したいです。

思いついたのは、gets関数で一文字読み込み、atoi関数で整数値に変換する方法でしたが、atoi関数に文字を入れると0が返るので、整数値の0と被ってしまいます。
他によい方法はないでしょうか。

どなたか詳しい方がおられましたら、ご教示お願いします。

いちこ
記事: 62
登録日時: 7年前
連絡を取る:

Re: 数値入力の例外処理について。

#2

投稿記事 by いちこ » 6年前

補足です。
最初の時点でのコードを下に記します。

コード:

//省略
int a;

while(1){
   printf("0から5までの数値を入力してください。\n");
   scanf("%d",&a);

   if(a<0 || a>5){
      printf("数値が正しくありません。もう一度入力してください。\n");
      coutinue;
   }
   break;
}
//省略
これに文字が入力された場合の例外処理を加えたいです。

かずま

Re: 数値入力の例外処理について。

#3

投稿記事 by かずま » 6年前

コード:

#include <stdio.h>

int main(void)
{
    int a;
    while (1) {
        printf("0から5までの数値を入力してください。\n");
        if (scanf("%d", &a) == 1 && a >= 0 && a <= 5) break;
        if (feof(stdin)) return 1;
        printf("数値が正しくありません。もう一度入力してください。\n");
        scanf("%*[^\n]");
    }
    printf("a = %d\n", a);
    return 0;
}

ただの屍のようだ

Re: 数値入力の例外処理について。

#4

投稿記事 by ただの屍のようだ » 6年前

[補足]:
8行:読み取り+正当性のチェック
9行:不正な入力チェック
11行:余計な入力を取り除く

[独り言]
(人はふたのある器である。傷口から中身をほんの一部、拝見できただけでも、槍で刺したのは無駄ではなかったようです)

いちこ
記事: 62
登録日時: 7年前
連絡を取る:

Re: 数値入力の例外処理について。

#5

投稿記事 by いちこ » 6年前

>>かずまさん
返信ありがとうございます!
書いていただいたコードを実行してみたら、うまく処理することができました。すごくうれしいです。
ありがとうございます。

>>ただの屍のようださん
返信ありがとうございます!
補足説明うれしいです(><)

お二人の返信を参考に、自分なりにコードについて調べてみましたが、よくわからないところがあるので
さらに質問させていただきます。
勉強不足で申し訳ありません。

feof(stdin)は、stdinがファイルの終わりがあると0以外、終わりがないと0を返すようですが、
文字入力されたとき、どうして0が返るのでしょうか。

また、11行目の意味は、改行を取り除いている、でいいでしょうか。

よろしくおねがいします。

かずま

Re: 数値入力の例外処理について。

#6

投稿記事 by かずま » 6年前

いちこ さんが書きました: feof(stdin)は、stdinがファイルの終わりがあると0以外、終わりがないと0を返すようですが、
文字入力されたとき、どうして0が返るのでしょうか。
文字入力されたとき、feof(stdin) は 0 を返しません。

コード:

int b;
    ...
    b = feof(stdin);
    printf("b = %d\n", b);
    if (b) return 1;
と書き換えてみたら分かります。

もっとたくさんの入力があるプログラムを書いて、デバッグするとき、
何度も同じキーボードから入力をするのは大変ですから、
ファイルに入力データを書いておいて、標準入力(stdin) をそのファイルに
切り替えることがあります。ファイルには終わりがあります。

scanf("%d", &a) は 3通りの値を返します。
1: 数字からなる文字列を読み込んで、数値に変換できた。
0: 数字以外の文字があったので、数値に変換できなかった。
EOF: 空白以外の文字がなく入力の終わりに達して、数値に変換できなかった。

コード:

int n;
    ...
    n = scanf("%d", &a);
    if (n == 1 && a >= 0 && a <= 5) break;
    if (n == EOF) { printf("EOF\n"); return 1; }
    // ここに来たら n == 0
変数 n を用意しない場合は、feof(stdin) で EOF かどうかのチェックができます。
いちこ さんが書きました: また、11行目の意味は、改行を取り除いている、でいいでしょうか。
改行は取り除きません。改行の直前までの文字をすべて取り除きます。
改行を取り除くのは次の scanf("%d", &a) の "%d" です。
"%d" は、空白を読み飛ばしたあと、あれば '+' か '-' の符号を、そして数字の列を読み込みます。
空白というのは、スペースやタブ以外に改行も含みます。
%d だけでなく、%s も %x も %f も空白を読み飛ばします。
空白を読み飛ばさないのは "%c" と %[" と "%n" ぐらいでしょう。

いちこ
記事: 62
登録日時: 7年前
連絡を取る:

Re: 数値入力の例外処理について。

#7

投稿記事 by いちこ » 6年前

>>かずまさん
返信ありがとうございます。
返信が遅くなってしまい申し訳ありません。
丁寧に教えてくださってありがとうございます。

scanfは空白を読み飛ばした後数字を読み込む、というのは自分でも調べてみて理解することができました。

ですが、
scanf("%*[^\n]");
というのが、なんだかよくわかりません。
この処理がないと、文字を入力したとき無限ループになってしまいますが、それはなぜなのでしょうか。

また、標準入力から値を受け取ったscanfがEOFを返すときは、Ctrl+z が押されたとき、で正しいでしょうか。

至らなくて申し訳ありませんが、よろしければご教示ください。

アバター
usao
記事: 1569
登録日時: 6年前

Re: 数値入力の例外処理について。

#8

投稿記事 by usao » 6年前

> scanf("%*[^\n]");
書式については scanf で検索するとすぐ見つかります.
↓リンクはwikipediaですが
http://ja.wikipedia.org/wiki/Scanf

役割については,既に説明されているように,
改行文字直前までを入力ストリームのバッファ(? 正式名称わからないけど,入力された内容がたまっている場所)から
読み込む(が,特に変数に格納したりしない = 取り除く)ことです.
scanf()は,予期せぬ入力:今回の例では数値を入力してほしいのにアルファベットを入力されたようなとき があったら
その入力を入力ストリームバッファから取り除かずに残したままにするので,これを放置しておくと
次回のscanf()で再びこのアルファベットに出くわし→放置→また出くわし…
ということになります.

いちこ
記事: 62
登録日時: 7年前
連絡を取る:

Re: 数値入力の例外処理について。

#9

投稿記事 by いちこ » 6年前

>>usaoさん
返信ありがとうございます。

なるほどです。丁寧に説明してくださってありがとうございます。
usao さんが書きました: 次回のscanf()で再びこのアルファベットに出くわし→放置→また出くわし…
だから無限ループになってしまうんですね。

もっと勉強します。
みなさんありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る