scanf
入力の読み込みと一口に言っても、状況により様々な事が要求されます。
単に、キーボードから数値を読み込む場合、あるいは、ファイルから読み込む場合、さらには、文字なども含めて読み込む場合など、入力方法の種類は多種多様です。
幸いなことに、UNIX では、標準入力という概念があり、キーボード入力とファイルからの入力とは、プログラムから見ると同じに取り扱える仕組みがあります。
入力されてくるものは、一般には文字であるが、ここでは、整数のみに限定するします。


整数変数への標準入力からの読み込みは、scanf という標準関数を用います。
その書式は、以下のとおりです。


    scanf("%d",&整数変数名);


注意するのは、何も入力がなければ、入力されるまで待つという点です。
また、ここで、整数変数名の前についている & は、実は重要な意味を持っていますが、ここでは重要な意味を持つおまじないと思ってください。
ダブルクォーテーションで囲まれた %d は、printf の時と同じような意味で、整数として読み込むという意味です。


例1
    int a;
    scanf("%d", &a);


この例では、整数変数 a に、標準入力から整数を読み込みます。
しかし、ディスプレイには、入力をうながすような目印は何も出ないので、これではいささか不親切です。
次の例のように通常は printf と組にして使うほうが良いでしょう。


例2
    int a;
    printf("整数を入力してください。 a = ");
    scanf("%d", &a);


これで、画面上には、


    整数を入力してください。 a = 


と出力され、ユーザーがキーボードから整数を入力するまで、プログラムは待つことになります。

しかし、これでも問題があります。何故ならば、もし、ユーザーが間違って文字をいれたとすると、この場合、変数 a には何も入力されません。
だから、入力に成功したのか、それとも失敗したのかを知る必要があります。

printf, scanf などは関数と呼ばれるいわば部品であり、C言語では、このような部品を使ってプログラムを作ることが出来るので、いい部品がたくさんあると全てを自分で作る必要がなくなり、プログラムの作成が非常に楽になります。
さて、この部品を呼び出して何等かの仕事(例えば画面への表示)をさせるような場合、その仕事の結果(うまく行ったかとか、失敗したか等)を知りたいこともある。
そのために一般にC言語では関数は値を持っています(これを返り値という)。
これは、関数を変数と同じように式の右辺等に使えることを意味します。
例えば、


    c = a * 3;


と同じような意味で、ある関数 keisan() があった場合、


    c = keisan() * 3;


などというような使い方が出来ます。
勿論、変数とは違うので、


    keisan() = 2;


などのように関数にある値を代入することはできません。


そこで scanf ですが、scanf には、読み込みの成功や、成功した個数、あるいは読み込みの失敗などを返り値で知らせるようになっています。
特に、読み込みに成功した場合は、変換に成功した個数を返すようになっているのです。
つまり、scanf は、キーボードからの入力を読み取り、指定された形式に変換後、その変換に成功した個数を表わすということです。 (この例の場合、1個しか読み込んでないので、変換に成功すると1が返る筈である)
そこで、例2を改良すると以下のようになる。


例3
    int a, kosuu;
    printf("整数を入力してください。 a = ");
    kosuu = scanf("%d", &a);
    if ( kosuu == 1 ){
        printf("入力した数値は、a = %d\n",a);
    }else{
        printf("入力が違います。\n");
    }


この例では、まず、キーボードから読み取った数値を変数 a に代入し、 scanf はその個数を返すので、それを変数 kosuu に代入しています。
従って、もし正しく入力されていたならば変数 kosuu には、1が入っているはずで、そうでない場合には全て入力が正しくないと思われる。


例3では、分かりやすく入力の個数を変数 kosuu に代入していたが、これはもっと簡単に書くことが出来ます。


例4
    int a;
    printf("整数を入力してください。 a = ");
    if ( scanf("%d", &a) == 1 ){
        printf("入力した数値は、a = %d\n",a);
    }else{
        printf("入力が違います。\n");
    }


scanf の結果を判断しているのは1箇所なので、整数変数を使わずに、そこに直接 scanf を書いています。
C言語では、こういう便利な事が出来ることが一つの特徴です。
ところが、実は、この例は更に簡単に書けます。


例5
    int a;
    printf("整数を入力してください。 a = ");
    if ( scanf("%d", &a) ){
        printf("入力した数値は、a = %d\n",a);
    }else{
        printf("入力が違います。\n");
    }


例4との違いを良く比べてみましょう。
例4では、scanf の結果と1とを if 文の条件で比較していましたが、今度はそれがありません。
これは、scanf が正常な入力の場合には1を返し、1は真として解釈されることを利用しているからです。


例4、5では、入力が間違っていた場合、再入力するためには、もう一度プログラムを実行し直す必要がありました。
しかし、多くの入力を要するプログラムでは、一度の間違いのために何度も入力をやり直させるのは、不親切です。
従って、入力が間違っていたら、何度でも正しい入力が得られるまで繰り返すように変更してみます。


例6
    int a;
    char buf[64];
    printf("整数を入力してください。 a = ");
    for (; scanf("%d",&a)!=1 ;){
        printf("入力が間違っています。\n a = ");
        scanf("%s",buf);
    }
    printf(" a = %d \n",a);


ここでは、繰り返しのために for 文を用いています。
まず、初期化は何も指定されていないので、継続条件が判定されます。
継続条件は、 scanf("%d",&a)!=1 なので、まず、scanf が実行され、その結果が1と比較されます。
もし、入力が間違っていた場合は0なので継続条件が真となり、「入力が間違っています。」が表示された後、改行されて、「a = 」が表示されて、再び、継続条件の判定に移ります。
重要なことは、最初に継続条件が判定されるので、もし、正しい入力だったら継続条件は偽となり、その場合は、for 文の中の文は実行されない点です。

また、scanf("%s",buf) という文がないと非常に困ったことになります。
実は、scanf は、入力が期待したものと違っていた場合には、読んだ文字を返却するようになっています。
何処に返却するかというと、標準入力に返します。
これは何か変なように思われるかもしれませんが、入力というのは実際に入力された文字を一つ一つ持っているわけではなくて、入力されたものを全て持っているのです。
例えば、入力が、「aリターンbリターン0リターン」であったとしよう。C言語で書けば、"a\nb\n0\n" となっていたとします。
この入力は、一旦貯蔵庫に納められます。
そして、scanf は、その貯蔵庫に文字を取りに行くのだと思ってください。
scanf("%d",&a); で、"a\n" を取り出し、文字 'a' を整数に変換しようとしますが、これは失敗するので、 "a\n" を貯蔵庫に返却します。
そのために、何度 scanf をくり返しても同じ事のくり返しになってしまいます。
従って、この入力を捨てる事が必要になります。
入力を捨てる方法には色々な方法がありますが、ここでは scanf() を使っています。
scanf("%s",buf) の buf は、ここでは詳しくは触れませんが、プログラムの先頭で char buf[64]; と宣言しておくようにします。


注意
scanf は、指定された形式への変換に失敗すると0を返すことは上に書いた通りですが、変換するべきものがなかった場合などには、-1 を返すことがあります。
通常、-1という値を用いずに、標準で定義されている EOF を用います。
従って、scanf の値を見るときには、0と等しいか否かという判定をすると問題が生じる場合があるので、ここでは 1(又はそれ以上)かそうでないかで判定している点に注意しましょう。