C++ 如何模拟“按任意键继续?”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1449324/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 20:00:57  来源:igfitidea点击:

How to simulate "Press any key to continue?"

c++

提问by itsaboutcode

I am trying to write a C++ program in which when user enter any character from keyboard and it should move to next line of code.

我正在尝试编写一个 C++ 程序,当用户从键盘输入任何字符时,它应该移动到下一行代码。

Here is my code:

这是我的代码:

char c;

cin>>c;

cout<<"Something"<<endl;

but this is not working, because it only move to next line when I input some character and then press ENTER.

但这不起作用,因为它只会在我输入一些字符然后按 ENTER 时移动到下一行。

OR

或者

If I use this

如果我用这个

cin.get() or cin.get(c)

it move to next line of instruction when I press Enter.

当我按 Enter 时,它会移动到下一行指令。

But I wanted it to move to next line on any key pressed on the keyboard, how this can be done?

但我希望它在键盘上按下的任何键上移动到下一行,如何做到这一点?

回答by itsaboutcode

On Windows:

在 Windows 上:

system("pause");

and on Mac and Linux:

在 Mac 和 Linux 上:

system("read");

will output "Press any key to continue..." and obviously, wait for any key to be pressed. I hope thats what you meant

将输出“按任意键继续...”,显然,等待按下任意键。我希望这就是你的意思

回答by Vinay Sajip

If you're on Windows, you can use kbhit()which is part of the Microsoft run-time library. If you're on Linux, you can implement kbhitthus (source):

如果您使用的是 Windows,则可以使用kbhit()Microsoft 运行时库的一部分。如果您使用的是 Linux,则可以kbhit这样实现(源代码):

#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>

int kbhit(void)
{
  struct termios oldt, newt;
  int ch;
  int oldf;

  tcgetattr(STDIN_FILENO, &oldt);
  newt = oldt;
  newt.c_lflag &= ~(ICANON | ECHO);
  tcsetattr(STDIN_FILENO, TCSANOW, &newt);
  oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
  fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);

  ch = getchar();

  tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
  fcntl(STDIN_FILENO, F_SETFL, oldf);

  if(ch != EOF)
  {
    ungetc(ch, stdin);
    return 1;
  }

  return 0;
}

Update:The above function works on OS X (at least, on OS X 10.5.8 - Leopard, so I would expect it to work on more recent versions of OS X). This gistcan be saved as kbhit.cand compiled on both Linux and OS X with

更新:上述功能适用于 OS X(至少,在 OS X 10.5.8 - Leopard 上,所以我希望它适用于更新版本的 OS X)。这个要点可以kbhit.c在 Linux 和 OS X 上保存和编译

gcc -o kbhit kbhit.c

When run with

当运行时

./kbhit

It prompts you for a keypress, and exits when you hit a key (not limited to Enter or printable keys).

它会提示您按下按键,并在您按下键时退出(不限于 Enter 或可打印键)。

@Johnsyweb- please elaborate what you mean by "detailed canonical answer" and "all the concerns". Also, re "cross-platform": With this implementation of kbhit()you can have the same functionality in a C++ program on Linux/Unix/OS X/Windows - which other platforms might you be referring to?

@Johnsyweb- 请详细说明“详细的规范答案”和“所有问题”的含义。另外,重新“跨平台”:通过这种实现,kbhit()您可以在 Linux/Unix/OS X/Windows 上的 C++ 程序中拥有相同的功能 - 您可能指的是哪些其他平台?

Further update for @Johnsyweb:C++ applications do not live in a hermetically sealed C++ environment. A big reason for C++'s success is interoperability with C. All mainstream platforms are implemented with C interfaces (even if internal implementation is using C++) so your talk of "legacy" seems out of place. Plus, as we are talking about a single function, why do you need C++ for this ("C with classes")? As I pointed out, you can write in C++ and access this functionality easily, and your application's users are unlikely to care howyou implemented it.

