difmfmdi   1년 전

우선 저는 백준알고리즘 방식에 익숙한 유저도 아니고 얼마안된 초본데..

저는 문제를 보면 당장 예제(입력과 출력)에서 포인트가 무엇인지 파악하려고 하는 유저입니다.

나중에 복잡한 알고리즘을 풀 때 도움이 되는 습관은 아니겠죠?.. // 우선 예제를 보고

Hello

Baekjoon

OnlineJudge

이렇게 입력되었을때 출력한다고 생각하면 100줄은 아니니 단순하게

3줄그대로 출력되야한다고 생각했는데.. 다른 질문들의 소스코드를 보니

2차원배열 사용이 되어있고,,

메모리낭비를 이유로 gets를 사용하지 말라시는 당부의말씀들..  여튼 짰습니다

#include<stdio.h>
#include<string.h>
int main(void)
{
char str1[100],str2[100],str3[100];

gets(str1);
gets(str2);
gets(str3);


puts(str1);
puts(str2);
puts(str3);
return 0;
}

100줄을 만족못해서일까요 틀렸습니다

그래서 다른 분들의 코드를 봤는데


#include <stdio.h>

int main(void)

{  char str[100][100];  int i;  for(i=0;i<100;i++) gets(str[i]);    for(i=0;i<100;i++) puts(str[i]);  return 0; }

이 프로그램은  틀렸어요

실행 시 100줄 입력받고 100줄 출력하는 결과를 확인하고 제출했는데 틀렸답니다.


#include <stdio.h>

int main(void) {  char s[101];  while(scanf("%[^\n]\n", s)==1)   printf("%s\n", s);  return 0;

}

그런데 이 프로그램은 이것이 맞았습니다!! 라고 통과되는 이유의 답변이 ->

{ 정규표현식 쓴거에요



[^\n]은 \n이거 빼고 다 받으라는 소리에요...



^이게 not의 의미가 있어요.



그리고 마지막에 \n이걸 쓴거는 \n거랑 똑같은거 매칭시키고 그건 버리라는거에요 (정확한 설명은 아닐지 몰라도 암튼 그렇습니다.)



그러니까 \n이거를 newline(개행)이라고하면



개행 나오기 전까지 다받으라는거에요, %s같은거로 받으면 공백단위로 받고 공백은 무시되는데, 저렇게 쓰게되면 공백이 있던 없던간에 개행문자(\n)나오기 전까지는 다 받으라는 뜻이 됩니다. 그리고 이게 while안에 있으니까 EOF나오기 전까지는 다 받겠네용 ㅎ?

}

이것인데


eof (end of file)이게 무슨개념인가요? -> 공백으로 시작하지 않고 공백으로 끝나지 않는다는 얘기가 이 부분과 상관이 있나요?

while은 1이기만하면 참이라서 계속 돌텐데 eof이게 나오기 전까지(?) 안나오니까 end of file은 없다라는 뜻에서 한 얘기인가요?

맞은 프로그램을 실행하면

입력받은걸 100줄 입력받지도 않고

n=0 부터 n+1번 입력시 n번째 입력할때의 값을 출력해주는 식으로..

(1(입력)

2(입력)

1(출력)

3(입력)

2(출력)

4(입력)

3(출력)

5(입력)

4(출력) 응 원래 이게답이야~ ㅎㅎ..이렇게

보여주는 프로그램이 정답처리가 되어서..)

문제가 <입력 받은 그대로 출력하는 프로그램을 작성하시오> 가 아니라

<입력 받는 대로 출력하는 프로그램을 작성하시오> 이어야 하지 않나요?

예제 입력 예제 출력만 보고 바로 눈치채지 못한 저의 잘못이었는지.. 

제가 다른 질문자들의 코드에 으레 동조하는 생각을 했던것이 잘못이었는지..?

//이런 경우나 문제같은 경우 여러분은 헷갈리시지 않는지 너무 간결하다고 생각이 들 때도 장애나 어려움이 없으신지 궁금해요..

제가 경험이 없고 모자라서 그런지도 .. 눈물..

"입력받은 그대로"보다는 "입력받는 대로"가 되어야 통과될 수 있는 형태의 문제인게 맞는지.. 알려주세요



plzrun   1년 전

제가 예전에 쓴 답변글을 퍼오신것 같네요?

ㅎㅎ일단 질문을 읽어보니 온라인저지가 stdin,stdout을 통해 입/출력을 하는 것을 잘 모르시는 것 같습니다.


문제 풀다 보시면 표준 입출력을 통해서 입/출력이 이루어진다고 쓰여있는 문제가 보일텐데

