C++ 从标准输入捕获字符,无需等待按enter键

C++ 从标准输入捕获字符,无需等待按enter键,c++,c,inputstream,C++,C,Inputstream,我永远记不起我是怎么做到的,因为我很少想到这一点。但是在C或C++中,从标准输入中读取字符的最好方法是不等待换行(按下回车)。 理想情况下,它不会将输入字符回显到屏幕上。我只想捕获击键而不影响控制台屏幕。 在纯C++中,这是不可能的,因为它太依赖于与“代码”> STDIN < /代码>连接的终端(它们通常是行缓冲的)。但是,您可以使用库进行以下操作: conio可用于Windows编译器。使用\u getch()函数为您提供一个字符,而无需等待回车键。我不是一个经常使用Windows的开发人员,

我永远记不起我是怎么做到的,因为我很少想到这一点。但是在C或C++中,从标准输入中读取字符的最好方法是不等待换行(按下回车)。
理想情况下,它不会将输入字符回显到屏幕上。我只想捕获击键而不影响控制台屏幕。

在纯C++中,这是不可能的,因为它太依赖于与“代码”> STDIN < /代码>连接的终端(它们通常是行缓冲的)。但是,您可以使用库进行以下操作:

  • conio可用于Windows编译器。使用
    \u getch()
    函数为您提供一个字符,而无需等待回车键。我不是一个经常使用Windows的开发人员,但我看到我的同学只使用了
    。见维基百科。它列出了 > GETCHE.()/<代码>。p>
  • 可用于Linux的诅咒。Windows也可以使用兼容的curses实现。它还有一个
    getch()
    函数。(尝试
    mangetch
    查看其手册页)。见维基百科


  • 如果你想实现跨平台兼容性,我建议你使用诅咒。这就是说,我确信有一些函数可以用来关闭缓存线(我认为这叫做“原始模式”,而不是“熟食模式”——查看
    manstty
    )。如果我没弄错的话,诅咒会以便携的方式为你处理

    >假设Windows,请参阅<强> RealCuloSealEng/<强>函数。

    C和C++对I/O采取非常抽象的视图,没有标准的方法来做您想要的。有标准的方法从标准输入流中获取字符(如果有),其他任何语言都没有定义。因此,任何答案都必须是特定于平台的,可能不仅取决于操作系统,还取决于软件框架

    这里有一些合理的猜测,但如果不知道目标环境是什么,就无法回答您的问题。

    CONIO.H

    您需要的功能包括:

    int getch();
    Prototype
        int _getch(void); 
    Description
        _getch obtains a character  from stdin. Input is unbuffered, and this
        routine  will  return as  soon as  a character is  available  without 
        waiting for a carriage return. The character is not echoed to stdout.
        _getch bypasses the normal buffering done by getchar and getc. ungetc 
        cannot be used with _getch. 
    Synonym
        Function: getch 
    
    
    int kbhit();
    Description
        Checks if a keyboard key has been pressed but not yet read. 
    Return Value
        Returns a non-zero value if a key was pressed. Otherwise, returns 0.
    
    利科尼奥

    Linux C++的CONIO.H实现


    最接近便携式的方法是使用库将终端置于“cbreak模式”。API是巨大的;你最想要的常规是

    • initscr
      endwin
    • cbreak
      nocbreak
    • getch

    祝你好运

    如果您在windows上,您可以使用来检测是否有任何输入

    HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
    DWORD events;
    INPUT_RECORD buffer;
    PeekConsoleInput( handle, &buffer, 1, &events );
    
    然后使用ReadConsoleInput“使用”输入字符

    PeekConsoleInput(handle, &buffer, 1, &events);
    if(events > 0)
    {
        ReadConsoleInput(handle, &buffer, 1, &events);  
        return buffer.Event.KeyEvent.wVirtualKeyCode;
    }
    else return 0
    
    老实说,这是我的一些旧代码,所以你必须稍微修改一下


    不过,最酷的是,它读取输入时没有任何提示,因此字符根本不会显示。

    以下是从专家C编程中提取的解决方案:Deep Secrets,它应该可以在SVr4上工作。它使用stty和ioctl

    #包括
    int kbhit()
    {
    int i;
    ioctl(0、FIONREAD和i);
    return i;/*返回可读取的字符数*/
    }
    main()
    {
    int i=0;
    intc='';
    系统(“stty原始回波”);
    printf(“输入'q'退出\n”);
    for(;c!='q';i++){
    if(kbhit()){
    c=getchar();
    printf(“\n在迭代%d时得到%c”,c,i);
    }
    }
    系统(“stty-echo”);
    }
    
    我在另一个论坛上发现了这个问题,当时我正在寻找解决同样问题的方法。根据我的发现,我对它做了一些修改。它工作得很好。我运行的是OS X,因此如果您运行的是Microsoft,则需要找到正确的system()命令以切换到原始模式和熟食模式

    #include <iostream> 
    #include <stdio.h>  
    using namespace std;  
    
    int main() { 
      // Output prompt 
      cout << "Press any key to continue..." << endl; 
    
      // Set terminal to raw mode 
      system("stty raw"); 
    
      // Wait for single character 
      char input = getchar(); 
    
      // Echo input:
      cout << "--" << input << "--";
    
      // Reset terminal to normal "cooked" mode 
      system("stty cooked"); 
    
      // And we're out of here 
      return 0; 
    }
    
    #包括
    #包括
    使用名称空间std;
    int main(){
    //输出提示
    cout在Linux(和其他类似unix的系统)上,这可以通过以下方式完成:

    #include <unistd.h>
    #include <termios.h>
    
    char getch() {
            char buf = 0;
            struct termios old = {0};
            if (tcgetattr(0, &old) < 0)
                    perror("tcsetattr()");
            old.c_lflag &= ~ICANON;
            old.c_lflag &= ~ECHO;
            old.c_cc[VMIN] = 1;
            old.c_cc[VTIME] = 0;
            if (tcsetattr(0, TCSANOW, &old) < 0)
                    perror("tcsetattr ICANON");
            if (read(0, &buf, 1) < 0)
                    perror ("read()");
            old.c_lflag |= ICANON;
            old.c_lflag |= ECHO;
            if (tcsetattr(0, TCSADRAIN, &old) < 0)
                    perror ("tcsetattr ~ICANON");
            return (buf);
    }
    
    #包括
    #包括
    char getch(){
    char-buf=0;
    结构termios old={0};
    if(tcgetattr(0,&old)<0)
    perror(“tcSetttr()”);
    old.c_lflag&=~ICANON;
    old.c_lflag&=~ECHO;
    old.c_cc[VMIN]=1;
    old.c_cc[VTIME]=0;
    if(tcsetattr(0、TCSANOW和old)<0)
    佩罗尔(“tcsetattr ICANON”);
    如果(读取(0,&buf,1)<0)
    perror(“read()”);
    old.c|lflag |=ICANON;
    old.c|lflag |=回声;
    if(tcsetattr(0、TCSADRAIN和old)<0)
    佩罗尔(“tcsetattr~ICANON”);
    返回(buf);
    }
    
    基本上,您必须关闭规范模式(和回音模式以抑制回音)。

    #包括
    如果(kbhit()!=0){
    
    你可以使用SDL(简单的DirectMedia库)进行移植,尽管我怀疑你可能不喜欢它的行为。当我尝试它时,我不得不让SDL创建一个新的视频窗口(尽管我的程序不需要它),并让这个窗口“抓取”几乎所有的键盘和鼠标输入(这对我的使用来说还行,但在其他情况下可能会很烦人或不可行)。我怀疑这有点过分,不值得这么做,除非必须具备完全的可移植性——否则请尝试其他建议的解决方案


    顺便说一句,如果您喜欢的话,这将分别为您提供按键和释放事件。

    我一直希望有一个循环来读取我的输入,而无需按返回键。 这对我有用

    #include<stdio.h>
     main()
     {
       char ch;
        system("stty raw");//seting the terminal in raw mode
        while(1)
         {
         ch=getchar();
          if(ch=='~'){          //terminate or come out of raw mode on "~" pressed
          system("stty cooked");
         //while(1);//you may still run the code 
         exit(0); //or terminate
         }
           printf("you pressed %c\n ",ch);  //write rest code here
          }
    
        }
    
    #包括
    main()
    {
    char ch;
    系统(“stty raw”);//在raw模式下设置终端
    而(1)
    {
    ch=getchar();
    如果(ch=='~'){//在按下“~”时终止或退出原始模式
    系统(“stty熟食”);
    //while(1);//您仍然可以运行代码
    退出(0);//或终止
    }
    printf(“您按了%c\n”,ch);//在此处编写rest代码
    }
    }
    
    在windows上对我有效:

    #include <conio.h>
    char c = _getch();
    
    #包括
    char c=_getch();
    
    我使用kbhit()来查看是否存在字符,然后使用getchar()
    #include<stdio.h>
     main()
     {
       char ch;
        system("stty raw");//seting the terminal in raw mode
        while(1)
         {
         ch=getchar();
          if(ch=='~'){          //terminate or come out of raw mode on "~" pressed
          system("stty cooked");
         //while(1);//you may still run the code 
         exit(0); //or terminate
         }
           printf("you pressed %c\n ",ch);  //write rest code here
          }
    
        }
    
    #include <conio.h>
    char c = _getch();
    
    // kbhit
    #include <stdio.h>
    #include <sys/ioctl.h> // For FIONREAD
    #include <termios.h>
    #include <stdbool.h>
    
    int kbhit(void) {
        static bool initflag = false;
        static const int STDIN = 0;
    
        if (!initflag) {
            // Use termios to turn off line buffering
            struct termios term;
            tcgetattr(STDIN, &term);
            term.c_lflag &= ~ICANON;
            tcsetattr(STDIN, TCSANOW, &term);
            setbuf(stdin, NULL);
            initflag = true;
        }
    
        int nbbytes;
        ioctl(STDIN, FIONREAD, &nbbytes);  // 0 is STDIN
        return nbbytes;
    }
    
    // main
    #include <unistd.h>
    
    int main(int argc, char** argv) {
        char c;
        //setbuf(stdout, NULL); // Optional: No buffering.
        //setbuf(stdin, NULL);  // Optional: No buffering.
        printf("Press key");
        while (!kbhit()) {
            printf(".");
            fflush(stdout);
            sleep(1);
        }
        c = getchar();
        printf("\nChar received:%c\n", c);
        printf("Done.\n");
    
        return 0;
    }
    
    #include <iostream>
    #include <ncurses.h>
    #include <future>
    
    char get_keyboard_input();
    
    int main(int argc, char *argv[])
    {
        initscr();
        raw();
        noecho();
        keypad(stdscr,true);
    
        auto f = std::async(std::launch::async, get_keyboard_input);
        while (f.wait_for(std::chrono::milliseconds(20)) != std::future_status::ready)
        {
            // do some work
        }
    
        endwin();
        std::cout << "returned: " << f.get() << std::endl;
        return 0;
    }
    
    char get_keyboard_input()
    {
        char input = '0';
        while(input != 'q')
        {
            input = getch();
        }
        return input;
    }
    
    #include <unistd.h>
    #include <termios.h>
    #include <stdio.h>
    #include <string.h>
    
    char* getStr( char* buffer , int maxRead ) {
      int  numRead  = 0;
      char ch;
    
      struct termios old = {0};
      struct termios new = {0};
      if( tcgetattr( 0 , &old ) < 0 )        perror( "tcgetattr() old settings" );
      if( tcgetattr( 0 , &new ) < 0 )        perror( "tcgetaart() new settings" );
      cfmakeraw( &new );
      if( tcsetattr( 0 , TCSADRAIN , &new ) < 0 ) perror( "tcssetattr makeraw new" );
    
      for( int i = 0 ; i < maxRead ; i++)  {
        ch = getchar();
        switch( ch )  {
          case EOF: 
          case '\n':
          case '\r':
            goto exit_getStr;
            break;
    
          default:
            printf( "%1c" , ch );
            buffer[ numRead++ ] = ch;
            if( numRead >= maxRead )  {
              goto exit_getStr;
            }
            break;
        }
      }
    
    exit_getStr:
      if( tcsetattr( 0 , TCSADRAIN , &old) < 0)   perror ("tcsetattr reset to old" );
      printf( "\n" );   
      return buffer;
    }
    
    
    int main( void ) 
    {
      const int maxChars = 20;
      char      stringBuffer[ maxChars+1 ];
      memset(   stringBuffer , 0 , maxChars+1 ); // initialize to 0
    
      printf( "enter a string: ");
      getStr( stringBuffer , maxChars );
      printf( "you entered: [%s]\n" , stringBuffer );
    }