fflush( stdin ) ???

dondek의 이미지

fflush( stdin );

man page에 보면,

Quote:
주의
fflush 는 C 라이브러리가 제공하는 유저 공간 버퍼만을
지운다는점에 주의해라. 데이터가 디스크에 저장되도록
확실히 하기 위해, 커널 버퍼들은 sync(2)나 fsync(2)로 역시
비워져야 한다.

이렇게 나오는데 언젠가 MSDN에서 fflush( stdin ); 과 같은 샘플 코드를
본 적이 있는 것같고, 자꾸 학생들도 저 코드를 물어보는데 써도 되는건지,
아니면 쓰면 안되는 것인지.. 그것도 아니면 환경에 따라서 다른건지 궁금합니다.

사용자가 키보드로 입력한 데이터를 저장하고 있는 버퍼를
프로그램이 임의로 삭제해버린다는 것이 옳은 것인가 하는 생각도 들더군여.

여러분들의 의견을 듣고 싶습니다.

전웅의 이미지

해당 환경이 따로 fflush(stdio); 에 대한 행동을 잘 정의해 준다면 문제는
없습니다만, 결코 이식성은 없습니다.

http://c-expert.uos.ac.kr/board/hclc_post_board/ScB.cgi?process=disp_data&datanum=523

그럼...

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

cinsk의 이미지

:evil: RTFM

man 3 fflush wrote:
The function fflush forces a write of all user-space buffered data for the given output or update stream via the stream's underlying write function.
sunyzero의 이미지

굳이 flush를 위한 목적으로 이 함수를 쓰는지 그 이유가 이상하네요.

stdin 에서 flush를 왜할까요? 입력에 대한 부분인데 입력이야 어차피 버퍼링을 통해서 들어오고(대부분 canonical input mode겠죠) 만일 non-canonical 로 들어온다면 버퍼링할 이유가 굳이 없으니까 플러쉬를 해야할 이유를 못찾을거 같은데...

========================================
* The truth will set you free.

전웅의 이미지

많은 분들이 scanf() 로 interactive input 을 읽고, 남아 있는 문자 (대개
newline) 을 제거하기 위해서 fflush(stdin); 을 사용하는 것으로 알고 있
습니다.

재미있는 사실은 (제 기억이 맞다면) M모 사의 컴파일러는 확장으로 표준
입력에 대해서도 fflush() 를 지원하고 있다는 것입니다. 표준에 의해 정의
되지 않은 부분이므로 임의의 행동을 정의할 수 있는 부분이긴 합니다만,
사실을 잘 모르고 계신 분들에게 충분히 오해의 여지를 남길 수 있는 확장
이라고 생각합니다

interactive input 에 scanf() 자체를 사용하는 것부터가 잠재적인 문제의
싹이 되겠지만, "이식성의 손해를 인지하고 또 그것을 감수하고라도" 위와
같은 "확장을 지원하는 환경" 에서 fflush(stdin); 을 쓰겠다 한다면 완전
히 잘못된 것이라고 말할 수만은 없습니다.

그럼...

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

ㅡ,.ㅡ;;의 이미지

dondek wrote:

사용자가 키보드로 입력한 데이터를 저장하고 있는 버퍼를
프로그램이 임의로 삭제해버린다는 것이 옳은 것인가 하는 생각도 들더군여.

여러분들의 의견을 듣고 싶습니다.

님이 궁금해 하시는것이 이건거 같은데..
프로그램에서 임의로 삭제하는것이 어떤입력의경우 우리가 원하지 않는 입력까지 같이 들어오는경우가 있습니다. 특히 사용하는 함수에 따라서..
그렇다면.. 새로입력받은경우에 그값을 입력받으려하는데 버퍼에서 오래된
다른값을 넘겨준다면 문제가 되기때문에 일단비우고 새로 받는것입니다.
일반적으로 Text 기반 프로그램작성할때 종종 저렇게 하지요..
"해주면 된다" 라고 생각하시면 될듯합니다...^^;;


----------------------------------------------------------------------------

ㅡ,.ㅡ;;의 이미지

