【发布时间】:2014-07-16 08:49:02
【问题描述】:
在 C++ 程序中暂停控制台的最佳方法是什么?
- 使用
cin.get() - 或使用
system("pause") - 或使用 C 函数,如
getch()或getchar()?
使用system("pause") 是否会导致代码不可移植并且无法在 UNIX 中工作?
cin.get() 更适合用来暂停控制台吗?
【问题讨论】:
标签: c++
在 C++ 程序中暂停控制台的最佳方法是什么?
cin.get()
system("pause")
getch() 或 getchar()?使用system("pause") 是否会导致代码不可移植并且无法在 UNIX 中工作?
cin.get() 更适合用来暂停控制台吗?
【问题讨论】:
标签: c++
可能有最好的方法(比如使用便携式cin.get()),但没有好的方法。完成工作的程序应该退出并将其资源还给计算机。
是的,system() 的任何使用都会导致代码不可移植,因为参数会传递给拥有您的进程的 shell。
在源代码中包含暂停代码迟早会导致麻烦:
#define 是地狱相反,探索您的 IDE。它可能有一个选项在运行后不关闭控制台窗口。如果没有,作为一个物有所值的开发者,在附近始终打开一个控制台窗口是一个很好的理由。
或者,您可以将其设为程序选项,但我个人从未见过带有选项--keep-alive-when-dead 的程序。
故事的寓意:这是用户的问题,而不是程序的问题。不要污染你的代码。
【讨论】:
如果你想编写可移植的 C++ 代码,那么我建议使用cin.get()。
system("PAUSE") 适用于 Windows,因为它需要执行名为“PAUSE”的控制台命令。但我不确定其他操作系统(如 Linux 或其他 Unix 衍生产品)是否支持这一点。所以这往往是不可移植的。
由于 C++ 已经提供 cin.get(),我认为没有令人信服的理由使用 C getch()。
【讨论】:
getch() 无论如何都不会被推荐,因为它没有在 ISO C++ 或 POSIX 中定义(它来自 MS conio.h)。
最佳方式很大程度上取决于目标平台、调试与发布使用等。
我认为没有一种最好的方法,而是以一种相当通用的方式“强制”等待输入类型场景,尤其是在调试时(通常这是编译入或编译出基于NDEBUG或_DEBUG),你可以尝试std::getline如下
inline void wait_on_enter()
{
std::string dummy;
std::cout << "Enter to continue..." << std::endl;
std::getline(std::cin, dummy);
}
我们根据需要不带“进入继续”。
【讨论】:
在 C++ 程序中暂停控制台的最佳方法是什么?
system("pause"); 和 getch();(来自 DOS 世界,IIRC)都是不可移植的。
cin.get() 更适合用来暂停控制台吗?
作为唯一的portable和standard选项,我会说是,但我个人认为不应该编写交互式控制台程序,即实际上暂停控制台或提示输入(除非有一个真的很好的理由,因为这会使 shell 脚本编写更加困难)。控制台程序应该通过命令行参数与用户交互(或者至少这种交互应该是默认的)。
以防万一您需要为 my-program-is-launched-from-the-IDE-and-immediately-closed-but-I-don't-have-enough-time-to-see 暂停程序-结果原因——不要那样做。只需配置您的 IDE 或直接从控制台启动 console 程序。
【讨论】:
没有好的方法可以做到这一点,但你应该使用便携式解决方案,所以避免system()调用,在你的情况下你可以使用cin.get()或getch(),正如你在你的问题,也有一个建议。使所有暂停由一个(或极少数)预处理器定义控制。
例如:
全局文件中的某处:
#define USE_PAUSES
#ifndef _DEBUG //I asume you have _DEBUG definition for debug and don't have it for release build
#undef USE_PAUSES
#endif
代码中的某处
#ifdef USE_PAUSES
cin.get();
#endif
这不是通用的建议,但您应该保护自己不要在发布版本中放置暂停,并且这些应该易于控制,我提到的全局文件可能不是那么全局,因为其中的更改可能会导致编译时间过长。
【讨论】:
(我的回答部分基于Yoank 的回答,部分基于Justin Time 的comment 另一个问题。)
cout << endl << "Press <Enter> to continue...";
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cin.get();
【讨论】:
system("pause") 是在 Windows 中暂停控制台的一种完全有效的方式,“暂停”实际上是 Windows 识别的系统命令,因此,您永远不必担心它会调用同名的程序或其他任何东西像那样。 system("pause") 在这方面很危险的想法是神话。
然而这不是 windows 之外的情况,所以最好使用预处理器来划分平台。
#ifdef _WIN32 || _WIN64
if(argc <= 1) // optional, prevents pausing if the user runs "program.exe -lol"
system("pause");
#endif
您可以根据需要添加预处理器分支以在其他平台上暂停...但在我看来,将其提供给 Windows 就绰绰有余了,因为无论如何 Linux 用户更有可能从控制台运行东西。此外,如果您有命令行解析器,则可以使用某些参数关闭暂停。 (您看到的代码 sn-p 中的条件实际上是“任何参数”,只是一个懒惰的例子。)
【讨论】:
我只是想补充一点,有一种方法可以得到你想要的,但它需要使用一些第三方库(或者你自己编写平台相关的代码)。
就我而言,cin 的最大缺点是您需要按 Return,而不仅仅是任何键。
假设你有一个按键监听器,你可以很容易地编写一个函数来等待用户点击 any 键。然而,找到一个独立于平台的密钥侦听器并非易事,而且很可能需要您加载较大库的一部分。
我的想法是这样的:
char wait_for_key() {
int key;
while ( ! (key == key_pressed(ANY)) ) {
this_thread::yield();
}
return convert_virtual_key_to_char(key);
}
实际的函数显然与我写的完全不同,这取决于你使用的库。
我知道以下库具有键侦听器(如果您知道,请随时在编辑中添加更多内容。):
【讨论】:
我总是使用几行代码来清除任何字符的输入流,然后等待输入被忽略。
类似:
void pause() {
cin.clear();
cout << endl << "Press any key to continue...";
cin.ignore();
}
然后任何时候我在程序中需要它,我都有自己的 pause();功能,没有系统暂停的开销。这只是在编写您希望保持打开或固定在某个点上的控制台程序时才真正存在的问题。
【讨论】:
这对我有用。
void pause()
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
std::string dummy;
std::cout << "Press any key to continue . . .";
std::getline(std::cin, dummy);
}
【讨论】:
回复较晚,但我认为这会对其他人有所帮助。
模仿系统(“暂停”)的一部分是模仿它要求用户做的事情:“按任意键继续......”所以,我们需要一些不等待简单地作为 std::cin 的返回的东西.get() 会做。甚至 getch() 在使用两次时也会出现问题(已经注意到第二次调用通常会跳过暂停,如果之后在同一按键上立即再次暂停)。我认为这与输入缓冲区有关。 System("pause") 通常不被推荐,但我们仍然需要一些东西来模仿用户可能已经期望的东西。我更喜欢 getch() 因为它不会在屏幕上回显,而且它是动态工作的。
解决方案是使用 do-while 循环执行以下操作:
void Console::pause()
{
int ch = 0;
std::cout << "\nPress any key to continue . . . ";
do {
ch = getch();
} while (ch != 0);
std::cout << std::endl;
}
现在它等待用户按下任意键。如果它被使用了两次,它会再次等待用户而不是跳过。
【讨论】: