C++ 程序中的暂停控制台

Posted

技术标签:

【中文标题】C++ 程序中的暂停控制台【英文标题】:Pause Console in C++ program 【发布时间】:2014-07-16 08:49:02 【问题描述】:

在 C++ 程序中暂停控制台的最佳方法是什么?

    使用cin.get() 或使用system("pause") 或使用 C 函数,如 getch()getchar()

使用system("pause") 是否会导致代码不可移植并且无法在 UNIX 中工作?

cin.get() 更适合用来暂停控制台吗?

【问题讨论】:

【参考方案1】:

可能有最好的方法(比如使用便携式cin.get()),但没有好的方法。完成工作的程序应该退出并将其资源还给计算机。

是的,system() 的任何使用都会导致代码不可移植,因为参数会传递给拥有您的进程的 shell。

在源代码中包含暂停代码迟早会导致麻烦:

有人忘记在签到前删除暂停代码 现在所有工作伙伴都想知道为什么应用程序不再关闭了 版本历史被污染 #define 是地狱 对于从控制台运行您的代码的人来说,这很烦人 尝试从脚本中启动和结束程序时非常、非常、非常烦人;如果您的程序是 shell 中管道的一部分,则非常烦人,因为如果程序没有结束,shell 脚本或管道也不会结束

相反,探索您的 IDE。它可能有一个选项在运行后不关闭控制台窗口。如果没有,作为一个物有所值的开发者,在附近始终打开一个控制台窗口是一个很好的理由。

或者,您可以将其设为程序选项,但我个人从未见过带有选项--keep-alive-when-dead 的程序。

故事的寓意:这是用户的问题,而不是程序的问题。不要污染你的代码。

【讨论】:

+1。如果由 IDE 运行,该请求来自需要读取控制台中的输出,一旦应用程序终止,它将关闭控制台。通过“真实”命令提示符运行的应用程序不会遇到此问题。 @black:如果 IDE 缺少保持控制台打开的功能,那么始终保持控制台在附近打开是一个很好的理由。暂停程序会导致版本控制出现问题,因为迟早有人会忘记再次删除暂停代码,或者导致#define-macros 出现问题,或其他任何问题。我想我应该扩大一下我的答案:) @phresnel:您说“尝试从脚本中启动和结束程序时非常、非常、非常烦人;如果您的程序是 shell 中管道的一部分,则非常烦人。”它是如何以及为什么令人讨厌的? @PravasiMeet:因为当程序没有结束时,调用程序的shell脚本或管道也不会结束。 @SebastianMach 实际上,“that”在这里是正确的,而“which”不是。从技术上讲。【参考方案2】:

如果你想编写可移植的 C++ 代码,那么我建议使用cin.get()

system("PAUSE") 适用于 Windows,因为它需要执行名为“PAUSE”的控制台命令。但我不确定其他操作系统(如 Linux 或其他 Unix 衍生产品)是否支持这一点。所以这往往是不可移植的。

由于 C++ 已经提供 cin.get(),我认为没有令人信服的理由使用 C getch()

【讨论】:

C getch() 无论如何都不会被推荐,因为它没有在 ISO C++ 或 POSIX 中定义(它来自 MS conio.h)。 conio.h 代表 CONsole Input/Output,主要用于 MS-DOS,出于兼容性原因,显然不标准。【参考方案3】:

最佳方式很大程度上取决于目标平台、调试与发布使用等。

我认为没有一种最好的方法,而是以一种相当通用的方式“强制”等待输入类型场景,尤其是在调试时(通常这是编译入或编译出基于NDEBUG_DEBUG),你可以尝试std::getline如下

inline void wait_on_enter()

    std::string dummy;
    std::cout << "Enter to continue..." << std::endl;
    std::getline(std::cin, dummy);

我们根据需要不带“进入继续”。

【讨论】:

@phresnel 程序满足用户需求。因此,任何用户需求也是程序需求。你真的需要用你的个人观点来垃圾邮件这个有效问题的所有答案吗? @phresnel;诚然,此类构造的一般合法使用是有限的。【参考方案4】:

在 C++ 程序中暂停控制台的最佳方法是什么?

system("pause");getch();(来自 DOS 世界,IIRC)都是不可移植的。

cin.get() 更适合用来暂停控制台吗?

作为唯一的portablestandard选项,我会说是,但我个人认为不应该编写交互式控制台程序,即实际上暂停控制台或提示输入(除非有一个真的很好的理由,因为这会使 shell 脚本编写更加困难)。控制台程序应该通过命令行参数与用户交互(或者至少这种交互应该是默认的)。

以防万一您需要为 my-program-is-launched-from-the-IDE-and-immediately-closed-but-I-don't-have-enough-time-to-see 暂停程序-结果原因——不要那样做。只需配置您的 IDE 或直接从控制台启动 console 程序。

【讨论】:

交互式控制台程序在 Unix 和 Linux 世界中相当普遍。此问题代码的不同之处在于它们确实在工作完成后退出。【参考方案5】:

没有好的方法可以做到这一点,但你应该使用便携式解决方案,所以避免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

这不是通用的建议,但您应该保护自己不要在发布版本中放置暂停,并且这些应该易于控制,我提到的全局文件可能不是那么全局,因为其中的更改可能会导致编译时间过长。

【讨论】:

【参考方案6】:

(我的回答部分基于Yoank 的回答,部分基于Justin Time 的comment 另一个问题。)

cout << endl << "Press <Enter> to continue...";
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cin.get();

【讨论】:

【参考方案7】:

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 中的条件实际上是“任何参数”,只是一个懒惰的例子。)

【讨论】:

谢谢,谢谢。【参考方案8】:

我只是想补充一点,有一种方法可以得到你想要的,但它需要使用一些第三方库(或者你自己编写平台相关的代码)。

就我而言,cin 的最大缺点是您需要按 Return,而不仅仅是任何键。

假设你有一个按键监听器,你可以很容易地编写一个函数来等待用户点击 any 键。然而,找到一个独立于平台的密钥侦听器并非易事,而且很可能需要您加载较大库的一部分。

我的想法是这样的:

char wait_for_key() 
    int key;
    while ( ! (key == key_pressed(ANY)) ) 
          this_thread::yield();
    
    return convert_virtual_key_to_char(key);

实际的函数显然与我写的完全不同,这取决于你使用的库。

我知道以下库具有键侦听器(如果您知道,请随时在编辑中添加更多内容。):

keycode SDL

【讨论】:

所有这些麻烦和代码污染都不是程序的问题。【参考方案9】:

我总是使用几行代码来清除任何字符的输入流,然后等待输入被忽略。

类似:

void pause() 
    cin.clear();
    cout << endl << "Press any key to continue...";
    cin.ignore();

然后任何时候我在程序中需要它,我都有自己的 pause();功能,没有系统暂停的开销。这只是在编写您希望保持打开或固定在某个点上的控制台程序时才真正存在的问题。

【讨论】:

【参考方案10】:

这对我有用。

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

【讨论】:

【参考方案11】:

回复较晚,但我认为这会对其他人有所帮助。

模仿系统(“暂停”)的一部分是模仿它要求用户做的事情:“按任意键继续......”所以,我们需要一些不等待简单地作为 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;
 

现在它等待用户按下任意键。如果它被使用了两次,它会再次等待用户而不是跳过。

【讨论】:

以上是关于C++ 程序中的暂停控制台的主要内容,如果未能解决你的问题,请参考以下文章

如何在Visual Studio代码中完成后暂停控制台c ++应用程序

_getch 似乎暂停了我的程序

从 C++ 禁用控制台的快速编辑模式

c++控制台程序线程问题

如何让程序暂停,然后有自己控制再运行!求助!vc6.0

C++控制台程序怎样使主函数无限循环