C言語の基本|scanfで変数に値を入力する

入力した整数・小数・文字を変数へ保存して、C言語プログラムを対話型へ一歩進めよう。

printfを使えるようになると、プログラムから文字や数値を画面へ表示できるようになります。

次に身につけたいのが、キーボードから入力した値を変数へ保存する方法です。

たとえば、年齢を入力してもらったり、小数を含む数値を受け取ったり、AやBといった1文字を入力してもらったりできれば、プログラムは決められた内容を表示するだけではなく、ユーザーの操作に応じて動けるようになります。

C言語では、このようなキーボード入力にscanf関数を利用できます。

ここでは、よく使う次の3種類の型への入力を中心に見ていきます。

  • int型:整数を扱う
  • double型:小数を含む実数を扱う
  • char型:1文字を扱う

scanfでは、入力する変数の型に合わせて変換指定を使い分けます。

特に覚えておきたいポイントは次の3つです。

  • scanfでは基本的に変数名の前へ&を付ける
  • double型への入力には%lfを使う
  • char型への入力では、%cの前に半角スペースを置いた %c が便利

一つずつ確認すれば、それほど難しくありません。

まずは、キーボードから入力した値がscanfを通って変数へ保存される流れから見ていきましょう。

変数へ値を入力する基本的な流れ

scanfを使ったプログラムは、次の3段階で考えると分かりやすくなります。

  1. printfで入力してほしい内容を表示する
  2. scanfでキーボード入力を受け取る
  3. printfで変数の内容を表示して確認する

たとえば整数を入力する場合は、次のようなイメージです。

printf("整数を入力してください > ");
scanf("%d", &value);
printf("入力された値は%dです\n", value);

実行すると、まずprintfによって入力案内が表示されます。

整数を入力してください >

続いてscanfのところで入力待ちになります。

ユーザーが25と入力してEnterキーを押すと、その25がvalueへ格納されます。そのあとprintfによって、valueに保存された値を確認できます。

図1:printf・scanf・変数の基本的な流れ

この図から分かること

scanfを使った入力処理では、いきなりscanfだけを書くのではなく、printfと組み合わせると分かりやすくなります。

まずprintfで、

何を入力すればよいか

をユーザーへ伝えます。

次にscanfが入力を受け取り、指定された変数へ値を書き込みます。

最後にprintfで変数を表示すれば、入力した値が正しく保存されたか確認できます。

基本的な流れは、

printfで案内
    ↓
scanfで入力
    ↓
変数へ保存
    ↓
printfで確認

となります。

scanfの基本形を確認しよう

scanfは、基本的に次の形で使用します。

scanf("変換指定", &変数名);

たとえばint型の変数numberへ10進整数を入力する場合は、次のようになります。

int number;

scanf("%d", &number);

ここには、scanfを理解するための重要な要素が2つあります。

部分意味
%d入力されたデータを10進整数として読み取る
&number読み取った値を書き込むnumberの場所を指定する

変換指定によって、入力を整数として読むのか、小数として読むのか、1文字として読むのかが決まります。

そして&変数名によって、読み取った値を保存する場所をscanfへ伝えます。

scanfではなぜ&を付けるのか

scanfで特に重要なのが&です。

たとえば次のコードでは、

scanf("%d", &number);

numberの前に&が付いています。

C言語では&を変数名の前に付けると、その変数が置かれているメモリ上のアドレスを取得できます。

アドレスとは、簡単に考えると変数の住所です。

scanfは入力された値を変数へ書き込む必要があります。

そのため、

どの変数へ値を書き込めばよいのか

をscanfへ知らせなければなりません。

そこで、

&number

として、numberが置かれている場所を渡します。

たとえば25を入力した場合は、次のような流れです。

25を入力
   ↓
scanfが25を読み取る
   ↓
&numberでnumberの場所を確認
   ↓
numberへ25を書き込む

最初は&を忘れやすいため、

scanfは値を書き込むので、書き込み先の住所が必要

と覚えておくと理解しやすいでしょう。

printfとscanfでは変数の渡し方が違う

printfとscanfでは、同じ%dを使う場合でも、変数の指定方法が異なります。

scanfでは次のようにします。

scanf("%d", &number);

printfでは次のようにします。

printf("%d\n", number);

違いは&です。

関数目的必要なもの記述例
scanf変数へ値を書き込む変数のアドレスscanf("%d", &number);
printf変数の値を表示する変数に入っている値printf("%d", number);

scanfは変数の中身を変更するため、変数の場所を知る必要があります。

一方、printfは変数にすでに入っている値を読み出して表示するだけなので、変数の値を渡します。

この違いを理解すると、scanfで&が必要になる理由も分かりやすくなります。

int型へ10進整数を入力する

整数を扱うint型へキーボードから値を入力するときは、%dを使います。

