08 Dec 2022

<aside> 🔚 문제를 풀다 보면 입력값이 몇개의 줄로 주어지는지 알려주지 않는 문제가 나온다. 바로 이런 경우에 코드가 지저분해진다 싶으면 한 번 읽어보자. 깔끔하게 코드가 나오는 사람들도 왜 깔끔하게 나오는지 자세히 알려줄테니 계속 알아보자.

</aside>

Table of Contents

오늘은 cin의 EOF 탐지에 대해서 파헤쳐 보자. 몇 개의 줄이 입력될건지 첫 줄에 주어지는 문제도 많지만, 그렇지 않은 문제들고 있다. 이런 경우에는 주어진 수만큼 반복문을 돌릴 수 없으니, 입력값의 맨 마지막에 있는 EOF(End of File)을 우리가 직접 감지해야 한다.

백준 10951번은 EOF가 나오기 전까지 두 수를 계속 더하는 문제이다. 기초를 탄탄히! EOF를 감지하는 부분을 파 보자.


std::cin.eof()

#include <iostream>                             
using namespace std;                            
int main()                                      
{                                               
    ios::sync_with_stdio(false);                
    cin.tie(NULL);                              
    int a, b;                                   
    while (true)                                
    {                                           
        cin >> a >> b;                          
        if (cin.eof())
						break; 
        cout << a + b << '\\n';                  
    }                                           
}

가장 직관적인 방법은 std::cin.eof()를 사용하는 방법이다. 만약 파일이 끝났다면 true를 반환할 것이다. 직관적이고 좋은 방법이지만 eof 체크와 반복문 탈출이 중간에 있으니까 뭔가 찝찝하다.


//이렇게 하지 마세요!
while (!cin.eof())                                
{                                           
    cin >> a >> b;                          
    cout << a + b << '\\n';                  
}                                           

조건으로 사용하니 일단 보기에는 훨씬 깔끔하다! while문 조건으로 eof()을 사용할 때는 느낌표(!)를 넣어서 EOF가 아닐 때 루프가 계속 돌아가게 하자. 진짜 함정은 이렇게 쓰면 마지막 a + b가 두 번 출력되기 때문에 오답이라는 것이다. 마지막 루프에서 cin이 읽으려고 할 때 그제서야 eof에 도달하기 때문이다. 이걸 해결하기 위해 다음과 같이 해 보자.

while (!(cin >> a >> b).eof())                                
{                                           
    cout << a + b << '\\n';                  
}                        

조건이 뭔가 복잡해 보이지만 문제는 해결된다. cin의 operator>>가 cin을 다시 반환한다는 점을 이용하는건데, 이렇게 하면 앞서 말한 함정에 빠지지 않고 정답이 된다. 찝찝함은 사라졌지만 느낌표와 이중 괄호 때문에 지나치게 복잡해 보인다.

while (cin >> a >> b)가 왜 될까?

제목으로 요란을 떨긴 했지만 이미 아는 사람도 있을 것이다. cin >> a >> b를 while문의 조건으로 넣는 것이다.

#include <iostream>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    int a, b;
    while (cin >> a >> b)
    {
        cout << a + b << '\\n';
    }
}