Issues reading input from stdin

Hello all,

I wanted to start using rust for some competitive programming problems, as the language is quite fast and I enjoy using it.

Although, I have encountered this bizarre error when reading from stdin. Where the handle to stdin never seems to close while reading from the console.

for example,

let stdin: Stdin = io::stdin(); 

for line in stdin.lock().lines().map(|r| r.unwrap()) {
 // arbitrary code ...      
}

Will get stuck in a infinite loop when reading from the console. When I paste in the input and press enter it will read the first n - 1 lines fine. I then have to press enter again for the last line to be read in. At this point, the handle to the stdin stream does not close, as I can continue to press enter and see the newlines still being read in. This entire process is being done within intellij (which can be buggy), so I decided to try and compile and run from the terminal with,

cargo run 

and then pasted in the input, but the exact same problem occurred.

So maybe its an issue with cargo run? I then tried

cargo build 
./target/debug/ah

But the same problem keeps happening.

Well, what about piping? That has to work. so I pasted my input into a file and
ran the following.

cat test.txt | ./target/debug/ah 

This actually does finally work, but it was a real pain in the butt. I am not sure why this happening and if it is OS specific. I run Linux Mint 20.3 Una with a Cinnamon desktop environment. My hunch would be the EOF byte is somehow never read or included, resulting in the handle being left open.

Every time the iterator returned by lines has next invoked, it will block until it encounters a newline. At that point it will return the whole line. Then the next loop iteration starts and the whole process starts over. You need a termination condition in your loop.

From the perspective of a program reading from stdin there's no reliable way to differentiate between an input being pasted all at once and being typed manually, which I think may be your point of confusion.

There is no EOF character, EOF is a state of a file descriptor.

EDIT: here's a good overview of EOF as a concept and where some of the confusion often comes from

3 Likes

When running program in terminal, EOF (that is, an action of closing the standard input) must be sent explicitly - can't check right now (on the phone), but AFAIK that's Ctrl+D in most shells.

3 Likes

Thank you, I tried having a terminating condition in the loop which does work better, but its still a little buggy for me. I have no problem just piping in the input since that's how its it'll be done on any server running the code. Thanks for the article about EOF, my years of c programming have been misleading ... :slight_smile: