0

私は SPL という独自の言語を書いています。プロパティから入力を読み取る Input コマンドがありISplRuntime.Inputます (これは ですTextReader)。他のすべてのコマンドはこのインターフェイスで実行されます。これにより、1 つのライブラリだけでさまざまなアプリを作成できるようになります。

次に、自分の言語をテストする別のコンソール アプリを作成しました。これは私の実装ですISplRuntimeInputand コンストラクターに注目してください。

public class MyRuntime : ISplRuntime {
    protected TextReader reader;
    protected bool stopped;

    public object Current {
        get;
        set;
    }

    public virtual TextReader Input {
        get {
            return reader;
        }
    }

    public object[] Memory {
        get;
        protected set;
    }

    public TextWriter Output {
        get {
            return Console.Out;
        }
    }

    public bool Stopped {
        get {
            return stopped;
        }

        set {
            stopped = value;
            if (value) {
                Console.WriteLine ();
                Console.WriteLine ("Program has finished");
            }
        }
    }

    public void ShowErrorMessage (string error) {
        Console.WriteLine (error);
    }

    public MyRuntime () {
        string s = Console.ReadLine ();
        reader = new StringReader (s);
        stopped = false;
        Memory = new object[20];
    }
}

ランタイムが構築されると、入力が求められます。そして、その入力を使用して を作成し、StringReaderそれをプロパティで返しInputます。したがって、入力は常に1行のみになります。

次に、入力を出力する SPL でプログラムを作成します。そして、そこが問題です!1 1 1 1 と入力すると、 1 1 1 が出力され、 a がスローされましたFormatException。これは私が数値入力を読む方法です:

private bool ReadFromInput (ISplRuntime runtime, out int i) {
    char stuffRead = (char)runtime.Input.Peek ();
    if (stuffRead == ' ') {
        i = 0;
        runtime.Input.Read ();
        return true;
    }

    if (char.IsNumber (stuffRead)) {
        string numberString = "";
        while (char.IsNumber (stuffRead)) {
            stuffRead = (char)runtime.Input.Read ();
            numberString += stuffRead;
        }

        i = Convert.ToInt32 (numberString); //This is where the exception occured! (Obviously, because there is no other methods that would throw it)
        return true;
    } else {
        i = 0;
        return false;
    }
}

パラメータruntimeは、先ほど見たランタイムです。数値の読み取りに成功した場合は true を返します。そして、その数値が出力パラメータiです。

"1\uffff"Visual Studio の [ウォッチ] ウィンドウを使用した後、例外がスローされたときに数値文字列であることがわかりました。だからこそ投げる!'\uffff'私はそれが行末文字であることを知っています(と思います) 。しかし、なぜそれが私の入力に現れるのでしょうか? Ctrl + Z を押すと行末になることは知っていますが (そう思います)、そうではありませんでした! 次にruntime.Input、ウォッチウィンドウで確認しました。結果は次のとおりです。

ここに画像の説明を入力

と呼ばれるフィールドがあることがわかり_sます。それは、読み取るように指示した文字列だと思います。見る?_sも含まれていませんが'\uffff'、なぜそれを読み取るのですか?

PS私はすでに解決策を知っています。whileループを少し変更するだけで機能します。しかし、なぜ行末を読むのか知りたいです。

4

1 に答える 1

4

ここにミステリーはありません -\uffffあなたのコードによって生成されます。必要なのは、ドキュメントを読み、呼び出したメソッドが何を返すかを理解することだけです。

TextReader.Peek メソッド

戻り値
の 型: System.Int32
次に読み取られる文字を表す整数。使用できる文字がない場合、またはリーダーがシークをサポートしていない場合は-1 。

TextReader.Read メソッド

戻り値
の 型: System.Int32
テキスト リーダーからの次の文字。使用できる文字がない場合は-1 。

-1( 0xffffffff) との関係がわかると思います\uffff

于 2015-11-22T01:26:34.533 に答える