入力の恐怖
恐怖の入力ミス
もしかしたら、筆者は相当なひねくれ者なのかもしれません。
前節では良いプログラムの見本のように紹介しておきながら、
これから、そのプログラムには、問題があると文句をつけるつもりでいるからです。
一体、先ほどのプログラムのどこに問題があったのでしょうか?
実は、scanf関数を使用していることが問題なのです。
scanf関数は、色々な問題を抱えている関数です。
入門書では比較的良く使われるにもかかわらず、本格的な開発では使われません。
会社(学校)によっては、scanf関数禁止令を出していることもあります。
しかし、先ほど作ったプログラムは、とくに問題なく動作していました。
一体、どこに問題があるのか・・・・、それは、入力ミスです。
正しく使っている限り、scanf関数はとくに問題を引き起こしませんが、
入力ミスがあった場合、とたんに恐ろしい問題を引き起こすことがあります。
これから、先ほどのプログラムを題材に、入力ミスのケースを紹介します。
区切り記号のミス
まずは起こりそうな例として、
区切り記号を打ち間違えてみます。
先ほどのプログラムでは、,で区切るようになっていましたが、
これをあえて無視して、スペースで区切ってみたいと思います。
次は、区切り記号を打ち間違えた場合の実行結果です。
最小値と最大値を , で区切って入力してください。:100 200
100~307 の合計は 9560 です。
始めに入力した 100 の方は正常に入力されているようなのですが、
後の 200 の方は、なぜか 307 などという数値になってしまっています。
この結果は、使用するコンパイラによって異なってくるので、
皆さんが実行させてみた場合は、別の結果が出てくるのかもしれません。
大きすぎる数値
次に、
極端に大きな数値を入力させてみたいと思います。
なお、最近のコンパイラはかなり大きな数値でも入力できてしまうので、
これを自分で試す場合は、16ビットコンパイラ(LSI C-86)を使ってください。
次は、大きすぎる数値を入力した場合の実行結果です。
最小値と最大値を , で区切って入力してください。:1,70000
1~4464 の合計は 4408 です。
70000 を入力したはずなのに、なぜか 4464 と認識されてしまっています。
しかも、答えまで、1~4464 の合計値にしては、どう考えても小さすぎます。
これらは、記憶できる範囲の限界を超えてしまったために起こる問題です。
入力のチェックをしようにも、入力された変数自体に 4464 と代入されているので、
4464 を入れたかったのか、打ち間違えて 4464 になったのかの区別ができません。
文字列の恐怖
さらに天邪鬼な実験をしてみたいと思います。
すなわち、数値を入力しろと言われているのに、
文字列を入力してみるのです。
次は、文字列を入力した場合の実行結果です。
最小値と最大値を , で区切って入力してください。:ABCDEF
11975~307 の合計は -16199 です。
もはやめっちゃくちゃです。
どうしてこうなったのかは、ビットの対応関係で一応説明はできるのですが、
説明してもしょうがないので、説明しません。
重要なのは、文字列を入力しているのに、なぜか計算されてしまっているという点です。
11957 とか 307 とかの数値はどこから出てきたのでしょうか?
当然、この数値自体が入力されたのか、入力ミスなのかは判別できません。
皆さんは、まさかこんなマヌケなミスを犯す人はいないと考えるかもしれませんが、
寝ぼけているかもしれませんし、ペットの猫がキーボードを踏みつけるかもしれません。
さらに困ったことに、
ウイルスやハッカーがわざとこの様な入力をすることがあります。
もし、大企業や政府で使われているプログラムでこんな事態が起こったら・・・。
解決法について
散々色々な入力ミスを見せられて、もういい加減に疲れたかもしれません。
そろそろ、解決策を提示しないと、皆さんもうんざりしてしまうでしょう。
しかし、実は、この問題の解決は簡単ではありません。
少なくとも、現在のあなたの知識では、これを解決することはできません。
解決策は、文字列として入力させて、そのデータを解析する方法が一般的です。
つまり、この問題を解決するには、文字列処理の方法を知らなくてはなりませんが、
現在のあなたの知識では、文字列処理を行うことは出来ないのです。
この問題の解決手段は、ずっと後になってから紹介することにします。
それまでは、仕方がないので、scanf関数を使い続けるしかありません。
その間は、くれぐれも入力ミスには気をつけるようにしてください。