cinsk wrote:
:evil: RTFM

man 3 fflush wrote:
The function fflush forces a write of all user-space buffered data for the given output or update stream via the stream's underlying write function.

huk hangul e ha na do up dda ㅡ,.ㅡ;;

hok si wee guk in?? ^^;

농담이었슴다..


----------------------------------------------------------------------------

전웅의 이미지

ㅡ,.ㅡ;; wrote:
프로그램에서 임의로 삭제하는것이 어떤입력의경우 우리가 원하지 않는 입력까지 같이 들어오는경우가 있습니다. 특히 사용하는 함수에 따라서..
그렇다면.. 새로입력받은경우에 그값을 입력받으려하는데 버퍼에서 오래된
다른값을 넘겨준다면 문제가 되기때문에 일단비우고 새로 받는것입니다.
일반적으로 Text 기반 프로그램작성할때 종종 저렇게 하지요..
"해주면 된다" 라고 생각하시면 될듯합니다...^^;;

저를 포함해 위에서 답변해 주신 분들의 공통적인 의견은

"해서는 안 된다"

입니다. 물론, 입력에 프로그램이 필요로 하지 않은 부적절한 내용이 있어
유의미한 부분이 나올 때까지 무시하는 것 자체가 항상 잘못된 행동은 아니
지만, 그러한 행동을 위해 fflush(stdin); 을 선택하는 것은 많은 경우에
부적절 합니다. 기대한대로 동작하지 않을 여러 가능성은 제 처음 답변에
링크되어 있습니다. 그보다는 지극히 정상적이고 예측 가능한 방법으로 입
력을 처리하는 것이 더 낫습니다. 예를 들어, 현재부터 다음 newline 까지
의 (stdin 으로 오는) 입력을 무시해야 하는 상황이라면,

void throw_all_characters_until_the_next_newline_inclusive_into_the_trash(void)
{
    int c;

    while ((c=getchar()) != EOF && c != '\n');
}

와 같은 함수를 사용하는 것이 좋습니다 - 물론, 함수명은 좀 줄여야 겠지
요. ;-)

그럼...

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

ㅡ,.ㅡ;;의 이미지

전웅 wrote:
ㅡ,.ㅡ;; wrote:
프로그램에서 임의로 삭제하는것이 어떤입력의경우 우리가 원하지 않는 입력까지 같이 들어오는경우가 있습니다. 특히 사용하는 함수에 따라서..
그렇다면.. 새로입력받은경우에 그값을 입력받으려하는데 버퍼에서 오래된
다른값을 넘겨준다면 문제가 되기때문에 일단비우고 새로 받는것입니다.
일반적으로 Text 기반 프로그램작성할때 종종 저렇게 하지요..
"해주면 된다" 라고 생각하시면 될듯합니다...^^;;

저를 포함해 위에서 답변해 주신 분들의 공통적인 의견은

"해서는 안 된다"

입니다. 물론, 입력에 프로그램이 필요로 하지 않은 부적절한 내용이 있어
유의미한 부분이 나올 때까지 무시하는 것 자체가 항상 잘못된 행동은 아니
지만, 그러한 행동을 위해 fflush(stdin); 을 선택하는 것은 많은 경우에
부적절 합니다. 기대한대로 동작하지 않을 여러 가능성은 제 처음 답변에
링크되어 있습니다. 그보다는 지극히 정상적이고 예측 가능한 방법으로 입
력을 처리하는 것이 더 낫습니다. 예를 들어, 현재부터 다음 newline 까지
의 (stdin 으로 오는) 입력을 무시해야 하는 상황이라면,

void throw_all_characters_until_the_next_newline_inclusive_into_the_trash(void)
{
    int c;

    while ((c=getchar()) != EOF && c != '\n');
}

와 같은 함수를 사용하는 것이 좋습니다 - 물론, 함수명은 좀 줄여야 겠지
요. ;-)

그럼...

ㅡ,.ㅡ;; 잘돌아가는 프로그램을 자기스타일과 맞지 않다고 "해서는 안된다"
고말할순 없지요..
분명히 해서도 되니까요...

