Search code examples
c#inputconsoleend-of-line

Why does StringReader read '\uffff'?


I am writing a language of my own called SPL. It has an Input command which reads input from the ISplRuntime.Input property (it is a TextReader). All other commands run on this interface because this way I can write different apps with just one library!

I then wrote another console app to test my language. This is my implementation of ISplRuntime. Focus on the Input and constructor:

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];
    }
}

When the runtime is constructed, it asks for input. And use that input to create a StringReader and return it in the Input property. So every time the input will only be one lline.

Then I write a program in SPL that outputs the input. And that is where the problem is! When I input 1 1 1 1 it prints 1 1 1 and threw a FormatException. This is how I read number input:

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;
    }
}

The parameter runtime is just the runtime you have just seen. It returns true if it successfully reads a number. And that number is the output parameter i.

After using the "Watch" window in Visual Studio, I found out that number string is "1\uffff" when the exception is thrown. That's why it throws it! I know (think) that '\uffff' is the end of line character. But why would it appear in my input? I know (think) that pressing Ctrl + Z makes a end of line, but I did not! Then I checked runtime.Input in the watch window. This is the result:

enter image description here

I see that there is a field called _s and I think that is the string that I told it to read from. See? _s doesn't even contain '\uffff', how come it reads it?

P.S. I already know the solution. I just need to change the while loop a little and it works. But I want to know why does it reads an end of line.


Solution

  • There is no mistery here - \uffff is produced by your code. All you need is to read the documentation and understand what the methods that you call return.

    TextReader.Peek Method

    Return Value
    Type: System.Int32
    An integer representing the next character to be read, or -1 if no more characters are available or the reader does not support seeking.

    TextReader.Read Method

    Return Value
    Type: System.Int32
    The next character from the text reader, or -1 if no more characters are available.

    Hope you see the relation between -1 (0xffffffff) and \uffff.