如何在 Visual C++ 中保持控制台窗口打开?

Posted

技术标签:

【中文标题】如何在 Visual C++ 中保持控制台窗口打开?【英文标题】:How to keep the console window open in Visual C++? 【发布时间】:2010-10-02 01:34:41 【问题描述】:

我刚开始使用 Visual C++,我想知道如何保留控制台窗口。

例如,这将是一个典型的“hello world”应用程序:

int _tmain(int argc, _TCHAR* argv[])

    cout << "Hello World";
    return 0;

我错过了什么?

【问题讨论】:

Amruth A. Pillai 您的代码没有显示“按任意键继续”谢谢 您可以通过简单的 std::cout 调用自行打印。 所有提议的解决方案的缺点是它们都不适用于调试(此处 Ctrl+F5 失败)以及应用程序意外停止时(此处所有断点或从标准输入读取主返回均失败)。我希望看到像 Eclipse 和其他 IDE 一样的 IDE 控制台窗口。他们只是在程序终止后继续向 stdout/stderr 显示输出。 @sybren 接受的答案适用于 CTRL+F5,为什么您想要一个适用于调试 (F5) 的解决方案?当然,调试的全部意义在于.. 调试?在调试会话中程序终止后暂停控制台有什么好处? @JBentley Eclipse 和其他 IDE 允许您在进程终止后读取程序的输出。您肯定看到了额外的好处,尤其是在尝试查找错误时?此外,断点仅在您知道程序终止的位置时才有效,这很难判断输出何时从屏幕上消失。 【参考方案1】:

使用 Ctrl+F5 启动项目,而不仅仅是 F5

程序退出后,控制台窗口现在将保持打开状态并显示Press any key to continue . . . 消息。

请注意,这需要 Console (/SUBSYSTEM:CONSOLE) 链接器选项,您可以按如下方式启用:

    打开您的项目,然后转到解决方案资源管理器。如果您在 K&R 中与我一起关注,您的“解决方案”将是“你好”,其下有 1 个项目,“你好”也是粗体。 右键单击“hello”(或任何您的项目名称。) 从上下文菜单中选择“属性”。 选择配置属性>链接器>系统。 对于右侧窗格中的“子系统”属性,单击右侧列中的下拉框。 选择“控制台 (/SUBSYSTEM:CONSOLE)” 单击“应用”,等待它完成所有操作,然后单击“确定”。 (如果“应用”显示为灰色,请选择其他子系统选项,单击“应用”,然后返回并应用控制台选项。我的经验是“确定”本身不起作用。)

CTRL-F5 和子系统提示一起工作;它们不是单独的选项。

(来自 http://social.msdn.microsoft.com/Forums/en-US/vcprerelease/thread/21073093-516c-49d2-81c7-d960f6dc2ac6 的 DJMorreTX 提供)

【讨论】:

这个运行程序不调试;最好有一个在调试和普通运行模式下都可以工作的解决方案。 对于无法在 makefile 项目中使用此解决方案的任何人,这是由于 Visual Studio 中的错误造成的。我刚刚发布了修复的答案。 可以确认!有一个不起作用的控制台应用程序这样做并且它起作用了。您无需使用cin.get(),getchar(), system("pause") 或任何其他垃圾更改您的代码。改变这个工作。 Ctrl+F5 表示“不调试就开始”。所以调试的时候不能用这个。只需在代码末尾添加system("pause");。这很有意义并且工作正常。【参考方案2】:

标准方式是在您的退货声明之前cin.get()

int _tmain(int argc, _TCHAR* argv[])

    cout << "Hello World";
    cin.get();
    return 0;

【讨论】:

我知道,因为程序已经在使用 cout,所以它已经被处理了,但我认为值得一提的是,您需要 #include 以及使用 std 命名空间: std::cin.get(). 这可行,但 Ctrl+F5 更好,尤其是在跟踪全局对象破坏等时。 -1 代表_tmain。我会为cin.get() 投票另一个-1,而不是为F5 放置断点或使用Ctrl F5。但我只被允许投反对票。 @Cheers:_tmain 有什么问题?这是编写针对控制台子系统的 Windows 应用程序的标准方法。偏离该标准是不好的做法。显然,这里没有人谈论可移植代码。问题说 Visual C++ 和 _tmain 是示例代码中出现的签名。是时候放弃这个宗教了。默认情况下,Windows 是“非标准”的,遵循 标准是有充分理由的。 @CodyGray:我对_tmain 的反对是因为它完全没有必要非标准(国际C++ 标准需要一个普通的main),并且因为它使用微软的T 宏方案,对于支持Windows 9x 来说是不必要的复杂和冗长。如果你觉得偏离标准是不好的做法,那么你绝对不应该使用tmain。使用 tmain 没有充分的理由,除非是为了拖钓,或者对于专业人士来说,显示一个人的完全无能。【参考方案3】:

return 行放置一个断点。

您是在调试器中运行它,对吧?

【讨论】:

大多数时候很困难,因为程序内可能有多个退出点 程序可能由于缺少 DLL 而无法启动,并且永远不会遇到该断点【参考方案4】:

另一种选择是使用

#include <process.h>
system("pause");

虽然这不是很便携,因为它只能在 Windows 上工作,但它会自动打印

按任意键继续...

【讨论】:

system("pause") 将保持您的处理器运行,不应使用它。使用 cin.get() 或等效的。 system&lt;stdlib.h&gt; 中声明。 @Krythic 我刚试过它并没有吃掉 100% 的 CPU。我的处理器使用率一直为 0% - 1%。无法复制。 system("pause") 会在cmd中调用"pause"命令,不会一直占用CPU。它本质上相当于 _getche()。【参考方案5】:

对于 makefile 项目,由于 Visual Studio 中的错误(至少在 2012 版之前存在 - 我还没有测试 2013),因此接受的解决方案失败。这个bug详细here.

要在 makefile 项目的程序终止后让控制台暂停,请执行以下步骤(对于 2010 - 2012 以外的版本,这可能会有所不同):

1) 将/SUBSYSTEM:CONSOLE 传递给链接器。 - 编辑:见下文。

