C++如何在任何时候通过按键跳出循环

4
我这里有一个循环,它应该每隔500毫秒读取一次设备上的输出。这部分工作得很好。然而,当我尝试引入cin.get来捕获按下键盘上的“n”键以停止循环时,我只收到了到此为止按下的键数相同数量的输出。如果我按下任何键(除了“n”)多次并按回车键,我将会得到更多输出。我需要的是让循环保持运行直到我想要停止,没有任何交互。

以下是代码:

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;
};

我的输出如下(在程序中有2个按键才能到达此阶段),除非我按几个键,然后按回车:
0.5    0 // as expected
1      2 // as expected
should be more values until stopped

我并没有特别偏好使用哪种类型的循环语句,只要它能正常工作就可以。

谢谢!


2
既然您已经在使用Sleep,最快的方法是将if (cin.get() == 'n')替换为if (GetAsyncKeyState(0x4E) & 0x8000)cin.get()是阻塞的。虽然在其中有500毫秒的延迟,但循环的一小部分并没有用于异步检查。有更好的方法,但如果您按住键一段时间或运气好的话,这种方法也可以工作。 - chris
它运行得很好,但是我需要按住键一段时间,这可能会成为以后的问题。你能指导我寻找替代方案吗?谢谢! - Victor Nik
你可以将钩子附加到你自己的进程上,以监视按键并在 hit n 时通知循环。或者,你也可以在一个单独的线程中获取输入,这似乎是新答案所采用的方法。 - chris
2个回答

11

cin.get()是一个同步调用,它会暂停当前执行的线程,直到它获得一个输入字符(你按下一个键)。

你需要在一个单独的线程中运行你的循环,并轮询原子布尔值,在主线程中进行cin.get()返回后更改。

它可能看起来像这样:

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; 
}

注意:上面的代码仅供参考,它使用了Boost库和最新版本的标准C++库。这些可能不可用。如果是这样,请使用您的环境中提供的替代方案。

2
有了C++-11,就有了std::thread。这里不需要使用Boost。 - Twonky

1

如果 (cin.get() == 'n')

这个调用会停止你的循环,直到它接收到你的按键。因此,你看到你的循环停止了。

cin.get() 会一直等待,直到它从你那里获得一个按键。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接