int quantity;

scanf("%d", &quantity);

たとえばユーザーが35を入力した場合は、

入力:35
   ↓
%dで10進整数として読み取る
   ↓
quantityへ35を格納

という処理になります。

int型では、scanfとprintfの両方で%dを使えます。

処理変換指定
scanfでint型へ入力%d
printfでint型を表示%d

入力と表示を組み合わせると、次のように書けます。

int quantity;

printf("個数を入力してください > ");
scanf("%d", &quantity);

printf("入力された個数は%dです\n", quantity);

たとえば12を入力すれば、quantityには12が保存されます。

double型へ実数を入力する

小数を含む値を扱いたい場合はdouble型を利用できます。

scanfでdouble型へ値を入力するときは、%lfを使用します。

double temperature;

scanf("%lf", &temperature);

たとえば23.5を入力すると、temperatureへ23.5が保存されます。

入力:23.5
   ↓
%lfでdouble型の値として読み取る
   ↓
temperatureへ23.5を格納

ここはscanfを学ぶときに間違えやすい部分です。

scanfでは、次のように型によって変換指定が異なります。

変数の型scanfで使用する変換指定
float%f
double%lf

double型の場合は、

scanf("%lf", &temperature);

とします。

scanfとprintfではdoubleの指定が異なる

double型は、入力するときと表示するときで使う指定が異なります。

scanfでdouble型へ入力するときは%lfです。

scanf("%lf", &temperature);

printfでdouble型の値を表示するときは%fを使用できます。

printf("%f\n", temperature);

整理すると次のようになります。

処理double型で使用する指定
scanfで入力%lf
printfで表示%f

初心者のうちは、

doubleをscanf → %lf
doubleをprintf → %f

とセットで覚えておくとよいでしょう。

char型へ1文字を入力する

1文字を保存したい場合はchar型を使います。

scanfでは%cを使用します。

char rank;

scanf("%c", &rank);

たとえばAを入力すれば、rankへ文字Aを格納できます。

ただし、%cには少し注意が必要です。

%cは、アルファベットや数字だけではなく、空白や改行も1文字として読み取ります

そのため、その前に別のscanfで数値を入力してEnterキーを押していると、そのときの改行が残り、次の%cがその改行を読み取ってしまうことがあります。

char型では %c の前の空白が役立つ

数値入力のあとなどにchar型へ1文字を入力するときは、次のように書く方法がよく使われます。

scanf(" %c", &rank);

%cの前に半角スペースが1つあります。

このスペースによって、scanfは入力に残っている空白文字を読み飛ばしてから、次の1文字を%cで読み取ります。

たとえば、

25を入力してEnter
        ↓
入力には改行が残ることがある
        ↓
scanf(" %c", &rank);
        ↓
先頭の空白指定で改行などを読み飛ばす
        ↓
次に入力されたAを%cで読み取る

という流れになります。

図2:int・double・charで変わるscanfの指定

この図から分かること

scanfでは、入力先となる変数の型に合わせて変換指定を変える必要があります。

今回扱う3つの型では、次の組み合わせになります。

int
↓
%d

double
↓
%lf

char
↓
%c

特に注意したいのがdoubleとcharです。

double型への入力では%lfを使います。

char型への入力では%cを使いますが、その前に半角スペースを置いた形にすると、それまでの入力で残った改行や空白を読み飛ばしてから1文字を受け取れるため便利です。

int・double・charへの入力をまとめて試してみよう

ここまで確認した3種類の入力を、1つのプログラムで試してみましょう。

今回は、商品の個数、商品の重さ、商品区分を入力するプログラムにしてみます。

商品の個数・重さ・区分を入力して表示するプログラム

ファイル名:5_8_1.c

#include <stdio.h>

int main(void)
{
    int count;
    double weight;
    char category;

    /* 商品の個数を入力する */
    printf("商品の個数を入力してください > ");
    scanf("%d", &count);

    /* 商品1個の重さを入力する */
    printf("商品の重さを入力してください(例: 2.75)> ");
    scanf("%lf", &weight);

    /* 商品区分を1文字で入力する */
    printf("商品区分を1文字で入力してください(例: A)> ");
    scanf(" %c", &category);

    /* 入力された内容を表示する */
    printf("\n入力された商品情報\n");
    printf("個数    : %d\n", count);
    printf("重さ    : %f\n", weight);
    printf("商品区分: %c\n", category);

    return 0;
}
実行結果の例
商品の個数を入力してください > 8
商品の重さを入力してください(例: 2.75)> 3.25
商品区分を1文字で入力してください(例: A)> C

入力された商品情報
個数    : 8
重さ    : 3.250000
商品区分: C

このプログラムでは、3種類の変数を用意しています。

int count;
double weight;
char category;

それぞれの役割は次のとおりです。

