[C言語のはじめ方] Part3: 標準入出力(printf, scanf)

C言語

プログラミングの世界へようこそ!🎉 C言語学習の第一歩として、今回はプログラムと「対話」するための基本中の基本、標準入出力について学びます。具体的には、コンピューターの画面に文字や数字を表示するprintf(プリントエフ)関数と、キーボードから文字や数字を入力してもらうscanf(スキャンエフ)関数です。

これらを使いこなせるようになると、ユーザーにメッセージを伝えたり、ユーザーからの指示を受け取ったりする、インタラクティブなプログラムを作れるようになります。難しく考えず、一緒に一歩ずつ進んでいきましょう!

準備: stdio.h のインクルード

printfscanf 関数を使うためには、プログラムの最初に「これらの関数を使いますよ」という宣言が必要です。これは #include <stdio.h> という1行をコードの先頭に書くことで行います。stdio は “Standard Input/Output”(標準入出力)の略です。これから書くコード例では、この一行が書かれているものとして進めますね。
#include <stdio.h> // これを書く!

int main(void) {
  // ここに printf や scanf を使ったコードを書く
  return 0;
}

画面に文字や数字を表示する `printf` 関数

まずは、コンピューターから私たち(ユーザー)へ情報を伝えるための関数、printf です。これを使うと、画面に好きな文字列や計算結果などを表示できます。

基本的な使い方: 文字列を表示する

