프로그래밍 언어를 접하면 어떤 언어를 배우든 우선 기본 입출력부터 시작한다.
C++에서는 cin()
과 cout()
을 사용한다.
#include <iostream>
int main()
{
int num;
std::cin >> num;
std::cout << "Hello!" << "\n";
std::cout << num << " is my favorite number!" << std::endl;
}
C언어만 해도 출력하려면 printf라는 함수 안에 인수를 집어넣으면 그만이었다.
하지만 C++에서는 함수 앞에 std::
를 굳이 적어야만 실행할 수 있다.
왜 그럴까? 바로 네임스페이스 때문이다.
네임스페이스(namespace)
표준 라이브러리에 있는 cout을 이용하고 싶은데, 만약 내가 만든 다른 라이브러리에 내 버전의 cout이 있다고 생각해보자.
컴파일러가 어떤 cout을 사용해야 하는지 스스로 판단할 수 있을까?
이런 상황에서 이름 충돌(name collision)이 발생한다.
C++에서는 이름 충돌을 방지할 수 있도록 개발자가 네임스페이스를 사용할 수 있다.
네임스페이스는 내부 식별자에 범위를 제공하는 선언적 영역이다.
표준 라이브러리에 있는 cout을 사용하겠다는 뜻으로 std::cout
이라 선언하는 것이다.
범위 지정 연산자 '::'
std와 cout 사이 콜론 두 개는 '범위 지정 연산자'다.
다양한 범위에서 사용되는 식별자를 식별하고 명확하게 구분하는 데 사용한다.
이 연산자를 통해서 "std 라이브러리에 있는 cout을 사용하라"라고 컴파일러에게 지시한다.
using namespace std
std::를 매번 함수마다 입력하기는 너무 번거롭다.
C++은 네임스페이스를 한 번에 명시할 수 있다. using namespace
를 이용하면 된다.
#include <iostream>
using namespace std;
int main()
{
int num;
cin >> num;
cout << "Hello!" << "\n";
cout << num << " is my favorite number!" << endl;
}
using namespace 지시문 뒤에 사용하려는 네임스페이스를 적는다. 대부분은 표준 네임스페이스인 std이다.
이 지시어를 통해서 컴파일러는 내가 표준 라이브러리를 기반으로 예약어를 사용하리란 사실을 알게 되고, 함수마다 네임스페이스를 명시하지 않아도 된다.
using namespace std
를 사용하면 cin, cout, endl뿐 아니라 std에 정의된 여러 이름들을 다 가져온다.
따라서 여전히 이름 충돌이 발생할 가능성이 있다.
namespace 전체를 가져오지 않고 필요한 각각의 이름만 가져오는 방법도 있다.
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
int main()
{
int num;
cin >> num;
cout << "Hello!" << "\n";
cout << num << " is my favorite number!" << endl;
}
학습하는 단계에서 하나의 소스코드만으로 작업할 때는 문제 없지만, 규모가 큰 프로그램에서 여러 라이브러리를 사용하게 되면 이런 방식은 최선의 방법이 아니라는 사실을 알고 있어야 한다.
cin과 cout
#include <iostream>
using namespace std;
int main()
{
int num;
cin >> num;
cout << "Hello!" << "\n";
cout << num << " is my favorite number!" << endl;
}
cin과 cout은 iostream 헤더 파일에 포함되어 있는 표준 입출력 함수이다.
cout은 콘솔이나 화면에 기본으로 설정되는 출력 스트림이다.
cin은 기본적으로 키보드를 사용하는 입력 스트림이다.
삽입 연산자 '<<'와 추출 연산자 '>>'
두 함수에 사용되는 연산자로 <<(삽입 연산자, insertion operator)와 >>(추출 연산자, extraction operator)가 있다.
삽입 연산자는 오른쪽에 있는 피연산자의 값을 삽입한다.
변수 num
에 있는 값은 삽입 연산자를 통해 cout 출력 스트림으로 들어간다.
스트림이란, 순서가 있는 데이터 집합에 대한 추상화이다.
시냇물이 흘러가듯이 그 안에 뭐가 얼마나 들어 있는지에 상관없이 데이터를 처리해준다.
cout은 삽입 연산자를 여러 번 사용해서 다양한 데이터를 받을 수 있지만, 데이터가 달라진다고 줄이 자동으로 바뀌지는 않는다.
개행하려면 \n
이나 endl
을 사용해야 한다. 특히 endl을 사용하면 스트림이 플러시(flush)되어 버퍼가 비워진다.
버퍼에 무언가가 남아 있으면 원하는대로 입력 또는 출력이 이루어지지 않을 수도 있다.
하지만 그만큼 처리 속도가 느리기 때문에, 입출력 속도가 중요한 요소로 작용하는 백준 등의 문제풀이에서는 개행 문자 \n을 사용하는 편이 나을 수도 있다.
추출 연산자는 cin 입력 스트림에서 정보를 추출한다.
C언어에서 표준입출력을 하려면
printf("%d", num); //정수
scanf("%s", str); //문자열
과 같이 서식 문자를 사용해야 했던 것과 달리 C++에서는 자료형을 알려주지 않아도 된다.
버퍼(buffer)와 입력 스트림
cin 입력 스트림을 통해 키보드에서 입력된 문자를 읽을 때, cin이 직접 읽지 않는다. 대신 입력된 문자는 버퍼에 저장된다.
버퍼는 데이터가 한 곳에서 다른 곳으로 이동하는 동안 임시로 데이터를 보관하는 영역이다.
cin >> num;
cout << num;
//" 123 "
//result: 123
만약 공백을 포함한 숫자를 입력하면 cin은 입력된 정수 이외의 공백을 모두 무시하고 수만을 받아들여 저장한다.
int num, num2;
cout << "Enter a num1: ";
cin >> num;
cout << "Enter a num2: ";
cin >> num2;
cout << num << " " << num2 << endl;
/*
Enter a num1: 100 200
Enter a num2: 100 200
*/
첫 번째 cin에서 받아들이는 변수를 하나만 지정했는데, 두 가지 변수를 입력하면 어떻게 될까?
"100 200"을 입력했다고 하면, 버퍼에 "100 200" 우선 저장되고 cin은 버퍼에서 값을 읽어들인다.
100을 입력받으면 공백을 통해 값이 끝났음을 알고 num
에 100을 저장할 것이다.
다음 cin이 실행되면 입력 스트림이 버퍼에서 값을 읽어들인 다음 위치에 200이 남아있다. 그래서 값을 입력하지 않아도 버퍼에 남아 있는 값을 읽어 200을 num2에 저장하게 된다.
cin >> num >> num2;
cout과 마찬가지로 추출 연산자를 이어붙여 여러 변수에 데이터를 입력받을 수 있다.
'프로그래밍 > C, C++' 카테고리의 다른 글
[C++] 조정자를 사용해 입출력 형식을 지정하는 방법 (0) | 2022.12.07 |
---|---|
[C++] 변수를 초기화하는 세 가지 방법 (0) | 2022.11.18 |
<C프로그래밍-새내기를 위한 첫 C 언어 책>연습문제 chapter 11(1번~10번) (0) | 2020.11.26 |
<C프로그래밍-새내기를 위한 첫 C 언어 책>연습문제 chapter 10(16번~21번) (0) | 2020.11.26 |
c언어 콘솔에서 음악 동시에 재생하기(mcisendCommand, playsound) (3) | 2020.11.18 |