08 Dec 2022
<aside> 🔚 문제를 풀다 보면 입력값이 몇개의 줄로 주어지는지 알려주지 않는 문제가 나온다. 바로 이런 경우에 코드가 지저분해진다 싶으면 한 번 읽어보자. 깔끔하게 코드가 나오는 사람들도 왜 깔끔하게 나오는지 자세히 알려줄테니 계속 알아보자.
</aside>
오늘은 cin의 EOF 탐지에 대해서 파헤쳐 보자. 몇 개의 줄이 입력될건지 첫 줄에 주어지는 문제도 많지만, 그렇지 않은 문제들고 있다. 이런 경우에는 주어진 수만큼 반복문을 돌릴 수 없으니, 입력값의 맨 마지막에 있는 EOF(End of File)을 우리가 직접 감지해야 한다.
백준 10951번은 EOF가 나오기 전까지 두 수를 계속 더하는 문제이다. 기초를 탄탄히! 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을 다시 반환한다는 점을 이용하는건데, 이렇게 하면 앞서 말한 함정에 빠지지 않고 정답이 된다. 찝찝함은 사라졌지만 느낌표와 이중 괄호 때문에 지나치게 복잡해 보인다.
제목으로 요란을 떨긴 했지만 이미 아는 사람도 있을 것이다. 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';
}
}