오류없이짜서 오류없이 동작하는데.. 안된다고할순없지요.
그러한 방식도 하나의 방식이라봅니다..
누가 더성능이 좋은가.. 의 문제는 있지만요..
개인적으로 그방식또한 나쁘지 않다고 봅니다.
그리고 Library 레퍼런스 예문에도 그렇게 사용했군요..


----------------------------------------------------------------------------

dondek의 이미지

ㅡ,.ㅡ;; wrote:
오류없이짜서 오류없이 동작하는데.. 안된다고할순없지요.
그러한 방식도 하나의 방식이라봅니다..
누가 더성능이 좋은가.. 의 문제는 있지만요..
개인적으로 그방식또한 나쁘지 않다고 봅니다.
그리고 Library 레퍼런스 예문에도 그렇게 사용했군요..

하지만 제 생각은 그 코드가 리눅스에서는 분명히 동작하지 않겠지요.
따라서 standard input output이라는 명색이 무색해지는거 아닌지요.

진리를 나의 수준으로 끌어내리지 마라.
나를 진리의 수준으로 끌어올려라. - 배꼽 중에서

죠커의 이미지

ㅡ,.ㅡ;; wrote:

ㅡ,.ㅡ;; 잘돌아가는 프로그램을 자기스타일과 맞지 않다고 "해서는 안된다"
고말할순 없지요..
분명히 해서도 되니까요...

오류없이짜서 오류없이 동작하는데.. 안된다고할순없지요.
그러한 방식도 하나의 방식이라봅니다..
누가 더성능이 좋은가.. 의 문제는 있지만요..
개인적으로 그방식또한 나쁘지 않다고 봅니다.
그리고 Library 레퍼런스 예문에도 그렇게 사용했군요..

정확한 방법이 있는데 그것을 따르지 않는 것은 스타일의 문제가 아닙니다. 성능이 좋은가의 문제가 아니라 누가 더 정교한 논리를 따르냐의 문제라고 생각합니다.

lsj0713의 이미지

ㅡ,.ㅡ;; wrote:

ㅡ,.ㅡ;; 잘돌아가는 프로그램을 자기스타일과 맞지 않다고 "해서는 안된다"
고말할순 없지요..
분명히 해서도 되니까요...

오류없이짜서 오류없이 동작하는데.. 안된다고할순없지요.
그러한 방식도 하나의 방식이라봅니다..
누가 더성능이 좋은가.. 의 문제는 있지만요..
개인적으로 그방식또한 나쁘지 않다고 봅니다.
그리고 Library 레퍼런스 예문에도 그렇게 사용했군요..

fflush(stdin)은 오류 없는 코드가 아닙니다. 엄연히 표준에 '정의되어 있지 않다'라고 쓰여있는 코드입니다. 물론 MS의 MSDN에서는 fflush(stdin)에 대해 정의해놓고 있고, 예제코드도 쓰여있습니다만, 그럼에도 불구하고 많은 분들의 의견은 쓰는 것이 좋지 않다는 것이었습니다. fflush(stdin)에 대해서는 han.comp.lang.c 에서 벌써 여러번에 걸쳐서 논의가 되고 있으므로 그쪽에서 관련 글을 검색해보시길 권합니다.

http://groups.google.com/groups?hl=ko&lr=&ie=EUC-KR&q=fflush&meta=group%3Dhan.comp.lang.c

전웅의 이미지

ㅡ,.ㅡ;; wrote:
ㅡ,.ㅡ;; 잘돌아가는 프로그램을 자기스타일과 맞지 않다고 "해서는 안된다"
고말할순 없지요..
분명히 해서도 되니까요...

이 문제는 스타일과 관련된 문제가 아닙니다. "스타일" 이란 그 자체가 프
로그램의 옳고 그름과는 무관한 것입니다. 하지만, 출력 stream 에 대해서
만 그 행동이 정의되고 이식성을 갖는 fflush() 를 입력 stream 인 stdin
에 사용하는 것은 스타일과는 무관한 "잘못된" 행동입니다.

