How can I read multiple lines from stdin and advance until EOF in Rust? I'm trying to translate this C++ code to Rust but I'm failing.
#include <iostream>
int main()
{
try {
std::string line;
while (std::getline(std::cin, line)) {
int length = std::stoi(line);
for (int i = 0; i < length; i++) {
std::string input;
std::getline(std::cin, input);
std::cout << input << std::endl;
}
}
} catch (std::invalid_argument const&) {
std::cout << "invalid input" << std::endl;
}
return 0;
}
The program is fed with this input. It starts reading the first line which is a number indicating the total number of lines following, then tries reading all these lines and advancing to the next number until it terminates (or finds an EOF?).
4 a bb ccc dddd 5 eeeee dddd ccc bb a
This is my Rust code. It compiles but it seems like it gets stuck in an infinite loop. I'm running it with program < lines.txt
in terminal. What I'm doing wrong?
use std::io::{self, BufRead};
fn main() -> io::Result<()> {
let stdin = io::stdin();
for line in stdin.lock().lines() {
let length: i32 = line.unwrap().trim().parse().unwrap();
for _ in 0..length {
let line = stdin.lock()
.lines()
.next()
.expect("there was no next line")
.expect("the line could not be read");
println!("{}", line);
}
}
Ok(())
}
The problem is you're calling stdin.lock()
twice which immediately deadlocks. That and you'll need to use only a single .lines()
call because its designed to consume the entire input. Fortunately, that just means we have to refactor the outer for
loop into a while
:
use std::io::{self, BufRead};
fn main() -> io::Result<()> {
let stdin = io::stdin();
let mut lines = stdin.lock().lines();
while let Some(line) = lines.next() {
let length: i32 = line.unwrap().trim().parse().unwrap();
for _ in 0..length {
let line = lines
.next()
.expect("there was no next line")
.expect("the line could not be read");
println!("{}", line);
}
}
Ok(())
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With