おはようございます、Reveの技術担当です。
久しぶりに記事を投稿します。
いやー、投稿するネタが見つからなかったもので
最近、CodeIQでプログラミングの問題を解くことがあるのですが、その際にちょっと(というよりだいぶ)悩んだことがあり、それを記事にしようかと。
(標準入力について)
プログラミングの経験者であればご存知かとは思いますが、標準入力とは簡単に言うとキーボード入力を指し、プログラム上で読み込み要求(メソッドなど)を実行することで入力されたデータを取得できます。
C#でも当然、標準入力を受け取るメソッドがありまして、Console.Read()やConsole.ReadLine()が該当します。通常は、改行文字の前までをひとつの文字列(string)として読み取るReadLineメソッドが使われ、改行キー(Windowsの場合はEnter)を押すことでキーボード入力を取得できます。
また、ReadLineでは改行文字を自動的に省いて処理を行ってくれます。
(ReadLineメソッドの弱点)
ですが、このReadLineメソッドにも仕様上の注意があり、それは実行すると改行が入力されるまでは処理を一時停止することです。つまり、改行が入力されないとプログラムは停止したままなのです。
冒頭のCodeIQで悩んだこともこれに関連しており、データの数があらかじめ把握できない状態で、どのように標準入力から抜け出すかでかなり時間を費やしました汗
入力が複数回あったので、whileループなどで繰り返し実行しなければすべてのデータを読み取れませんが、どこで終わるか分からないため、入力が全て終わった後もReadLineメソッドを実行してプログラムが停止したままになります。
1 2 3 |
//1行分(改行まで)の標準入力を読み取る string s = Console.ReadLine(); //改行が入力されないと、ここで停止したまま!! //(後の処理ができなくなる) |
こちらで仕様を決められるのであれば、特定の文字列を読み込むとループを抜け出すといった条件分岐も可能ですが、自動入力で必要最低限のデータしか入力されないため、この手法も不可能です。
つまり、自動入力でデータの数(入力回数)が分からない場合、ReadLineメソッドではデータを読み込んで処理することができません(一応、マルチスレッドで制限時間ありの処理を行う方法もあります…CodeIQではエラーになりますが)。
(標準入力ストリームから直接読み込む)
そこで、タイトルのように標準入力を一度に読み取る方法がないかと調べたところ、ありましたw
Console.In.ReadToEndメソッドがまさしく求めたとおりのメソッドで、これを実行すればまだ読み込まれていない(バッファに残った)入力データを全て読み取れます。
使い方は簡単で、文字列変数に代入する形で実行すれば、標準入力データがひとつの文字列として返されます。
1 |
string s = Console.In.ReadToEnd(); |
ひとつ注意点としては、改行文字も含めて全て読み込むのでReadLineの時と同じ処理が使用できない場合があります。
たとえば、CSV形式のデータを読み取る際に、stringクラスのSplitメソッド(特定の文字で区切る)を利用するだけでは、データの読み込みでエラーが発生します(数値への変換時に、改行文字がついた部分はエラーになる)。
そのため、改行文字の処理も自分で記述する必要があります。
もうご存知の方も多いかと思いますが、もしお役に立てば幸いです。
では(・ω・)/
ちなみに、これだけで2~3時間悩んだ当方はヘボプログラマー、略してヘボグラマーです汗
もっとコードが書けるようになりたいorz
コメント