[입출력을 개선하는 방법]
대부분 알고리즘 해석과 debug 하는 데 있어 console창을 많이 사용합니다.
이미 다들 알고계시겠지만 C++에서 콘솔에 입출력하는 방법은 두 가지 존재합니다.
기존의 Scanf와 Printf를 사용하는 방법과 std함수의 cin과 cout를 이용하는 방법입니다.
그런데 문제 해석에 있어 어떤부분은 cout를 사용해도 정상적으로 진행되고,
어떤 부분은 진행이 안 되는 케이스가 존재합니다.
이런 현상을 이해하기 위해서는 정확하게 어떤 식으로 std함수가 동작하는지 확인해야 하지만 시간상 해결방법을 먼저 설명하겠습니다.
코드의 앞부분에
cin.tie(NULL)
sync_with_stdio(false)
두개 문장을 입력하면 증상이 해결됩니다.
[cin.tie]
tie는 의미와 반대로 cin과 cout를 묶음을 풀어주는 역할을 합니다.
std::cout << "Enter Name : ";
std::cin >> name;
예제를 보면 <<(출력 연산자), >>(입력 연산자)를 순서대로 이해할 수 있습니다.
Enter Name 메시지가 디스플레이된 이후에 name변수에 입력을 받는 순서를 생각할 수 있습니다.
그러나 tie를 선언해주면 Enter Name이 출력되기 전에 입력을 받기 위해 기다리는 현상이 발생될 수 있습니다.
왜냐하면 대부분 출력 자체가 버퍼로 구성되어 있어 버퍼가 처리되기 전까지 약간의 시간이 있기 때문에 그 시간에 입력명령이 실행되면 입력을 먼저 받게 되기 때문입니다.
따라서 출력이후 입력 순서를 확실하게 하고 싶다면 해당 부분을 동기화해 주는 작업이 별도로 필요합니다.
여담으로 출력 연산자와 입력 연산자는 각각 ostream istream에 선언되어 있으며 단순히 외워서 사용하는 게 편합니다.
추가적으로 사용자 입맛에 따라 커스터마이징하여 overloading, overriding 하여 사용하기도 하는데 거의 사용할 일이 없기 때문에 신경 쓰지 않아도 됩니다.
[sync_with_stdio]
해당 구문은 C의 stdio와 C++의 iostream을 동기화시켜주는 역할을 합니다.
일반적으로 C++에서 C언어의 입출력인 Scanf와 Printf를 모두 사용할 수 있는데 sync_with_stdio(false) 구문을 사용하면 동기화를 해제하기 때문에 C언어 입출력을 사용할 수 없습니다.
해당 구문을 사용하면 동기화 작업이 스킵되므로 성능 향상을 기대할 수 있으나 멀티스레드 환경에서 동기화가 깨져있기 때문에 출력순서를 보장할 수 없습니다. 따라서 여기서도 순서를 동기화하는 작업이 별도로 필요하게 됩니다.
[결론]
해당 기능은 단순 테스트코드로 생각하시고 실제 개발에 있어서는 사용하지 않는게 좋겠습니다.
내부적인 동기화 작업을 모두 할 수 있는 수준이라 생각하시면 사용하셔도 무방하지만 어느 곳에서는 동기화하고 어느 곳에서는 동기화하지 않으면 결국 스파게티가 되는 건 시간문제이기 때문입니다.