Reading STDIN from separate lines and using println!

Can someone explain how I can fix this logic?

#[macro_use] extern crate dmoj;

fn main() {
    let mut done = false;

    while !done {
        for i in 1..=3 {
            println!("{}", i);

            if scan!(char).to_string() == "D" {
                done = true;
                break
            }
        }
    }
}

It's supposed to print the integer until I enter "DONE" (simple right?) current execution is to immediately wait for input and keep collecting until I enter "DONE" or "D". I've tried everything I could reasonably expect to work.

As you've noticed, scan! blocks until input is read. If you're just using this function by itself, whenever you call it, your code will just be waiting on input.

I think the most standard solution to this is to use two threads - one for doing the work and printing output, and another for reading input & letting the first thread know to stop. You could then use something like an Arc<AtomicBool> or Arc<Mutex<bool>> to have the threads communicate the simple message of "is it done?"

The other option here is to have some sort of check for "is input available?". Whether or not this is possible generally depends on what crates you're using to handle input. Generally, libraries which are built to handle TUIs make this easier; crossterm, for instance, has a crossterm::event::poll function which will tell you whether or not an event is available. I don't know if this is possible with dmoj.

Regardless, a thread-based solution should be possible here to word around the fact that scan! blocks.

2 Likes

Wasn't able to take that and run with it though I think some relevant information has also been supplied here: Dancing and learning/singing (Rust async example)

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.