ファイルの読み込みとwhile

ホームC#入門講座第2章:疑似サイコロ > ファイルの読み込みとwhile

ファイルの読み込みとwhile

while構文の特徴

まず始めに言いますが、繰り返し構文には3つあります。for構文・while構文・do-while構文です。

そして、これらの使い分けをする場合は、非常に限られており、whileを使って便利な場面はあまり多くありません。なぜなら、whileでforの代用をしようとすると、インクリメントを入れなくてはいけないからです。

(forの場合)

for(int i=1;i<11;i++)
	Console.WriteLine("{0}回目",i);

(whileの場合)

int i = 1;
while(i<11)
{
	Console.WriteLine("{0}回目",i);
	i++;
}

明らかにforの方がスマートです。

ですから、whileは「インクリメントをする必要がない場合」の繰り返しに用いるのが一般的です。そのもっとも身近な例が、ファイルの読み込みです。まず、ソースコードを示しましょう。

StreamReaderクラスのReadLine()メソッド

using System;
using System.IO;

namespace NewWorld
{
	class MainClass
	{
		public static void Main(string[] args)
		{	
			StreamReader sr = new StreamReader("/home/satoshi/test.txt");
			string line;
			while((line = sr.ReadLine()) != null)
				Console.WriteLine(line);
			sr.Close();

		}
	}
}

はっきり言いますが、このコードは現段階では少し難しいと思います。オブジェクト指向もnullも学んでないので、分からなくてもいいです。

StreamReaderというのは、ファイルを読み込む機械だと思ってください。そこから1行ずつ読み取って表示するというプログラムです。ファイルの指定が私のパソコンにあわせてLinux仕様になっています。

while((line = sr.ReadLine()) != null)
	Console.WriteLine(line);

今回理解してもらうのはここだけです。これを分解します。

sr.ReadLine()

「ConsoleクラスのReadLine()メソッド」は何度か登場しました。今回は「StreamReaderクラスのReadLine()メソッド」です。黒い画面から読み取るかファイルから読み取るかの違いですから、わざと同じ名前のメソッドなのです。

(line = sr.ReadLine())

ファイルから1行読み取って、string型のlineという変数に代入します。問題は「ファイルが終わったとき」です。ファイルが終了したら null という記号をReadLine()は送ってきます。つまり、ファイルが終わったときは null という記号が line に格納されることになります。(厳密には参照の概念から不適切ですが、ここではあえて「格納」という言葉を使用します。)

(line = sr.ReadLine()) != null

この「判別式」に登場する「!=」は「==」の逆で、「等しくない」ことを判別します。つまり、lineがnullでないときに、whileの内容が繰り返し実行されます。lineがnullになったら「line == null」なので、whileの中は実行されなくなります。

ReadLine()の最大の特徴は、「次の行を読み込む」ということです。1行目を読み取ったら自動的に次は2行目に移動する、という特殊な動きをします。このため、forで使ったようにわざわざ変数を増やしていく必要がないのです。このような機能をforで実行しようと思えば、まず行数を計算して、その行数分だけ繰り返すという処理になります。

「次を読み込む」という性質はwhileにとってとても好都合な性質です。whileが威力を発揮するのはこのような場合であり、多くの書籍やサイトでforの代わりに使っているのは本来の使い方ではないと私は思っています。ただし、それはプログラマの好みです。よりシンプルなwhileを好む人もいますから、一概に「間違っている」と言うことはできません。ただし、みなさんが使い分けるとしたら、このような「次」に注目して使い分けるようにしてください。

do-while構文

実を言うと、私はdo-while構文をどうしても使わなくてはいけない場面に遭遇したことが一度もありません。なので具体的な例が思いつきません。

do-whileの最大の特徴は、「判別式の評価に関わりなく、最低限1回は実行したい」という要望に答えることです。ですが、そのような要望が具体的なプログラムとして思い描けませんので、興味があれば自分で調べてみてください。

エスケープシーケンス

上のプログラムのファイルのパスをWindows用に変えようとしたら、エラーが起こるはずです。たとえ正確なパスを示し、かつそのパスにファイルがあったとしても。

それは、Windowsのファイル構造を示す「\」という文字はプログラミングでは特殊な意味を持っているからです。これはエスケープ文字と呼ばれ、後ろに1文字ついて特殊なエスケープシーケンスを表します。たとえば「\n」は「改行」であり、「\t」は「タブ」です。

\にはこのような記号があるため、「\」自体を表す場合は「\\」のように2個つなげて書く必要があります。そうすれば、うまく読み込んでくれるはずです。

なお、エスケープ文字を無視する機能も備わっています。文字列の前に「@」を付けて、「@"C:\Windows\test.txt"」と書くことで、すべてのエスケープ文字が円マークとして解釈されます。

ほかに様々なエスケープシーケンスがあるので、いろいろと調べてみてください。