IT

Enter를 누르지 않고 표준 입력에서 문자를 캡처합니다.

lottoking 2020. 6. 2. 21:13
반응형

Enter를 누르지 않고 표준 입력에서 문자를 캡처합니다.


나는 종종 그렇게하지 않기 때문에 내가 어떻게하는지 기억할 수 없다. 그러나 C 또는 C ++에서 줄 바꿈을 기다리지 않고 표준 입력에서 문자를 읽는 가장 좋은 방법은 무엇입니까 (Enter를 누르십시오).

또한 입력 문자를 화면에 에코하지 않는 것이 이상적입니다. 콘솔 화면에 영향을 미치지 않고 키 입력을 캡처하고 싶습니다.


순수한 C ++에서는 이식 가능한 방식으로 불가능합니다. 연결 된 터미널에 너무 많이 의존하기 때문입니다 stdin(일반적으로 라인 버퍼링 됨). 그러나이를 위해 라이브러리를 사용할 수 있습니다.

  1. conio는 Windows 컴파일러에서 사용 가능합니다. _getch()기능을 사용하여 Enter 키를 기다리지 않고 문자를 제공하십시오. 나는 빈번한 Windows 개발자는 아니지만, 반 친구들이 그것을 포함 <conio.h>하고 사용하는 것을 보았습니다 . conio.hWikipedia를 참조하십시오 . 그것은 나열 getch()Visual C ++에서 사용되지 선언된다.

  2. Linux에서 사용할 수있는 저주. Windows에서도 호환되는 curses 구현을 사용할 수 있습니다. getch()기능 있습니다. ( man getch맨 페이지를 보려고 시도하십시오 ). Wikipedia의 저주참조하십시오 .

크로스 플랫폼 호환성을 목표로하는 경우 curses를 사용하는 것이 좋습니다. 즉, 라인 버퍼링을 해제하는 데 사용할 수있는 기능이 있다고 확신합니다 ( "요리 모드"와 달리 "원시 모드"라고 생각합니다 man stty.). 내가 실수하지 않으면 저주는 휴대용 방식으로 당신을 위해 그것을 처리 할 것입니다.


Linux (및 기타 유닉스 계열 시스템)에서는 다음과 같은 방법으로 수행 할 수 있습니다.

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

기본적으로 표준 모드 (및 에코를 억제하려면 에코 모드)를 꺼야합니다.


동일한 문제를 해결하는 동안 다른 포럼에서 이것을 발견했습니다. 내가 찾은 것에서 약간 수정했습니다. 잘 작동합니다. 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; 
}

코니 오

필요한 기능은 다음과 같습니다.

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.

libconio http://sourceforge.net/projects/libconio

또는

conio.h의 Linux C ++ 구현 http://sourceforge.net/projects/linux-conioh


#include <conio.h>

if (kbhit() != 0) {
    cout << getch() << endl;
}

이 용도는 kbhit()키보드를 누를 사용되는 경우 확인 getch()누르고있는 캐릭터를 얻을 수 있습니다.


창문에 있다면 PeekConsoleInput사용 하여 입력이 있는지 감지 할 수 있습니다 .

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

솔직히 말하면 이것은 내가 가지고있는 오래된 코드에서 온 것이므로 약간만 사용해야합니다.

멋진 점은 아무 것도 묻지 않고 입력을 읽으므로 문자가 전혀 표시되지 않는다는 것입니다.


Windows를 가정하면 ReadConsoleInput 함수를 살펴보십시오 .


C and C++ take a very abstract view of I/O, and there is no standard way of doing what you want. There are standard ways to get characters from the standard input stream, if there are any to get, and nothing else is defined by either language. Any answer will therefore have to be platform-specific, perhaps depending not only on the operating system but also the software framework.

There's some reasonable guesses here, but there's no way to answer your question without knowing what your target environment is.


The closest thing to portable is to use the ncurses library to put the terminal into "cbreak mode". The API is gigantic; the routines you'll want most are

  • initscr and endwin
  • cbreak and nocbreak
  • getch

Good luck!


I use kbhit() to see if a char is present and then getchar() to read the data. On windows, you can use "conio.h". On linux, you will have to implement your own kbhit().

See code below:

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

The following is a solution extracted from Expert C Programming: Deep Secrets, which is supposed to work on SVr4. It uses stty and ioctl.

#include <sys/filio.h>
int kbhit()
{
 int i;
 ioctl(0, FIONREAD, &i);
 return i; /* return a count of chars available to read */
}
main()
{
 int i = 0;
 intc='';
 system("stty raw -echo");
 printf("enter 'q' to quit \n");
 for (;c!='q';i++) {
    if (kbhit()) {
        c=getchar();
       printf("\n got %c, on iteration %d",c, i);
    }
}
 system("stty cooked echo");
}

I always wanted a loop to read my input without pressing return key. this worked for me.

#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
      }

    }

works for me on windows:

#include <conio.h>
char c = _getch();

ncurses provides a nice way to do this! Also this is my very first post (that I can remember), so any comments at all are welcome. I will appreciate useful ones, but all are welcome!

to compile: g++ -std=c++11 -pthread -lncurses .cpp -o

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

You can do it portably using SDL (the Simple DirectMedia Library), though I suspect you may not like its behavior. When I tried it, I had to have SDL create a new video window (even though I didn't need it for my program) and have this window "grab" almost all keyboard and mouse input (which was okay for my usage but could be annoying or unworkable in other situations). I suspect it's overkill and not worth it unless complete portability is a must--otherwise try one of the other suggested solutions.

By the way, this will give you key press and release events separately, if you're into that.

참고URL : https://stackoverflow.com/questions/421860/capture-characters-from-standard-input-without-waiting-for-enter-to-be-pressed

반응형