딱히 명시해주지 않아도 온라인저지에서 입출력은 표준입출력을 통해 이뤄집니다.


근데 여기서 stdin, stdout을 버퍼라고 생각하시면 되는데요.

그니까 입력 버퍼랑 출력버퍼가 따로 있다는 얘기에요

그래서 내가 입력을 하면 scanf를 통해서 입력버퍼에만 쓰이구요 printf()를 하면 컴퓨터가 해당 내용을 출력버퍼에 쓰는 겁니다.


그럼 콘솔창(출력화면)에 보여지는건 내가 타이핑 할 때 입력버퍼에 들어가는게 보이는거고,

프로그램이 printf()를 하면 그걸 컴터가 출력버퍼에 쓰는데 그 버퍼에 있는게 모니터에 뿌려지는 것 뿐이거든요.


그래서 freopen("./input.txt", "w", stdout); 이런 구문을 추가하면,

stdout(표준 출력) 버퍼에 쓰여진 것이 원래 기본값으로 모니터에 뿌려지게 되어있는데

그러지말고 input.txt라는 파일에 쓰라는 의미가 됩니다.


결국 입력받고 출력하고를 번갈아가면서해도 온라인저지는 출력버퍼만 확인하니까 아무런 문제가 없습니다.



그리고 보통 몇줄의 인풋이 들어온다라고 명시되어있지 않은 문제의 경우

'대체 어떻게 인풋을 그만 받으라는 건가~?'라는 의문이 드실때가 있으실텐뎅

EOF를 받으면 인풋을 멈추게 하면 됩니다.


EOF의 경우 전부다 그런건 아닌데, (저도 정확히 몰라서)

c/c++에선 -1로 인식을 해요. (사람들이 컴파일러마다 다르다곤 하지만 -1아닌걸 본적이 없음.)

-1을 2의 보수로 표현하면 1111111111...(모두 1) 이죠.


콘솔창에서는 ctrl+d를 눌러서 EOF를 줄 수 있구요.

온라인 저지의 경우 채점할 때 file에 있는걸 긁어다가 인풋을 넣을테니 맨 마지막에 EOF가 들어가겠죠.


scanf는 원래 리턴값이 있는데, EOF를 받으면 EOF를 리턴합니다.

그래서 while(scanf(...) != EOF) { ... } 이런식으로 써주면 알아서 돌다가 더이상 인풋이 없으면 끝나게 됩니다.

콘솔창에서 테스트할때는 아까 말씀드렸다시피 ctrl+d로 끊어주구요.


근데 아까 EOF를 -1이라고 했잖아요? 그리고 -1을 2의 보수로 표현한 이유는 좀 더 깔끔하게 표현하는걸 보여드릴려고 했던거거든요?

그니까 방금 위에서 쓴 코드는 while(~scanf(...)) {...} 이런식으로 표현이 가능해요.

어떤 숫자값에 ~이거를 하면 모든 비트를 전부 바꾸라는 얘긴데

-1은 2진법으로 전부 11111111111111...이고

이 비트들을 모두 바꾸면 결국 0이니까 EOF를 받으면 while의 조건문이 false가 돼서 탈출하겠죠.



아~ 다썼다.

plzrun   1년 전

위에 글 쓴 사람입니다.

그러니까 아래와 같이 쓰면 아주 깔끔하겠죠? ㅎ

difmfmdi   1년 전

어렵네요 근데 이런 상식을 공부하는게 쫌 부담스러워요

시간지나면 까먹을것 같아서.. 그래도 친절한 설명 감사합니다~~


plzrun   1년 전

이런건 한번 알면 까먹을리가 없죠. :D

difmfmdi   1년 전

:ㅇ ㅋㅋ네 문제풀다가 한글 메모리 더 차지하는거랑 문자&문자열 상식 알면서도 까먹고  많이 헤맸던 기억때문에

여튼 thank you

difmfmdi   1년 전

지금 더블릿에서 EOF 개념이 이해되서 글 남겨요

http://59.23.27.112/30stair/EO...

이글 펴보실 분들 참고하시길

#include<stdio.h>
#define EOF  -1
int main()
{
 int a,b;
   while ( scanf("%d %d",&a,&b) != EOF ) { //EOF 대신에 -1 을 주어도 됩니다.
      printf("%d\n",a+b);
   }
   return 0;
}


유닉스(리눅스)에서는 ctrl - d ,windows 에서는 ctrl - z 가 EOF 로 약속되어 있습니다.


댓글을 작성하려면 로그인해야 합니다.