2017-03-16 3 views
0

C에서 sgtpep/pmenu과 같은 앱을 쓰고 싶습니다.C에서 stdin을 올바르게 읽는 방법은 무엇입니까?

그런 다음 ncurses 라이브러리를 살펴보기 시작합니다. 내 첫번째 시도는 메뉴를 선택할 수 있습니다. 예를 들어, 내가 ls | ./a.out 할 때, 그것은 모든 파일을 보여줄 수 있어야하고, DUP 또는 DOWN을 누를 때 첫 번째 것을 강조 표시하면 그에 따라 다른 항목이 강조 표시됩니다.

전체 코드는 here입니다.

프로그램이 키를 누르지 않습니다. 루프 내의 mvprintw(n+1, 0, "%d\n", ch);은 항상 -1을 인쇄합니다.

그런 다음 관련없는 코드를 제거하고 최소한의 예제를 얻습니다.

#include <stdio.h> 

char buf[100]; 

int main(int argc, char **argv) { 
    int ch; 

    while (fgets(buf, sizeof(buf), stdin)) puts(buf); 

    ch = getch(); 
    printf("%d\n", ch); 
    ch = getch(); 
    printf("%d\n", ch); 
    ch = getch(); 
    printf("%d\n", ch); 
    ch = getch(); 
    printf("%d\n", ch); 

    return 0; 
} 

ch 항상 -1입니다. 나는 stdin이 깨끗하지 않으므로 fgets 이후에 fflush(stdin)을 사용하지만 그 결과는 같습니다.

stdin에서 올바른 방법은 무엇입니까?

#include <stdio.h> 

char buf[100]; 

int main(int argc, char **argv) { 
    int ch; 

    while (fgets(buf, sizeof(buf), stdin)) puts(buf); 

    fflush(stdin); 

    ch = getchar(); 
    printf("%d\n", ch); 
    ch = getchar(); 
    printf("%d\n", ch); 
    ch = getchar(); 
    printf("%d\n", ch); 
    ch = getchar(); 
    printf("%d\n", ch); 

    return 0; 
} 

내가 프로그램을 수정, 그래서 그것이 더 이상 ncurses 관련이 없습니다

UPD1


하지만 ls | ./a.out를 실행 ch-1을 보여주는 유지합니다.

UPD2

사용 newterm


inout 작품을 리디렉션합니다. 당신이 그런 식으로 저주하는 표준 입력 전환 위하여려고하는 경우에

FILE *fd = fopen("/dev/tty", "r+"); 
set_term(newterm(NULL, fd, fd)); // instead of initscr() 
noecho(); 
cbreak(); 
keypad(stdscr, TRUE); 

print_menu(cur, n); 

while (true) { 
    ch = getch(); 

    if (ch == KEY_UP || ch == 'k') --cur; 
    else if (ch == KEY_DOWN || ch == 'j') ++cur; 

    cur = (cur + n) % n; 

    print_menu(cur, n); 
} 

endwin(); 
+0

이 질문은 실제로 ncurses 질문입니다. 실제로는 C 질문이 아닙니다. POSIX 시스템에서 C로 읽는 가장 낮은 수준의 API는 실제로'fgets' 메소드가 아니라 POSIX'read' 시스템 호출입니다. 나는 그것이 문제가있는 곳이라고 생각하지 않습니다. 문제는 터미널이 "원시 모드"가 아니라는 것입니다. 터미널을 원시 모드로 설정하는 방법을 기억하지 못합니다. 터미널마다 다를 것이라고 생각합니다. 그리고 ncurses가 이런 종류의 것을 처리하는 초기화 함수를 가지고 있다고 확신합니다. –

+0

print_menu()에 "refresh()"가 표시되지 않습니다. ncurses 애플리케이션 작성에 대한 자세한 내용은 다음을 참조하십시오. http://invisible-island.net/ncurses/ncurses-intro.html – TonyB

+0

@TonyB Thanks! 이것은 복사 및 붙여 넣기 오류입니다 ... 코드 구조를 변경하여 명확하게 만들었지 만'refresh()'를 추가하는 것을 잊어 버렸습니다. – delta

답변

1

, 당신은 표준 입력을 읽는 완료되면, 예를 들어, /dev/tty를 상기 단말 장치를 열해야합니다. 터미널을 열면 newterm (initscr과 달리 입/출력 스트림에 대한 매개 변수가있는)을 사용하여 저주를 초기화 할 수 있습니다.

예를 들어 ncurses test-program 또는 dialog을 참조하십시오.

+0

고마워요! 프로그램을 조금 더 업데이트 했으므로 curses 라이브러리와 관련이 없습니다. 그러나 문제는 여전히 존재합니다. 입력이 파이프되는 동안 입력을 얻으려는 잘못 된 방법이 있습니까? – delta

+0

감사합니다. Thomas! 드디어 당신이 의미하는 바를 얻었습니다. 'newterm'은 다중 터미널이있을 때 작동합니다. – delta

+0

예, 대부분 그렇지만 이와 같은 경우에 사용됩니다. –

-1

curses는 stdin 대신 사용할 수 있습니다.

C 모델은 사용자가 콘솔에서 라인을 작성하여 라인 편집 기능을 제공합니다. 그는 그가 행복 할 때까지 화살표 키를 백 스페이스로 사용하고 줄을 따라 이동할 수 있습니다. 그런 다음 입력을 누르면 프로그램이 전체 행을 가져옵니다. 그런 다음 프로그램은이를 처리하고 대개 다음 줄을 묻는 메시지를 표시합니다.

저주가 키보드를 사용하므로 키 패드로 사용할 수 있습니다. "z"("왼쪽", "x"는 "오른쪽")이라는 작은 공간 침략자 게임을 가질 수 있습니다.결과적으로, stdin에서 동시에 읽으려고해서는 안되며, 문자를 얻지 만, curses 시스템은 이상한 방식으로 그것들과 상호 작용할 것입니다. 독점적으로 저주를 읽습니다.

마지막 프로그램에서는 EOF까지 입력을 읽습니다. 따라서 후속 입력은 EOF입니다.

관련 문제