如何模拟"按任意键继续?"

its*_*ode 78 c++

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

这是我的代码:

char c;

cin>>c;

cout<<"Something"<<endl;
Run Code Online (Sandbox Code Playgroud)

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

要么

如果我用这个

cin.get() or cin.get(c)
Run Code Online (Sandbox Code Playgroud)

按Enter键进入下一行指令.

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

小智 56

在Windows上:

system("pause");
Run Code Online (Sandbox Code Playgroud)

在Mac和Linux上:

system("read");
Run Code Online (Sandbox Code Playgroud)

将输出"按任意键继续...",显然,等待按任何键.我希望那就是你的意思

  • 忘了慢,它调用第一个名为"pause"的程序,碰巧在PATH中找到它,并给它调用程序的权限级别.即使您是学生只是测试自己的代码,它仍然是一个巨大的安全风险. (11认同)
  • 没错,但它只有一条线!有时,将计算机保存一段时间是不值得的. (8认同)
  • @XDfaceme - pause是system()要求windows运行的实际程序.但是,如果有另一个名为'pause'的程序,并且Windows首先找到该程序,它将运行它.我想我可能会过分夸大其重要性,但是使用cin.get()并点击返回以暂停/取消暂停程序仍然更容易 (5认同)
  • `system`调用外部程序.您无需调用外部程序等待任何密钥!就像打电话给另一个人在你坐在它前面打开电脑一样 - 这是一个缓慢的解决方案. (4认同)
  • 我不是绝对的粉丝。笼统地声明 system("pause") 是一种安全风险,即使在测试您自己的代码时它也很糟糕,这在这里使事情变得不成比例。cin.get() 可能是正确的解决方案,但它并没有解决被问到的问题...... cin.get() 仅在按下“输入”或“返回”后才响应。问题具体是响应任何按键。system("pause") 正是这样做的。首先,我认为这很有用的唯一地方是在从 Visual Studio 调试时的开发类中,所以我认为 system("pause") 可以工作 (2认同)

Vin*_*jip 51

如果您使用的是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;
}
Run Code Online (Sandbox Code Playgroud)

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

gcc -o kbhit kbhit.c
Run Code Online (Sandbox Code Playgroud)

在运行时

./kbhit
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • @Johnsyweb:我知道RAII及其带来的好处,我自己就是一个古老的C++手.我的观点仍然存在:声明与幕后工作之间没有明确的联系.虽然它可能使用闪亮的C++习语而不是普通的旧C语言,但我的观点是它没有什么可以照亮的,而且很难掩盖正在发生的事情.这不是以任何方式针对您个人 - 这只是关于如何使用C++来创建不必要的难以理解的代码的意见.我现在会离开我的肥皂盒,"努夫说. (4认同)
  • 一切都很好,但仍然会在标准输入上捕获任何以前的垃圾:-) (2认同)

Kei*_*son 7

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

comp.lang.c FAQ的问题19.1 涵盖了这个问题,包括Windows,类Unix系统甚至MS-DOS和VMS的解决方案.

快速而不完整的摘要:

  • 你可以使用curses图书馆; 调用cbreak()后跟getch()(不要与Windows特定的getch()功能混淆).注意,curses通常控制终端,所以这可能是过度的.
  • 您可以使用它ioctl()来操纵终端设置.
  • 在POSIX兼容的系统,tcgetattr()并且tcsetattr()可能是一个更好的解决方案.
  • 在Unix上,您可以使用它system()来调用stty命令.
  • 在MS-DOS上,您可以使用getch()getche().
  • 在VMS(现在称为OpenVMS)上,Screen Management(SMG$)例程可能会起作用.

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

  • 所有这些多平台解决方案都可以由某人编写一个函数来完成,该函数的实现是为了根据您的平台做正确的事情,并使用大量预处理器来确定该平台是什么。 (2认同)

Kir*_*sky 6

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

  • 然后,唯一的选择是为您计划支持的每个操作系统实现所需的功能. (2认同)

Luc*_*cas 5

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

我不知道 Vinay 如何知道你正在使用 Mac OS X。但对于大多数类 UNIX 操作系统来说,它应该像这样工作。非常有帮助,因为资源是opengroup.org

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

#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;
}
Run Code Online (Sandbox Code Playgroud)

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

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


Sal*_*n A 5

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

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


小智 5

这很简单.我制作了一个程序,它的工作非常完美......这就是程序.

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

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\nSee, Its Working....Have a Good day";
    getch();
}
Run Code Online (Sandbox Code Playgroud)

  • conio 仅适用于 Windows (3认同)