2014-02-11 3 views
2

나는 표준 입력에서 문자를 제거 할 방법을 찾고있는 프로그래밍 학생이다. 난 당신이 같은 것을 할 다양한 형태, 여기에 부여 된 기술을 시도했다 :비어 있거나 비어 있지 않을 때 C에서 표준 입력을 지움

문제는 아무것도로 시작하는 표준 입력에없는 경우,이 기능은 기다리고 주위에 앉아 것 같다
void clearStdIn(void) 
{ 
    char c; 
    while((c = getchar()) != '\n' && c != EOF) 
     /* discard */ ; 
} 

제어 흐름이 계속 진행될 수 있기 전에 사용자가 Enter 키를 누르십시오. 어떻게해야합니까?

+2

당신이 뭘 하려는지? stdin은 일반적으로 _ 주위에 문자가 없으므로 아마도 매우 드문 상황에 처하게 될 것입니다. – FtM

+2

@mander : 일반적으로 콘솔 앱의 경우 입력을 입력하는 사람이 프로그램보다 먼저 얻을 수 있습니다. 드문 경우이지만 (소프트웨어는 빠름) 숙련 된 사용자가 쉽게 사용할 수 있습니다.취소/취소 입력은 빠른 사용자가 중지하고 소프트웨어가 따라 잡기를 기다려야한다는 것을 의미합니다. 이는 사용자에게 문제를 일으키고 나쁜 생각입니다. – Brendan

+0

표준 메서드는 문자가 입력 버퍼에 남아 있는지 여부를 결정하는 표준 기능이 없습니다. 따라서 구현에 따라 처리가 달라집니다 (예 : fflush (stdin), rewind (stdin) 등) – BLUEPIXY

답변

-1

표준 입력이 기본적으로 "블로킹"이므로 입력이 없으면 입력을 버리지 않고 입력을 버릴 수 없으므로이 입력을 멀리 할 수 ​​없으므로 이식성이 없습니다.

가지고있는 경우 select()을 사용하여 입력이 있음을 감지 한 다음 읽음을 삭제할 수 있습니다. 한 번에 하나의 문자가 아닌 "큰"블록을 읽는 것이 좋습니다.

getchar() returns int, 상수 EOF이 아니며 문자는입니다. "out of band" communication의 예입니다. 문자가 아닙니다.

+0

Derp, 그 EOF 문제를 해결할 것입니다 ... 그리고'select()'를 살펴볼 것입니다; 고마워요. – mander

0

두 가지 문제가 있습니다. 첫 번째는 내가 흐름 제어라고 부르는 것입니다. '발신자'(예 : 콘솔 애플리케이션을 사용하는 빠른 타이피스트)가 '수신기'(예 : 느린 콘솔 애플리케이션 소프트웨어)보다 빠르게 데이터를 전송하는 상황에서는 데이터를 잃지 않고 버퍼를 갖고 싶어합니다 데이터 손실을 방지합니다.

간단한 예를 들어, 강사가 자신이해야 할만큼 똑똑하다면 자동화 된 스크립트를 사용하여 학생의 과제를 사전 테스트하여 자신의 삶을 편하게 만듭니다. 이 경우 STDIN은 실제로 파일이됩니다 (STDOUT의 데이터가 예상 패턴과 일치하는지 확인). STDIN의 모든 것을 버리면 모든 입력을 버리고 실패합니다.

두 번째 문제는 응용 프로그램을 입력과 동기화 된 상태로 유지하는 것입니다. 이것은 보통 사용자 입력 행을 가져 와서 (파싱하고 파싱 된 데이터로 무언가를 한 다음), 다음 행을 가져 오는 등의 방법으로 수행됩니다. 잘못 입력하면 (예 : 입력 행의 일부만 가져 오기) 가져온 것의 끝과 줄의 끝 사이의 모든 문자를 처리 할 수있는 방법을 찾아야합니다. 여기서 간단한 해결책은 처음부터 잘못해서는 안됩니다. "사용자 입력 전체 행 가져 오기"기능 (아마도 gets())을 사용하고 사용자 입력을받은 후 사용자 입력 행을 구문 분석하는 것에 대해 걱정하십시오.