@Johnsyweb 的进一步更新:C++ 应用程序不存在于密封的 C++ 环境中。C++ 成功的一个重要原因是与 C 的互操作性。所有主流平台都是用 C 接口实现的(即使内部实现是使用 C++),所以你谈论“遗留”似乎不合适。另外,当我们谈论单个函数时,为什么需要 C++ 来实现这个(“C with classes”)?正如我所指出的,您可以用 C++ 编写并轻松访问此功能,您的应用程序用户不太可能关心您是如何实现它的。

回答by Keith Thompson

There is no completely portable solution.

没有完全便携的解决方案。

Question 19.1 of the comp.lang.c FAQcovers this in some depth, with solutions for Windows, Unix-like systems, and even MS-DOS and VMS.

comp.lang.c FAQ 的问题 19.1对此进行了一定的深入探讨,提供了适用于 Windows、类 Unix 系统甚至 MS-DOS 和 VMS 的解决方案。

A quick and incomplete summary:

一个快速且不完整的总结:

  • You can use the curseslibrary; call cbreak()followed by getch()(not to be confused with the Windows-specific getch()function). Note that cursesgenerally takes control of the terminal, so this is likely to be overkill.
  • You might be able to use ioctl()to manipulate the terminal settings.
  • On POSIX-compliant systems, tcgetattr()and tcsetattr()may be a better solution.
  • On Unix, you can use system()to invoke the sttycommand.
  • On MS-DOS, you can use getch()or getche().
  • On VMS (now called OpenVMS), the Screen Management (SMG$) routines might do the trick.
  • 你可以使用curses图书馆;调用cbreak()后跟getch()(不要与特定于 Windows 的getch()函数混淆)。请注意,curses通常会控制终端,因此这可能有点矫枉过正。
  • 您也许可以ioctl()用来操作终端设置。
  • 在POSIX兼容的系统,tcgetattr()并且tcsetattr()可能是一个更好的解决方案。
  • 在 Unix 上,您可以使用system()来调用stty命令。
  • 在 MS-DOS 上,您可以使用getch()getche()
  • 在 VMS(现在称为 OpenVMS)上,屏幕管理 ( SMG$) 例程可能会起作用。

All these C solutions should work equally well in C++; I don't know of any C++-specific solution.

所有这些 C 解决方案在 C++ 中都应该同样有效;我不知道任何特定于 C++ 的解决方案。

回答by Kirill V. Lyadvinsky

To achieve this functionality you could use ncurseslibrary which was implemented both on Windows and Linux (and MacOS as far as I know).

要实现此功能,您可以使用在 Windows 和 Linux(据我所知,还有 MacOS)上实现的ncurses库。

回答by BoldX

