第2章09 ユーザからの入力を受け付ける@イチからゲーム作りで覚えるC言語

C言語で入力を受け付け

イチからゲーム作りで覚えるC言語
連載ページ一覧へ
2章10 論理演算(BOOL演算)
NEXT : 2章10 論理演算(BOOL演算)
2章08 プログラムにコメントを書く : PREV

この記事でやること

前回はプロジェクト「0060_comment」を新しく作り、コメントをソースコードに書き込む方法をお話をしました。
今回は、新しくプロジェクト「0070_inputkey」を作り、ユーザからの入力を受け付ける方法をお話します。入力の方法はたくさんありますので、基本的なものからお話します。

この記事はゆる~くC言語でコンソールゲームを作りながらプログラミングを学ぶための連載記事です。シリーズものですので記事の一覧はこちらを参照してくださいね。

プレイヤーからの文字入力を受け付けるプログラム

ではではプレイヤーからの文字入力を取り扱うサンプルプログラムを作成してみましょう。
プロジェクト「0070_intputkey」を新しく用意し、プロジェクトに空の「Scanf_s.c」を追加し、下のソースコードをコピペして動かしてみましょう。

#include <stdio.h>
int main(void) {
 char playerName[12];
 printf("プレイヤーの名前を入力してください。\n");
 printf("半角で 11 文字、全角で 5 文字までです。\n");
 printf("プレイヤーの名前 : ");

 // キーボードからの入力を求める
 scanf_s("%s", playerName, 12);

 // プレイヤーのステータスを表示
 printf("+------[ステータス]------+\n");
 printf("|%10s : %-11s|\n", "名前", playerName);
 printf("+------------------------+\n");
}

コピペなりして、実行してみて下さい。

プレイヤーの名前を入力してください。
半角で 11 文字、全角で 5 文字までです。
プレイヤーの名前 :

こんな結果になり、標準入力(Standard Input)からの文字列の入力を待つ状態になります。

標準入力とは通常はキーボードのことです。ついでに、標準出力(Standard Output)とは通常はコンソール画面のことです。文字がコンソール上に表示されるとき、標準出力されています。この用語はC言語に限らず使われています。

では、この状態でなにかキーボードで入力してみましょう。
「プレイヤーの名前 : 」の右側にキーボードから入力した文字がそのまま表示されると思います。文字を入れてエンターキーで完了します。
ためしに、「ぷらんく」と入れると、以下のようにプログラムの続きが実行されます。

プレイヤーの名前を入力してください。
半角で 11 文字、全角で 5 文字までです。
プレイヤーの名前 : ぷらんく
+------[ステータス]------+
|      名前 : ぷらんく   |
+------------------------+

ステータスの欄にちゃんと「ぷらんく」が表示されています!
ではでは、一行づつ見ていってみましょう!

char型で文字列の領域の確保

3行目では char型で playerName という配列の変数を宣言しています。
※配列については少し前のページ(コチラ)でお話してます。

char playerName[12];

playerName には配列として 12 個の char 型の変数を確保しているので、12文字(12バイト)を格納できます。ただし、文字列は最後に NULL終端文字(’\0’)が必要ですので、実際に使える文字は半角で 11 文字(11バイト)です。

日本語は 1 文字で 2 バイトとられるものがほとんどなので、11 ÷ 2 = 5 余り 1 ということで日本語は5文字までということを書いています。

プログラム内の”全角で5文字まで”は日本語版Windows のコマンドプロンプトを使用してのデフォルト設定を前提にしています。
前のページでchar型を扱うとき、ASCIIコード表をつかっての1文字と数値の変換と、日本語は1バイトに収まらないものが多いという話をしたかと思います。
こういった数値と文字の変換ルールは「文字コード」というもので定義されています。
OSが日本語版Windows なら、コマンドプロンプトは通常 Shift-JIS と呼ばれる文字コードの一種である「Windows31j」が使われています。
Window31j は別名 CP932、MS932とか呼ばれることがあります。
Shift-JISでは日本語は半角カタカナなどの一部は1バイト、通常は2バイトが1文字あたりに必要となります。

