본격적으로 for문 문제를 풀기 전에 주의해야 할 점이 있다. 입출력 방식이 느리면 여러 줄을 입력받거나 출력할 때 시간초과가 날 수 있다는 점이다.
C++을 사용하고 있고 cin/cout을 사용하고자 한다면, cin.tie(NULL)과 sync_with_stdio(false)를 둘 다 적용해 주고, endl 대신 개행문자(\n)를 쓰자. 단, 이렇게 하면 더 이상 scanf/printf/puts/getchar/putchar 등 C의 입출력 방식을 사용하면 안 된다.
또한 입력과 출력 스트림은 별개이므로, 테스트케이스를 전부 입력받아서 저장한 뒤 전부 출력할 필요는 없다. 테스트케이스를 하나 받은 뒤 하나 출력해도 된다.
첫 줄에 테스트케이스의 개수 T가 주어진다. T는 최대 1,000,000이다. 다음 T줄에는 각각 두 정수 A와 B가 주어진다. A와 B는 1 이상, 1,000 이하이다.
각 테스트케이스마다 A+B를 한 줄에 하나씩 순서대로 출력한다.
5
1 1
12 34
5 500
40 60
1000 1000
2
46
505
100
2000
#include <stdio.h> int main() { int T, i, A, B; scanf("%d", &T); for (i=0; i<T; i++){ scanf("%d %d", &A, &B); printf("%d\n", A+B); } return 0; }
예제 입출력 보고 5줄 입력받고 5줄 나와야 하는 줄 알고 한참 고민했다....ㅋㅋ 근데 그냥 한 줄씩 입출력이었음..!
#include <iostream> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(NULL); int T, i, A, B; cin >> T; for (i=0; i<T; i++){ cin >> A >> B; cout << A+B << "\n"; } return 0; }
!!주의할 것!! \n은 꼭 ""로 감싸주기! 이거 때문에 컴파일 에러나서 수정해서 다시 제출함ㅎ;
지금까지 백준 단계별 순서에 따라 풀어왔던 문제들과 달리 이번 문제에서는 시간 단축을 위한 팁을 주고 있더라구요. 근데 이 팁 안에 처음 보는 녀석들이 언급되어 각각에 대해서 정리하고 넘어가겠습니다.
우선 C++ 컴파일러에는 sync_with_stdio(true)가 default로 저장되어 있습니다. 이는 C++와 C를 혼용할 수 있도록 만들어주는 녀석이에요. 동기화를 시켜주는 셈이죠. 즉 아래와 같은 코드가 가능해집니다.
#include <iostream>
using namespace std;
int main() {
int A;
cin >> A;
printf("%d", A);
cout << "Hello";
return 0;
}
위 코드를 실행해 A에 1을 입력하면 1Hello
가 출력됩니다.
이번엔 코드에 ios::sync_with_stdio(false)를 넣어볼게요.
#include <iostream>
using namespace std;
int main() {
ios::sync_with_stdio(false)
int A;
cin >> A;
printf("%d", A);
cout << "Hello";
return 0;
}
이 코드는 실행해 A에 2를 입력하면 Hello2
가 출력됩니다.
2가 앞에 나와야 할 것 같지만 순서가 달라졌습니다. 왜 이럴까요?
아래 코드도 살펴보겠습니다.
#include <iostream>
using namespace std;
int main(){
int A;
cin >> A;
cout << a;
printf("년 끝, ");
cout << 2022;
printf("년 ");
printf("시작! ");
cout << "굿 럭";
return 0;
}
A에 2021을 입력하면 이 코드의 실행결과는 2021년 끝, 2022 시작! 굿 럭
이 출력됩니다.
하지만 코드에 ios::sync_with_stdio(false);
를 포함시키면
20212022굿 럭년 끝, 년 시작!
이 출력됩니다.
즉 ios::sync_with_stdio(false);
가 포함되면
C++의 임시저장공간(독립 버퍼)를 사용해 속도가 빨라지는 장점은 있지만,
C와 혼용이 불가능해집니다. ios::sync_with_stdio(false);
가 포함된 코드에서 C와 C++ 혼용시 보통 C++ 출력을 먼저 한 후 C 출력을 합니다.
이제 cin.tie(NULL);
또는 cout.tie(NULL)
은 어떤 기능을 해주는지 살펴봅시다.
프로그램은 버퍼가 가득 찰 때까지 기다리지 않고
개행 문자 입력시 버퍼가 자동으로 비워(flush)집니다.
cin과 cout이 묶여(tie)있을 때는 cin, cout을 계속 번갈아 써도 입출력이 동시에 나타납니다. 그런데 untie시키면, 즉 tie(NULL)하면 입력을 모두 받아야 출력이 됩니다.
이게 무슨 말이냐 하면..
cin과 cout은 각각 stream buffer를 지니는데, cin.tie(NULL)
을 하면 cin 전에 cout의 stream buffer을 flush하지 않습니다.
즉, cout으로 무언가 출력하도록 한 후 다음 line에서 cin으로 입력을 받을 경우, 출력이 안 되었는데 입력을 받기 위해 대기하는 경우가 발생합니다. 왜냐하면 cout << ~~;
는 stream buffer에서 console창으로 flush됨을 의미하지 않기 때문입니다. flush하려면 개행과 flush를 하는>>endl
을 써줘야 합니다.
위의 긴 설명을 이해하기 위해 아래 두 코드를 살펴보겠습니다.
백준 15552 문제 풀이를 아래와 같이 작성해볼게요.
#include <iostream>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cin.tie(NULL);
int T, i, A, B;
cin >> T;
for (i=0; i<T; i++){
cin >> A >> B;
cout << A+B << '\n';
}
return 0;
}
이 코드의 실행 결과는 다음과 같은데,
3
1 1
2 3
5 5
2
5
10
(위 4줄은 입력, 아래 3줄은 출력)
즉, 출력이 안 되었는데 입력을 받았죠?
어떻게 보면 복잡한 내용 같지만 정말 많이 배우는 하루였네요!:)