단일 문자 만 읽기 위해 getchar ()로 Enter 키를 누르는 것을 피하는 방법은 무엇입니까?


80

다음 코드에서 :

으로 Enter입력 한 모든 글자를 인쇄 하려면을 눌러야 하는데이 getchar작업은하고 싶지 않습니다.하고 싶은 것은를 누르지 않고 소개 한 글자를 즉시 ​​반복해서 보는 것 Enter입니다. 예를 들어, 문자 'a'를 누르면 옆에 다른 'a'가 표시됩니다.

하지만 'a'를 눌러도 아무 일도 일어나지 않으면 다른 글자를 쓸 수 있고 다음을 누를 때만 사본이 나타납니다 Enter.

어떻게 할 수 있습니까?

cc -o example example.c컴파일을 위해 Ubuntu 에서 명령을 사용하고 있습니다.


5
이것은 OS 및 터미널이 입력을 처리하는 방법에 따라 크게 달라집니다. 운영 환경을 지정하면 더 나은 답을 얻을 수 있습니다.
goldPseudo

cplusplus.com/forum/articles/19975에 제공된 답변 은 WinAPI를 사용하는 Windows 에서 작동합니다.

답변:


72

Linux 시스템에서는 stty명령을 사용하여 터미널 동작을 수정할 수 있습니다 . 기본적으로 터미널 Enter은를 누를 때까지 모든 정보를 버퍼링 하고 C 프로그램으로 보내기도합니다.

프로그램 자체에서 동작을 변경하는 빠르고 더럽고 특별히 이식 할 수없는 예제 :

이것은 stty cooked원래 터미널 설정이 무엇인지 확인하는 것이 아니라 프로그램이 종료 될 때 원하는 동작 이라고 가정하기 때문에 실제로 최적이 아닙니다 . 또한 모든 특수 처리가 원시 모드에서 건너 뛰기 때문에 많은 키 시퀀스 (예 : CTRL-C 또는 CTRL-D )가 프로그램에서 명시 적으로 처리하지 않으면 예상대로 작동하지 않습니다.

man stty정확히 달성하려는 것에 따라 터미널 동작을 더 많이 제어 할 수 있습니다 .


사용 system은 나쁜 생각입니다.
Sapphire_Brick

너무 많은 원시 .... 나는 ENTER를 기다릴 수없는 해결책을 찾고 있었다. 이 솔루션은 모든 입력 단자 기능을 제동합니다.
ABC

93

이것은 OS에 따라 다르며 UNIX와 같은 환경에있는 경우 ICANON 플래그가 기본적으로 활성화되어 있으므로 입력은 다음 '\n'또는 EOF. 표준 모드를 ​​비활성화하면 즉시 문자를 얻을 수 있습니다. 이것은 다른 플랫폼에서도 가능하지만 직접적인 크로스 플랫폼 솔루션은 없습니다.

편집 : 나는 당신이 우분투를 사용하도록 지정했음을 알았습니다. 어제 비슷한 내용을 게시했지만 이로 인해 터미널의 많은 기본 동작이 비활성화됩니다.

모든 캐릭터가 두 번 나타납니다. 이것은 입력이 즉시 터미널로 다시 에코되고 프로그램이 다시 입력하기 때문 putchar()입니다. 출력에서 입력을 연결 해제하려면 ECHO 플래그도 설정해야합니다. 적절한 줄을 다음과 같이 변경하면됩니다.


9
하나는 TBH 있지만, 이것은 아마도 원래의 포스터와 편안 코드의 수준 아니다)
Andomar

2
큰! 그것이 내가 찾던 것입니다!
Denilson Sá Maia

자세한 설명과 함께 도움을 주셔서 감사합니다. 내 문제가 해결되었습니다.
kaminsknator

너무 기본적인 것이 달성하기가 너무 어렵고 휴대가 불가능하다는 것은 믿기지 않습니다.
Pedro77 20:08에

12

getchar ()는 많은 플랫폼에서 Enter 키를 눌러 입력해야하는 표준 함수입니다. 플랫폼은 해당 키를 누를 때까지 입력을 버퍼링하기 때문입니다. 많은 컴파일러 / 플랫폼은 ENTER를 신경 쓰지 않는 비표준 getch ()를 지원합니다 (플랫폼 버퍼링을 우회하고 ENTER를 다른 키처럼 취급합니다).