ㅡ,.ㅡ;; wrote:
오류없이짜서 오류없이 동작하는데.. 안된다고할순없지요.

(확장을 통해 제공하기 때문에) 이미 되는 implementation 도 더러 있다고
말씀 드렸습니다. 하지만, "모든" implementation 에서 허락된 것이 아니기
에 이식성에 대한 인식이 있어야 한다고 말씀드린 것입니다. 참고로 표준이
특정 행동을 undefined behavior 로 둔 경우, 이는 해당 행동을 사실상 의
존해서는 안 되는 "잘못된" 행동으로 규정한 것입니다. 일반적인 C 언어의
관점에서, 또한 상대적으로 표준을 잘 따르는 UNIX-like 환경을 고려했을
때 (최소한 이곳이 M모사 제품을 위한 개발자 사이트는 아니라고 생각합니
다) 그와 같은 "잘못된" 행동을 표면적으로 억제하는 것은 (아니면, 최소한
격려하지 않는 것은) 충분히 바람직하다고 생각합니다.

ㅡ,.ㅡ;; wrote:
그러한 방식도 하나의 방식이라봅니다..
누가 더성능이 좋은가.. 의 문제는 있지만요..

지금 문제는 "성능" 의 문제가 아닙니다. 일례로 newline 을 포함해 뒤따르
는 입력을 무시하는 목적을 놓고 볼 때, 제가 보여드린 간단한 예는 모든
환경에서 예상 가능하고 동일한 행동이 보장되는 것이고, fflush(stdin);
은 소수의 환경에서만 기대하는 행동을 얻을 수 있는 방법입니다.

ㅡ,.ㅡ;; wrote:
개인적으로 그방식또한 나쁘지 않다고 봅니다.

"개인적으로" 그 방식이 좋지 않다고 봅니다. 하지만, 지금 문제는 개인적
인 선호를 묻는 것은 아니라 생각합니다.

ㅡ,.ㅡ;; wrote:
그리고 Library 레퍼런스 예문에도 그렇게 사용했군요..

근거를 부탁드립니다. 그 레퍼런스가 "일반적인" C 언어를 설명하고 있는
것이라면 레퍼런스가 틀린 것입니다. 만약, 그 레퍼런스가 특정
implementation (예를 들면 M모사의 컴파일러) 의 행동을 설명한 것이라면
(해당 환경에서는 분명 참이지만) 이를 함부로 일반화해서는 안 됩니다 -
위에 cinsk 님이 인용하셨듯이 man page 는 (표준과 마찬가지로) 사용해서
는 안 되는 것으로 명시하고 있습니다.

다시 한번 강조하지만, "해보니까 되더라" 는 그야말로 "해보니까 되는" 그
환경에서만 가능한 것입니다. 최소한 현재 OP 께서 가정하고 계시는 환경에
서, 또 C 표준에서도 입력 stream 에 fflush() 를 사용하는 것은 정의되어
있지 않습니다.

그럼...

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

ㅡ,.ㅡ;;의 이미지

어.. Linux 에서는 안되는거 맞네요.. ㅡ,.ㅡ;

도스시절에 저걸 써보고 안했더니.. 리눅스에서는 안되는줄 몰랐습니다. 지송.

근데 왜 안될까... 되야하는게 정상인거 같은데..

레퍼런스는 유닉스 DOS 둘다를 위해 써놓은 레퍼런스네요..
예문이 DOS만 생학하고 해놨나봅니다..

:oops: 근데 불과 답글올린지 몇분안되어.. 반대글이 올라오다니.. 놀랬습니다.^^;;; 사람들이 이글만 보고 있었구나..ㅡ,.ㅡ;;


----------------------------------------------------------------------------

cdpark의 이미지

ㅡ,.ㅡ;; wrote:
:oops: 근데 불과 답글올린지 몇분안되어.. 반대글이 올라오다니.. 놀랬습니다.^^;;; 사람들이 이글만 보고 있었구나..ㅡ,.ㅡ;;

잘못된 답변은 보자마자 고치는 게 사회 전체적으로도 이익입니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.