ParseIntError for simple integer parsing


#1

I’m trying to parse a file of integers line and line but my program panics on the first line that’s read. Would really appreciate it if someone can take a look for me.

https://play.rust-lang.org/?gist=55ab4e8ff32f773e90c3a0f1909f9ae0&version=stable

The output I get in the terminal suggests that it read the first line correctly, and then panicked.

https://pastebin.com/FJGwXuUm


#2

Are you sure you don’t have whitespace in there? They occupy bytes, so num_bytes > 0 but are (obviously) not parsable into an i32.


#3

as vitalyd says and additional in line 13 you crate a new variable called num_bytes witch shadows num_bytes from line 6 and will be dropped after every iteration of the loop.
So the unchanged value of num_bytes from line 6 will be reused for all iterations.
To prevent the shadowing you have to remove the let from line 13


#4

So I printed out the number of bytes that are read and surprisingly 6 bytes are read in “2148”, then I realized the line is probably terminated with \r\n, which is why Rust is having trouble parsing the string into an integer. Popping the string twice did the trick.

Thanks for the help though!


#5

Excellent point, I’ll be sure to fix that.


#6

The safer way is to use a trimmed str like line.trim().parse::<i32>(), or just trim_right if you prefer. This way you’re not hard-coding that the line ending will be two chars – it’s probably just one '\n' on unix.


#7

Unless there’s a performance reason to reuse a String buffer across lines, I would iterate over BufReader::lines() and let it take care of line endings.


#8

would line.trim() remove both \r and \n from the end of the string, or would I have to call it twice? I agree with what you’ve said about not hard-coding two pop() calls.


#9

I’m guessing iterating over BufReader::lines() would be more idiomatic?


#10

It will remove any amount of whitespace in just one call.


#11

Awesome, I’ve just changed the code and it works. Only thing I had to watch out for was converting the &str back to a String

line = line.trim().to_string();

#12

Not sure I’d call it more idiomatic. It’s at a slightly higher level of abstraction, which removes the possibility of certain bugs (like the line ending handling). Its only downside really is it allocates a new String for each line. If that doesn’t matter then it’s preferable.

The only non-idiomatic thing that jumps out in your code is manually trying to pop off line ending chars, which has already been discussed.


#13

Whoa I feel like I learned so much about Rust today, thanks for all the great advice.


#14

There shouldn’t be a need for that - you can parse out of a &str.


#15

True, I’d totally forgotten about that. Will incorporate the changes, thanks a bunch!