キーボードからの入力文字列を文字列変数に代入

9行目で、プレイヤーからのキーボード入力を受け付けて変数に代入する、新しい関数 scanf_s が登場しています。

scanf_s("%s", playerName, 12);

scanf_s 関数をこのように書くと、文字列変数 playerName にキーボード(標準入力)から入力した文字列を代入することができます
scanf_s( 書式指定文字列  , 文字列変数, 入力を受け付ける文字列の最大バイト数 );
今回は関数の第3引数に12を指定しているので、 12 バイトまでの入力を受け付けます。

ここで注意ですが、キーボードからコンソール画面に文字を入力してエンターキーを押したとき、最後に’\0’(NULL終端文字)を含めた状態で文字列がコンソールから scanf_s 関数に送られます

scanf_s 関数でコンソールから文字列が送られてきたとき、1文字1文字を playnerName にコピーしていきますが、その時 ‘\0’ があったらコンソールから送られた文字列の最後と判断しています。ですので、入力できる文字列は 11バイト + ‘\0′(NULL終端文字列)となりますので、11文字までが実際の入力できる文字数です。

scanf_s の書式指定文字列は、printf と似ていて、%s や %d などの変換指定子を指定できます。printf では文字を出力するために整数などのデータから文字への変換をしていましたが、scanf_s では変数に代入するためにコンソールからの文字列をデータ(文字列や整数)に変換する機能を持ちます。

scanf_s 関数でよく使う変換指定子

scanf_s 関数では文字列以外にも、整数や小数を書いた文字列を、データ(int型や double 型)に変換する機能があります。よく使うこういった入力のための変換指定子ものを例をつけてまとめておきます。

よく使われる入力変換指定子と使い方の例
処理記号
文字列を入力%schar message[200];
scanf_s(“%s“, message, 200);
※文字列を入れるときだけ、3つ目の引数で入力できる文字数の上限を指定します。この場合は 200 文字を指定しています。
整数を入力%dint answer;
scanf_s(“%d“, &answer);
※変数名の頭に「&」記号を付ける必要があります。
long型に整数を入力%ldint answer;
scanf_s(“%ld“, &answer);
float型に小数を入力%ffloat taion;
scanf_s(“%f“, &taion);
double型に小数を入力%lfdouble kyori;
scanf_s(“%lf“, &kyori);

scanf_s 関数でちゃんと変数に入力できたかの確認

ゲームプレイヤーはいろいろな文字をキーボード入力できちゃいますので、ちゃんとこちらが想定した入力がされたのかをチェックする必要があります。このチェックをちゃんとしないと、バグの元になったりします。

想定外の回答の入力

想定外の回答の入力

例えばチェックする内容としては・・

文字列の入力の場合のチェック

  • 文字数はあってる?文字が少なすぎてないか、多すぎてないか
  • 入力された各文字はOKなものか。例えばおかしな記号が入力されてないか。
  • 日本語などのワイド文字はいれられてもOKか。
  • 大文字、小文字などの制限はなくてOKか。

数字の入力の場合のチェック

  • 数値の範囲はOKか。
  • 数値でない文字(英文字や記号、空白)などが入っていないか。

全般的なチェック

  • そもそもちゃんと入力がされたか。

などがいろいろなチェックがありそうですね。
このページでは、最後の「そもそもちゃんと入力がされたか。」について補足としてお話しようと思います。

scanf_s関数で「ちゃんと入力された文字列の数」を取得

例えば、今回のソースコードで名前の入力を求められたとき、「123456789012」と入力したとします。全部で12文字を入力してますね。でも scanf_s 関数で 11 文字までしか入らないよう制限をかけています。この時どうなるでしょうか?

プレイヤーの名前を入力してください。
半角で 11 文字、全角で 5 文字までです。
プレイヤーの名前 : 123456789012
+------[ステータス]------+
|      名前 :        |
+------------------------+

名前の欄になにも表示されていませんね。
指定した文字を超えた場合は、変数には空文字が代入されます。
空文字は ‘\0’ だけが入っている文字列で、“”とも書けます。