In windows, this short program accomplishes the goal: getchpauses the console until a key is pressed (https://www.geeksforgeeks.org/difference-getchar-getch-getc-getche/)

在 Windows 中,这个简短的程序实现了目标:getch暂停控制台直到按下某个键(https://www.geeksforgeeks.org/difference-getchar-getch-getc-getche/

#include<iostream.h>
#include<conio.h>

using namespace std;

void  check()
{
    char chk; int j;
    cout<<"\n\nPress any key to continue...";
    chk=getch();
    j=chk;
    for(int i=1;i<=256;i++)
      if(i==j) break;
    clrscr();
}

void main()
{
    clrscr();
    check();
    cout<<"\n\nIt works!";
    getch();
}

It should be noted that getch is not part of the standard library.

需要注意的是 getch 不是标准库的一部分。

回答by Lucas

I looked into what you are trying to achieve, because I remember I wanted to do the same thing. Inspired by VinayI wrote something that works for me and I sort of understand. But I am not an expert, so please be careful.

我研究了你想要实现的目标,因为我记得我想做同样的事情。受Vinay 的启发,我写了一些对我有用的东西,我有点理解。但我不是专家,所以请小心。

I don't know how Vinay knows you are using Mac OS X. But it should work kind of like this with most unix-like OS. Really helpful as resource is opengroup.org

我不知道 Vinay 是如何知道您使用的是 Mac OS X。但是对于大多数类 Unix 的操作系统,它应该像这样工作。真的很有帮助,因为资源是opengroup.org

Make sure to flush the buffer before using the function.

确保在使用该函数之前刷新缓冲区。

#include <stdio.h>
#include <termios.h>        //termios, TCSANOW, ECHO, ICANON
#include <unistd.h>     //STDIN_FILENO


void pressKey()
{
    //the struct termios stores all kinds of flags which can manipulate the I/O Interface
    //I have an old one to save the old settings and a new 
    static struct termios oldt, newt;
    printf("Press key to continue....\n");

    //tcgetattr gets the parameters of the current terminal
    //STDIN_FILENO will tell tcgetattr that it should write the settings
    // of stdin to oldt
    tcgetattr( STDIN_FILENO, &oldt);
    //now the settings will be copied 
    newt = oldt;

    //two of the c_lflag will be turned off
    //ECHO which is responsible for displaying the input of the user in the terminal
    //ICANON is the essential one! Normally this takes care that one line at a time will be processed
    //that means it will return if it sees a "\n" or an EOF or an EOL
    newt.c_lflag &= ~(ICANON | ECHO );      

    //Those new settings will be set to STDIN
    //TCSANOW tells tcsetattr to change attributes immediately. 
    tcsetattr( STDIN_FILENO, TCSANOW, &newt);

    //now the char wil be requested
    getchar();

    //the old settings will be written back to STDIN
    tcsetattr( STDIN_FILENO, TCSANOW, &oldt);

}


int main(void)
{
  pressKey();
  printf("END\n");
  return 0;
}

O_NONBLOCK seems also to be an important flag, but it didn't change anything for me.

O_NONBLOCK 似乎也是一个重要的标志,但它对我没有任何改变。

I appreciate if people with some deeper knowledge would comment on this and give some advice.

如果有更深入了解的人对此发表评论并提供一些建议,我将不胜感激。

回答by Salman A

You could use the Microsoft-specific function _getch:

您可以使用 Microsoft 特定的函数_getch

#include <iostream>
#include <conio.h>
// ...
// ...
// ...
cout << "Press any key to continue..." << endl;
_getch();
cout << "Something" << endl;

回答by Rohit Vipin Mathews

This works on a Windows Platform:It Uses the Microprocessor registers directly and can be used to check key press or mousebutton

这适用于 Windows 平台:它直接使用微处理器寄存器,可用于检查按键或鼠标按钮

    #include<stdio.h>
    #include<conio.h>
    #include<dos.h>
    void main()
    {
     clrscr();
     union REGS in,out;
     in.h.ah=0x00;
     printf("Press any key : ");

     int86(0x16,&in,&out);
     printf("Ascii : %d\n",out.h.al);
     char ch = out.h.al;
     printf("Charcter Pressed : %c",&ch);
     printf("Scan code : %d",out.h.ah);
     getch();
    }

回答by John Doe

If you're using Visual Studio 2012 or older, use the getch()function, if you are using Visual Studio 2013 or newer, use _getch(). You will have to use #include <conio.h>. Example:

如果您使用的是 Visual Studio 2012 或更早版本,请使用该getch()函数,如果您使用的是 Visual Studio 2013 或更高版本,请使用_getch(). 您将不得不使用#include <conio.h>. 例子:

#include <iostream>
#include <conio.h>

int main()
{
   std::cout << "Press any key to continue. . .\n";
   _getch(); //Or getch()
}

回答by Nick Dandoulakis

You can use the getcharroutine.

您可以使用getchar例程。

From the above link:

从上面的链接:

/* getchar example : typewriter */
#include <stdio.h>

int main ()
{
  char c;
  puts ("Enter text. Include a dot ('.') in a sentence to exit:");
  do {
    c=getchar();
    putchar (c);
  } while (c != '.');
  return 0;
}