Чтение и анализ целых чисел из текстового файла - PullRequest
2 голосов
/ 21 марта 2009

Я пытаюсь получить строку целых чисел из текстового файла и разобрать их в отдельные переменные. Текстовый файл настроен так:

ID: HP: MP: STR: WIS: СПД: GOLD: XP

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

Я хочу разделить их символом: между каждым. Одна из проблем, с которыми я сталкиваюсь, - это возможность прочитать файл построчно как строки, проанализировать их, а затем сохранить проанализированные строки как целые. Вот код, который я пытаюсь использовать до сих пор:

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

При выполнении этого кода я получаю следующую ошибку:

Входная строка была в неправильном формате. Он ссылается на эту часть кода:

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

Ответы [ 3 ]

3 голосов
/ 21 марта 2009

Ну, во-первых, нужно выяснить, что за плохой ввод был.

Если вы ожидаете неверных входных данных, используйте int.TryParse вместо int.Parse. Если вы не ожидаете неверных входных данных, тот факт, что он вызывает исключение, вероятно, уместен - но вы должны проверить свои данные, чтобы выяснить, в чем дело.

Я бы также рекомендовал делать разбор вызова один раз , а не в каждом случае. Это не так, как будто вы делаете разный вид разбора для каждого поля.

3 голосов
/ 21 марта 2009

Почему foreach? Как насчет:

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

и так далее. С проверкой заранее, что mstats достаточно долго.

Немного Linq позволит получить массив целых чисел за один выстрел:

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

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

Что касается работы кода, попробуйте распечатать строку текста и каждый фрагмент текста непосредственно перед передачей в Parse. Если это не целое число, это ваша проблема.

2 голосов
/ 21 марта 2009

Очень хорошим способом разбора ввода текста всегда являются регулярные выражения.

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

Метод GetValue проверяет извлеченное значение. Если совпадение не удалось (возможно, "" или "AB" вместо числа - g.Success имеет значение false), вы можете обработать его так, как вы хотите. По-моему, я просто использую запасное значение.

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

...