4

What I have here is a loop that is supposed to read the output on a piece of equipment every 500 milliseconds. This part works fine. However, when I try to introduce cin.get to pick up the key "n" being pressed to stop the loop, I only get as many outputs as the number of key presses up to this point. If I press any keys (apart from 'n') several times followed by enter, I will get a few more outputs. What I need is the loop keep looping without any interaction until I want it to stop.

Here's the code:

for(;;)
{
    count1++;
    Sleep(500);
    analogInput = ReadAnalogChannel(1) / 51.0;
    cout << count1*0.5 << "     " << analogInput << endl;
    outputFile << count1*0.5 << ", " << analogInput << endl;
    if (cin.get() == 'n') //PROBLEM STARTS WITH THIS INTRODUCED
        break;
};

My output is as follows (there are 2 key presses to get to this stage in the program) unless I press a few more keys followed by enter:

0.5    0 // as expected
1      2 // as expected
should be more values until stopped

I have no particular preference in which type of loop to use, as long as it works.

Thanks!

Victor Nik
  • 75
  • 1
  • 1
  • 6
  • 2
    Seeing as how you're already using `Sleep`, the quickest way would be to replace `if (cin.get() == 'n')` with `if (GetAsyncKeyState(0x4E) & 0x8000)`. `cin.get()` is blocking. With a 500ms delay in there, though, not that big of a portion of the loop is going toward the asynchronous check. There are better ways to do it, but that will work if you hold the key down for a little bit or get lucky. – chris May 05 '13 at 03:53
  • It worked fine, however I need to hold down the key for a bit, which might become an issue later on. Could you point me in the right direction to alternative solutions, please? – Victor Nik May 05 '13 at 04:25
  • You could attach a hook to your own process to monitor keystrokes and notify the loop when n is hit. Alternatively, you *could* get input in a separate thread, which seems to be the route the new answer went. – chris May 05 '13 at 04:30

2 Answers2

11

cin.get() is a synchronous call, which suspends the current thread of execution until it gets an input character (you press a key).

You need to run your loop in a separate thread and poll the atomic boolean, which you change in main thread after cin.get() returns.

It could look something like this:

std::atomic_boolean stop = false;

void loop() {
    while(!stop)
    {
        // your loop body here
    }
}

// ...

int main() {
    // ...
    boost::thread t(loop); // Separate thread for loop.
    t.start(); // This actually starts a thread.

    // Wait for input character (this will suspend the main thread, but the loop
    // thread will keep running).
    cin.get();

    // Set the atomic boolean to true. The loop thread will exit from 
    // loop and terminate.
    stop = true;

    // ... other actions ...

    return EXIT_SUCCESS; 
}

Note: the above code is just to give an idea, it uses Boost library and a latest version of standard C++ library. Those may not be available to you. If so, use the alternatives from your environment.

weekens
  • 8,064
  • 6
  • 45
  • 62
1

if (cin.get() == 'n')

This call will stop your loop until it receives a key from you. There by stopping your loop as you see happening.

cin.get() will sit there until it gets a keystroke from you.

playerone
  • 127
  • 1
  • 8