제정신 소프트웨어는 폐기/무시하지 않고 일종의 "알 수없는 문자 이후 ..."오류 메시지를 생성하여 원치 않는/예상치 못한 문자를 처리합니다. 파싱하는 동안 파싱하는 동안이 작업을하는 것이 가장 좋습니다. 사용자가 입력 한 데이터를 잘못 입력 한 경우가 있습니다. 간단한 예를 들어, "22 개월 입력"을 상상해보십시오.이 경우 사용자가 몇 년을 입력 할 것으로 예상하고 "22"를보고 "개월"을보고 오류가 발생합니다 ("잘못된 입력 - 나이를 일 년 수로 "). 당신은 사용자가 22 년을 원했다고 가정하지 않습니다.

+0

문제는 우리 (C 프로그래밍 학생)가 버퍼 오버런의 가능성 때문에 gets()를 사용하지 않아야한다는 것입니다. 그래서 fscanf와 버퍼를 사용했는데, stdin에 여분의 텍스트가 남을 수 있습니다. 브렌든에게 조언 해줘서 고마워. – mander

+0

당신은'gets()'에 문제가없는'malloc()'과'realloc()'과'getc()'를 사용하여 "get line" 'fscanf()'가 원인. – Brendan

1

과 같이 할 수 차단하지 않고 (휴대용 방법으로) 입력 스트림을 플러시 :

#include <stdlib.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <errno.h> 

int flush_inputstream(int fd) 
{ 
    int result = 0; 

    int flags = fcntl(fd, F_GETFL); 
    if (-1 == flags) 
    { 
    perror("fcntl() failed getting flags"); 

    result = -1; 
    goto lblExit; 
    } 

    if (!(flags & O_NONBLOCK)) /* If stream isn't non-blocking */ 
    {       /* set it to be non-blocking. */ 
    result = fcntl(fd, F_SETFL, O_NONBLOCK); 
    if (-1 == result) 
    { 
     perror("fcntl() failed setting O_NONBLOCK"); 

     goto lblExit; 
    } 
    } 

    /* Loop reading from the stream until it is emtpy: */ 
    do 
    { 
    char c = 0; 
    ssize_t bytesRead = read(fd, &c, 1); 
    if (-1 == bytesRead) 
    { 
     if ((EAGAIN != errno) && (EWOULDBLOCK != errno)) 
     { 
     perror("read() failed"); 

     result = -1; 
     } 

     break; 
    } 
    } while (1); 

    if (!(flags & O_NONBLOCK)) /* If stream had not be non-blocking */ 
    {       /* re-set it to not be non-blocking. */ 
    int result_fcntl = fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); 
    if (-1 == result_fcntl) 
    { 
     perror("fcntl() failed setting flags"); 

     if (0 == result) /* Do not overwrite prvious error! */ 
     { 
     result = result_fcntl; 
     } 

     goto lblExit; 
    } 
    } 

lblExit: 

    return result; 
} 

/* To test this: */ 
int main(void) 
{ 
    int fd = fileno(stdin); 

    printf("Feed some chars via the keyboard now!\n"); 

    sleep(3); 

    printf("Game Over! Press enter to see stdin is empty\n"); 

    if (-1 == flush_inputstream(fd)) 
    { 
    fprintf(stderr, "flush_inputstream() failed"); 
    return EXIT_FAILURE; 
    } 

    char s[16] = ""; 
    if (NULL == fgets(s, sizeof(s), stdin)) 
    { 
    perror("fgets() failed"); 
    } 

    printf("%s\n", s); 

    return EXIT_SUCCESS; 
} 
관련 문제