[백준] 10951번. A + B - 4

leeeha·2021년 10월 18일
0

백준

목록 보기
19/186

https://www.acmicpc.net/problem/10951

EOF이 될 때까지 입력 받는 방법

참고 자료: https://st-lab.tistory.com/257

이 문제의 핵심은 몇 개의 테스트 케이스를 입력 받을지 알 수 없다는 것이다.

파일의 끝에 도달하여 더 이상 읽을 데이터가 없을 때, 입력 스트림은 EOF(End Of File)을 리턴한다. (정수로는 -1)
하지만 입력 파일을 따로 생성하여 읽지 않는 한, 일반적인 키보드에서는 EOF키가 없기 때문에 EOF (입력 끝) 상태를 전송할 수 없다. 대신에, 키맵이 따로 있는데 콘솔창에서 윈도우는 CTRL + Z를, 리눅스(유닉스) 계열은 CTRL + D를 입력해주면 된다.

이 문제는 결국 EOF이 될 때까지 반복해서 입력을 받으면 되는 문제이다.

scanf 함수

stdio.h (또는 cstdio) 헤더 파일에 포함된 scanf 함수는 int형을 반환하는데, 그 값은 정상적으로 읽어들인 입력 데이터의 개수이다. 파일의 끝(EOF)에 도달하면, -1을 반환한다.

while(scanf("%d %d", &a, &b) != -1) {
	...
}

cin.eof() 함수

cin 객체의 멤버함수인 eof()은 파일의 끝에 도달하면 true를 반환한다. 그런데, 다음과 같이 코드를 작성하면 어떤 결과가 나올까?

char val;
while(!cin.eof()) {
	cin >> val;
	cout << val;
}

a
a
b
b
c
c
d
d
^Z
d

EOF 상태가 되었을 때 아무것도 출력되지 않고 바로 루프가 종료되어야 하는데, d가 한번 더 출력되는 문제가 발생한다. 그 이유는 Ctrl+Z로 EOF 상태를 전송했을 때, val에는 이전 루프의 값인 d가 저장되어 있어 이 값이 출력되기 때문이다.

eof() 함수가 올바른 시점에 true가 되려면 (cin >> val).eof() 과 같이 "읽기 시도를 한 후"에 eof 검사를 해야 한다!

char val;
while (!(cin >> val).eof()) {
    cout << val;
}

a
a
b
b
c
c
d
d
^Z

cin operator bool

eof() 함수보다 더 간단한 방법은 다음과 같다.

while(cin >> a >> b) {
	...
}

cin은 원래 스트림 객체를 반환하지만 조건문에 들어가면 연산자 오버로딩에 의해 bool형을 리턴한다. (입력 스트림이 정상이면 true, 아니면 false)

풀이

방법1: scanf

#include <cstdio>

int main() {
	int a, b;

	// 또는 scanf("%d %d", &a, &b) == 2 로도 가능
	while (scanf("%d %d", &a, &b) != EOF) {
		printf("%d\n", a + b);
	}

	return 0;
}

방법2: cin.eof()

#include <iostream>
using namespace std;

int main() {

	int a, b;
	while (!(cin >> a >> b).eof()) { // eof() 대신 fail()을 사용해도 된다.
		cout << a + b << "\n";
	}

	return 0;
}

방법3: cin operator bool

#include <iostream>
using namespace std;

int main() {

	int a, b;
	while (cin >> a >> b) {
		cout << a + b << "\n";
	}

	return 0;
}

0ms가 나온 건 scanf 함수를 사용한 경우, 그리고 아래 코드를 추가하여 입출력 속도를 향상시킨 경우이다.

ios::sync_with_stdio(false);
cin.tie(NULL);

https://velog.io/@jxlhe46/C-cin-cout-시간-초과-문제-해결-방법

profile
습관이 될 때까지 📝

0개의 댓글