一番簡単な使い方は、表示したい文字列をダブルクォーテーション(")で囲んで printf に渡すことです。

#include <stdio.h>

int main(void) {
  printf("こんにちは、C言語の世界へ!"); // ダブルクォーテーションで囲んだ文字が表示される
  return 0;
}

これをコンパイルして実行すると、画面に「こんにちは、C言語の世界へ!」と表示されます。簡単でしょう? 😊

変数の値を表示する – 書式指定子の登場

文字列だけでなく、プログラムの中で計算した結果や、変数に保存されている値を表示したい場合も多いですよね。そんな時は書式指定子(しょしきしていし)を使います。書式指定子は、printf に対して「ここに、こういう種類の値を入れて表示してね」と指示する特別な記号です。

よく使う書式指定子には、以下のようなものがあります。

  • %d : 整数(int型など、decimalのd)を表示
  • %f : 小数(float型やdouble型、floating point numberのf)を表示
  • %c : 1文字(char型、characterのc)を表示
  • %s : 文字列(char型の配列など、stringのs)を表示

使い方は、表示したい文字列の中に書式指定子を埋め込み、printf の後ろにカンマ(,)で区切って、表示したい変数や値を追加します。

#include <stdio.h>

int main(void) {
  int age = 20;
  float height = 175.5;
  char initial = 'T';
  char name[] = "山田太郎"; // 文字列は char の配列で表現することが多い

  printf("年齢: %d歳\n", age); // %d の場所に age の値(整数)が入る
  printf("身長: %f cm\n", height); // %f の場所に height の値(小数)が入る
  printf("イニシャル: %c\n", initial); // %c の場所に initial の値(1文字)が入る
  printf("名前: %s\n", name); // %s の場所に name の値(文字列)が入る

  printf("---- 複数の値を一度に表示 ----\n");
  printf("%sさんの年齢は%d歳、身長は%.1f cm、イニシャルは%cです。\n", name, age, height, initial);
  // %s, %d, %.1f, %c の順に対応する変数がカンマ区切りで指定されている
  // %.1f は小数点以下1桁まで表示する、という意味 (f の前に .桁数 をつける)

  return 0;
}

実行結果は以下のようになります。

年齢: 20歳
身長: 175.500000 cm
イニシャル: T
名前: 山田太郎
---- 複数の値を一度に表示 ----
山田太郎さんの年齢は20歳、身長は175.5 cm、イニシャルはTです。

%f はデフォルトだと小数点以下6桁まで表示します。コード例のように %.1f と書くと、小数点以下1桁までの表示に調整できます。

もっと便利に!特殊文字

文字列の中で特別な意味を持つ文字もあります。これを特殊文字(またはエスケープシーケンス)と呼びます。

  • \n : 改行します (New line)。これまでの例でも使っていましたね!
  • \t : タブ文字を挿入します。文字の開始位置を揃えたい時などに便利です。
  • \" : ダブルクォーテーション自体を表示したい場合に使います。
  • \\ : バックスラッシュ(円マーク)自体を表示したい場合に使います。
#include <stdio.h>

int main(void) {
  printf("一行目です。\n二行目です。\n"); // \n で改行
  printf("名前:\t山田太郎\n"); // \t でタブ挿入
  printf("年齢:\t20歳\n"); // タブで開始位置が揃う(場合がある)
  printf("彼は言った、「\"こんにちは!\"」と。\n"); // \" で " を表示
  printf("ファイルパス: C:\\Users\\Taro\n"); // \\ で \ を表示
  return 0;
}

実行結果:

一行目です。
二行目です。
名前:   山田太郎
年齢:   20歳
彼は言った、「"こんにちは!"」と。
ファイルパス: C:\Users\Taro

printf を使いこなせば、かなり柔軟な表示ができるようになりますね!👍

キーボードからの入力を受け取る `scanf` 関数

次に、ユーザーからの情報をプログラムに取り込むための関数、scanf です。これを使うと、キーボードから入力された数値や文字を変数に格納できます。

基本的な使い方: 変数に入力する

scanf の基本的な形は、printf と少し似ています。どの種類のデータを入力するかを示す書式指定子と、そのデータを格納する変数を指定します。

非常に重要な注意点があります。scanf で値を格納する変数を指定するときは、変数名の前に `&`(アンパサンド) を付ける必要があります(文字列を %s で読み取る場合など、一部例外はありますが、基本的には付けると覚えてください)。

#include <stdio.h>

int main(void) {
  int userAge; // 入力された年齢を格納する変数

  printf("あなたの年齢を入力してください: ");
  scanf("%d", &userAge); // %d で整数値を入力し、userAge 変数の場所(&userAge)に格納

  printf("あなたは %d 歳なのですね。\n", userAge);

  return 0;
}

このプログラムを実行すると、「あなたの年齢を入力してください: 」と表示された後、キーボードからの入力を待ちます。例えば 25 と入力して Enter キーを押すと、「あなたは 25 歳なのですね。」と表示されます。

なぜ `&` が必要? – アドレスの概念への導入

なぜ scanf では変数名の前に & が必要なのでしょうか?

printf は変数の「値」を使って表示するだけでした。しかし scanf は、入力された値をその変数に「書き込む」必要があります。そのためには、変数がコンピューターのメモリの「どこにあるか」という場所(アドレス)の情報が必要になります。

変数名の前に & を付けると、その変数の「値」ではなく、「アドレス」を意味します。つまり、scanf("%d", &userAge); は、「これからキーボードで入力される整数値を、userAge という変数が確保されているメモリ上の場所に書き込んでね」と指示しているのです。

この「アドレス」の概念は、C言語の非常に重要な特徴である「ポインタ」に繋がっていきますが、今は「scanf で変数に値を入れるときは & が必要」と覚えておけば大丈夫です!(文字列を %s で読み取る場合は、配列名自体がアドレスを示すため、通常 & は付けません。)

いろいろなデータ型を入力する

printf と同様に、scanf でも書式指定子を使って様々な型のデータを入力できます。

#include <stdio.h>

int main(void) {
  int number;
  float value;
  char grade;
  char firstName[50]; // 文字列を格納するための char 型配列 (十分なサイズを確保)

  printf("整数を入力してください: ");
  scanf("%d", &number);

  printf("小数を入力してください: ");
  scanf("%f", &value);

  // 注意: %c の直前の改行文字を読み込まないように、%c の前にスペースを入れることが多い
  printf("成績(1文字 A, B, Cなど)を入力してください: ");
  scanf(" %c", &grade); // %c の前に半角スペース

  printf("名前(姓のみ、半角英字)を入力してください: ");
  scanf("%s", firstName); // %s で文字列を入力する場合、& は通常不要

  printf("--- 入力結果 ---\n");
  printf("整数: %d\n", number);
  printf("小数: %f\n", value);
  printf("成績: %c\n", grade);
  printf("名前: %s\n", firstName);

  return 0;
}

このコードを実行し、例えば以下のように入力したとします。

整数を入力してください: 100
小数を入力してください: 3.14
成績(1文字 A, B, Cなど)を入力してください: A
名前(姓のみ、半角英字)を入力してください: Suzuki

すると、以下のような出力が得られます。

--- 入力結果 ---
整数: 100
小数: 3.140000
成績: A
名前: Suzuki

`%c` の前のスペースについて

上のコード例で scanf(" %c", &grade); のように、%c の前に半角スペースを入れている点に注目してください。これは、scanf("%f", &value); で小数を入力した際に最後に押した Enter キー(改行文字 `\n`)が入力バッファに残り、次の scanf(" %c", ...) がその改行文字を読み込んでしまうのを防ぐためのおまじないです。スペースを入れることで、scanf は改行文字などの空白文字を読み飛ばしてから、目的の文字(この場合は ‘A’)を読み取ってくれます。初心者がハマりやすいポイントの一つです!

`%s` の注意点

scanf("%s", firstName); で文字列を入力する場合、スペースや改行が見つかると、そこで入力の終わりとみなされます。そのため、「Taro Yamada」のようにスペースを含む名前を入力しようとしても、「Taro」までしか firstName に格納されません。

また、もっと重要な注意点として、用意した配列のサイズ(この例では firstName[50] で50文字分)を超える長さの文字列が入力されると、バッファオーバーフローという深刻な問題を引き起こす可能性があります。これはプログラムの誤動作やセキュリティ上の脆弱性につながります。安全なプログラムを作るためには、入力文字数を制限するなどの対策が必要ですが、まずは `%s` を使う際には、入力される文字列が配列サイズに収まるように注意しましょう。

複数の値を一度に入力する

scanf では、スペースや改行で区切ることで、一度に複数の値を入力することもできます。

#include <stdio.h>

int main(void) {
  int x, y;

  printf("2つの整数をスペース区切りで入力してください (例: 10 25): ");
  scanf("%d %d", &x, &y); // スペースで区切って書式指定子を並べる

  printf("入力された値: x = %d, y = %d\n", x, y);

  return 0;
}

実行して 10 25 と入力して Enter を押すと、「入力された値: x = 10, y = 25」と表示されます。

`scanf` を使う上での注意点 ⚠️

scanf は手軽に入力処理を行えますが、少し扱いに注意が必要な関数でもあります。

  • 書式指定子と変数の型を一致させる: %d で入力するなら int 型の変数、%f なら floatdouble 型の変数を & 付きで指定する必要があります。型が違うと、予期せぬ動作やエラーの原因になります。
  • 予期せぬ入力への対応: 例えば、%d で整数を入力してほしいところに、ユーザーが誤って文字(例: “abc”)を入力すると、scanf はうまく値を読み取れず、プログラムが意図通りに進まなくなることがあります。本格的なプログラムでは、このようなエラー入力に備える処理が必要になりますが、最初のうちは「正しい形式で入力する」ことを心がけましょう。
  • 入力バッファの問題: 先ほどの %c の前のスペースの話のように、キーボードから入力された文字は一旦「入力バッファ」という場所に溜められ、scanf がそこから読み取ります。このバッファに予期せぬ文字(特に改行文字 `\n`)が残っていると、次の scanf の動作に影響を与えることがあります。
  • `%s` の危険性: 前述の通り、%s はバッファオーバーフローの危険性があります。入力文字数を制限する機能を持つ、より安全な関数(例: fgets)を使うことが推奨される場合もありますが、まずは scanf("%s", ...); の基本的な使い方と危険性を理解しておきましょう。

これらの注意点は、プログラミングを進めていく中で徐々に理解が深まっていく部分です。現時点では、「scanf は便利だけど、少し気を付けて使う必要があるんだな」という意識を持っておけば十分です。

`printf` と `scanf` を使ってみよう!

では、printfscanf を組み合わせた簡単なプログラムを2つ作ってみましょう。

例1: 名前を入力して挨拶するプログラム

#include <stdio.h>

int main(void) {
  char name[50]; // 名前を格納する配列

  printf("あなたのお名前(半角英字)を入力してください: ");
  scanf("%s", name); // & は不要

  printf("こんにちは、%sさん! C言語の学習、頑張りましょう!💪\n", name);

  return 0;
}

これを実行し、例えば “Alice” と入力すると、

こんにちは、Aliceさん! C言語の学習、頑張りましょう!💪

と表示されます。

例2: 2つの整数を入力して合計を表示するプログラム

#include <stdio.h>

int main(void) {
  int num1, num2, sum;

  printf("1つ目の整数を入力してください: ");
  scanf("%d", &num1);

  printf("2つ目の整数を入力してください: ");
  scanf("%d", &num2);

  sum = num1 + num2; // 入力された2つの数を足し算

  printf("%d + %d = %d\n", num1, num2, sum); // 計算結果を表示

  return 0;
}

これを実行し、例えば 105 を順番に入力すると、

1つ目の整数を入力してください: 10
2つ目の整数を入力してください: 5
10 + 5 = 15

と表示されます。入力された値を使って計算し、その結果を表示する、というプログラムの基本的な流れができましたね!

まとめと次のステップへ

今回は、C言語で画面に情報を表示する printf 関数と、キーボードから情報を受け取る scanf 関数について学びました。

  • printf は、文字列や変数の値を画面に出力する関数です。書式指定子 (%d, %f, %c, %s など) や特殊文字 (\n, \t など) を使って、表示形式を整えることができます。
  • scanf は、キーボードからの入力を変数に格納する関数です。書式指定子を使って入力するデータの種類を指定し、値を格納する変数のアドレス (&変数名) を渡すのが基本です(%s など一部例外あり)。
  • scanf を使う際には、型の一致、予期せぬ入力、入力バッファ、%s でのバッファオーバーフローなどに注意が必要です。

標準入出力は、これからあなたが作る多くのプログラムで必要となる、非常に基本的な機能です。最初は少し戸惑うかもしれませんが、実際にコードを書いて動かしてみることで、だんだんと使い方に慣れていくはずです。

次回は、プログラムでデータを扱うための「入れ物」である変数と、その「種類」を表すデータ型int, float, char, double など)について、さらに詳しく学んでいきます。今回の printfscanf で使った知識が、さらに深まりますよ!お楽しみに!🚀

コメント

タイトルとURLをコピーしました