busyhuman   8년 전

테스트케이스잡고하니

1. 처음에 0이 뜨고(문자열입력을 무시함)

2. 값이 다르게 나옵니다.

뭐가 문제인가요?

yukariko   8년 전

getline이 테스트케이스의 개수를 받는 라인을 읽기때문입니다.

반복문에 들어가기전에 getline을 부르거나 ignore 함수를 사용하거나 방법은 여러가지가 있습니다.

kesakiyo   8년 전

@yukariko 님의 설명을 보충하자면

이 문제를 이해하기 위해서는 입력버퍼라는 개념을 이해햐아 합니다.

콘솔창에서 입력을 하게되면 이게 다이렉트로 메모리에 저장이 되는게 아니라

입력버퍼에 들어가고 난 다음에 cin, getline 등의 입력함수가 입력버퍼에서

시퀀스를 꺼내오는 형식으로 입출력이 이루어 집니다.


이제 여기서 cin과 getline의 입력방식을 이해해야 합니다.

1. cin의 입력방식

cin은 앞에 있는 화이트 스페이스를 무시하고 입력을 받습니다.

그렇게 화이트 스페이스를 무시하고 입력 포멧에 맞는 데이터를 받거나 화이트 스페이스를 만나면 입력을 그만 받습니다.

그리고 만난 화이트 스페이스를 그대로 보존합니다.


2. getline의 입력방식

getline에서 delimiter (번역판에서는 제한자) 라는 개념이 나오는데요, getline의 기본 delimiter는 개행문자입니다.

getline은 앞에 있는 delimiter를 무시하지 않고 만나면 그 즉시 끝입니다. 그리고 delimiter를 삭제해 버리죠.


자. 이제 사전지식을 가지고 testcase를 분석해 봅시다.


테스트 케이스를 한 행에 쭉 나열하면

5[\n]OOXXOXXOOO[\n]OOXXOOXXOO[\n]OXOXOXOXOXOXOX[\n]OOOOOOOOOO[\n]OOOOXOOOOXOOOOX[\n]

와 같은 형식이 될 것입니다. 여기서 [\n]는 개행문자를 의미하고 1byte의 입력버퍼 공간을 차지하고 있습니다.


상황 1.

cin >> n;

을 하는 순간 어떻게 될까요? 위에 얘기한것처럼 5를 n에 입력받고 화이트 스페이스를 만났으니 그대로 입력을 그만받습니다.

화이트 스페이스를 그대로 보존합니다. 그렇다면 입력버퍼는

[\n]OOXXOXXOOO[\n]OOXXOOXXOO[\n]OXOXOXOXOXOXOX[\n]OOOOOOOOOO[\n]OOOOXOOOOXOOOOX[\n]

위와같은 모습이 되겠죠.


상황 2.

getline(cin, s);

을 하면 어떤 일이 발생할까요? 앞서 말했듯이 getline은 기본적으로 개행문자를 delimiter로 가지고 있고 만나는 순간 입력을 그만받습니다.

그리고 그 delimiter를 삭제하지요. 그렇다면 입력버퍼는 아래와 같이 변하게 됩니다.

OOXXOXXOOO[\n]OOXXOOXXOO[\n]OXOXOXOXOXOXOX[\n]OOOOOOOOOO[\n]OOOOXOOOOXOOOOX[\n]

그리고 s는 빈 문자열이 되겠죠.


상황 3.

다시한번 getline(cin, s); 를 하게 됩니다.

그렇다면 볼것도 없이 버퍼는 아래처럼 변하게 되겠죠.

OOXXOOXXOO[\n]OXOXOXOXOXOXOX[\n]OOOOOOOOOO[\n]OOOOXOOOOXOOOOX[\n]

만약 작성자 님께서 올바른 솔루션을 작성하셨다면 답이 하나씩 밀리게 될 것입니다. 그리고 마지막 답은 안나오겠죠?


그렇다면 해결책은 무엇일까요.

어차피 중간에 화이트스페이스가 없다면 s를 cin으로 받거나, @yukariko 님이 말씀하신것처럼 getline이 있는 for문 전에 cin.ignore(1) 이나 cin.get() 등을 이용해

버퍼를 하나 비워주고 시작하면 되겠죠.


물론 입력함수는 이게 전부 다가 아닙니다.

설정을 줄 수 있는건 많고 신기한 입출력함수도 많으니까요.

하지만 위에서 말한것은 앞으로 많은 문제를 풀 때 외에도 프로그램을 할 때 도움이 될 배경지식이니 알고 계시면 좋을거 같아 자세히 적어봅니다.


휴 힘드네요.

그럼 즐프~

busyhuman   8년 전

갈 길이 멀고도 까마득하네요 ㅋㅋ

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