LEARN C++ 1.5
1.5 iostream 소개 : cout, cin, and endl
입출력 라이브러리
입출력(io) 라이브러리는 기본적인 입출력을 담당하는 C++ 표준 라이브러리의 일부이다. 입출력 라이브러리의 기능을 사용하면 키보드에서 입력을 받고, 입력받은 데이터를 콘솔에 출력할 수 있다. iostream에서 io 부분은 입력과 출력을 나타낸다
iostream 라이브러리에 정의된 기능들을 사용하기 위해서는 iostream
헤더를 코드의 최상단에 작성해주어야 한다.
#include <iostream>
std::cout
iostream 라이브러리에는 우리가 사용할 수 있는 미리 선언된 변수들이 포함되어 있다. 그 중에서도 가장 유용한 것은 std::cout
이라고 할 수 있다. std::cout
를 통해 콘솔 화면에 텍스트를 출력하기 위해서 데이터를 전송할 수 있다. cout
은 character output
을 의미한다.
#include <iostream> // for std::cout
int main()
{
std::cout << "Hello world!"; // print Hello world! to console
return 0;
}
위의 코드에서 std::cout
에 접근하기 위해 iostream을 포함시켰다. main 함수 내부에는 std::cout
을 삽입 연산자(<<)와 함께 사용해서 Hello world!
라는 글자를 콘솔에 출력할 수 있도록 전송해주고 있다.
std::cout
은 글자뿐만 아니라 숫자도 출력할 수 있다.
#include <iostream> // for std::cout
int main()
{
std::cout << 4; // print 4 to console
return 0;
}
당연히 변수의 값도 출력할 수 있다.
#include <iostream> // for std::cout
int main()
{
int x{ 5 }; // define integer variable x, initialized with value 5
std::cout << x; // print value of x (5) to console
return 0;
}
같은 줄에 하나 이상을 출력하고 싶으면 삽입 연산자를 하나의 명령문에 여러번 사용해서 이어주면 된다.
#include <iostream> // for std::cout
int main()
{
std::cout << "Hello" << " world!";
return 0;
}
이번에는 변수의 값과 함께 글자를 출력하는 명령문을 만들어보자.
#include <iostream> // for std::cout
int main()
{
int x{ 5 };
std::cout << "x is equal to: " << x;
return 0;
}
std::endl
콘솔에 라인을 분리해서 출력을 하고 싶으면 커서를 다음 라인으로 이동시켜야 한다. 커서를 다음 라인으로 이동시키는 방법 중 하나가 std::endl
을 사용하는 것이다. std::endl
을 사용하면 콘솔에 개행 문자를 출력하게 된다.
#include <iostream> // for std::cout and std::endl
int main()
{
std::cout << "Hi!" << std::endl; // std::endl will cause the cursor to move to the next line of the console
std::cout << "My name is Alex." << std::endl;
return 0;
}
출력 라인이 완료될 때마다 개행 문자를 출력하는 것이 Best Practice다.
std::cout은 버퍼링된다.
가장 좋아하는 놀이공원에서 롤러코스터를 탄다고 가정해보자. 승객들이 나타나서 줄을 설 것이다. 그러면 주기적으로 롤러코스터가 도착해서 태울 수 있는 최대 정원까지 승객들을 탑승시킬 것이다. 롤러코스터의 정원이 가득차거나 시간이 지났을 때, 롤러코스터는 탑승한 승객과 함께 출발하면서 운행을 시작하게 된다. 현재 롤러코스터에 탑승할 수 없는 승객은 다음을 기다려야 한다.
이 롤러코스터 탑승에 대한 설명은 std::cout
으로 전송된 출력이 C++에서 처리되는 방식과 비슷하다. 콘솔에 출력을 요청하며 함께 전달한 출력물은 콘솔에 즉시 전달되지 않는다. 대신에 출력물이 라인에 들어가고 이러한 출력물들을 관리하기 위해 따로 마련된 메모리 영역(버퍼)에 저장된다. 그러면 버퍼가 주기적으로 플러시되면서 콘솔에 출력에 필요한 출력물이 전달된다.
따라서 버퍼가 플러시되기 전에 프로그램이 멈추게 되면 버퍼에서 대기중인 출력물들은 콘솔에 표시되지 않게 된다.
std::endl vs '\n'
콘솔의 커서를 다음 라인으로 이동시키기 위한 개행을 하기 위해 std::endl
을 사용할 수 있다. 그런데 std::endl
을 사용하는 것은 실제로 두 가지 작업을 함께 수행하기 때문에 약간 비효율적인 부분이 있다. std::endl
을 사용하면 다음과 같은 작업이 수행된다.
std::endl
이 커서를 콘솔의 다음 라인으로 이동시킨다.- 그리고 버퍼를 플러시한다.
콘솔에 글자를 작성할 때, 우리는 일반적으로 각 라인의 끝마다 버퍼를 플러시하지 않는다. 강제로 버퍼를 플러시하는 것보단, 시스템이 주기적으로 버퍼를 플러시하는 것이 더 효율적이라 할 수 있다.
std::endl
이 가진 이런 특성 때문에 개행문자 \n
을 사용하는 것이 커서를 다음 라인으로 이동시킬 때 더 효과적인 방식이라 할 수 있다. \n
은 콘솔이 커서를 다음 라인으로 이동시키지만, 버퍼를 플러시 하라고 하지는 않는다. 그래서 std::endl
보다 성능이 좋은 편이다.
#include <iostream> // for std::cout
int main()
{
int x{ 5 };
std::cout << "x is equal to: " << x << '\n'; // Using '\n' standalone
std::cout << "And that's all, folks!\n"; // Using '\n' embedded into a double-quoted piece of text (note: no single quotes when used this way)
return 0;
}
std::cin
std::cin
은 iostream 라이브러리에 정의된 또다른 변수다. std::cout
이 콘솔에 출력하는 역할을 했다면 std::cin
은 추출 연산자(>>)와 함께 키보드로부터 입력을 전달받는다. 키보드로부터 들어온 입력은 변수에 저장해서 사용해야 한다.
#include <iostream> // for std::cout and std::cin
int main()
{
std::cout << "Enter a number: "; // ask user for a number
int x{ }; // define variable x to hold user input (and zero-initialize it)
std::cin >> x; // get number from keyboard and store it in variable x
std::cout << "You entered " << x << '\n';
return 0;
}
위와 같이 프로그램을 작성하고 실행을 하면 8번 라인에 있는 std::cin
명령문에서 키보드 입력을 기다릴 것이다. 숫자를 입력하고 엔터를 누르면 입력한 값이 변수 x에 할당이 될 것이다.
std::cin
을 사용해서 입력을 받을 때 \n
을 사용할 필요는 없다. 사용자는 값을 입력하고 엔터를 눌러야 하는데, 이 과정에서 커서가 콘솔의 다음 라인으로 이동하기 때문이다.
std::cin
역시 한 라인에서 여러 값을 입력받을 수 있다.
#include <iostream> // for std::cout and std::cin
int main()
{
std::cout << "Enter two numbers separated by a space: ";
int x{ }; // define variable x to hold user input (and zero-initialize it)
int y{ }; // define variable y to hold user input (and zero-initialize it)
std::cin >> x >> y; // get two numbers and store in variable x and y respectively
std::cout << "You entered " << x << " and " << y << '\n';
return 0;
}
std::cin
을 사용해서 값을 입력받으면 입력받은 값을 할당할 변수가 키보드 입력값으로 다시 초기화가 된다. 따라서 사용자가 값을 입력하는 경우에 변수의 값을 미리 초기화를 해야 하는지 의문을 가질 수 있다. 이전 챕터에서 변수를 항상 초기화하는 것이 Best Practice라는 것을 배웠기 때문에 사용자 입력값을 받는 경우에도 위의 예제와 같이 변수를 초기화하는 것이 Best Practice라 할 수 있다.
std::cin의 특징
#include <iostream> // for std::cout and std::cin
int main()
{
std::cout << "Enter a number: "; // ask user for a number
int x{}; // define variable x to hold user input
std::cin >> x; // get number from keyboard and store it in variable x
std::cout << "You entered " << x << '\n';
return 0;
}
위와 같은 코드가 있을 때 std::cin
을 이용해 사용자는 숫자뿐만이 아니라 문자도 입력할 수 있다. 그런데 변수 x는 정수형 변수인데, 숫자가 아닌 경우에는 어떻게 작동을 할까?
a
와 같은 문자를 입력하면 x에는 0이 들어간다.(기본값을 가진 상태로 초기화를 시켰기 때문)- 0.5, 0.7과 같은 소수 자릿수를 가진 수를 입력하면 x에는 0이 들어간다.(소수의 자릿수는 정수형 변수에 들어가면서 버려짐)
- -3과 같은 음수는 정수이기 때문에 정상적으로 x에 할당된다.
Hello
와 같은 문자열을 입력하는 경우에도 x에는 0이 들어간다.(문자와 마찬가지로 기본값을 가짐)- 300억과 같이 큰 숫자를 입력하면 int의 최대값이 x에 할당될 가능성이 높다. 시스템에 따라 결과가 다를 수 있다.
- 123abc와 같이 숫자 뒤에 문자열이 포함되어 있으면 숫자 부분만 x에 할당된다.