C言語の基本|C言語の入出力の基本

表示と入力がつながると、プログラムは人とやり取りできるようになる。C言語の標準入出力を、基本の形から身につけよう。

C言語の入出力の基本

これまでに作成したC言語のプログラムでも、printfを使って文字や数値を画面に表示してきました。画面に結果が現れると、プログラムがどのように動いたのかを目で確認できます。

しかし、プログラムと人とのやり取りは、表示するだけではありません。キーボードから数値などを入力し、その値をプログラムに渡すこともできます。

C言語では、画面への表示とキーボードからの入力を、標準入出力という仕組みで扱います。

  • プログラムから画面へ情報を送るのが標準出力
  • キーボードなどからプログラムへ情報を渡すのが標準入力

標準入出力が使えるようになると、プログラムは決められた結果を表示するだけでなく、利用者に入力を求め、その内容に応じた結果を返せるようになります。

ここでは、画面表示に使うprintfを中心に、文字列の表示、改行、変換指定、引数、返却値を順番に確認します。そのうえで、キーボード入力と画面表示をどのように組み合わせるのかも見ていきましょう。

標準入力と標準出力とは

標準入出力は、プログラムが外部と情報をやり取りするための基本的な仕組みです。

種類情報の流れ身近な例
標準入力外部からプログラムへ入るキーボードから数値を入力する
標準出力プログラムから外部へ出る画面に文字や計算結果を表示する

学習用のプログラムでは、標準入力をキーボード、標準出力をターミナルやコマンドプロンプトの画面として考えると分かりやすいでしょう。

たとえば、年齢を入力して結果を表示するプログラムなら、情報は次のように流れます。

キーボードから年齢を入力
        ↓
プログラムが値を受け取る
        ↓
受け取った値を処理する
        ↓
結果を画面に表示する

入力と出力を組み合わせることで、プログラムと利用者の間にやり取りが生まれます。

図1:標準入力と標準出力の情報の流れ

この図から分かること

キーボードから渡された情報は、標準入力を通してプログラムに入ります。プログラムが作ったメッセージや計算結果は、標準出力を通して画面に表示されます。

入力と出力は反対方向の情報の流れですが、実際のプログラムでは組み合わせて使うことが多くあります。

printfは画面に情報を表示する関数

printfは、文字や数値を標準出力へ送り、画面に表示するための関数です。

関数とは、決められた処理をひとまとまりにしたものです。printfに表示したい情報を渡すと、その内容を指定された形式で画面へ出力してくれます。

表示する内容
    ↓
printf
    ↓
画面に表示

printfという名前のfは、formatを表しています。単に文字を表示するだけでなく、整数、小数、文字などの形式を指定して表示できることが特徴です。

printfを使うための準備

printfを使うプログラムでは、ソースファイルの先頭付近に次の行を書きます。

#include <stdio.h>

stdioはstandard input/outputを短くした名前で、標準入出力を表します。stdio.hには、printfなどの標準入出力関数を使うために必要な宣言が用意されています。

#includeは、指定したヘッダーファイルの内容を取り込むためのプリプロセッサ指令です。

#include <stdio.h>

この1行によって、コンパイラはprintfの名前だけでなく、どのような引数を受け取り、どのような値を返す関数なのかを確認できます。

stdio.hを取り込まずにprintfを使うと、正しく宣言されていない関数を呼び出すことになり、警告やエラーの原因になります。

printfの基本的な書き方

文字列だけを表示する場合は、次の形でprintfを使います。

printf("表示する文字列");

printfの丸括弧の中に渡す情報を引数といいます。この例では、表示する文字列がprintfの引数です。

文の終わりにはセミコロンが必要です。

printf("C言語を学習します");

このコードを実行すると、画面には次のように表示されます。

C言語を学習します

ただし、文字列の末尾に改行がないため、次に表示される内容は同じ行の続きに現れます。

書式文字列と表示する値

文字列の中に整数などを埋め込みたい場合は、次の形で記述します。

printf("書式文字列", 表示する値);

たとえば、整数の10を文章の中に表示するなら、次のように書きます。

printf("練習問題は%d問です\n", 10);

このコードには、2つの引数があります。

