Console入出力

コンソール画面の入出力

C#では「Console」というキーワードを用いて、コンソール画面への文字列を表示したり、ユーザーからのキー入力をプログラムに受け取ったりします。
(コンソール画面=背景が真っ黒で文字だけが表示されるアレ。標準入出力、コマンドプロンプト)
ここではコンソール入出力について簡単に説明します。

Console.WriteLine

Console.WriteLineは、今までのサンプルコードでも頻繁に使用している、コンソール画面に文字列を出力するメソッド(関数)です。
使い方は今まで説明してきた通り、出力したい値をそのまま引数に指定します。


static void Main(string[] args)
{
    int num = 5;
    bool bo = true;
    string str = "abcde";

    Console.WriteLine(num);
    Console.WriteLine(bo);
    Console.WriteLine(str);

    Console.ReadLine();
}
5
True
abcde

上記コードでは引数にint型、bool型、string型の変数をそれぞれ指定しています。

通常のメソッドは引数のデータ型は決められていて、それ以外のデータ型は受け付けてくれません。
しかしConsole.WriteLineメソッドはあらゆるデータ型をそのまま指定できます。
これはメソッドのオーバーロードという同じ名前のメソッドを複数定義できる機能を用いて実現しています。
(詳しくは上記ページで説明しています)

複合書式

Console.WriteLineメソッドは引数を複数同時に取ることができます。
この時、第一引数には複合書式という特殊な文字列を指定します。
これは第二引数以降の値をどのような形式で表示するかを決定するための文字列です。


static void Main(string[] args)
{
    int num1 = 5, num2 = 7;

    Console.WriteLine("変数num1は{0}、変数num2は{1}", num1, num2);

    Console.ReadLine();
}
変数num1は5、変数num2は7

このコードは、第一引数の文字列の特定の個所が、第二、第三引数の値に置き換えて表示されます。

複合書式中の{0}{1}インデックスコンポーネント(単にインデックスとも)やパラメーター指定子といいます。
{0}は第二引数の値に、{1}は第三引数の値にそれぞれ置き換えられて表示されます。
これはいくらでも増やすことができますし、回数や順序も自由です。


int num1 = 5, num2 = 7;
string str = "abc";

Console.WriteLine("{1}, {2}, {0}, {2}",
    num1, num2, str);
7, abc, 5, abc

ただし、存在しない引数の番号をインデックスに指定すると実行時エラーとなります。


//存在しない「第三引数」を表示しようとしている
//実行時エラー
Console.WriteLine("{1}", 5);

複合書式についてはstring.Formatメソッドの項で詳しく解説しています。

Console.Write

コンソールへの文字列の出力はConsole.Writeメソッドを使用することもできます。
WriteLineメソッドとの違いは、出力の最後に改行が入らないという点だけです。
場面に応じて使い分けると良いでしょう。


Console.WriteLine("改行される");

Console.Write("改行された");
Console.Write("改行されない");

Console.WriteLine(" ここで改行→");

Console.Write("↑改行された");
改行される
改行された改行されない ここで改行→
↑改行された

Console.ReadLine

文字の入力はConsole.ReadLineメソッドで行います。


static void Main(string[] args)
{
    Console.WriteLine("何か文字を入力してください。");

    string str = Console.ReadLine();
    Console.WriteLine("今入力した文字: {0}", str);

    Console.ReadLine();
}
何か文字を入力してください。
abcde
今入力した文字: abcde

実行結果の赤字の斜体の文字列はユーザーのキーボード入力を示しています。
実際のプログラムの実行結果では色や書体は変わりません。

上記の実行結果は、上記コードを実行後にキーボードから「abcde」「Enter」と入力したところです。

Console.ReadLineメソッドは引数がありません。
メソッドが実行された時点でプログラムは一時停止され、ユーザーからのキーボード入力を待ちます。
改行を一行と認識するので、エンターキーが押されると処理が続行されます。

戻り値は今キーボードから入力された文字列(string型)です。
string型なのでそのままstring型変数に代入できます。
キー入力の最後に改行がありますが、この改行は読み捨てられます。
(string型変数に代入しても最後に改行文字は入らない)

