while문에서의 scanf에서 %c와 %s 의 차이가있는가보네요?

picpic76의 이미지

정상적으로 돌아가는 코드입니다.

void main()
{
int num;
char select[10];
//char select;

while(1)
{
printf("Insert num :");
scanf("%d",&num);
printf("Grade %d is A\n",num);

printf("Reply yes or no :");
scanf("%s",&select);
printf("%s",select);
}
}

그냥 무한루프로 정수와 문자열 입력받고 출력하는 프로그램입니다.

그런데 입력받는 문자열을 문자로 바꾸었을시 이해할수없는 상황이 벌어지더군요.
아래 코드입니다. 단지 select만 char형으로 선언했습니다.

void main()
{
int num;
//char select[10];
char select;

while(1)
{
printf("Insert num :");
scanf("%d",&num);
printf("Grade %d is A\n",num);

printf("Reply yes or no :");
scanf("%c",&select);
printf("%c",select);
}
}

이코드에서는 두번째 scanf 이놈이 입력을 받지않고 나가더군요. 리턴타입도 확인한결과
EOF가 아니였습니다.

초보로썬 좀 당황스럽네요. 조언주시면 감사하겠습니다.

익명사용자의 이미지

scanf("%d",&num);

이 코드는 정확하게 숫자까지만 입력을 받으며, 그 뒤의 엔터키로 인한 개행문자는 입력버퍼에 그대로 남습니다. 이것이 이후 입력에 영향을 끼치게 됩니다.

scanf함수로 이 문제를 해결하는 것은 까다롭고 쉽지 않습니다. 그래서 때로는 fgets함수와 sscanf함수의 조합으로 줄단위로 입력을 받은뒤 따로 해석하기도 합니다.

picpic76의 이미지

void main()
{

char *select,*_num;
int num;
select=(char*)malloc(SIZE);
_num=(char*)malloc(SIZE);

while(1)
{
printf("Insert num :");
fgets(_num,SIZE,stdin);
num=atoi(_num);
printf("Grade %d is A\n",num);


printf("Reply yes or no :");
fgets(select,SIZE,stdin);
printf("%s",select);
}

free(select);
free(_num);
}

이렇게 작성하는것도 올바른 사용법이라고 할수있을까요?
조금 궁금합니다. 제가 경험이 전무해서요 ^^

안녕하세요. 초보 리눅서입니다
잘부탁해요 ^^

harisoo의 이미지

엔터문자를 받을 임시변수만 잇으면 됩니다.

char dummy, select;

while(1){
scanf("%c%c",&select,&dummy);
printf("%c",select);
}

picpic76의 이미지

안녕하세요. 초보 리눅서입니다
잘부탁해요 ^^

'\n' 이 있다는것을 생각못했네요.
그것이 입력버퍼에 남아있었다니.. 조언감사합니다. ^^
그런데 궁금한건 지정한 dummy 변수가 select 변수보다 앞에 있어야 dummy 함수가
개행문자를 처리하지 않을까요? 알쏭달쏭..ㅎㅎ

안녕하세요. 초보 리눅서입니다
잘부탁해요 ^^

harisoo의 이미지

우선 저희가 입력을 하면 그 순서대로 버퍼에 쌓입니다.

당연히 입력후 맨마지막 값은 결국 개행문자가 되겟군요..

그러므로 더미가 마지막 개행문자를 받으면 버퍼는 다 출력되기 때문에 쌓일 이유가 없는것이죠..

그리고 한가지 더..

scanf()를 쓰던 fgets()을 쓰던 스트림으로 받을때는 입력된 문자열이 개행문자를

만날때까지 읽어서 저장을 합니다. 그렇기 때문에 스트림으로 받을 때는 더미가 필요가 없습니다.

하지만 한 캐릭터씩 읽을 때는 1바이트만 읽으면 되므로 개행문자가 남는거죠.

익명사용자의 이미지

덧글중에 더미 변수 이야기가 나와서..

그냥 fflush()
라는 함수를 써서 키보드 버퍼를 비워버리면 안되나요?

...?

익명사용자의 이미지

fflush()는 출력 버퍼에 대해서만 사용 가능하며, 입력 버퍼에 대해 사용하는 것은 이식성이 없습니다. 게다가 키보드를 통한 입력 외에도, 파이프나 리다이렉션을 통한 입력이 가능하다는 점을 고려해 볼 때, fflush()를 입력 스트림에 대고 사용하는 것은 바람직하지 않습니다.

익명사용자의 이미지

그냥 \n만 한번 더읽어서 해결된다면 얼마나 좋겠습니까마는, 늘 사용자는 프로그래머의 의도대로 행동하지 않으며,

" \n"
" 1234\n"
" 1234 \n"
" 1234 1234\n"
"abcde\n"
"\n"
"씨발왜안돼\n"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaa\n"

와 같은 여러가지 입력값이 가능합니다.

게다가 파이프나 리다이렉션 등을 고려하면 변수는 더더욱 많아집니다.

C 배울때 빼고는 scanf 쓸일이 얼마나 있겠습니까마는, 입력 스트림을 다룰 때 그런 문제들이 있다는 점 정도는 기억해두시길 바랍니다.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.