2) 在文本编辑器中打开您的项目文件 (.vcxproj)。

3) 在根&lt;project&gt; 标记内,插入以下内容:

<ItemDefinitionGroup>
  <Link>
    <SubSystem>Console</SubSystem>
  </Link>
</ItemDefinitionGroup>

4) 在您的解决方案中重新加载项目。

5) 在不调试的情况下运行程序 (CTRL + F5)。

编辑:

根据我在下面的评论,设置链接器选项 /SUBSYSTEM:CONSOLE 实际上与 makefile 项目无关(如果您使用的是 MSVC 以外的编译器,甚至不一定可能)。重要的是按照上面的步骤 3 将设置添加到 .vcxproj 文件中。

【讨论】:

我以前从未听说过第 3 步。你确定这是必需的并且有效吗? @mooingduck 是的,在我对your answer here 的cmets 之后,我现在发现将/SUBSYSTEM:CONSOLE 传递给链接器实际上是无关紧要的——步骤3 才是最重要的。请记住,我的回答与 makefile 项目有关 - 在 makefile 项目中,IDE 无法知道您传递给链接器的内容(您甚至可能没有使用具有 /SUBSYSTEM:CONSOLE 选项的编译器),而且它是项目本身,它跟踪它是否是一个控制台程序。我将相应地编辑我的答案。 @mooingduck 我还可以确认我自己在 makefile 项目中使用了这个解决方案,SCons 作为构建系统,MSVC 和 MinGW 作为编译器。我知道没有其他方法可以让 IDE 在以非调试模式终止后暂停控制台。 @chuckleplant 恐怕不行,我的工作流程正好相反,从 VS 调用 SCons。我最初手动创建了我的 VS makefile 项目,以便它们将配置变量传递给我的 SCons 脚本(例如 32/64 位、编译器名称、发布/调试),然后处理其余的逻辑。在那个设置中,项目文件不需要改变,所以我没有使用 SCons 的任何自动生成功能。我已经切换到 Linux,所以我不再使用 VS。由于这是一个 VS 错误,因此可能值得向 SCons 提交功能请求以处理所需的额外步骤。 或者,您可以在 SCons 脚本中包含一些 Python 代码,以便在每次生成项目文件时自行完成。我相信 VS 项目文件符合 XML 标准,因此添加缺少的元素应该相当容易,并且只需要几行代码。我建议从here(对于 Python 2.x)或here(3.x)开始。 This answer 也可能感兴趣。【参考方案6】:

您可以在 return 语句之前使用 cin.get();cin.ignore(); 以避免关闭控制台窗口。

【讨论】:

【参考方案7】:

只需在 main 的最后一个大括号上放一个断点。

    int main () 
       //...your code...
       return 0;
     //<- breakpoint here

它对我有用,无需调试即可运行。它还在断点之前执行析构函数,因此您可以检查这些析构函数上打印的任何消息(如果有)。

【讨论】:

【参考方案8】:

只需在 _tmain 方法的右括号中添加一个断点。这是一种更简单的方法,而且您无需添加代码即可进行调试。

【讨论】:

【参考方案9】:
int main()

    //...
    getchar();
    return 0;

【讨论】:

【参考方案10】:

main() 的结尾大括号上放置一个断点。即使有多个return 语句,它也会被触发。唯一的缺点是不会捕获对exit() 的调用。

如果您不进行调试,请按照 Zoidberg 的回答中的建议并使用 Ctrl+F5 而不仅仅是 F5 来启动您的程序。

【讨论】:

【参考方案11】:

我的 2 美分:

选择1:在main()末尾添加断点

选择 2:在 return 0; 之前添加此代码:

std::cout << "Press ENTER to continue..."; //So the User knows what to do
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