変数保存する内容
countint商品の個数
weightdouble商品の重さ
categorychar商品区分を表す1文字

入力するときも、それぞれの型に対応した変換指定を使用しています。

変数scanfの記述変換指定
countscanf("%d", &count);%d
weightscanf("%lf", &weight);%lf
categoryscanf(" %c", &category);%c

int型の入力部分を詳しく確認する

最初の入力処理は商品の個数です。

printf("商品の個数を入力してください > ");
scanf("%d", &count);

printfによって入力案内を表示し、そのあとscanfで入力を待ちます。

実行例では8を入力しています。

商品の個数を入力してください > 8

scanfの変換指定は%dです。

scanf("%d", &count);

%dは、入力されたデータを10進整数として読み取る指定です。

そのため8を入力すると、

8を入力
   ↓
%dで10進整数として読み取る
   ↓
&countでcountの場所を指定
   ↓
countへ8を格納

という処理になります。

結果を表示するところでも%dを使っています。

printf("個数    : %d\n", count);

ここではcountに入っている8が表示されます。

double型の入力部分を詳しく確認する

次は商品の重さです。

printf("商品の重さを入力してください(例: 2.75)> ");
scanf("%lf", &weight);

weightはdouble型です。

double weight;

そのためscanfでは%lfを使用しています。

scanf("%lf", &weight);

実行例では3.25と入力しています。

商品の重さを入力してください(例: 2.75)> 3.25

処理の流れは次のとおりです。

3.25を入力
   ↓
%lfでdouble型の値として読み取る
   ↓
&weightでweightの場所を指定
   ↓
weightへ3.25を格納

結果を表示するときは%fを使用しています。

printf("重さ    : %f\n", weight);

そのため、実行例では次のように表示されます。

重さ    : 3.250000

%fでは小数点以下が6桁表示される

printfで%fをそのまま使った場合、通常は小数点以下6桁まで表示されます。

今回のweightには3.25が入っていますが、

printf("%f\n", weight);

とすると、

3.250000

のように表示されます。

小数点以下の表示桁数を変更したい場合は、精度を指定できます。

たとえば小数点以下1桁なら、

printf("%.1f\n", weight);

となります。

weightが3.25なら、この場合は次のように表示されます。

3.2

小数点以下2桁なら、

printf("%.2f\n", weight);

として、

3.25

のように表示できます。

今回重要なのは、scanfでdouble型へ入力するときは%lf、printfで表示するときは%fという違いです。

char型の入力部分を詳しく確認する

最後は商品区分です。

printf("商品区分を1文字で入力してください(例: A)> ");
scanf(" %c", &category);

categoryはchar型です。

char category;

1文字を読み取るため、変換指定には%cを使用します。

ただし今回のコードでは、

scanf(" %c", &category);

のように、%cの前へ半角スペースを置いています。

これは、その前に行った数値入力で残っている可能性がある改行などの空白文字を読み飛ばすためです。

実行例ではCを入力しています。

商品区分を1文字で入力してください(例: A)> C

処理のイメージは次のようになります。

それまでの入力で残った改行
         ↓
先頭の半角スペースで読み飛ばす
         ↓
Cを入力
         ↓
%cで1文字として読み取る
         ↓
categoryへCを格納

結果を表示するときも%cを使います。

printf("商品区分: %c\n", category);

そのため、

商品区分: C

と表示されます。

%cの前にスペースがないとどうなるのか

たとえば次のように書いたとします。

scanf("%c", &category);

%cは、改行や空白も1文字として読み取ります。

直前に、

3.25

と入力してEnterキーを押している場合、その入力のあとには改行が残っています。

すると%cが、その改行を1文字として読み取ってしまう場合があります。

イメージすると次のようになります。

3.25を入力してEnter
        ↓
改行が残る
        ↓
scanf("%c", &category);
        ↓
%cが改行を読み取る
        ↓
ユーザーが文字を入力する前にscanfが終了

そこで、

scanf(" %c", &category);

とします。

先頭のスペースには、空白文字を読み飛ばす働きがあります。

残っている改行
       ↓
先頭のスペースで読み飛ばす
       ↓
次の文字を待つ
       ↓
Cを入力
       ↓
%cでCを読み取る

数値入力のあとに1文字を入力する場面では、とても役立つ書き方です。

scanfの書式文字列はシンプルにする

scanfでは、書式文字列を必要以上に複雑にしないほうが分かりやすくなります。

整数を入力したいなら、基本的には次のようにします。

scanf("%d", &count);

次のような形は避けたほうがよいでしょう。

scanf("count = %d", &count);

この場合scanfは、数値だけではなく、入力された内容にcount = という文字まで含まれていることを期待します。

つまり単に、

8

と入力するだけでは意図した読み取りになりません。

入力案内はprintfに任せて、

