수업을 듣다가 아래 두개의 구문에 대한 의문이 생기게 되었습니다. 과연 정확히 이 두 표현식이 정확히 의미하는 바가 무엇일까? 오늘은 아래 코드에 대한 해석과 비교하는 것에 대해 다룹니다.
while(cin)
while(cin >> x)
//What is the difference?
C++ 앞 부분을 조금이라도 공부해보신 분들이 있다면 cin 이라는 것에 대해 아실겁니다.
C언어에서 scanf와 대응되는 것으로 C++에서는 <iostream> 이라는 헤더 파일에 있는 녀석인데 서식 문자 없이 간편하게 입력을 받을 수 있죠.
int x;
cin >> x;
위 2줄의 코드를 이용하면 C++에서 간편하게 변수에 값을 입력 받을 수 있습니다.
(데이터 타입에 상관 없이 cin이 알아서 입력을 잘 처리해줍니다.)
그런데 만약 저 위에서 숫자가 아닌 문자열과 같은 다른 입력으로 int x; 에 값을 저장하려고 했다고 생각해봅시다.
만약에 이렇게 되면 cin 객체의 상태는 false(비정상) 이 되며 프로그램이 종료되게 됩니다. 한 마디로 cin의 값이 false 가 됬다고 보면 됩니다.
그러면 cin 으로 계속 입력을 받는데 자료형에 맞게 제대로 된 값만을 넣었을때만 계속 반복하는 형태로 진행하려면 어떻게 해야할까요?
무한반복, 무한 입력 뭔가 while() 문이 떠오릅니다. 한번 머리속에 떠오른 대로 아래 코드를 작성해 봅시다.
#include <iostream>
using namespace std;
int main()
{
while(cin){
cout << "Test";
}
return 0;
}
프로그램을 실행해보시면 뭔가 cin 으로 계속 입력을 받을 것이라는 기대와는 반대로 Test라는 문자열이 무한루프 되면서 출력됩니다. 왜 그럴까요?
우선 이해해야할 점은 cin 이라는 것 자체가 특별한 놈이 아니란겁니다. 분명 입력을 받는데 도와주는 역할을 하는건 맞지만 입력을 받는건 어디까지나 >> 연산자를 이용해서 cin >> x; 처럼 입력을 받을때나지 cin 자체로는 그냥 변수나 다름이 없습니다.
(우리가 매일 사용하던 int x; 나 여러 변수들이나 cin 은 크게 다를 바가 없다는 말입니다.)
cin 은 아까도 말했듯이 입력이 비정상적으로 이루어지면 false 상태가 되며 기본적으론 true(정상 상태) 로 있습니다.
우리가 사용하던 변수와 크게 다를바가 없으므로 while문 조건으로 cin 을 검사하면 cin 상태는 현재 true 이므로 while(true); 로 해석되어서 무한 루프를 도는것입니다.
즉 while(cin) 자체로는 입력을 받는 기능이 없습니다. 단순히 cin이 정상인지 검사하는 것이죠.
cin이 특별해서 cin만 써주면 스스로 입력을 받는 그런 마법같은 존재가 아니라 그냥 변수나 크게 다름이 없단걸 우선 이해하셔야 합니다.
#include <iostream>
using namespace std;
int main()
{
while(cin){
int x;
cin >> x;
cout << x << endl;
}
return 0;
}
1
1
2
2
3
3
4
4
5
5
asdf
0
--------------------------------
Process exited after 1.928 seconds with return value 0
계속하려면 아무 키나 누르십시오 . . .
위 내용을 제대로 이해하셨다면 while(cin) 으로는 cin 상태만 검사하고 while 실행식 안에선 cin >> 으로 입력을 계속 받으면 됩니다. cin 의 상태가 바뀌는건 cin 으로 입력을 받다가 잘못된 입력이 들어오면 false로 바뀌는거니깐요.
그런데 위 표현식이 조금 지저분하다거나 (직관적이지 않다거나) 문제 조건에 따라 코드를 줄여야 하는 상황이 있다고 봅시다.
저 위에 cin 으로 입력 받는 부분과 cin 이 정상인지 체크하는 부분을 한 문장으로 줄일 수 있습니다. 아래를 보시죠.
#include <iostream>
using namespace std;
int main()
{
int x;
while(cin >> x){
cout << x << endl;
}
return 0;
}
1
1
2
2
3
3
4
4
5
5
asdf
--------------------------------
Process exited after 1.73 seconds with return value 0
계속하려면 아무 키나 누르십시오 . . .
위 코드랑 하는 일은 거의 같습니다. 조금 다른 점은 위 코드에서는 x값이 제대로 입력되지 않을때 x 값을 찍어보면 cin 과 같이 false 값이 나오게 되는데 여기선 쓸데없는 0이 출력되지 않는군요.
표현식이 아까랑은 달라졌습니다. while(cin >> x) 이렇게 사용했는데요.
이 while 조건문을 해석해보면 2가지 스텝으로 구성되어 있습니다.
1. cin >> x 로 입력을 받습니다.
2. 이후 cin이 정상인지 체크합니다.
왜 이렇게 두가지 스탭이 있는진 아래 코드를 우리가 평상시에 어떻게 해석하는지 생각해보시면 됩니다.
#include <iostream>
using namespace std;
int main()
{
int x = 0;
while(++x > 0){
cout << "mugen loop?";
}
return 0;
}
while(++x > 0) 이 조건문은 어떻게 해석해야 할까요?
우선 ++x를 먼저 계산해서 x의 1값이 증가된 값이라고 해석을 할겁니다. x에 0이 저장되어 있으니깐
결론적으로 1 > 0 이 되겠네요. 이제 끝날까요? 아니죠!
while문은 기본적으로 조건식이 참일때 계속 실행을 하므로 1 > 0 이 참인지 검사하겠네요. 1 > 0 은 참이므로 조건식은 결론적으로 True 가 되서 while(True) 로 무한루프가 돌게 되겠네요.
++x > 0 라는 조건식을 따질때도 먼저 연산자 계산을 하고 들어갔듯이 cin >> x 의 경우에도
>>가 연산자고 x가 피연산자인 형태의 연산이기 때문에 먼저 입력을 받는게 시작되고, 나중에 조건을 따지게 됩니다.
정리
1. while(cin) 은 cin 객체의 상태가 정상인지 체크함 (입력 받는 기능은 없음)
2. while(cin >> x) 는 x에 입력 받은 이후 cin 객체의 상태가 정상인지 체크함. (만약에 x에 이상한 값이 들어가면 cin 객체의 상태가 false가 되서 아예 while 문 안의 코드가 실행되지 않을 것임.)
What is good code?
사실 C++ 출력, 입력이 다른 언어에 비해 조금 특수한 편이라 그렇지 while(cin) 이나 while(cin >> x) 나 그렇게 좋은 코드는 아닌 거 같습니다. 그럼에도 가끔 다른분들의 소스나 백준 문제 풀이를 하다보면 이런걸 사용하시는 분이 꼭 있어서 한번 정리해보았습니다.
'프로그래밍 > C++' 카테고리의 다른 글
[C++] Visual Studio <std::filesystem> 사용하기 (2) | 2022.06.11 |
---|---|
[C++] std_lib_facilities.h 헤더 파일 이란? (0) | 2022.04.02 |
[C++] new와 delete (0) | 2022.03.12 |
[C++] Lvalue와 Rvalue란? (0) | 2022.03.09 |
[C++] 참조자 (레퍼런스, Reference) (0) | 2022.03.08 |