質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.60%

  • C

    3569questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

数字を入力する際に文字を弾く方法について

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 4,794

kopokopo

score 1

最近、C言語の勉強を始めた初心者です。

数字を入力する際に0~100以外の数字と文字列を弾くようにしたのですが、
一つ困ったことがあります。

    printf("点数を入力してください。\n");    scanf("%d",&ten1);
    tena=getchar();
    while(ten1<0 || ten1>100){
        printf("値に誤りがあります。もう一度入力してください。\n");    scanf("%d",&ten1);
        tena=getchar();
    }

数字やアルファベット一文字を入力すると、1回だけエラー文を出してもう一度入力をさせます。
しかし、容量が大きくなるとその分エラー文が増えてしまいます。
("aaaaa"なら5回、"あ"なら2回)
この表示を1回だけにするにはどうすれば良いでしょうか?
また、文字を弾く方法は調べながらやりましたがこれは正しいですか?

よろしくお願いします。
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+2

scanfで直接特定パターンの文字列を読み込むことはおすすめしません(パターンに合わない入力がストリームに残り続け、あとから別な読み込みで処分する必要が出てきます)。

誤入力があることを前提とするなら、fgetsで1行読み込んで、sscanfstrtolなどのような関数を使って必要なデータを抽出するという方がすっきり書けます(1行読み込む関数にはgetsもありましたが、最大の長さを指定できないという問題点があったため、使用してはいけません)。

参考ページ

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/05/12 16:30

    回答ありがとうございます。
    なるほど・・・そのような関数もあるのですね。勉強になりました。
    次回、プログラムを書く時はそちらの関数も使用してみることにします。

    キャンセル

checkベストアンサー

0

うーん、複数回エラーメッセージが表示されるのはコンパイラ依存のバグかもしれませんが…
バグを引き起こしているのは入力バッファの残りカスに起因していると思います。

たぶん、以下のように記述すればエラーを修正することができます。
int number;
scanf("%d", &number);
while(getchar() != '\n'); // scanf実行後この記述を追加

より良い修正方法としてはmaisumakunさんのおっしゃるようにfgets等を使用することですが、学習に際してscanfを使う場合には上記のように'\n'まで読み捨てを行うといいでしょう。

この理由についてはscanfの動作を知る必要があります。
scanfは文字列から特定パターンを読み込み、引数に読み取った値を代入しますが、以下のように動作しています。
  1. パターンにマッチした読み取り可能な文字を見つけるまで読み捨てる ※%dなら0-9を見つけるまで 入力"a123b"なら"a"は捨てられる
  2. パターンとして認識できる間読み取りを続ける ※%d 入力"a123b"なら3まで bは0-9では無い
  3. パターンの認識から外れたところで読み取りを終了する ※"a123b"なら"b\n"が入力バッファに残る

入力バッファ自体はENTERキーを押下するところまで読み込まれるので、入力バッファの最後には必ず"\n"が含まれます。tena=getchar()はscanf()後に他の関数の動作が不安定なためにつけたものと思いますが、動作が不安定になるのはscanf実行後'\n'が最低1文字分入力バッファに残るためです。逆に言うと、残った入力バッファの終端は必ず'\n'になるので'\n'まで読み飛ばすことで入力バッファに残ったゴミを処理することができます。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/05/12 16:36

    回答ありがとうございます。
    たしかにエラーが修正され、一度だけの表示になりました。
    scanfの仕様とエラーが出る理由がよく理解出来ました。
    この先、scanfを使用して動作に不具合を起こした時はこのことを思い出すようにします。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.60%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 解決済

    素数判定[C言語]

    ある整数を与えて、素数かどうか判定するというプログラムを作ったのですが、コンパイル出来て実行してみたところ、プログラムが停止してしまいました。 ミスの場所を教えてください。解説もあ

  • 受付中

    点数別分布グラフ

    点数分布のグラフですが、少し長いように感じました。もう少し短くすることはできますか? またこのコードに対して何かご意見がありましたらお願いします。 #inc

  • 解決済

    文字列strの中に、文字cが含まれている個数

    文字列strの中に、文字cが含まれている個数(含まれていなければ0とする)を返すという問題でした。 自分でコードを書いてみたのですが、 どこかに問題があるみたいで、問題点を指摘し

  • 解決済

    コンパイルは通るけど実行過程でエラーが出て終了する

    コンパイルは通るのですがコードretryのところで 0 か 1を選んでも表示がでなくて1を押すと エンター2回押しで再実行できるのですが 0を押すとエラー表示がでて終了 し

  • 解決済

    [C言語] 2次元配列に一文字ずつ格納する方法

    前提・実現したいこと お世話になります。またしても初歩的な内容で申し訳ないのですが、現在勉強のため、入力を平面として捉え、「0」「1」に変換して位置関係を保持したまま出力する、と

  • 解決済

    C言語でキーボードから入力した文字を表示した後、文字とそのASCIIコードを表示するコードのエラー

    前提・実現したいこと C言語でキーボードから入力した文字(character)を表示した後、その文字のASCIIコードを表示するコードを書いています。以下のエラーがコンパイル時に表

  • 解決済

    C言語でwhileとif文を組み合わせたコードのエラー

    前提・実現したいこと ここに質問したいことを詳細に書いてください 文字が小文字アルファベットの場合は、入力文字を入力してその大文字を返し、 それ以外の場合は、新しい入力を促すコード

  • 解決済

    c言語 入門レベル問題 double

    練習問題通りにコーデングしたいですが、なぜこいう実行結果になってしまいましたか? #include <stdio.h> double tanka,suryo,kingaku

同じタグがついた質問を見る

  • C

    3569questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。