引数の位置内容役割
1つ目書式文字列表示する文章と形式を指定する
2つ目10%dの位置に表示する整数を渡す

%dは整数を表示する位置を表します。このような指定を変換指定といいます。

表示結果は次のようになります。

練習問題は10問です

改行を入れてメッセージを表示する

複数のメッセージを見やすく表示するには、改行の位置を自分で指定します。C言語では、文字列の中に\nを書くと、その位置で表示行を切り替えられます。

3行の案内メッセージを表示するプログラム

ファイル名:5_1_1.c

#include <stdio.h>

int main(void)
{
    /* 3行の案内メッセージを順番に表示する */
    printf("C言語の入出力を学びます\n");
    printf("最初に画面表示を確認します\n");
    printf("続いてキーボード入力へ進みます\n");

    return 0;
}
実行結果の例
C言語の入出力を学びます
最初に画面表示を確認します
続いてキーボード入力へ進みます

このプログラムでは、printfを3回呼び出しています。それぞれの文字列の末尾に\nがあるため、1回表示するたびに次の行へ移動します。

1つ目のprintfを実行すると、次の文字列と改行が出力されます。

printf("C言語の入出力を学びます\n");

改行後の位置から、2つ目のprintfによる表示が始まります。そのため、3つのメッセージが1行ずつ分かれて表示されます。

また、3つ目の文字列にも\nがあるため、表示後のカーソルは次の行へ移動します。実行後の画面を見やすくするためにも、最後の出力に改行を入れる習慣を付けておくとよいでしょう。

改行を指定しない場合の表示

printfは、呼び出すたびに自動で改行する関数ではありません。文字列の中に\nがなければ、次のprintfも現在の行の続きから表示します。

改行せずに3つのメッセージを表示するプログラム

ファイル名:5_1_2.c

#include <stdio.h>

int main(void)
{
    /* 改行を入れずに3つのメッセージを表示する */
    printf("入力する値を確認します。");
    printf("半角の整数を入力します。");
    printf("入力後にEnterを押します。");

    return 0;
}
実行結果の例
入力する値を確認します。半角の整数を入力します。入力後にEnterを押します。

3つのprintfを書いていますが、どの文字列にも\nがありません。そのため、表示位置が次の行へ移らず、すべてのメッセージが横につながります。

文章を続けて表示したい場合は、この動作を利用できます。一方、別々の案内として見せたい場合は、適切な位置に\nを入れる必要があります。

たとえば、次のように書けば、それぞれを別の行に表示できます。

printf("入力する値を確認します。\n");
printf("半角の整数を入力します。\n");
printf("入力後にEnterを押します。\n");

\nはエスケープシーケンス

\nは、エスケープシーケンスと呼ばれる特別な表記です。

ソースコード上ではバックスラッシュとnの2文字に見えますが、文字列の中では改行を表す1つの制御文字として扱われます。

よく使われるエスケープシーケンスには、次のものがあります。

書き方意味主な使い方
\n改行次の行へ移動する
\t水平タブ表示位置に一定の間隔を空ける
\\バックスラッシュ文字として\を表示する
\"ダブルクォーテーション文字列の中に"を表示する

たとえば、項目と数値の間にタブを入れる場合は次のように書けます。

printf("科目\t点数\n");
printf("国語\t85\n");
printf("数学\t92\n");

表示例は次のようになります。

科目    点数
国語    85
数学    92

タブによる間隔は実行環境によって見え方が異なることがあります。そのため、必ず表の列が完全にそろうとは限りませんが、簡単な項目の区切りには利用できます。

文字列の中にダブルクォーテーションを表示したい場合は、"を使います。

printf("画面に\"入力してください\"と表示します\n");

表示結果は次のとおりです。

画面に"入力してください"と表示します

通常のダブルクォーテーションは文字列の開始と終了に使われます。"と書くことで、文字列を終了させずにダブルクォーテーションそのものを表示できます。

図2:printfで文字列と値が表示される仕組み

この図から分かること

printfは、書式文字列を左から読みながら表示します。通常の文字はそのまま出力し、%dの位置には後ろから渡された整数を当てはめます。

