C言語今更再認識: scanfの不可解な挙動,2回入力要求したのに | 技術日誌

技術日誌

ここでは,電子工作,木工などの趣味での記録を書いています。
なお当初はKMK研究所のメインテーマであるSPSのノウハウを書いてきましたが,順次SPSノウハウのページに複製を作っていきます。

 C言語を学び始めると(私は独学ですが)最初に出てくるのが,キーボードからの入力にscanf関数を使うことです。この関数は,暴走させたり,思い通りの入力にならなかったりする使いにくい関数です。入力値を代入する場所(下のプログラムでは&iとsです。入門本では「&はおまじないと考えよ」などと書かれています。sには&が付いていません。きちんと説明しないといけないですね)の指定を間違えると,パソコン中のとんでもない場所のメモリを書き替えてしまって,パソコンがハングアップする場合があります。後者の例を示します。

  上のプログラムは,まず,キーボードから整数の入力を要求します(6行目)。入力された値を書き出した後,再びキーボードから文字列の入力を要求します(9行目)。そして,その値を書き出した後,5秒間待って(12行目)終了します。

 下の実行結果は,整数の入力要求に123と答え,文字列の入力要求にabcと答えた結果です。意図した通り,i=123とs=「abc」がうまく取り入れられていることが分かります。

 ところが,整数の入力要求にaと答える(正しい応答ではありませんが)と,上とは異なり,2回目の入力を待たずに,下の様に5秒止めるところに行ってしまいました。不可解です。

 上の実行結果にこの不可解な挙動の理由のヒントが現れています。iに入力するべき所に,「a」と答えているにもかかわらず,iには「a」が入らず(整数型変数ですから入るわけはありませんが),999になっています。これは,プログラムの最初に初期値として与えた値です。そして,キーボードから入れた「a」は2回目の応答として扱われました。これらのことから分かることは次のようになります。

 整数iを受け取るscanf文に文字を答えると,キーボードからの値は門前払いして,iの値は変えられない。次に文字列sを受け取るscanf文が実行されたとき,門前払いされた文字(列)が,ここで受け取られる。scanfは入力値を“門前払い”することがあることにより,不可解な挙動になるということでした。