Reputation:
I'm trying to get a line of integers from a text file and parse them into separate variables. The text file is set up like this:
ID:HP:MP:STR:WIS:SPD:GOLD:XP
0:100:50:10:5:12:5:10
I want to split them with the : symbol in between each. One of the problems I'm having with this is being able to read the file line by line as strings, parsing them, and then storing the parsed strings as ints. Here is the code I'm attempting to use so far:
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;
}
}
I get the following error when this code runs:
Input string was not in a correct format. It references this part of the code:
if (j == 0) id = int.Parse(s);
Upvotes: 2
Views: 7778
Reputation: 2884
A very good way for parsing text input are always regular expressions.
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;
}
The method GetValue checks the extracted value. If the match failed (perhaps "" or "AB" instead of a number - g.Success is false) you can handle it the way you want. In my way i simply use an fallback value.
http://msdn.microsoft.com/en-us/library/hs600312.aspx
Upvotes: 2
Reputation: 116744
Why the foreach
? How about:
id = int.Parse(mstats[0]);
hp = int.Parse(mstats[1]);
and so on. With a check beforehand that mstats
is long enough.
A bit of Linq would let you get an array of integers in one shot:
int[] fields = line.Split(delimeterChars).Select(s => int.Parse(s)).ToArray();
id = field[0];
hp = field[2];
As for getting the code working, try printing out the line of text, and each piece of text just before you pass it to Parse. If it's not an integer, that's your problem.
Upvotes: 3
Reputation: 1503509
Well, the first thing is to find out what the bad input was.
If you're expecting bad input data, use int.TryParse
instead of just int.Parse
. If you're not expecting bad input data, the fact that it's throwing an exception is probably appropriate - but you should examine your data to find out what's wrong.
I'd also recommend putting the parsing call once rather than in every case. It's not like you're doing a different kind of parsing for each field.
Upvotes: 3