\nに到達すると改行します。このように、書式文字列には表示する文章だけでなく、値を入れる位置や改行方法も記述できます。

変換指定を使って値を表示する

printfでは、変数に保存されている値も表示できます。そのとき、値の種類に対応する変換指定を使用します。

代表的な変換指定は次のとおりです。

変換指定主に対応するデータ表示例
%dint型の整数123
%fdouble型の浮動小数点数3.140000
%c1文字A
%s文字列Hello

printfで%fを使用する場合、float型の値も関数に渡されるときにdouble型へ変換されます。そのため、printfではfloat型とdouble型の表示に%fを使います。

入門段階では、まず次の対応を覚えておくとよいでしょう。

  • int型の整数には%d
  • 小数には%f
  • char型の1文字には%c
  • 文字列には%s

整数を文章の中に埋め込む

変数の値を表示する場合は、書式文字列の後ろに変数名を書きます。

学習時間と練習問題数を表示するプログラム

ファイル名:5_1_3.c

#include <stdio.h>

int main(void)
{
    /* 学習時間と練習問題数を用意する */
    int reading_minutes = 35;
    int exercise_count = 8;

    /* %dの位置に変数の値を表示する */
    printf("今日の読書時間は%d分です\n", reading_minutes);
    printf("練習問題は%d問解く予定です\n", exercise_count);

    return 0;
}
実行結果の例
今日の読書時間は35分です
練習問題は8問解く予定です

reading_minutesには35、exercise_countには8が保存されています。

次のprintfでは、%dとreading_minutesが対応しています。

printf("今日の読書時間は%d分です\n", reading_minutes);

そのため、%dの位置に35が表示されます。

2つ目のprintfでは、%dにexercise_countの値である8が入ります。

printf("練習問題は%d問解く予定です\n", exercise_count);

値をコードの文章に直接書き込むのではなく、変数を渡している点が重要です。変数の値が変われば、表示される数値も変わります。

複数の変換指定は左から順番に対応する

1つのprintfに複数の値を渡すこともできます。

int lesson_count = 4;
int exercise_count = 8;

printf("教材を%d項目読み、問題を%d問解きます\n",
       lesson_count, exercise_count);

変換指定と値は、左から順番に対応します。

書式文字列内の位置対応する値表示される数値
1つ目の%dlesson_count4
2つ目の%dexercise_count8

表示結果は次のようになります。

教材を4項目読み、問題を8問解きます

変数を渡す順番を逆にすると、表示される位置も入れ替わります。

printf("教材を%d項目読み、問題を%d問解きます\n",
       exercise_count, lesson_count);

この場合、表示結果は次のようになります。

教材を8項目読み、問題を4問解きます

コンパイルできたとしても、文章の意味は誤ったものになります。変換指定の並びと、後ろに渡す値の並びを確認しましょう。

変換指定の数をそろえよう

書式文字列の変換指定と、後ろに渡す値の数はそろえる必要があります。

次のコードは、%dが2つあるのに値が1つしかありません。

printf("%d項目と%d問を学習します\n", lesson_count);

2つ目の%dに対応する値がないため、正しい表示は保証されません。

反対に、%dが1つなのに値を2つ渡しても、2つ目の値は表示に使われません。

printf("%d項目を学習します\n", lesson_count, exercise_count);

基本となる対応は次のとおりです。

変換指定の数 = 表示する値の数

コンパイル時の警告を有効にすると、このような間違いを見つけやすくなります。警告が表示された場合は、そのままにせず、変換指定の種類や個数を確認しましょう。

データ型に合った変換指定を使おう

変換指定には、それぞれ対応するデータ型があります。

たとえば、int型の変数を%fで表示するのは正しい組み合わせではありません。

int score = 80;
printf("%f\n", score);

正しくは%dを使います。

int score = 80;
printf("%d\n", score);

同じように、double型には%fを使います。

double temperature = 24.5;
printf("%.1f\n", temperature);

%.1fは、小数点以下を1桁表示する指定です。表示結果は次のようになります。

24.5

代表的な対応を整理すると、次のようになります。

データ宣言例適した変換指定
整数int score = 80;%d
小数double rate = 2.5;%f
文字char grade = 'A';%c
文字列文字の並び%s

