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:
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.
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.
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.
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
.