2

How can I enter an input without causing the code to stop executing? I have been searching for an answer during the last 20 minutes without result.

cin >> string; pauses the code AFAIK.

Would I need to use multithreading, or is there a better way? (I don't even know if multithreading would work.)

I've recently started learning c++, I am a beginner to say the least, so please explain thoroughly and include any library I might need, thank you.

Mandera
  • 2,647
  • 3
  • 21
  • 26
  • 1
    What do you expect to happen if you prompt for input but keep going without waiting for that input? That seems like a fast way to introduce race conditions. – Cory Kramer Sep 30 '14 at 17:55
  • 2
    You're going to need to think in far more detail about the structure of your program and what you want it to do. What should be happening in the background while that user input is pending? How should that background task be interrupted when user input is made available? These are crucial factors to consider but you haven't considered them in your question. – Lightness Races in Orbit Sep 30 '14 at 17:58
  • Is there no way you can input variables while the code is running? Something like `while(true) {if(getConsoleInput() == "blabla") randomFunction();}` – Mandera Sep 30 '14 at 18:00
  • possible duplicate of [Real-time keyboard input to console (in Windows)?](http://stackoverflow.com/questions/7519039/real-time-keyboard-input-to-console-in-windows) – vines Sep 30 '14 at 18:04
  • It really depends on what you want to do. If you just want your program to stop doing what it is doing, use `kbhit()` as the answer suggested. However, if you are planning something like a videogame (for instance) you will need to use a thread. Using while(true) usually stinks (active waiting, consuming resources for just waiting). – Javi Sep 30 '14 at 18:15
  • I simply want to be able to call a function with an input parameter while the code is running. – Mandera Sep 30 '14 at 18:19

3 Answers3

11

Here's an example of how you can read a token from the standard input stream using >> in parallell with another call using multithreading.

#include <iostream>
#include <thread>
#include <future>

int main() {
    // Enable standard literals as 2s and ""s.
    using namespace std::literals;

    // Execute lambda asyncronously.
    auto f = std::async(std::launch::async, [] {
        auto s = ""s;
        if (std::cin >> s) return s;
    });

    // Continue execution in main thread.
    while(f.wait_for(2s) != std::future_status::ready) {
        std::cout << "still waiting..." << std::endl;
    }

    std::cout << "Input was: " << f.get() << std::endl;
}

Here the call to std::async with the launch parameter std::launch::async runs a task asynchronously on a different thread. std::async returns a handle to the task run in parallel called a future. This future can be used to check if the task is finished or not. The result of the task can also be returned from the std::future object using the member function std::future::get.

The task I'm passing to std::async is a simple lambda expression that creates a string, reads a token from the stream into the string and returns it (the ""s is a standard literal introduced in C++14 that returns an empty std::string object).

After calling std::async the main thread continues executing statements (in parallel with the asynchronously run task). In my example a while loop is executed that simply waits for the asynchronous task to finish. Note the use of std::future::wait_for that only blocks for 2 seconds on every iteration. std::future::wait_for returns a status that can be compared against to check if the task is finished or not.

Finally the call to std::future::get will return the result of the asynchronously run task. If we hadn't have waited for the task to finish, the call would block until the result was ready.

Be careful not to read from the standard input in the main thread also (in parallel) as the read call is not an atomic transaction and the data may be garbled.

Community
  • 1
  • 1
Felix Glas
  • 15,065
  • 7
  • 53
  • 82
  • 1
    Wow, I would call this overkill. In general the recommendations are to stay away from threads unless absolutely necessary. There are platform specific techniques that can be used without explicit threading. – Thomas Matthews Sep 30 '14 at 19:57
3

There are two algorithms for getting input without blocking (pausing). The first is polling, the second is by event (interrupt).

Polling For Input

Polling involves periodically checking for input. With a keyboard, this could be reading the keyboard for a keypress. With serial ports, it could mean checking the status of the receive register.

Blocking or waiting for input on some systems would consist of polling forever, until an input is received.

Input Events

On some platforms, an event is sent when input is detected. For example, Windows OS receives an event that a key was pressed and sends the message to the task in focus. On embedded systems, the hardware could dereference a function pointer at an interrupt vector.

Blocking for input on event based systems means sleeping until the event is received.

Summary

The standard C++ language does not provide a standard function for retrieving input without blocking. The implementation of the C++ input functions is platform dependent and may or may not block. For example, the platform could wait until a newline is received before returning a single character.

Many platforms or operating systems have functionality where you can test a port for input (polling) or be notified when the input has occurred (event driven). Since you didn't specify which platform you are using, the details stop here.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
0

use kbhit().

while(1)
{
    if(kbhit())
    {
        // do what ever you want.
    }
}
Armita
  • 345
  • 1
  • 12
  • "I've recently started learning c++, I am a beginner to say the least, so please explain thoroughly and include any library I might need, thank you." I have no idea what I am supposed to do with this. I can't even call it though: "error: 'kbhit' was not declared in this scope". – Mandera Sep 30 '14 at 18:16
  • @Mandera check [here](http://www.cprogramming.com/fod/kbhit.html) for more details, but if you explain about what you want to do, maybe there is a better way of doing it. – Armita Sep 30 '14 at 18:22
  • I simply want to be able to call a function with an input parameter while the code is running. – Mandera Sep 30 '14 at 18:23
  • if you want to continue whatever you where doing during the function call, you have to use threads, but if it is possible for your main loop to stop during the function call, just call inside the if(kbhit())... if you press a key, this if will be True. @Mandera – Armita Sep 30 '14 at 18:29
  • Too bad, this will only work on platforms that have the `kbhit()` function, which is not standard. – Thomas Matthews Sep 30 '14 at 19:58