2009-03-21 16 views
2

Ich versuche, eine ganze Zahlenzeile aus einer Textdatei zu erhalten und sie in separate Variablen zu zerlegen. Die Textdatei ist wie folgt aufgebaut:Integer aus einer Textdatei lesen und analysieren

ID: HP: MP: STR: WIS: SPD: GOLD: XP

0: 100: 50: 10: 5: 12: 5: 10

Ich möchte sie mit dem: -Symbol dazwischen teilen. Eines der Probleme, die ich dabei habe, ist, die Datei Zeile für Zeile als Zeichenfolgen lesen zu können, sie zu analysieren und dann die analysierten Zeichenfolgen als Eingaben zu speichern. Hier ist der Code, den ich versuche, so weit zu verwenden:

class monster 
{ 
    string line; 
    string[] mstats; 
    string[] mname; 
    char[] delimeterChars = {':'}; 
    int id; 
    int i = -1; 
    int j = 0; 
    int hp; 
    int mp; 
    int str; 
    int wis; 
    int spd; 
    int gold; 
    int xp; 

    public monster(int id) 
    { 
     StreamReader stats = new StreamReader("monsterStats.txt"); 
     while(i != id) 
     { 
      i++; 
      line = stats.ReadLine(); 
      mstats = line.Split(delimeterChars); 
      j = 0; 
      foreach(string s in mstats) 
      { 
       if (j == 0) id = int.Parse(s); 
       else if (j == 1) hp = int.Parse(s); 
       else if (j == 2) mp = int.Parse(s); 
       else if (j == 3) str = int.Parse(s); 
       else if (j == 4) wis = int.Parse(s); 
       else if (j == 5) spd = int.Parse(s); 
       else if (j == 6) gold = int.Parse(s); 
       else if (j == 7) xp = int.Parse(s); 
       j++; 
      } 
     } 
     curHp = hp; 
     curMp = mp; 
     curSpd = spd; 
     curStr = str; 
     curWis = wis; 
    } 
} 

ich folgende Fehlermeldung erhalten, wenn dieser Code ausgeführt wird:

Eingabezeichenfolge war nicht in einem korrekten Format. Es verweist auf diesen Teil des Codes:

if (j == 0) id = int.Parse(s); 
+0

Wow, ich erkennen, dass das "Schlüssel" I am oberen Ende der Textdatei mit der ID hatte: HP: MP ... lol alles wurde, durcheinander. Völlig vergessen, dass es da oben war. Danke für alle Ratschläge zum Aufräumen des Codes! Erstanwender hier, ich werde sicher wiederkommen, wenn ich noch mehr Fragen habe! –

+1

Oh man, ich überlegte, ob ich fragen sollte, ob diese Kopfzeile in der Datei war, aber dachte: "Naaah ... kann das nicht sein!" :) –

Antwort

3

Warum die foreach? Wie wäre es mit:

id = int.Parse(mstats[0]); 
hp = int.Parse(mstats[1]); 

und so weiter. Prüfen Sie vorher, dass mstats lang genug ist.

Ein bisschen Linq würde Sie ein Array von ganzen Zahlen in einem Schuss bekommen:

int[] fields = line.Split(delimeterChars).Select(s => int.Parse(s)).ToArray(); 

id = field[0]; 
hp = field[2]; 

Wie für den Code immer arbeitet, versuchen, die Textzeile auszudrucken, und jedes Stück Text, bevor Sie gerade Übergeben Sie es an Parse. Wenn es keine ganze Zahl ist, ist das dein Problem.

+0

+1 für die Einfachheit.Beachten Sie, dass dies wie erwartet eine Ausnahme auslöst, wenn die Spalte einen nicht ganzzahligen Wert enthält. –

+0

+1 für 'String.split'. Dieser Eingabe ist es weit überlegen, einen regulären Ausdruck zu verwenden. Auch für das Vorschlagen, den Text auszudrucken, um zu sehen, was falsch ist. Offensichtlich, aber wichtig. – Brian

3

Nun, die erste Sache ist, herauszufinden, was die schlechte Eingabe war.

Wenn Sie erwarten schlechte Eingabedaten, verwenden Sie int.TryParse statt nur int.Parse. Wenn Sie nicht schlechte Eingabedaten erwarten, ist die Tatsache, dass es eine Ausnahme wirft, wahrscheinlich angemessen - aber Sie sollten Ihre Daten untersuchen, um herauszufinden, was falsch ist.

Ich würde auch empfehlen, die Parsing-Aufruf einmal anstatt in jedem Fall. Es ist nicht so, als würden Sie für jedes Feld eine andere Art von Parsing durchführen.

2

Eine sehr gute Möglichkeit zum Parsen von Texteingabe sind immer reguläre Ausdrücke.

Regex r = new Regex(@"(?<id>\d+):(?<hp>\d+):(?<mp>\d+):(?<str>\d+):(?<wis>\d+):(?<spd>\d+):(?<gold>\d+):(?<xp>\d+)"); 

// loop over lines 
Monster m = new Monster(); 
Match mc = r.Match(input); 

m.hp = GetValue(mc.Groups["hp"], m.hp); 
m.mp = GetValue(mc.Groups["mp"], m.mp); 
m.str = GetValue(mc.Groups["str"], m.str); 
... 


// method to handle extracted value 
private static int GetValue(Group g, int fallback) 
{ 
    if (g == null) throw new ArgumentNullException("g"); 
    return g.Success ? Convert.ToInt32(g.Value) : fallback; 
} 

Die Methode GetValue prüft den extrahierten Wert. Wenn die Übereinstimmung fehlgeschlagen ist (vielleicht "" oder "AB" anstelle einer Zahl - g.Success ist falsch), können Sie damit umgehen, wie Sie wollen. In meiner Art verwende ich einfach einen Fallback-Wert.

http://msdn.microsoft.com/en-us/library/hs600312.aspx

+0

Sag nicht "immer". Es gibt Ausnahmen. html zum Beispiel. – mpen

Verwandte Themen