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

70

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

  1. 使用cin.get()
  2. 或者使用system("pause")
  3. 还是使用像getch()getchar()这样的C函数?

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

cin.get()是否更好用于暂停控制台?

11个回答

72

可能有一种最佳方式(比如使用可移植的 cin.get()),但是并没有一个的方式存在。完成任务的程序应该退出并将其资源归还给计算机。

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

在您的源代码中有暂停代码,早晚会引起麻烦:

  • 有人在提交之前忘记删除暂停代码
    • 现在所有的工作伙伴都要想知道为什么应用程序不再关闭
    • 版本历史被污染了
  • #define太可怕了
  • 对于从控制台运行您的代码的任何人都很讨厌
  • 当尝试从脚本内部启动和结束程序时,这非常非常非常讨厌;如果程序不结束,shell脚本或管道也不会结束

相反,探索您的IDE。它可能有一个选项,在运行后不关闭控制台窗口。如果没有,作为一位值得花钱的开发人员,总是在附近打开控制台窗口绝对是一个很好的理由。

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

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


3
这个请求源于需要在IDE运行时阅读控制台输出,但当应用程序终止时,IDE将关闭控制台。通过“真正的”命令提示符运行的应用程序不会遇到这个问题。 - edmz
2
@black:如果IDE缺乏保持控制台打开的功能,那么这是一个很好的理由,始终在附近保持控制台打开。暂停程序会导致版本控制问题,因为迟早有人会忘记再次删除暂停代码,或者出现#define宏的问题,或其他问题。我认为我应该扩展一下我的答案 :) - Sebastian Mach
1
@phresnel:你说“如果尝试从脚本内部启动和结束程序,那么这非常非常非常令人恼火;如果你的程序是shell管道的一部分,那么就更加令人恼火。”为什么会如此令人恼火?有何原因? - Destructor
2
@PravasiMeet:因为当程序不结束时,调用程序的shell脚本或管道也不会结束。 - Sebastian Mach
1
@HelloGoodbye 为什么呢? - Lightness Races in Orbit
2
@SebastianMach 实际上,“that”在这里是正确的,而“which”则不是。从技术上讲。 - Lightness Races in Orbit

25

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

system("PAUSE")在Windows上有效,因为它需要执行名为"PAUSE"的控制台命令。但是我不确定其他操作系统如Linux或其他Unix衍生版本是否支持它。因此,这往往是不可移植的。

由于C++已经提供了cin.get(),我认为没有必要使用C的getch()


8
不建议使用C getch(),因为它没有在ISO C++或POSIX中定义(它来自于MS conio.h)。 - Grzegorz Szpetkowski
3
conio.h的全称是CONsole Input/Output,主要用于MS-DOS操作系统,在后来为了兼容性而被保留下来,但很明显它不是标准的。 - nameless

5

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

我认为没有一种最好的方式,但是在相当通用的情况下“强制”等待输入场景,特别是在调试时(通常会根据 NDEBUG_DEBUG 进行编译或禁用),您可以尝试以下的 std::getline

inline void wait_on_enter()
{
    std::string dummy;
    std::cout << "Enter to continue..." << std::endl;
    std::getline(std::cin, dummy);
}

根据需要,使用或不使用“按回车键继续”功能。

1
@phresnel的程序是为了满足用户需求而存在的。因此,任何用户需求也都是程序需求。您真的需要在回答这个有效问题时发送所有答案吗?请不要加入个人观点。 - Christophe
@phresnel; 是的,这样的结构的一般合法使用是有限的。 - Niall

3
哪种是在C++程序中暂停控制台的最佳方式? system("pause");getch();(来自DOS世界,如果我没记错)都不可移植。
cin.get()是否更好用于暂停控制台? 作为唯一的可移植标准选项,我认为是这样的,但我个人认为不应编写交互式控制台程序,即实际上暂停控制台或提示输入的程序(除非有一个真正很好的理由,因为这使得Shell脚本更加困难)。控制台程序应通过命令行参数与用户进行交互(或者至少这种交互应该是默认的)。
以防万一需要暂停程序以便"从IDE启动我的程序并立即关闭但我没有足够的时间查看结果"的原因 - 不要那样做。只需配置您的IDE或直接从控制台启动控制台程序即可。

交互式控制台程序在Unix和Linux世界中非常常见。与本问题的代码不同之处在于,它们在工作完成后确实会退出。 - Sebastian Mach

2

没有一种“好”的方法来做到这一点,但您应该使用可移植的解决方案,因此避免在您的情况下使用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

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


2

system("pause")是在Windows控制台暂停的一种有效方式,"pause"实际上是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用户更有可能从控制台运行程序。此外,如果您有一个命令行解析器,您可以使用某些参数关闭暂停。(您在代码片段中看到的条件实际上是“任何参数都可以”,只是一个懒惰的例子。)

谢谢,谢谢。 - heyitsalec

1

我的答案部分基于Yoank的回答,部分基于另一个问题上Justin Time评论

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

0

我经常使用几行代码来清除输入流中的任何字符,然后等待输入以忽略它们。

类似这样:

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

在程序中,每当我需要暂停时,我都可以使用自己的pause()函数,而无需使用系统暂停造成额外负担。这仅在编写控制台程序并希望保持打开或固定在某个点时才是一个问题。

0

虽然回复晚了,但我认为这会对其他人有帮助。

模拟 system("pause") 的一部分是模拟它要求用户执行的操作:“按任意键继续...” 所以,我们需要一些东西,它不仅等待简单的回车键,就像 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;
} 

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

0

这对我有效。

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

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