프로그래밍

 3198, 1/160 회원가입  로그인  
   jsk0612
   scanf 참 아리달송 하네요;; 질문요ㅜ

http://www.hackerschool.org/HS_Boards/zboard.php?AllArticle=true&no=3020 [복사]


전에도 scanf 관련된 질문을 드렸었는데요 또 scanf의 미궁속에 또 빠져서 찾아보다 정 안되서 이렇게 질문 올립니다ㅜ

#include<stdio.h>

#define MAX 2

int main()
{
        char a[MAX][MAX];
        char b[MAX][MAX];
        int i, j;

        printf ("--- start array 'a' ---\n");

        for (i = 0; i < MAX; i++)
                for (j = 0; j < MAX; j++)
                        scanf (" %c", &a[i][j]);

        fflush(stdin);

        printf ("--- start array 'b' ---\n");

        for (i = 0; i < MAX; i++)
                for (j = 0; j < MAX; j++)
                        scanf ("%c ", &b[i][j]);

        for (i = 0; i < MAX; i++)
        {
                for (j = 0; j < MAX; j++)
                        printf ("a[%d][%d] = %c (%d)\t", i, j, a[i][j], a[i][j]);
                printf ("\n");
        }

        printf ("\n");

        for (i = 0; i < MAX; i++)
        {
                for (j = 0; j < MAX; j++)
                        printf ("b[%d][%d] = %c (%d)\t", i, j, b[i][j], b[i][j]);
                printf ("\n");
        }

        return 1;
}

위의 대충 소스는 2x2배열 2개가 있습니다.
문자를
A B
1 2 이런식으로 입력 받는건데요

이제 본격적인 질문이요

b배열입력할때 즉 scanf ("%c ", &b[i][j]);
여기서요 2x2 즉 4번을 입력하고
왜 한번을 더쳐야 하는지 의문이네요
물론 위에 a배열처럼 scanf (" %c" &b[i][j]);
이렇게 하면 되는건 알고 있는데

왜인지가 궁금해서요ㅜ
해쿨에서 얼핏 보기엔 scanf는 \n이 버퍼에 저장되는걸로 알고 있는데
연관해서 생각해보려고 해도 제가 멍청해서 그런지 힘드네요ㅠ

위에 b배열에 관한것과 scanf 에 관해서 심화적으로 좀 알려주세요ㅠ

  Hit : 5015     Date : 2011/05/27 05:26



    