1
+1 맞습니다. getchar()Enter 키를 누른 후에 만 ​​문자를 하나씩 읽기 시작합니다
Andomar

32
getchar()ENTER는 신경 쓰지 않고 stdin을 통해 오는 모든 것을 처리합니다. 라인 버퍼링은 OS / 터미널 정의 동작 인 경향이 있습니다.
goldPseudo

1
@goldPseudo : 사실이지만 거의 모든 플랫폼이 입력을 버퍼링하므로 대부분의 실제 사례에서 볼 수있는 동작입니다. 지원되는 경우 getch ()는 버퍼링을 관리하거나 무시합니다. 일부 오래된 DOS 구현은 하드웨어와 직접 상호 작용하기 위해 OS 버퍼링을 우회했습니다. 다른 구현은 동일한 동작을 얻기 위해 stdin을 플러시 할 수 있습니다.
Eric J.

10
그럼에도 불구하고 getchar()“엔터를 눌러야한다”는 것이 아니라 환경이다.
Benji XVI

1
매우 간결하고 이해하기 쉽습니다. 다른 최고 등급의 답변은 불필요한 기술 세부 사항을 압도적으로 던집니다.
mzoz

6

I / O는 운영 체제 기능입니다. 대부분의 경우 운영 체제는 Enter 키를 누를 때까지 입력 한 문자를 프로그램에 전달하지 않습니다. 이를 통해 사용자는 입력을 프로그램으로 보내기 전에 백 스페이스 및 재 입력과 같은 입력을 수정할 수 있습니다. 대부분의 경우 이것은 잘 작동하고 사용자에게 일관된 인터페이스를 제공하며 프로그램이이를 처리하지 않아도됩니다. 어떤 경우에는 프로그램이 키를 누를 때 키에서 문자를 가져 오는 것이 바람직합니다.

C 라이브러리 자체는 파일을 처리하며 데이터가 입력 파일에 들어가는 방식에는 관심이 없습니다. 따라서 언어 자체에서 키를 누를 때 얻을 수있는 방법은 없습니다. 대신 이것은 플랫폼에 따라 다릅니다. OS 나 컴파일러를 지정하지 않으 셨기 때문에 찾아 드릴 수 없습니다.

또한 표준 출력은 일반적으로 효율성을 위해 버퍼링됩니다. 이것은 C 라이브러리에 의해 수행되므로 fflush(stdout);각 문자가 작성된 후에 C 솔루션이 있습니다. 그 후 문자가 즉시 표시되는지 여부는 운영 체제에 달려 있지만 내가 익숙한 모든 OS가 즉시 출력을 표시하므로 일반적으로 문제가되지 않습니다.


6

나는 Lucas 대답을 좋아하지만 조금 더 자세히 설명하고 싶습니다. man이 다음과 같이 설명 하는 termios.hnamed 에 내장 함수가 있습니다.cfmakeraw()

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

사용 사례


참고 cfmakeraw()로 비 휴대용, 비표준 확장 POSIXtermios.h 반드시 사용할 수 없습니다.
Andrew Henle

4

Unix 파생물 (Ubuntu)에서 작업하고 있기 때문에 여기에 한 가지 방법이 있습니다. 권장되지는 않지만 작동합니다 (명령을 정확하게 입력 할 수있는 한).

지루할 때 인터럽트를 사용하여 프로그램을 중지하십시오.

  • 'echo'줄은 현재 터미널 설정을 복원 할 쉘 스크립트로 저장합니다.
  • 'stty'줄은 대부분의 특수 처리를 끄고 ( Control-D예를 들어 효과가 없음) 문자를 사용할 수있는 즉시 프로그램에 보냅니다. 더 이상 타이핑을 편집 할 수 없음을 의미합니다.
  • 'sh'줄은 원래 터미널 설정을 복원합니다.

'stty sane'이 목적에 맞게 설정을 충분히 정확하게 복원하면 절약 할 수 있습니다. '-g'형식은 'stty'버전간에 이식 할 수 없지만 (따라서 Solaris 10에서 생성 된 것은 Linux에서 작동하지 않거나 그 반대의 경우도 마찬가지 임) 개념은 모든 곳에서 작동합니다. 'stty sane'옵션은 보편적으로 사용할 수없는 AFAIK (그러나 Linux에 있음)입니다.


