programing

단일 문자 읽기 전용으로 getchar()를 사용하여 Enter 키를 누르지 않도록 하려면 어떻게 해야 합니까?

coolbiz 2023. 1. 27. 21:58
반응형

단일 문자 읽기 전용으로 getchar()를 사용하여 Enter 키를 누르지 않도록 하려면 어떻게 해야 합니까?

다음 코드:

#include <stdio.h>

int main(void) {   
  int c;   
  while ((c=getchar())!= EOF)      
    putchar(c); 
  return 0;
}

입력한 모든 문자를 인쇄하려면 를 눌러야 합니다.getchar하지만 나는 이것을 하고 싶지 않다. 내가 하고 싶은 것은 글자를 눌러서 내가 소개한 글자가 누르지 않고 바로 반복되는 것을 보는 것이다.예를 들어, 문자 'a'를 누르면 옆에 다른 'a'가 표시됩니다.

aabbccddeeff.....

그러나 'a'를 누르면 아무 일도 일어나지 않고 다른 문자를 쓸 수 있으며 다음을 누를 때만 복사본이 나타납니다.

abcdef
abcdef

이거 어떻게 해?

.cc -o example example.c우분투의

OS에 으로 활성화되어.UNIX와 같은 환경에 있는 경우 ICANON 플래그는 디폴트로 유효하게 되어 있기 때문에 입력은 다음까지 버퍼링됩니다.'\n' ★★★★★★★★★★★★★★★★★」EOF됩니다. 표준 모드를 비활성화하면 캐릭터가 즉시 표시됩니다.이는 다른 플랫폼에서도 가능하지만 직접적인 크로스 플랫폼 솔루션은 없습니다.

편집: Ubuntu를 사용하도록 지정하셨습니다.어제 비슷한 글을 올렸습니다만, 이것으로 단말기의 많은 디폴트 동작이 무효가 됩니다.

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


int main(void){   
    int c;   
    static struct termios oldt, newt;

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

    /*ICANON normally 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);          

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

    /*This is your part:
    I choose 'e' to end input. Notice that EOF is also turned off
    in the non-canonical mode*/
    while((c=getchar())!= 'e')      
        putchar(c);                 

    /*restore the old settings*/
    tcsetattr( STDIN_FILENO, TCSANOW, &oldt);


    return 0;
}

모든 캐릭터가 두 번 나타납니다.이 입력된 을 "Dell"로 입니다.putchar()입력과 출력의 관련성을 해제하려면 ECHO 플래그를 켜야 합니다.적절한 행을 변경하여 다음과 같이 할 수 있습니다.

newt.c_lflag &= ~(ICANON | ECHO); 

시스템에서는 Linux 를 할 수 .stty명령어를 입력합니다.기본적으로는 단말기는 C 프로그램으로 전송하기 전에 를 누를 때까지 모든 정보를 버퍼링합니다.

프로그램 자체에서 동작을 변경할 수 있는 빠르고 더럽고 특별히 휴대할 수 없는 예:

#include<stdio.h>
#include<stdlib.h>

int main(void){
  int c;
  /* use system call to make terminal send all keystrokes directly to stdin */
  system ("/bin/stty raw");
  while((c=getchar())!= '.') {
    /* type a period to break out of the loop, since CTRL-D won't work raw */
    putchar(c);
  }
  /* use system call to set terminal behaviour to more normal behaviour */
  system ("/bin/stty cooked");
  return 0;
}

'아까는 게 좋을 것 같다'는최적인 점에 해 주세요.그것은 단지 다음과 같은 것을 상정하고 있기 때문입니다.stty cooked원래 터미널 설정이 무엇이었는지 확인하는 것이 아니라 프로그램 종료 시 필요한 동작입니다.또한 특수 처리는 모두 raw 모드에서 건너뛰기 때문에 많은 키 시퀀스(CTRL-C 또는 CTRL-D 등)는 프로그램에서 명시적으로 처리하지 않으면 실제로 예상대로 작동하지 않습니다.

하면 돼요.man stty달성하려는 항목에 따라 터미널 동작을 보다 효과적으로 제어할 수 있습니다.

getchar()는 많은 플랫폼에서 ENTER 키를 누를 때까지 입력이 버퍼링되기 때문에 입력을 받기 위해 ENTER 키를 눌러야 하는 표준 함수입니다.많은 컴파일러/플랫폼은 ENTER에 관심이 없는 비표준 getch()를 지원합니다(플랫폼 버퍼링을 건너뛰고 ENTER를 다른 키처럼 취급합니다).

