もう解決しちゃってますけど、ちょっとだけ補足...と思ったら長くなっちゃいました。でも、scanf()を真面目に考えるとこうなっちゃうんです。
scanf()って、「とりあえず」ならともかく、真面目にエラー対応とかを考え出すと相当面倒なことになったりします。なにしろ、入出力装置がテレタイプとかそんなだった時代の産物ですから。そのころは、コンピュータ様に入力するのに間違えるなんて...だったんでしょうね(私も知らない)
まず、データの入り口。もしかして、scanf()はキーボードからなにか入力する関数、と思ってます? そんな決まりはありません。scanf()は、標準入力ストリームからデータを(取り出せれば)取り出す関数です。標準入力ストリームってなんだ? OSが与えてくる入力文字列です。デフォルトでは、OSはキーボードからのデータを入力文字列として与えてくるので、scanfがキーボードからの入力として使われることが多いのです。「リダイレクト」という機能を使うと、キーボード以外、例えばファイルから標準入力にデータを流し込んだりも出来ます。
ここで気をつけなきゃいけないのはOSが与えてくる、ということ。つまり、C言語の制御の外なんです。キーボードを叩いてコンピュータの中に取り込むまではOSがやっちゃいます。なので、C言語の範囲では「指定文字以外の入力を禁止する」というのは言葉通りには出来ません。入力された文字はとにかくC言語の入り口までは入ってきてしまうのです。不要な文字は、入ってきちゃったのを捨てる/無視することになります。
ここでもう一ついやらしいところ。書式指定子(%dとか%sとか)でデータ形式を指定してデータを取り出すわけですが、それって何をしているのかを把握しないと、今回のような「無限ループ」になっちゃったりします。
基本的な考え方は「指定と一致したデータだけを取り込む」こと。
%dや%sでは、標準入力の先頭から位置文字ずつ取り込み、最初がホワイトスペース(空白、水平タブ、改行)だったら、なにかの文字に出会うまで読み飛ばします。なにかの文字に出会ったら、指定の変換が出来るかどうか試します。成功するなら、次の文字も取り込んで変換出来るかどうか試します。次々と試して、変換出来ない文字に出会ったら、これまでに取り込んだデータで確定して、与えられているアドレスに格納します。そして、変換できなかった文字は、標準入力に戻します。
さて。書式指定が"%d"に対して、"s"が入力されたらなにが起こるでしょうか。"s"は数値に変換出来ないので、scanfは一文字も取り込めず変換失敗、ポインタが指しているアドレス内容は変更されません。で、"s"は標準入力に戻してしまいます。質問のプログラムでは、変数aは0に初期化されていたので0のまま。0だともう一度scanfでデータを取り込もうとするのですが...標準入力の先頭は、先程変換に失敗した"s"が戻されています。ので、scanfはまた"s"を取り込んで変換失敗、"s"を標準入力に戻して、次のscanfでまた...これが「無限ループ」の正体です。タイトルの「int型に文字を入れると」は、起こった現象としては「int型に文字を入れられなかったので」ということですね。
ということで、各氏解説されているように、scanf()で何とかしたいなら、まず戻り値で変換に失敗したことを検出し、変換できなかったデータを何らかの方法で捨ててから、(失敗して戻されたのではない)新しい入力データを取り込む、というようなことが必要になるのです。
あるいは、このscanf()の仕組みで細工するくらいなら、標準入力にあるデータを文字列として全部取り出してしまい、自前で解釈したほうがいっそすっきり、という考えも出てくるわけで。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2019/07/22 02:27
2019/07/22 02:31
退会済みユーザー
2019/07/22 02:41
退会済みユーザー
2019/07/22 02:49
2019/07/22 02:54
退会済みユーザー
2019/07/22 03:16
2019/07/22 03:22