J'écris moi-même un langage appelé SPL. Il a une commande d'entrée qui lit l'entrée de la propriété ISplRuntime.Input
(il s'agit d'un TextReader
). Toutes les autres commandes fonctionnent sur cette interface car je peux ainsi écrire différentes applications avec une seule bibliothèque! J'ai ensuite écrit une autre application de console pour tester ma langue. Ceci est ma mise en œuvre de ISplRuntime
. Focus sur le Input
et constructeur:Pourquoi StringReader lit-il ' uffff'?
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];
}
}
Lorsque le moteur d'exécution est construit, il demande d'entrée. Et utilisez cette entrée pour créer un StringReader
et le renvoyer dans la propriété Input
. Donc, chaque fois que l'entrée sera seulement une ligne.
Puis j'écris un programme en SPL qui produit l'entrée. Et c'est là que le problème est! Quand j'ai entré 1 1 1 1, il a imprimé 1 1 1 et a lancé FormatException
. Voici comment je l'ai lu la saisie du numéro:
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;
}
}
Le paramètre runtime
est juste le temps d'exécution que vous venez de voir. Il renvoie true s'il lit avec succès un nombre. Et ce nombre est le paramètre de sortie i
. Après avoir utilisé la fenêtre "Regarder" dans Visual Studio, j'ai découvert que la chaîne de nombre est "1\uffff"
lorsque l'exception est levée. Voilà pourquoi il le jette! Je sais (pense) que '\uffff'
est le caractère de fin de ligne. Mais pourquoi cela apparaîtrait-il dans ma contribution? Je sais (pense) que presser Ctrl + Z fait une fin de ligne, mais je ne l'ai pas fait! Puis j'ai vérifié dans la fenêtre de la montre. Ceci est le résultat:
Je vois qu'il ya un champ appelé _s
et je pense que la chaîne est que je l'ai dit à lire. Voir? _s
ne contient même pas '\uffff'
, comment se fait-il qu'il le lit?
post-scriptum Je connais déjà la solution. J'ai juste besoin de changer la boucle while
un peu et cela fonctionne. Mais je veux savoir pourquoi lit-il une fin de ligne.
_pos = 7, _length = 7. Vous n'avez pas à appuyer sur Ctrl + Z pour obtenir la condition de fin de fichier sur un StringReader, il ne dispose plus de caractères. –
@HansPassant Donc le dernier caractère lu est toujours ''\ uffff' '? – Sweeper
Si vous lisez un personnage et qu'il n'y en a plus, il n'y a pas de dernier caractère. Et vous aurez -1. –