"로 압박하지 않는 방법"

우선 단말기 입력은 일반적으로 회선 또는 완전 버퍼 중 하나입니다.은, 합니다.일반적으로 이 버퍼는 다음과 같은 경우에 프로그램으로 플러시됩니다. \n제공되었습니다.stdin이것은 프레스에 의해 to에 의해 작성된 것입니다.

getchar()쇠사슬의 끝에 있습니다.버퍼링 프로세스에 실제로 영향을 주는 기능은 없습니다.


"어떻게 해야?"

특정 시스템 호출을 사용하여 다른 응답에서 설명한 것처럼 단말기의 동작을 명시적으로 변경할 필요가 없는 경우 우선 폐기합니다.

유감스럽게도 표준 라이브러리 기능은 없으며, 단일 문자 입력 시 버퍼를 플러시할 수 있는 휴대용 방법도 없습니다.다만, 실장 베이스의 솔루션과 포터블이 아닌 솔루션이 있습니다.


Windows/MS-DOS 에서는, 헤더 파일내에 와 함수가 있습니다.이 함수는 원하는 대로 동작합니다.새 행이 버퍼를 플러시 할 때까지 기다리지 않고 한 글자를 읽습니다.

와의 주요 차이점은 가 콘솔에서 실제 입력 문자를 즉시 출력하지 않는다는 것입니다.추가 정보"e"echo를 나타냅니다.

예:

#include <stdio.h>
#include <conio.h>   

int main (void) 
{
    int c;

    while ((c = getche()) != EOF)
    {
        if (c == '\n')
        {
            break;
        }

        printf("\n");
    }

    return 0;
}

Linux에서 직접 문자 처리 및 출력을 얻는 방법은 ncurses-라이브러리 내의 옵션 및 루틴을 사용하는 것입니다.

를 사용하여 이른바 표준 화면을 초기화하고 루틴을 사용하여 동일한 화면을 닫아야 합니다.

예:

#include <stdio.h>
#include <ncurses.h>   

int main (void) 
{
    int c;

    cbreak(); 
    echo();

    initscr();

    while ((c = getch()) != ERR)
    {
        if (c == '\n')
        {
            break;
        }

        printf("\n");
        refresh();
    }

    endwin();

    return 0;
}

를 기동하려면 , 「」를 .-lncursesncurses - ncurses - ncurses - ncurs - ncurs - ncurses - ncurs - ncurs - ncurs - ncurs - ncurs - ncurs - ncurs

ncurses를 사용할 수 .getch()getchar().