您需要为std::numeric_limits 添加&lt;iomanip&gt;

【讨论】:

【参考方案12】:

只需在代码末尾添加 system("pause") ,然后像这样返回 0

#include <stdlib.h>

int main()

    //some code goes here
    system("pause")
    return 0;

【讨论】:

【参考方案13】:

cin.get(),或system("PAUSE")。 没听说你可以用return(0);

【讨论】:

【参考方案14】:

正如一些人已经指出的那样,Zoidbergs 解决方案不附加调试器,这是您通常不想要的。

imo 的最佳选择是相应地配置您的 VS(从 VS 2017 开始),方法是转到工具 > 选项 > 调试 > 常规。在那里你取消选中“调试停止时自动关闭控制台”(在最底部),这可能在你的情况下被选中。

【讨论】:

这是正确答案但是,您还需要在链接器中添加控制台 (/SUBSYSTEM:CONSOLE) 选项。 我没有选中这个框,但它仍然关闭。我不知道去哪里将@Wheezil 的建议添加到链接器中。 项目属性->链接器->所有选项搜索“sub”就可以看到【参考方案15】:

我包含#include &lt;conio.h&gt;,然后在return 0; 行之前添加getch();。反正我在学校就是这么学的。我看到上面提到的方法有很大的不同。

【讨论】:

-1:除了让程序本身暂停通常是错误的解决方案之外(因为在大多数情况下,这不是您希望发布的二进制文件具有的行为),conio.h 是 @ 987654321@,过时了,是 C 头文件,不是 C++!不幸的是,学校里有很多不好的编程实践。 人们希望这仅在测试期间使用,它不是您在最终版本中保留的东西。如果您正在为 Windows 编写代码,#include / _getch(); 有什么问题?它的编写速度比 cin.get() 快,不需要按 2 个键(至少一个字符+回车),并且仅在调试或发布模式下不起作用。那怎么了?【参考方案16】:

遇到了同样的问题。我在 return 语句之前使用_getch()。它有效。

【讨论】:

您可能希望在代码中添加示例和解释,尤其是对于很久以前提出/回答的问题。此外,您的答案在功能上与几个旧答案相同,并且使用与另一个现有答案相同的调用。【参考方案17】:

(有些选项可能叫不同的名字。我不使用英文版)

我遇到了同样的问题,当我使用“空项目”选项创建项目时,将项目创建为“Win32-console application”而不是“空项目”。在现在弹出的对话框中,您按“继续”,然后您可以选中“空项目”选项并按确认。之后 CTRL + F5 将打开一个不会自动关闭的控制台。

【讨论】:

【参考方案18】:

我遇到了同样的问题;在我的应用程序中有多个 exit() 点,无法知道它到底在哪里退出,然后我发现了这一点:

atexit(system("pause"));

atexit(cin.get());

这样,无论我们退出程序的哪个位置,它都会停止。

【讨论】:

这些都不是对atexit的有效调用。 atexit 采用函数指针,而不是整数。【参考方案19】:

另一种选择:

#ifdef _WIN32
#define MAINRET system("pause");return 0
#else
#define MAINRET return 0
#endif

主要:

int main(int argc, char* argv[]) 
    MAINRET;

【讨论】:

【参考方案20】:

其实,真正的解决方案是项目模板本身的选择。 您必须在旧版 VS 中选择 Win32 控制台应用程序,或者先填写项目名称,然后双击 Windows 桌面向导,然后选择 Win32 控制台应用程序。然后此时选择空项目。然后,这允许原始提问者真正想要的东西,而无需添加额外的停止点和保持代码。 我也遇到了这个问题。答案也在 MSDN 网站上。

【讨论】:

【参考方案21】:

下面是一种在不修改任何代码的情况下保持命令窗口打开的方法,无论执行如何停止:

在 Visual Studio 中,打开 Project Property Pages -> Debugging

对于命令,输入$(ComSpec)

对于命令参数,输入/k $(TargetPath)。将任何参数附加到您自己的应用程序。

现在F5Ctrl-F5在新窗口中执行Windows/System32/cmd.exe/k 确保命令提示符在执行完成后保持打开状态。

缺点是执行不会在断点处停止。

【讨论】:

【参考方案22】:

你可以把 保持窗口打开(); 这里的return之前是一个例子

int main()

    cout<<"hello world!\n";
    keep_window_open ();
    return 0;

【讨论】:

keep_window_open() 来自哪里,例如哪个头文件和库? 它来自这个 std_lib_facilities.h 但大多数时候你都包含它

以上是关于如何在 Visual C++ 中保持控制台窗口打开?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Visual Studio C++ 中使用代码关闭控制台窗口

Visual C++ 编程技巧之二

如何使用Visual Studio2010编译C语言

用于输出的 Visual Studio 代码 C++ 终端

如何使用visual studio 2017编写一个C++程序

microsoft visual c++ 14.0 is required 怎么解决 python