printf("商品の個数を入力してください > ");
scanf("%d", &count);

のように役割を分けると、コードも入力方法も分かりやすくなります。

複数の値を続けて入力することもできる

scanfでは、複数の変換指定を並べることもできます。

たとえば、int型の変数aとbへ2つの整数を入力するなら、

scanf("%d%d", &a, &b);

と書けます。

入力として、

10 20

を与えた場合は、

10
↓
aへ格納

20
↓
bへ格納

という対応になります。

変換指定の並び順と、後ろに書く変数の並び順を対応させることがポイントです。

scanfは入力内容が合わないと読み取りに失敗する

scanfは、どのような入力でも自動的に正しい値へ変換してくれるわけではありません。

たとえば次のコードがあるとします。

scanf("%d", &count);

%dは10進整数を読み取るための指定です。

ここでユーザーが、

ABC

のような整数として読み取れないデータを入力すると、scanfは正常に整数を読み取れません。

さらに、読み取れなかった文字が入力に残ることがあります。

すると、次に実行されるscanfでも同じ文字が読み取りの邪魔をする場合があります。

入門段階では、まず次の2点を押さえておきましょう。

  • scanfでは変換指定に合わない入力を読み取れないことがある
  • 読み取れなかった入力が残り、次のscanfへ影響することがある

特に繰り返し処理と組み合わせた場合、同じ読み取り失敗が何度も繰り返され、処理が進まなくなることもあります。

入力エラーへの詳しい対処方法は、scanfの基本的な入力ができるようになってから学ぶと理解しやすくなります。

図3:scanfで正しく入力できる場合と失敗する場合

この図から分かること

scanfは、指定された形式に合う入力であれば、読み取った値を変数へ格納して次の処理へ進みます。

たとえば、

scanf("%d", &count);

に対して25を入力すれば、%dで10進整数として読み取れるため、countへ25を格納できます。

一方、

ABC

のような整数ではない文字を入力すると、%dでは読み取れません。

その場合、読み取れなかった入力が残り、その後のscanfにも影響する可能性があります。

scanfを使うときは、

変数の型、変換指定、ユーザーが入力するデータ

の3つが対応していることが大切です。

scanfで止まって見えるのは入力待ち

scanfを使ったプログラムを実行すると、途中で処理が止まったように見えることがあります。

たとえば、

商品の個数を入力してください >

と表示されたところから画面が変わらなかったとしても、通常は異常ではありません。

プログラムはscanfでキーボード入力を待っています。

printfで入力案内
       ↓
scanfを実行
       ↓
入力待ち
       ↓
ユーザーが値を入力
       ↓
Enterキー
       ↓
scanfが読み取る
       ↓
次の処理へ進む

値を入力してEnterキーを押せば処理が進みます。

scanfを初めて使うと、

プログラムが固まったのではないか

と思うことがありますが、入力を求めている画面なら正常な動作です。

処理が終わらなくなったときはCtrl+Cで停止できる

入力に失敗した状態で繰り返し処理を行うプログラムなどでは、意図せず処理が何度も繰り返されてしまうことがあります。

コマンドプロンプトやターミナル上で実行しているプログラムを止めたい場合は、一般的にCtrlキーを押しながらCキーを押すことで実行を中断できます。

Ctrl + C

scanfで入力を待っているだけの場合は、通常は値を入力してEnterキーを押せばよいので、強制終了する必要はありません。

Ctrl+Cは、

  • プログラムが意図しない繰り返しから抜けられない
  • 入力をやり直すために一度プログラムを終了したい
  • 実行中のプログラムを中断したい

といった場合の停止方法として覚えておくと便利です。

scanfで変数へ入力するときに確認したいポイント

scanfでint、double、charへ入力するときは、それぞれの型と変換指定の対応を確認しながら書いてみましょう。

変数の型scanfでの指定printfでの表示入力例
int%d%d25
double%lf%f3.25
char%c%cA

数値入力のあとにchar型へ入力する場合は、次のように先頭へ半角スペースを置く方法が便利です。

scanf(" %c", &category);

また、scanfでは基本的に変数のアドレスを渡します。

scanf("%d", &count);
scanf("%lf", &weight);
scanf(" %c", &category);

一方、printfでは変数に格納されている値を表示するため、&は付けません。

printf("%d\n", count);
printf("%f\n", weight);
printf("%c\n", category);

入力処理を書くときは、

printfで入力内容を案内する
        ↓
scanfで値を受け取る
        ↓
変数へ格納する
        ↓
printfで結果を確認する

という流れで考えると整理しやすくなります。

まずはint型の%d、double型の%lf、char型の %c の3つを実際に入力し、キーボードから入力した値が変数へ保存され、その値をprintfで確認できるところまで動かしてみると、scanfによる変数入力の仕組みをしっかりつかめます。