2

'ncurses'라이브러리를 포함하고 getch()대신 getchar().


1

예, Windows에서도이 작업을 수행 할 수 있습니다. conio.h 라이브러리를 사용하는 아래 코드는 다음과 같습니다.


6
문제는 태그입니다 C 가 아니라 C ++
Spikatrix

@CoolGuy 그래서 뭐? 누군가 똑같은 질문을 열었지만 태그를 c에서 C ++로 변경하면 왜 누구에게나 도움이 될까요?
Andreas Haferburg

@AndreasHaferburg 여기에 C ++ 답변이 없기 때문에, 특히 잘못 작성된 답변이 아니기 때문에 wink wink .
Sapphire_Brick

1

현재 작업중인 과제에서이 문제 / 질문이 떠 올랐습니다. 또한 어떤 입력에서 가져 오는지에 따라 다릅니다. 나는 사용하고있다

프로그램이 실행되는 동안 입력을 얻으려면 명령과 관련된 파일 스트림이어야합니다.

우분투 컴퓨터에서 테스트 / 타겟팅해야하는데,

또는

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

이제 모든 것이 copacetic입니다.


2
이 솔루션은 OS에 따라 다릅니다.
Ottavio Campana

0

이 코드는 저에게 효과적이었습니다. 주의 : 대부분의 컴파일러 (GCC 사용)가 지원하더라도 표준 라이브러리의 일부가 아닙니다.

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


0

" 어떻게 누르면 피하기 위해 Enter함께 getchar()? "

우선, 터미널 입력은 일반적으로 라인 또는 완전 버퍼링입니다. 이는 운영 체제가 터미널의 실제 입력을 버퍼에 저장한다는 것을 의미합니다. 일반적으로이 버퍼는 fe \n가에서 신호 화 / 제공 될 때 프로그램으로 플러시됩니다 stdin. 이것은 프레스에 의해 만들어진 fe Enter입니다.

getchar()체인의 끝에 있습니다. 실제로 버퍼링 프로세스에 영향을 미칠 수있는 능력이 없습니다.


" 어떻게 할 수 있습니까? "

도랑 getchar()다른 답변에서 잘 설명한 것처럼 터미널의 동작을 명시 적으로 변경하기 위해 특정 시스템 호출을 사용하지 않으려는 경우 우선 입니다.

불행히도 표준 라이브러리 기능이 없으며 단일 문자 입력에서 버퍼를 플러시하는 이식 가능한 방법이 없습니다. 그러나 구현 기반 및 비 휴대용 솔루션이 있습니다.


Windows / MS-DOS 에는 헤더 파일 에 getch()getche()함수 가 있습니다.이 기능은 conio.h원하는 작업을 정확히 수행합니다. 줄 바꿈이 버퍼를 비울 때까지 기다릴 필요없이 단일 문자를 읽습니다.

주요 차이점 getch()getche()getch()동안 콘솔 바로 출력하지 실제 문자 입력을 수행 getche()한다. 추가 "e"echo를 의미합니다 .

예:


Linux에서 직접 문자 처리 및 출력을 얻는 방법은 cbreak()echo()옵션과 getch()refresh() 은 ncurses-library에서 루틴 입니다.

참고, 당신은 소위 초기화하는 데 필요한 표준 화면 과를 initscr()과와 같은를 닫습니다 endwin()루틴.

예:


참고 : -lncurses링커가 ncurses-library를 검색하고 찾을 수 있도록 옵션을 사용 하여 컴파일러를 호출해야합니다 .


-1

기본적으로 C 라이브러리는 반환을 볼 때까지 출력을 버퍼링합니다. 결과를 즉시 인쇄하려면 다음을 사용하십시오 fflush.


2
그러나 출력은 문제의 일부입니다. 질문자는 프로그램이 눌렀을 때 키를 읽고 화면에 즉시 인쇄하기를 원합니다. 그것은 입력 및 출력 문제입니다.
David Thornley

즉 fflush는 출력 만 플러시하지만 getchar는 키를 누른 후에도 여전히 반환되지 않습니다 (키가 버퍼링 됨).
NickSoft
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.