数字を入力しても「戻り値はstring型」であることに注意してください。
string型ですからそのまま四則計算等はできません。
string型をint型等に変換する方法はデータ型の相互変換を参照してください。

Console.Read

キーボード入力を受け取るメソッドはほかにもConsole.Readがあります。
これはConsole.WriteLineメソッドとConsole.Writeメソッドの関係とはやや異なります。
Console.Readメソッドは文字列ではなく一文字を読み取ります。

Console.Readメソッドの戻り値はint型の数値で、そのまま文字として使用することはできません。
この数値は文字コードというものです。
コンピュータは内部的に数値しか扱えませんから、文字も内部的には数値で管理されています。
例えば「a」は「97」、「b」は「98」...といった具合です。
これを文字として扱うにはchar型にキャストします。


int c = Console.Read();

Console.WriteLine(c);
Console.WriteLine((char)c);
a
97
a

上記の実行結果は「a」の一文字を入力した場合です。
「a」は内部的には97という数値で管理されています。

標準入出力ストリーム

コンソール画面に入出力されるデータは、標準入出力ストリームという場所に一時的に保存された状態になります。
キーボードなどからの入力は標準入力ストリーム、ディスプレイなどへの出力は標準出力ストリームと言い、それぞれ独立しています
ストリームとは「流れ」のことで、入出力されるデータを一連の「流れ」と見立てた概念です。

標準入力はキーボード、標準出力はディスプレイですが、これは固定というわけではなく入出力先を変更することも可能です。
本サイトでは特に断りがない場合は標準入力はキーボード、標準出力はディスプレイとして説明しています。

■キーボードからの入力ストリームのイメージ図
入力ストリームのイメージ図

ユーザーからのキーボード入力は一時的に入力ストリーム内に保存されます。
エンターキーが押下(改行)されることで入力の終わりの合図となり、ストリーム内のデータがプログラム側に渡されます。

この動作はConsole.ReadLineメソッドでもConsole.ReadLineメソッドでも同じです。
Console.ReadLineメソッドは最後の改行まですべて読み取るので、入力ストリーム内に文字は残りません。
しかしConsole.Readメソッドは一文字しか読み取りませんから、入力ストリーム内にデータが残る場合があります。

すると、以下のような現象が発生します。


static void Main(string[] args)
{
    int num1, num2;
    Console.WriteLine("何か文字を入力してください。");

    num1 = Console.Read();
    num2 = Console.Read();

    Console.WriteLine("{0}, {1}", num1, num2);

    Console.WriteLine("エンターキーで終了。");
    Console.ReadLine();
}
何か文字を入力してください。
abc
97, 98
エンターキーで終了。

Console.Readメソッドを二回実行しているのでキーボード入力待ちも二回発生するように思いますが、実際には最初のキーボード入力時に何か文字を入力してEnterキーを押下すると、その瞬間にプログラムは終了してしまいます。
上の実行結果では文字入力後の出力も表示していますが、プログラムの終了と同時にコンソール画面を閉じる設定にしている場合は、実行結果を確認する間もなく一瞬で画面が閉じてしまいます。

Console.Readメソッドは「入力ストリームから一文字読み取る」メソッドです。
入力ストリーム内にデータがない場合はユーザーからの入力待ちになりますが、すでにストリーム内にデータがある場合はキーボード入力待ちになることなくストリームから文字を読み取ります。

■キーボードからの入力ストリームのイメージ図
入力ストリームのイメージ図2

ユーザーが実際に何文字入力するかはわからないため、Readメソッドをうまく扱うにはループ文と組み合わせる必要があります。
(while文の項で再度説明します)
Readメソッドはこの処理が少し面倒なため、ReadLineメソッドのように気軽に使用できません。

キーボード入力が必要な場合はConsole.ReadLineメソッドを使用し、一文字が欲しいなら受け取った文字列をプログラム側で一文字ずつに分解したほうが多くの場合で簡単です。
例えばConsole.ReadLineメソッドで一文字を受け取る場合は以下のように書けます。


string s = Console.ReadLine();

if (s == "")
{
    Console.WriteLine("入力は空です");
}
else
{
    //先頭の一文字を取り出し
    Console.WriteLine(s[0]);
    char c = s[0];
}