変換指定と実際のデータ型が合っていない場合、表示が乱れるだけでなく、プログラムの動作が正しく保証されないことがあります。

printfの引数を整理しよう

関数を呼び出すときに丸括弧の中へ渡す情報を、引数といいます。

次のprintfには、3つの引数があります。

printf("%d月%d日です\n", month, day);
順番引数役割
1つ目書式文字列文章と2つの%dを指定する
2つ目month1つ目の%dに表示する
3つ目day2つ目の%dに表示する

最初の引数で表示のひな型を指定し、2つ目以降の引数で変換指定に当てはめる値を渡します。

printfは、必要な値の個数が呼び出しごとに変わる関数です。このような仕組みにより、1つの値だけでなく、複数の値を組み合わせた表示もできます。

printfは処理結果を返す

printfは画面に情報を表示するだけでなく、処理の結果を呼び出し元へ返します。この値を返却値、または戻り値といいます。

printfが正常に動作した場合は、出力した文字数に相当する値を返します。出力に失敗した場合は、負の値を返します。

通常の入門用プログラムでは返却値を使わないことが多いため、次のように呼び出すだけで問題ありません。

printf("処理を開始します\n");

必要であれば、返却値をint型の変数に保存できます。

printfが返した出力数を確認するプログラム

ファイル名:5_1_4.c

#include <stdio.h>

int main(void)
{
    int output_count;

    /* printfの返却値を変数に保存する */
    output_count = printf("Hello\n");

    /* 返却値を表示する */
    printf("最初のprintfが返した値は%dです\n", output_count);

    return 0;
}
実行結果の例
Hello
最初のprintfが返した値は6です

最初のprintfが出力する内容は、次の6文字です。

  • H
  • e
  • l
  • l
  • o
  • 改行

そのため、この例ではprintfが6を返し、その値がoutput_countに保存されます。

output_count = printf("Hello\n");

続くprintfでは、output_countの値を%dで表示しています。

printf("最初のprintfが返した値は%dです\n", output_count);

日本語などのマルチバイト文字を含む場合は、実行環境の文字コードによって返却値の数え方が直感的な文字数と一致しないことがあります。返却値の仕組みを確認する練習では、今回のように半角英字を使うと分かりやすいでしょう。

キーボード入力の基本的な流れ

標準入力では、利用者がキーボードから入力した情報をプログラムが受け取ります。

整数の入力にはscanfなどを利用できますが、ここでは入力処理の細かな書き方よりも、画面表示とのつながりを整理しておきましょう。

入力を利用するプログラムは、一般に次のような流れで動きます。

  1. printfで入力してほしい内容を表示する
  2. 利用者がキーボードから値を入力する
  3. プログラムが入力された値を受け取る
  4. 受け取った値を変数に保存する
  5. 変数の値を計算や判定に利用する
  6. printfで処理結果を表示する

たとえば、利用者に年齢を入力してもらう場合、入力処理だけを置いても、何を入力すればよいのか分かりません。

そのため、先に案内メッセージを表示します。

printf("年齢を半角の整数で入力してください\n");

このようなメッセージをプロンプトと呼ぶことがあります。利用者が迷わないように、入力する内容、形式、順番などを具体的に伝えることが大切です。

入力と出力は組み合わせて使う

入力された値を受け取るだけでは、利用者には処理結果が分かりません。反対に、固定された内容を表示するだけでは、利用者の操作をプログラムへ反映できません。

標準入力と標準出力を組み合わせることで、次のようなやり取りが作れます。

プログラム:学習時間を分単位で入力してください
利用者  :45
プログラム:今日の学習時間は45分です

この流れでは、標準出力と標準入力が次の順番で使われています。

順番処理入出力の種類
1入力内容を案内する標準出力
2利用者が値を入力する標準入力
3入力された値を保存するプログラム内部の処理
4入力内容や結果を表示する標準出力

入力前の案内と入力後の結果表示があることで、利用者は次に何をすればよいのか、プログラムがどのように処理したのかを確認できます。

図3:入力案内から結果表示までの流れ

この図から分かること

