fflush(stdin) 사용
그래서 구글의 빠른 검색은fflush(stdin)
입력 버퍼를 지우기 위해 입력 버퍼를 사용하지 못하도록 경고하는 수많은 웹사이트가 표시된다.하지만 그게 바로 우리 CS 교수님이 수업 시간에 가르쳐준 방법이야.
사서도 .fflush(stdin)
교수님이 사용하시는데 흠잡을 데 없이 효과가 있는 것 같아도 정말 사용을 자제해야 할까?
단순함: 이 동작은 정의되지 않은 동작이며,fflush
출력 스트림에서 호출하도록 되어 있다.이것은 C 표준에서 발췌한 것이다.
intflux(FILE *ostream);
ostream은 가장 최근 작업이 입력되지 않은 출력 스트림 또는 업데이트 스트림을 가리키며, fflush 함수는 해당 스트림이 호스트 환경에 전달되기 위해 작성되지 않은 데이터를 파일에 기록하도록 한다. 그렇지 않으면 동작이 정의되지 않는다.
그래서 이것은 "얼마나 나쁜"지의 문제가 아니다.fflush(stdin)
단순히 휴대할 수 없기 때문에 컴파일러 간에 코드를 휴대할 수 있도록 하려면 사용하지 마십시오.
코멘트를 답변으로 변환하는 중.
TL;DR — 휴대용 코드가 사용되지 않음
이 답변의 나머지 부분은 휴대용 코드가 사용하지 않는 이유를 설명한다.fflush(stdin)
. "신뢰할 수 있는 코드가 사용되지 않음"을 추가하는 것이 유혹적이다.fflush(stdin)
", 이것은 또한 일반적으로 사실이다.
C 및 POSIX 휴가fflush(stdin)
정의되지 않은 행동으로서.
POSIX, C, C++ 의 표준fflush()
(때문에) 행동이 정의되지 않았다고 명시적으로 진술한다.stdin
입력 스트림)이지만 시스템 정의에 방해가 되는 것은 없다.
ISO/IEC 9899:2011 — C11 표준은 다음과 같이 말한다.
§7.21.5.2fflush 함수
2 만약
stream
가장 최근 작업이 입력되지 않은 출력 스트림 또는 업데이트 스트림을 가리킴fflush
함수는 해당 스트림이 호스트 환경에 전달되기 위해 작성되지 않은 데이터를 파일에 기록하도록 한다. 그렇지 않으면 동작이 정의되지 않는다.
POSIX는 대부분 C 표준을 무시하지만 이 텍스트를 C 확장자로 표시한다.
[CX] ③ 읽기 위해 열린 스트림의 경우, 파일이 아직 EOF에 있지 않고 파일이 탐색할 수 있는 파일인 경우, 기본 열린 파일 설명의 파일 오프셋을 스트림의 파일 위치로 설정하고, 다음에 의해 스트림에 다시 밀어넣은 문자를 스트림에 설정한다.
ungetc()
또는ungetwc()
스트림에서 후속적으로 읽히지 않은 파일 오프셋은 폐기되어야 한다.⌫
단자는 찾을 수 없으며 파이프나 소켓도 찾을 수 없다는 점에 유의하십시오.
을 다음과 같이 한다.fflush(stdin)
2015년에 마이크로소프트와 비주얼 스튜디오 런타임은 의 행동을 정의하는데 사용되었다.fflush()
이와 같은 입력 스트림에서(그러나 링크는 2021년에 다른 텍스트로 연결됨):
스트림이 입력을 위해 열려 있는 경우,
fflush
버퍼의 내용을 삭제하십시오.
은 싸이그윈이 상당한 가 상당히 보편적인 의 예다.
fflush(stdin)
입력을 지우지 않는다.
이러한 이유로 내 코멘트의 이 응답 버전은 'Microsoft와 Visual Studio 런타임'을 언급한다. 만약 당신이 비 Microsoft C 런타임 라이브러리를 사용한다면, 당신이 보는 행동은 그 라이브러리에 따라 달라진다.
웨더 베인은 또 다른 질문에 대한 논평에서 2021년 6월 이전에 마이크로소프트가 2015년 이 답을 쓸 때 원래 명시했던 것과 비교해서 설명을 바꿨다고 지적했다.현재 다음과 같이 되어 있다.
스트림이 읽기 모드로 열렸거나 스트림에 버퍼가 없는 경우 다음 호출
fflush
아무 효과도 없고, 어떤 완충제도 유지된다.로의 전화.fflush
에 대한 사전 호출을 무효로 하다.ungetc
개울에
Carvat Lector: 의존하지 않는 것이 아마도 가장 좋을 것이다.fflush(stdin)
어느 플랫폼에서나
Linux 문서와 실행 방식이 서로 모순되는 것 같음
놀랍게도 리눅스는 명목상 의 행동을 문서화한다.fflush(stdin)
또한, 심지어 그것을 같은 방식으로 정의하기도 한다(기적의 기적).이 인용문은 2015년에 나온 것이다.
입력 스트림의 경우,
fflush()
기본 파일에서 가져오지만 응용 프로그램에서 사용하지 않은 버퍼링된 데이터는 모두 삭제하십시오.
2021년에 견적서는 다음과 같이 변경된다.
입력 스트림의 경우,
fflush()
기본 파일에서 가져오지만 응용 프로그램에서 사용하지 않은 버퍼링된 데이터는 모두 삭제하십시오.개천의 개방 상태는 영향을 받지 않는다.
그리고 Linux에 관한 또 다른 정보원은 다음과 같이 동의한다(문단 휴식을 주거나 취함).
검색 가능 파일과 관련된 입력 스트림(예: 디스크 파일, 파이프 또는 단자는 아님)
fflush()
기본 파일에서 가져오지만 응용 프로그램에서 사용하지 않은 버퍼링된 데이터는 모두 삭제하십시오.
이들 중 어느 것도 POSIX 규격에 의해 만들어진 요점을 명시적으로 다루지 않는다.ungetc()
.
2021년 zwol은 리눅스 문서화가 개선되었다고 논평했다.내가 보기에는 아직 개선의 여지가 있는 것 같다.
2015년 리눅스 문서화에서 다음과 같은 내용이 나와 다소 어리둥절하고 놀랐다.fflush(stdin)
효과가 있을 것이다.그러한 제안에도 불구하고, 대부분의 경우 Linux에서는 작동하지 않는다.나는 방금 Ubuntu 14.04 LTS에 대한 문서를 확인했는데, 위에 인용된 내용이 명시되어 있지만, 경험상으로는, 적어도 입력 스트림이 단말기와 같은 검색 불가능한 장치인 경우에는 작동하지 않는다.
demo-fflush.c
#include <stdio.h>
int main(void)
{
int c;
if ((c = getchar()) != EOF)
{
printf("Got %c; enter some new data\n", c);
fflush(stdin);
}
if ((c = getchar()) != EOF)
printf("Got %c\n", c);
return 0;
}
출력 예제
$ ./demo-fflush
Alliteration
Got A; enter some new data
Got l
$
이 출력은 Ubuntu 14.04 LTS와 Mac OS X 10.11.2 모두에서 얻었다.내가 이해하기로는 리눅스 매뉴얼의 내용과 모순된다.만약fflush(stdin)
작업이 성공했으므로 두 번째 작업에서 정보를 얻으려면 텍스트를 새로 입력해야 함getchar()
책을 읽다
POSIX 표준에 따르면, 더 나은 데모가 필요하며, 리눅스 문서를 명확히 해야 한다.
demo-fflush2.c
#include <stdio.h>
int main(void)
{
int c;
if ((c = getchar()) != EOF)
{
printf("Got %c\n", c);
ungetc('B', stdin);
ungetc('Z', stdin);
if ((c = getchar()) == EOF)
{
fprintf(stderr, "Huh?!\n");
return 1;
}
printf("Got %c after ungetc()\n", c);
fflush(stdin);
}
if ((c = getchar()) != EOF)
printf("Got %c\n", c);
return 0;
}
출력 예제
참고:/etc/passwd
찾을 수 있는 파일이야우분투에서 첫 줄은 다음과 같다.
root:x:0:0:root:/root:/bin/bash
Mac OS X에서 처음 4개 라인은 다음과 같다.
##
# User Database
#
# Note that this file is consulted directly only when the system is running
즉, 맥 OS X의 상단에 해설이 있다./etc/passwd
file. 비코멘트 라인은 일반 레이아웃을 준수하므로root
입력 항목:
root:*:0:0:System Administrator:/var/root:/bin/sh
Ubuntu 14.04 LTS:
$ ./demo-fflush2 < /etc/passwd
Got r
Got Z after ungetc()
Got o
$ ./demo-fflush2
Allotrope
Got A
Got Z after ungetc()
Got B
$
맥 OS X 10.11.2:
$ ./demo-fflush2 < /etc/passwd
Got #
Got Z after ungetc()
Got B
$
Mac OS X 동작이 를 무시(또는 최소한 무시하는 것처럼)함)fflush(stdin)
(이 문제에 대해 POSIX를 따르지 않음).리눅스 동작은 문서화된 POSIX 동작에 해당하지만, POSIX 규격은 검색이 가능한 파일을 지정하지만, 물론 터미널은 탐색을 지원하지 않는다.그것은 또한 마이크로소프트의 사양보다 훨씬 덜 유용하다.
요약
한다.fflush(stdin)
그러나 그 행동은 2015년에서 2021년 사이에 바뀌었다.윈도우즈 플랫폼에서 기본 윈도우즈 컴파일러 및 C 런타임 지원 라이브러리를 사용하여 문서화된 대로 작동한다는 것이 명백하다.
반대로 문서화했음에도 불구하고 표준 입력이 단말일 때는 Linux에서는 작동하지 않지만, 훨씬 더 세심하게 단어화된 POSIX 규격을 따르는 것 같다. C의 면에 면의 행동.fflush(stdin)
할 수 없는 라는 한정자를 했는데, 않다POSIX는 '입력 파일을 검색할 수 없는 경우'라는 한정자를 추가하지만, 단자는 그렇지 않다.그 행동은 마이크로소프트의 행동과 같지 않다.
따라서 휴대용 코드는 사용하지 않는다. 마이크로소프트의 플랫폼에 묶여 있는 코드는 그것을 사용할 수 있고 그것은 예상대로 작동할 수 있지만, 휴대성 문제에 주의해야 한다.
파일 설명자에서 읽지 않은 단말기 입력을 삭제하는 POSIX 방법
읽지 않은 정보를 터미널 파일 설명자에서 삭제하는 POSIX 표준 방법(예: 파일 스트림과 반대로)stdin
)는 Unix 시스템의 tty 입력 대기열에서 읽지 않은 데이터를 플러시하는 방법에 설명되어 있다.그러나 이는 표준 I/O 라이브러리 수준 이하로 운영되고 있다.
나는 네가 절대 전화해서는 안 된다고 믿는다.fflush(stdin)
우선 입력을 플러시할 필요가 없다는 단순한 이유 때문에.현실적으로, 여러분이 입력을 플러시해야 한다고 생각할 수 있는 단 하나의 이유가 있는데, 바로 그것이 바로 어떤 나쁜 입력을 극복하기 위해서입니다.scanf
에 걸려 있다.
예를 들어, 당신은 루프를 읽고 있는 프로그램을 가지고 있을 수 있다.scanf("%d", &n)
으로 .와 같은 가 아닌 을 곧 될 것이다이제 곧 당신은 사용자가 처음으로 다음과 같은 숫자가 아닌 문자를 입력하는 것을 알게 될 것이다.'x'
프로그램은 무한 루프에 들어간다.
이 상황에 직면했을 때, 나는 기본적으로 세 가지 선택이 있다고 믿는다.
- (사용하지 않는 경우) 입력 플러시
fflush(stdin)
, 그리고 전화해서.getchar
까지 캐릭터를 읽을 수 있는 루프로.\n
, 자주 권하는 바와 같이). - 숫자가 필요할 때 숫자가 아닌 문자를 입력하지 않도록 사용자에게 알리십시오.
- 입력을 읽는 것 외에 다른 것을 사용하라.
쟈, 보아라면scanf
입력을 읽는 가장 쉬운 방법인 것 같고, 그래서 선택 #3은 무섭고 어려워 보인다.하지만 #2는 정말 구제불능인 것 같다. 왜냐하면 모든 사람들이 사용자 친화적이지 않은 컴퓨터 프로그램이 문제라는 것을 알고 있기 때문에, 더 잘하면 좋을 것이다.그래서 너무 많은 초창기 프로그래머들이 1번을 할 수밖에 없다고 느끼면서 구석에 그려진다.그들은 거의 또는 그 이하를 사용하여 입력을 해야 한다.scanf
, 즉, 나쁜 입력에 걸릴 것이라는 뜻, 즉 나쁜 입력에 대해 플러싱할 방법을 찾아야 한다는 뜻, 즉 그들이 쓰기를 몹시 유혹하고 있다는 뜻이다.fflush(stdin)
.
모든 초기 C 프로그래머들이 다른 트레이드오프를 할 수 있도록 격려하고 싶다.
C 프로그래밍 경력의 초기 단계에서는 다른 것을 사용하기 전에
scanf
, 단지 잘못된 입력에 대해 걱정하지 마십시오.진짜.위 2번 출구로 나가십시오.이렇게 생각해봐:초심자라 아직 모르는 것이 많고, 아직 모르는 것 중 하나는 의외의 입력에 우아하게 대처하는 것이다.가능한 한 빨리 가 아닌 다른 기능을 사용하여 입력을 하는 방법을 배우십시오.이때, 여러분은 나쁜 입력에 우아하게 대처하기 시작할 수 있고, 여러분이 이용할 수 있는 더 많은, 훨씬 더 나은 기술들을 가지게 될 것이며, 나쁜 입력에 대해 "flush the bad input"을 전혀 시도하지 않아도 될 것이다.
또는, 다시 말해서, 아직 꼼짝 못하고 있는 초심자들이scanf
콥아웃 #2를 자유롭게 사용할 수 있어야 하며, 준비가 되면 거기서부터 기술 #3까지 졸업해야 하며, 그 누구도 기술 #1을 사용하여 입력을 플러싱하려고 해서는 안 된다. 물론 그런 것은 아니다.fflush(stdin)
.
사용.fflush(stdin)
입력을 플러싱하는 것은 문자 "S"와 같은 모양의 막대기를 사용하여 물을 다우싱하는 것과 같다.
그리고 사람들이 "더 좋은" 방법으로 입력을 조절하도록 돕는 것은 마치 S스틱 다우너에게 달려가서 "아니, 잘못하고 있어, Y자 모양의 막대기를 사용해야 해!"라고 말하는 것과 같다.
다시 말해, 진짜 문제는 그것이 아니다.fflush(stdin)
효과가 없다.호출fflush(stdin)
근본적인 문제의 증상이다.너는 왜 아예 입력을 "몰래"해야 하니?그건 네 문제야.
그리고, 보통, 그 근본적인 문제는 당신이scanf
, 입력에 예기치 않게 새로운 줄이나 다른 "수동" 텍스트를 남기는 많은 도움이 되지 않는 모드 중 하나에서.그러므로, 가장 좋은 장기적 해결책은 ,보다 더 나은 기술을 사용하여 입력하는 방법을 배우는 것이고, 따라서 입력의 처리되지 않은 입력과 다른 특색을 전혀 다룰 필요가 없다.
기존의 답변 중 문제의 핵심 측면을 지적하는 것은 하나도 없다.
'입력 버퍼 지우기'를 원하는 자신을 발견하면 아마도 명령줄 인터랙티브 프로그램을 작성하고 있을 것이며, 자신이 원하는 것은 아직 읽지 않은 현재의 입력 라인에서 문자를 삭제하는 것이라고 말하는 것이 더 정확할 것이다.
이것은 하는 일이 아니다.다음을 지원하는 C 라이브러리fflush
입력 스트림에서 아무것도 하지 않거나, 기본 파일에서 읽었지만 애플리케이션에 전달되지 않은 버퍼링된 데이터를 삭제하는 것으로 문서화하십시오.그것은 쉽게 현재 라인의 나머지 부분보다 많거나 적거나 둘 중 하나일 수 있다.그것은 아마도 많은 경우에 우연히 작동하는데, 왜냐하면 (기본 모드에서) 단말 드라이버는 한 번에 한 줄씩 명령줄 인터렉티브 프로그램에 입력을 공급하기 때문이다.그러나 디스크의 실제 파일에서 프로그램에 입력을 공급하려고 하는 순간(아마도 자동화된 테스트를 위해), 커널과 C 라이브러리는 라인 경계와 관계 없이 큰 "블록"(대개 4~8kB)의 데이터 버퍼링으로 전환되며, 프로그램이 파일의 첫 줄을 처리한 후 sk를 처리하는 이유가 궁금해질 것이다.수십 개의 선을 긋고 아래 보이는 임의의 선 가운데를 집어낸다.또는 손으로 타이핑한 매우 긴 줄에 프로그램을 테스트하기로 결정하면 터미널 드라이버가 한 번에 전체 줄을 제공할 수 없게 되고fflush(stdin)
다 빼먹지 않을 거야
그래서 너는 대신 무엇을 해야 하니?내가 선호하는 접근방식은, 한 번에 한 줄씩 입력하는 경우, 한 줄 전체를 읽는 것이다.C 라이브러리는 특별히 다음과 같은 기능을 가지고 있다.fgets
(C90에서는 휴대성이 매우 뛰어나지만, 여전히 매우 긴 줄을 청크로 처리하도록 만든다)getline
(POSIX별, 그러나 관리 예정)malloc
긴 줄이 얼마가 걸리든 한 번에 처리할 수 있도록 버퍼링(ed buffer for you for you)보통 stdin에서 직접 "현재 라인"을 처리하는 코드에서 "현재 라인"을 포함하는 문자열을 처리하는 코드까지 직접 번역이 있다.
기준에 따르면fflush
출력 버퍼에만 사용할 수 있음, 그리고 명백하게stdin
하나가 아니다.단, 일부 표준 C 라이브러리는 다음을 사용한다.fflush(stdin)
연장으로서그럴 경우 사용할 수 있지만 휴대성에 영향을 미치기 때문에 더 이상 표준 규격 C 라이브러리를 사용할 수 없으며 동일한 결과를 기대할 수 없게 된다.
POSIX에서 인용:
읽기 위해 열린 스트림의 경우, 파일이 아직 EOF에 있지 않고 파일이 탐색할 수 있는 파일이 있는 경우, 기본 열린 파일 설명의 파일 오프셋은 스트림의 파일 위치로 설정되어야 하며, 스트림에서 후속적으로 읽히지 않은 ungetc() 또는 ungetwc()에 의해 스트림에 다시 밀어넣어진 문자는 해제되어야 한다.카드 처리됨(파일 오프셋을 더 이상 변경하지 않음)
터미널은 검색할 수 없다는 점에 유의하십시오.
참조URL: https://stackoverflow.com/questions/2979209/using-fflushstdin
'IT이야기' 카테고리의 다른 글
HMAC-SHA1에 대한 목표-C 샘플 코드 (0) | 2022.04.28 |
---|---|
Vuejs 2가 어레이에서 이동하는 항목, 어레이 인덱싱 유지 안 함 (0) | 2022.04.28 |
"구조 해킹"은 기술적으로 정의되지 않은 행동인가? (0) | 2022.04.28 |
"정적 맥락에서 비정적 방법을 참조할 수 없다"는 이면의 이유는 무엇인가? (0) | 2022.04.28 |
@input 이벤트 실행 메서드 전에 값 프로펠러를 확인하시겠습니까?VeValidate/Vue (0) | 2022.04.28 |