それと、下のように書くと、scanf_s 関数で何個の文字列を読み取ることができたかの結果を数字で取得できます。

int kazu;
char nyuuryoku[10];
kazu = scanf_s("%s", nyuuryoku , 10 );

このサンプルでは、 (ちゃんと)9 文字以内で入力したとき、結果として1つの文字列を変数 nyuuryoku に代入できたため、変数 kazu に結果の 1 が入ります。
そして、10文字以上を入力したときは、ちゃんと変数に入力できなかったので、kazu に結果の 0 が入ります。
ちょっと唐突に式がでてきましたが、右辺の scanf 関数の結果が整数 1 となり、変数 kazu に代入されています。

変数 = 関数(引数);

このような書き方で、変数に 右辺の関数の戻り値 の結果を代入することができます。関数がだす結果を「関数の戻り値」と呼びます。「戻り値」は「もどりち」と読みます。「かえりち」とは読まないので要注意です。

関数について、あらかじめ用意された printf や scanf_s などを使ったり、自分で新しい関数を作ったりもできます。
関数についての詳しい話はまた別のページでお話しようと思いますので、ここでは関数の戻り値を変数に入れることができる、とだけ理解してもらえればと思います。

同じように、数字を入力させたいのに文字が入れられてしまった場合でも同じように、「ちゃんと数字が入ったのか」のか、結果を見ることができます。

int kazu;
int nyuuryoku;
kazu = scanf_s("%d", &nyuuryoku );

たとえば、このサンプルで数字「123」といれると、変数 nyuuryoku に整数 123 が代入され、無事に1つ変数に代入ができたので scanf_s 関数の戻り値は 1 となり、変数 kazu に 1 が入ります。

でも数字ではなく、ここでイジワルな人が「あいうえお」なんて入れると、整数ではないので、ちゃんと変数 nyuuryoku に代入できず、 scanf_s 関数の戻り値は 0 となります。

scanf_s 関数の戻り値の使い方は?

変数に代入したいのに、戻り値が 0 だったら、ちゃんと思った通りに入力されていないので、もう一度 scanf_s 関数を呼び出して、入力がうまくいくまで繰り返し入力を求める、なんていう処理にすることができます。
そういった繰り返しの処理などや、”もし戻り値が 0 だったら” という if の処理は、後のページでまたお話しますね。

scanf_s 関数で 2個 の変数への代入をする方法

scanf_s 関数では同時に複数個の変数への代入をすることができます。
例えば、2個の文字列と 1 個の整数を入力するにはこのように書きます。

int kazu;
char name[20];
char sukina_tabemono[21];
int  tairyoku;
kazu = scanf_s("%s %s %d", name, 20, sukina_tabemono , 21 ,&amp;tairyoku);

scanf_s の一つ目の引数に “%s %s %d” と書いてありますね。
これで、「文字列1 文字列2 整数」と入力することで一度に三つの入力を変数に代入することができます。文字列と文字列の間にスペースやタブがあると、区切りと見なされます。
例えば上のサンプルで「ぷらんく□白きのこ□□1」(□は半角スペース) と入力すると、変数はそれぞれ下のように代入されます。

  • 変数 name に文字列「ぷらんく」
  • 変数 sukina_tabemono に文字列「白きのこ」
  • 変数 tairyoku に整数 1

そして、3 つの変数が無事に入力されたので、scanf_s 関数の結果として 3 が得られます。
変数 kazu には 3 が代入されることになります。

昔ながらの scanf 関数

このページではキーボード(標準入力)からの入力を受け付けるために scanf_s 関数という関数を使いました。
でも、昔は scanf 関数という関数をよく使っていました。
昔のソースコードなどを参考にするときに目にするかと思いますので、参考として別のページでお話しておきたいと思います。

あとがき

今回はここまで。おつかれさまでした。

イチからゲーム作りで覚えるC言語
連載ページ一覧へ
2章10 論理演算(BOOL演算)
NEXT : 2章10 論理演算(BOOL演算)
2章08 プログラムにコメントを書く : PREV

非常に参考になったサイトさまや、参考文献など

ページの更新履歴

更新日更新内容
更新なし