나는 루카스의 대답을 좋아하지만, 조금 더 자세히 설명하고 싶다. there in in in in in in in in in in in in in 에는 기능이 내장되어 있습니다.termios.h '''cfmakeraw()다음과 같이 설명합니다.

cfmakeraw() sets the terminal to something like the "raw" mode of the
old Version 7 terminal driver: input is available character by
character, echoing is disabled, and all special processing of
terminal input and output characters is disabled. [...]

이것은 기본적으로 Lucas가 제안한 것과 동일하며, man 페이지 termios(3)에서 설정한 정확한 플래그를 확인할 수 있습니다.

사용 사례

int c = 0;
static struct termios oldTermios, newTermios;

tcgetattr(STDIN_FILENO, &oldTermios);
newTermios = oldTermios;

cfmakeraw(&newTermios);

tcsetattr(STDIN_FILENO, TCSANOW, &newTermios);
c = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &oldTermios);

switch (c) {
    case 113: // q
        printf("\n\n");
        exit(0);
        break;
    case 105: // i
        printf("insert\n");
        break;
    default:
        break;

I/O는 운영 체제 기능입니다.대부분의 경우 운영체제는 ENTER를 누를 때까지 입력된 문자를 프로그램에 전달하지 않습니다.이를 통해 사용자는 프로그램으로 보내기 전에 입력(백스페이스 및 재입력 등)을 수정할 수 있습니다.대부분의 경우 이 기능은 잘 작동하며 사용자에게 일관된 인터페이스를 제공하여 프로그램에서 이 문제를 해결할 필요가 없어집니다.경우에 따라서는 프로그램이 키를 누를 때 키에서 문자를 가져오는 것이 바람직합니다.

C 라이브러리 자체는 파일을 다루며 데이터가 입력 파일에 어떻게 들어오는지는 상관하지 않습니다.따라서 언어 자체로는 키를 누를 때 키를 얻을 수 있는 방법이 없습니다.대신 플랫폼에 따라 다릅니다.OS나 컴파일러를 지정하지 않았기 때문에 조회할 수 없습니다.

표준 통상은 .은 C라이브러리에 .C솔루션은 ''입니다.따라서 C 솔루션이 있습니다.그것은fflush(stdout);아, 네.그 후, 문자가 곧바로 표시되는지는 operating system에 따라 다르지만, 익숙한 OS라면 모두 즉시 출력이 표시되므로, 통상은 문제가 되지 않습니다.

Unix 파생 모델(Ubuntu)에서 작업하고 있기 때문에 권장되지는 않지만 (명령어를 정확하게 입력할 수 있는 한) 동작합니다.

echo "stty -g $(stty -g)" > restore-sanity
stty cbreak
./your_program

프로그램이 지루할 때 인터럽트를 사용하여 프로그램을 중지합니다.

sh restore-sanity
  • 'echo' 행은 현재 터미널 설정을 복원하는 셸 스크립트로 저장합니다.
  • 'stty' 행은 특수 처리의 대부분을 끄고(예: 효과가 없음) 문자를 사용할 수 있는 즉시 프로그램으로 전송합니다.더 이상 타이핑을 편집할 수 없습니다.
  • 'sh' 행은 원래 터미널 설정을 되돌립니다.

'stty sane'이 당신의 목적에 맞게 충분히 정확하게 설정을 복원한다면 당신은 절약 할 수 있다.'-g' 형식은 'stty' 버전 간에 이식할 수 없습니다(Solaris 10에서 생성된 것은 Linux에서 동작하지 않습니다). 단, 그 개념은 어디에서나 유효합니다.「stty sane」옵션은, AFAIK(Linux에서는 이용하실 수 없습니다).

디폴트로는 C 라이브러리는 리턴이 검출될 때까지 출력을 버퍼링합니다.즉시 하려면 , 「 」를 사용합니다.fflush:

while((c=getchar())!= EOF)      
{
    putchar(c);
    fflush(stdout);
}

네, Windows에서도 할 수 있습니다.아래 코드는 conio를 사용하는 것입니다.h 라이브러리

#include <iostream> //basic input/output
#include <conio.h>  //provides non standard getch() function
using namespace std;

int main()
{  
  cout << "Password: ";  
  string pass;
  while(true)
  {
             char ch = getch();    

             if(ch=='\r'){  //when a carriage return is found [enter] key
             cout << endl << "Your password is: " << pass <<endl; 
             break;
             }

             pass+=ch;             
             cout << "*";
             }
  getch();
  return 0;
}

현재 작업 중인 과제에서 이 문제/질문이 발생했습니다.또, 어느 입력으로부터 취득하고 있는지에 따라서도 다릅니다.사용하고 있다

/dev/tty

프로그램 실행 중에 입력을 받기 위해서는 명령어와 관련된 파일스트림이 필요합니다.

테스트/타깃을 해야 하는 우분투 머신에서는 단순히 필요한 것 이상의 것이 필요했습니다.

system( "stty -raw" );

또는

system( "stty -icanon" );

다음과 같이 --file 플래그와 명령어 경로를 추가해야 했습니다.

system( "/bin/stty --file=/dev/tty -icanon" );

이제 모든 게 정상이에요.

이 암호는 나에게 효과가 있었어.주의: 대부분의 컴파일러(GCC 사용)가 지원하는 경우에도 표준 라이브러리의 일부가 아닙니다.

#include <stdio.h>
#include <conio.h>
int main(int argc, char const *argv[]) {
    char a = getch();
    printf("You typed a char with an ASCII value of %d, printable as '%c'\n", a, a);
    return 0;
}

이 코드는 첫 번째 키 누름을 감지합니다.

다음을 확인하는 새 함수를 만들 수 있습니다.

#include <stdio.h>

char getChar()
{
    printf("Please enter a char:\n");

    char c = getchar();
    if (c == '\n')
    {
        c = getchar();
    }

    return c;
}

int main(int argc, char *argv[])
{
    char ch;
    while ((ch = getChar()) != '.')
    {
        printf("Your char: %c\n", ch);
    }

    return 0;
}

<conio>의 getch() 대신 _getch()를 사용할 수 있습니다.h>

언급URL : https://stackoverflow.com/questions/1798511/how-to-avoid-pressing-enter-with-getchar-for-reading-a-single-character-only

반응형