[.NET] 競技プログラミングで解いたプログラムをローカル環境でテストしたい時に便利な裏ワザ

こんにちは、ニアです。

今回は競技プログラミングやオンラインハッカソンの問題で、解いたプログラムが正しく動作するかどうかを、Visual Studioなどのローカル環境でテストする時に、便利な裏ワザを紹介していきます。

#1. 解いたプログラムをローカル環境でテストする時の課題点
解いたプログラムを実行する時、競技プログラミングやオンラインハッカソンなどのオンライン実行環境では、標準入力にデータがあらかじめ入力されており、そこから読み込むことになります。

しかし、ローカル環境でテストするとなると、

* 入力データをキーボードから一々入力するのが面倒くさい
* うっかり入力ミスをして例外がスローされた
* 入力データと出力データが混ざってコンソール画面がカオスになった

なんてことを経験したことがありませんか？　因みに上の2つは私も経験したことがあります。

![18-1.PNG](https://qiita-image-store.s3.amazonaws.com/0/78881/f8c8c1b1-7a16-7d5c-a8c5-44fe5a4526ae.png)

そこで、標準入力をキーボードの代わりにテキストファイルに設定し、ローカル環境でもオンライン実行環境の標準入力と同じ様に利用できるようにしていきます。

#2. ローカル環境でも、オンライン実行環境の標準入力と同じ様に利用できるようにする

##Step 1. 入力データを入れるテキストファイルを作成
まずは入力データを入れるためのテキストファイルを、実行ファイルと同じ場所に作成します。
例えばVisual Studio上でデバッグ実行する時は、そのテキストファイルを「[プロジェクトのフォルダー]\\bin\\Debug」の中に（但し、C++/CLIの場合は[プロジェクトのフォルダー]の直下に）配置します。

```text:stdin.txt
※入力データをここに入力します。
```

##Step 2. 標準入力のストリームをキーボードからテキストファイルに変更

**[StreamReader](https://msdn.microsoft.com/ja-jp/library/system.io.streamreader.aspx)**クラスで、先ほど作成したテキストファイルを開きます。

```csharp:テキストファイルを開く（C#）
var exStdIn = new System.IO.StreamReader( "stdin.txt" );
```

**[Console.SetIn( TextReader )](https://msdn.microsoft.com/ja-jp/library/system.console.setin.aspx)**メソッドで、そのStreamRederオブジェクトを指定します（※StreamRederクラスはTextReaderクラスを継承しています）。

```csharp:標準入力をテキストファイルに設定（C#）
System.Console.SetIn( exStdIn );
```

こうすることで、標準入力をキーボードからテキストファイルに設定することができます。例えばConsole.ReadLineメソッドで、テキストファイルから1行分の文字列を読み込むことができます。

#3. **C#**、**VB.NET**、**F#**、**C++/CLI**で、標準入力をキーボードからテキストファイルに設定するコード一覧

##**C#**

```csharp:標準入力をキーボードからテキストファイルに設定するコード（C#）
var exStdIn = new System.IO.StreamReader( "stdin.txt" );
System.Console.SetIn( exStdIn );
```

##**VB.NET**

```vbnet:標準入力をキーボードからテキストファイルに設定するコード（VB.NET）
Dim exStdIn = New System.IO.StreamReader( "stdin.txt" )
System.Console.SetIn( exStdIn )
```

##**F#**

```fsharp:標準入力をキーボードからテキストファイルに設定するコード（F#）
let exStdIn = new System.IO.StreamReader( "stdin.txt" )
System.Console.SetIn( exStdIn )
```

##**C++/CLI**

```cpp:標準入力をキーボードからテキストファイルに設定するコード（C++/CLI）
auto exStdIn = gcnew System::IO::StreamReader( L"stdin.txt" );
System::Console::SetIn( exStdIn );
```
※C++/CLIの場合、C言語の標準入力関数（scanf関数）やC++の入力ストリーム（cinオブジェクト）には影響しません。

#4. 使い方

「標準入力をキーボードからテキストファイルに設定するコード」をMain関数の最初に（但し、F#でエントリーポイントがない場合はファイルの先頭に）貼り付けます。

あとはいつも通りにプログラムを作成するだけです。


```csharp:Program.cs（オンライン環境用）
using System;

class Program {
	static void Main( string[] args ) {
		int a = int.Parse( Console.ReadLine() ),
		    b = int.Parse( Console.ReadLine() );

		Console.WriteLine( a + b );
	}
}
```

```csharp:Program.cs（ローカル環境用）
using System;

class Program {
	static void Main( string[] args ) {
		// 以下の2文が加わるだけです！
		var exStdIn = new System.IO.StreamReader( "stdin.txt" );
		System.Console.SetIn( exStdIn );

		int a = int.Parse( Console.ReadLine() ),
		    b = int.Parse( Console.ReadLine() );

		Console.WriteLine( a + b );
	}
}
```

```text:入力（ローカル環境では「stdin.txt」）
10
20
```

```text:出力
30
```

これで、競技プログラミングで解いたプログラムのデバッグが捗りますね！

##◆ Attention !

プログラムを提出する時は、**今回紹介した「標準入力をキーボードからテキストファイルに設定するコード」を消す or コメントアウトする**のを忘れずにね！（うっかり忘れると、ランタイムエラーで0点という悲惨な採点結果になってしまいます）
![18-2.PNG](https://qiita-image-store.s3.amazonaws.com/0/78881/8941557e-944b-24c7-0235-155c5c6b0c92.png)
※画像は[paizaオンラインハッカソン・Lite](https://paiza.jp/poh/kirishima)の採点結果より

提出前に動作を確認する機能がある場合、1回チェックしてみることを強く推奨します。もし、ランタイムエラー出て原因が例外「System.IO.FileNotFoundException」の場合、そのコードを削除 or コメントアウトし忘れている可能性があります。
![18-3.PNG](https://qiita-image-store.s3.amazonaws.com/0/78881/1381dfeb-28e6-0225-1eed-0280c13cd90f.png)
※画像はpaizaオンラインハッカソンのコード実行結果より

それでは、See you next!