KRR
/*제가 허접수준이라 님의 원하시는 답을 해드릴수 없을 거 같지만 그래도 제가 아는 한도안에서는 이야기해드릴려고 합니다.
머 그냥 무시하셔도 되고요.. 다른 좋은 님들이 답변 달아 주실꺼라 전 믿습니다.

일단 질문이 상당히 난해한데. 실행해보니 대충 알겠네요..

그래서 그냥 제가 수정했습니다.

#include<stdio.h>

#define MAX 2

int main(void)
{
int a[MAX][MAX];
int b[MAX][MAX];
int i, j;

printf ("--- start array 'a' ---\n");

for (i = 0; i < MAX; i++)
for (j = 0; j < MAX; j++)
scanf ("%d", &a[i][j]);


printf ("--- start array 'b' ---\n");

for (i = 0; i < MAX; i++)
for (j = 0; j < MAX; j++)
scanf ("%d", &b[i][j]);

printf("\n");
for (i = 0; i < MAX; i++)
for (j = 0; j < MAX; j++)
printf ("a[%d][%d] = %d (%d)\t", i, j, a[i][j], a[i][j]);

printf ("\n");

for (i = 0; i < MAX; i++)
for (j = 0; j < MAX; j++)
printf ("b[%d][%d] = %d (%d)\t", i, j, b[i][j], b[i][j]);


return 0;
}일단은... wn이 남긴 했나 보네요..

흠.. 일단 vc++인가 windows에만 fflush(stdin)가 보장된다고 어디시 들은거 같은데...

머 구지 그렇게 하지 않더라도.

다른 방법으로 없앨 수 있기에..
2011/05/27  
KRR 아오.. 이제 글쓰기가 한결 편해졌네...

일단 제가 아는 한도에서 답변해드리지요..

그러니깐 우리가 키보드로 입력한 값이 메모리에 올라가는데 그 곳이 아마 버퍼라고 전 생각하고 있습니다.(자세히 잘모른 그냥 이렇게 생각하고 있어요..)

printf(" 여기쓰는 글자")도 버퍼에 올라간다고 생각하고 있고요.. 그니깐 메모리...어느 구역..버퍼..

암튼.. 이걸 막기 위해서는 버퍼에 남아있는 쓰레기 \n (아스키코드값으로는 10인가... 그러니깐.. 이건 님이 확인해보기..)

없에거나.. 어디에다가 방출해주어야하는데..

전 그냥 printf(라는걸 달아서 그냥 방출해주었답니다.

아.. 그리고 님도 아시다시피.. 님 소스가 좀 많이.. 먼가 틀린거 같아서.. ㅎㅎㅎ

저도 아직 부족해서 이것밖에 답변해드릴수 없네요. ㄷㄷ
2011/05/27  
KRR ("%c ", &b[i][j]);
(" %c", &b[i][j]);

차이가 뭘까요.. 상당히.. 난해하네요..

일단 글자 입력에 대해서 이야기하시는거 같은데..
%c(sp)
(sp)%c 무슨 차이일까요... 결국엔 별 차이 없는거 같은데..

메모리에 올라가는건 마찬가지.. 머 뒤에 쳤다고 사라지는 것도 아니고.. \n에 남아 있는 건데..

맨마지막 입력시 붙은 망할 \n만 없애면 될듯해요..
(참.. 허접하죠.. ㅈㅅ합니다... )
2011/05/27  
KRR http://kin.naver.com/qna/detail.nhn?d1id=1&dirId=1040101&docId=67818093&qb=ZmZsdXNo&enc=utf8§ion=kin&rank=2&search_sort=0&spq=0&pid=gO93Ug331xGsssr34lGssv--304628&sid=Td91xIVo300AABZoL4A 2011/05/27  
prosthetics 가장 많이 사용하면서도 실상은 전혀 모르고 있던 scanf에 대해 생각하려니까 막막했습니다.

질문자님 덕분에 scanf에 대해 깊이 생각하고 저나름대로의 답을 냈습니다.

답을 냈을때의 기쁨은 정말 오랜만에 느끼는 것이라 행복했습니다 >,.<!

잡소리는 그만하고 저의 답을 알려드리겠습니다.

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
<1> scanf의 속을 들여다 볼 수 없다! 볼 수 있는건 함수의 원형뿐 ㅜ.,ㅜ

scanf의 내용은 Microsoft사의 소유물입니다.
MS사가 만든 함수이기 때문에 Lib파일에 감춰져 있으며 우리가 들여다 볼 수 없게 되어있지요.
(돈을 받고 팔아야 하니까요.)
따라서 우리가 볼 수 있는 내용은 header file인 <stdio.h>에 들어있는 proto-type뿐입니다.
(fflush를 사용하시니 여기까지는 이해가 가시겠지요?)

헤더파일이 제공하는 원형은 다음과 같습니다.
_CRTIMP int __cdecl scanf(const char *, ...);

_CRTIMP int__cdecl 를 알고 싶으시면 calling convention이라고 따로 google에 쳐보시구요.
보시면 매개변수로 const char *, ...를 받고 있습니다.
여기에 대한 설명 역시 필요하시면 찾아보시길(이미 알고있으리라 생각합니다.)
즉, "~~~"이 문자열과 ...을 입력으로 받는다는 것이지요.



<2> const char *로 해야하는 일.

scanf가 어떻게 생겼는지 보다, 직접 scanf를 만든다고 생각해보세요.
전체를 만든다고 생각하면 또 길어질테니 스페이스가 들어간 부분만 따로 처리를 한다고 생각합시다.
보통 스페이스를 활용하는 부분은 다음과 같습니다.
scanf("%d %d",&a,&b);
즉, *******두개의 문자를 받을 때********라는 말이지요!
다시 말하면 이 말인즉슨 "스페이스를 만나면 값(수,문자,문자열 등)을 한번 더 입력받는다."
라는 처리가 들어갈 가능성이 농후하다는 말입니다.

<3> 스페이스가 들어가는 경우

마지막으로 저의 이론을 정리하며 scanf에 공백문자를 사용한 경우를 예로 들겠습니다.

-1) scanf("%d",&a);
그냥 값을 치면 a에 들어갑니다.
-2) scanf(" %d",&a);
스페이스를 만났으니 값을 하나 입력받고 그 값을 a에 넣고 함수 종료
-3)scanf("%d ",&a);
일단 값을 받고 a에 입력한다.
스페이스를 만나 값을 하나 더 입력받고 함수종료
->이때문에 b배열에서 값을 하나 더 입력해야 하는 겁니다.

2011/05/27  
KRR 아.. 그렇군요..

꽤 놀랍네요..

그렇다면 함수에 들어가기전 함수는 입력된 문자열을 먼자 본다는 것도 되는군요.

일단 아직 허접이라.. 글이 좀 난해하지만.. 무슨말씀을 하시는지 알겠습니다...

오히려 제가 배워가네요... ㅎㅎㅎ
2011/05/27  
jsk0612 추가 질문 있는데요;;

그럼 scanf ("%c", &a); 가 있다고 가정하면

scanf ("%c", &a); //이것과

scanf (" %c", &a); // 이것은 차이가 없어야 하지 않나요?

그러나 위의 scanf를 사용하면 다음 scanf때 \n까지 입력이 들어가서 지장이 있는데

아래에 scanf를 사용하면 \n가 다음 scanf까지 지장을 안주는데

그건 왜 그런가요?

scanf (" %c", &a); // 이것은 값을 입력하면 a에 넣어지면 \n가 버퍼까지 안가고
그냥 바로 종료하게 되있는건가요?
2011/05/28  
prosthetics 두 경우 모두 버퍼에 newline이 남아있는데 jsk0612님이 짜신 코드를 볼 수 있을까요?

아래는 제가 짠 코드입니다.
#include <stdio.h>

void main()
{
char str[20];
char str2[20];

scanf(" %s",str);
gets(str2);
printf("%s",str);
printf("%s",str2);
}
2011/05/28  
prosthetics 아, 다음 코드처럼 scanf를 2개 연속으로 놓았을때는 두번쨰 scanf가 무시당하지 않습니다.
이것또한 scanf내부 함수의 사정이라서(하는 일은 간단한데 내부는 복잡하죠 ㅎㅎ)
유추, 해석에 의해서만 답변을 드릴 수 밖에 없습니다.
그러나 이것은 정확하지 않은 답이기에 제가 답변할 수 있는 범위를 넘었다고 볼 수 있네요.

#include <stdio.h>

void main()
{
char str[20];
char str2[20];

scanf("%s",str);
scanf("%s",str2);
printf("%s",str);
printf("%s",str2);
}
2011/05/28  
jsk0612 scanf를 생각도 없이 쓰다가

파고 들려고 하니깐 %s는 무시 안당하고 %c는 무시당하고 꽤 복잡하네요;;;

저만 복잡한건가요ㅜ
2011/05/28  
prosthetics 그건 %s하고 %c의 차이입니다.

%s는 NULL을 만날때까지 입력, 혹은 출력을 하는데 비해

%c는 '한문자'만 입력 혹은 출력을 하거든요.

scanf함수에서 %s일때랑 %c일때의 경우를 나눠서 처리할 수도 있는 것이죠.
(내부 못봐서 정확히 모름)

scanf는 C언어를 배울때 가장 처음 접하면서도(가장 많이 자주 쉽게 사용하면서도)

실상은 키보드라는 하드웨어에서 입력을 받기 때문에 내부가 많이 복잡합니다.
(거기다가 안을 볼 수 있는 것도 아니니까요)

jsk0612님만 복잡한것이 아니고 정말로 그 함수 내부가 복잡한겁니다.
2011/05/29  
jsk0612 그렇군요... 더 실력을 쌓고 나서 다시 봐야겠네요..

답변해주신 모든 분들 감사합니다
2011/06/02  
han9551 리버싱 해보신 분들은 아시겟지만.

scanf에서 " "공백을 포멧스트링으로 주면 말입니다.

공백문자를 제거하는 루틴을 수행합니다.

이 루틴은, "%s","%d"에서는 실행되지만, "%c"는 실행되지 않습니다.
그 차이는, 문자열을 받아들이는가, 문자 하나만을 받아들이는가의 차이입니다.

scanf(" ");는 기능적인 면에서 fflush(stdin);과 같습니다.
2011/06/16