入力を受け取るプログラムでは、最初にprintfで案内を表示すると、利用者が何を入力すればよいのか分かりやすくなります。

入力された値は変数に保存され、その後の計算や表示に利用されます。最後に結果を表示することで、入力が正しく処理されたことも確認できます。

画面表示で起こりやすい間違い

printfは基本的な関数ですが、書式文字列や引数の指定を間違えると、意図した結果になりません。

特に確認したいのは、次の点です。

  • 必要な位置に\nが入っているか
  • 変換指定と値の数が合っているか
  • 変換指定とデータ型が対応しているか
  • 引数の順番が正しいか
  • 文字列をダブルクォーテーションで囲んでいるか
  • 文末にセミコロンがあるか
  • stdio.hを取り込んでいるか

\nを付け忘れている

printf("処理を開始します");
printf("値を入力してください");

この場合、2つの文章は同じ行につながります。

処理を開始します値を入力してください

行を分けるなら、次のようにします。

printf("処理を開始します\n");
printf("値を入力してください\n");

変換指定と値の個数が合っていない

printf("%d個と%d円です\n", item_count);

%dが2つあるため、対応する整数も2つ必要です。

printf("%d個と%d円です\n", item_count, unit_price);

値を渡す順番が違っている

printf("個数は%d個、単価は%d円です\n",
       unit_price, item_count);

文法上はどちらもint型なので、型の不一致を知らせる警告が出ないことがあります。しかし、個数と単価が逆の位置に表示されます。

正しい順番は次のとおりです。

printf("個数は%d個、単価は%d円です\n",
       item_count, unit_price);

変数名が分かりやすければ、こうした順番の間違いにも気づきやすくなります。

データ型と変換指定が合っていない

double study_hours = 2.5;
printf("%d\n", study_hours);

double型の値を表示する場合は%fを使います。

double study_hours = 2.5;
printf("%.1f\n", study_hours);

型と変換指定の不一致は、単に表示が少し変わるだけの問題ではありません。正しい動作が保証されないため、必ず対応を確認しましょう。

日本語が文字化けするときの確認

日本語を含むプログラムを実行すると、文字が正しく表示されないことがあります。この場合、ソースコードのprintfが間違っているとは限りません。

文字化けには、主に次の設定が関係します。

  • ソースファイルの文字コード
  • ターミナルの文字コード
  • コンパイラが扱う文字コード
  • 使用しているフォント

WindowsのコマンドプロンプトをUTF-8へ切り替える場合は、必要に応じて次のコマンドを実行します。

chcp 65001

そのうえで、VS CodeのソースファイルもUTF-8で保存されているか確認します。

日本語が正しく表示されないときは、次の順番で確認するとよいでしょう。

  1. ソースファイルがUTF-8で保存されているか確認する
  2. コマンドプロンプトでchcp 65001を実行する
  3. もう一度プログラムを実行する
  4. 日本語を表示できるフォントが使われているか確認する

文字コードは実行環境に関係する設定です。英数字は正常で日本語だけが乱れる場合は、プログラムの処理よりも文字コードを確認してみましょう。

printfは動作確認にも役立つ

printfは、利用者に結果を見せるだけでなく、プログラムの動作を確認するためにも使えます。

たとえば、計算前と計算後の値を表示すれば、どの段階で想定と違う結果になったのか調べやすくなります。

printf("計算前の個数: %d\n", item_count);
printf("計算後の合計: %d\n", total_price);

プログラムの途中経過を表示して問題の場所を探す作業は、デバッグの基本的な方法のひとつです。

これから条件分岐や繰り返し処理を学ぶと、プログラムの動きは少しずつ複雑になります。そのときにもprintfで変数の値や処理の進み方を表示すると、コードの状態を確認しやすくなります。

まずは、次の操作を自然に書けるようになることを目標にしてみてください。

  • printfで文字列を表示する
  • \nで適切な位置に改行を入れる
  • %dでint型の整数を表示する
  • 変換指定と引数の順番をそろえる
  • 入力の前に分かりやすい案内を表示する
  • 入力後の結果を画面に表示する

この基本が身につけば、入力された値を計算に利用したり、条件によって異なるメッセージを表示したりするプログラムへ、無理なく進めるようになります。