티스토리 뷰

주의 사항!

  • 이 글은 제가 직접 공부하는 중에 작성되고 있습니다.
  • 따라서 제가 이해하는 그대로의 내용이 포함됩니다.
  • 따라서 이 글은 사실과는 다른 내용이 포함될 수 있습니다.

 

다음은 C++에서 "Hello world!"를 출력하는 예제입니다. 

#include <iostream>

int main()
{
	int i;
	double d;

	std::cout << "enter num : ";                              //printf("enter num : ");
	std::cin >> i >> d;                                       //scanf("%d%lf", &i, &d);
	std::cout << "Hello world!" << std::endl;                 //printf("Hello world!\n");
	std::cout << "Hello " << "world!" << std::endl;           //printf("Hello "); printf("world!\n");
	std::cout << i << ' ' << 'A' << ' ' << d << std::endl;    //printf("%d A %lf\n", i, d);
}

/*
실행 결과

enter num : 20 3.14
Hello world!
Hello world!
20 A 3.14

*/

 

위 예제를 살펴보면 std::cout과 std::cin, std::endl과 같은 이상한 놈들이 눈에 들어옵니다. 이들이 무엇인지는 처음 보는 것이겠지만 실행 결과를 보아 이들이 입출력에 관여한다는 것을 유추할 수 있을 것입니다. std::cout은 출력, std::cin은 입력을 위해 사용하고, std::endl은 줄 바꿈을 하기 위해 사용하는 모습입니다. 또 std::cout으로 출력할 때는 '<<'로 출력할 데이터와 데이터 사이를 구분하고, std::cin으로 입력받을 때는 '>>'로 입력받을 데이터와 데이터 사이를 구분하는 모습입니다.

 

코드의 가장 위에는 익숙한 전처리 지시자 #include가 보입니다. 그리고 iostream 헤더 파일을 인클루드 하고 있습니다. C언어에서는 입출력을 위해 stdio.h 헤더 파일을 인클루드 했지만, C++에서는 iostream 헤더 파일을 인클루드 합니다. 근데 해당 파일에 .h 확장자가 붙어 있지 않다는 것을 알 수 있습니다. 왜 그럴까요?

 

사실 C++의 헤더 파일도 확장자를 가집니다. 그런데 사용자 정의 헤더 파일이 아닌, 라이브러리의 헤더 파일인 경우에 한해서 확장자를 생략하도록 약속되어 있습니다. 그 이유는 C++ 표준과 관련이 있습니다. 과거에는 C++도 C언어와 마찬가지로 헤더 파일에 확장자를 붙여 iostream.h와 같이 사용했습니다. 그런데 새로운 C++ 표준이 도입되면서 새로운 표준 라이브러리가 또 생겨났고, 이 새로운 라이브러리의 헤더 파일을 사용할 때는 확장자를 붙이지 않기로 약속했습니다. 즉, iostream.h는 과거의 표준 라이브러리의 헤더 파일을 의미하고, iostream은 최근 라이브러리의 헤더 파일을 의미하게 됩니다. 

 

std::cout

std::cout 변수는 C언어의 printf() 함수처럼 콘솔 화면에 데이터를 출력시키는 창구 역할을 수행합니다. 아래와 같이 '<<' 연산자를 이용해서 출력할 대상을 연이어 출력할 수 있습니다. 만약 출력 대상의 마지막에 '<<'연산자를 사용하고 이어 std::endl을 출력하면 개행을 하게 됩니다. 즉, std::endl은 '\n'과 같은 의미를 가지고 있습니다.

std::cout << '출력대상1' << '출력대상2' << '출력대상3';

std::cout << '출력대상1' << '출력대상2' << '출력대상3' << std::endl;

 

'출력 대상'의 위치에는 정수, 실수, 문자, 문자열, 변수 등등 모든 것이 올 수 있습니다. 그리고 C언어와 달리 %d, %lf, %c, %s와 같은 서식 문자로 출력 포맷을 지정하지 않고, 데이터의 성격에 따라 적절한 출력이 이뤄지기 때문에 C언어의 출력방식보다 편리합니다.

 

std::cin

C++에서 키보드로부터 입력되는 데이터는 std::cin이라고 하는 표준 입력 변수를 통해 전달받습니다.

 

std::cin 변수를 사용하는 방법은 아래와 같으며 std::cout의 사용법과 매우 유사합니다. 하지만 std::cin 변수는 '<<' 연산자가 아닌 '>>' 연산자를 사용합니다. 

std::cin >> '입력대상1' >> '입력대상2' >> '입력대상3';

 

데이터 입력도 출력과 같이 변수의 입력 포맷을 지정하지 않았습니다. C언어에서는 scanf 함수를 사용해 데이터를 입력받을 때, %d, %lf, %c, %s와 같은 서식 문자를 사용했습니다. 하지만 C++에서는 변수만 알맞게 선언하고 나면 서식 문자는 필요 없이 바로 데이터를 입력받을 수 있습니다.

 

std::cerr

std::cerr 변수는 에러가 발생하여 데이터를 콘솔 화면에 출력할 때 사용합니다. 사용 예시는 아래와 같습니다.

std::cerr << "에러가 발생하였습니다." << std::endl;

 

std::cout과 똑같이 데이터를 콘솔 화면에 출력하는 것인데 무엇이 다른지 궁금할 수 있습니다. std::cout 변수는 버퍼를 가지고 있어서 버퍼에 데이터가 쌓이면 출력하지만, std::cerr 변수는 버퍼가 없어서 즉시 화면에 출력한다는 차이점이 있습니다. 때문에 에러 발생 시 에러 메시지를 곧바로 받기 위해 사용합니다.

std::clog

C++에서는 앞에서 언급한 std::cout 변수와 std::cerr 변수 이외에 추가로 std::clog라는 표준 로그 변수를 제공합니다. std::clog 변수는 std::cerr 변수와 동일한 기능을 제공합니다.

 

std::cout, std::cin, std::endl, std::cerr, std::clog 등은 모두 iostream 헤더 파일에 정의되어 있습니다.

 

출력 포맷 지정

지금부터는 std::cout 변수를 사용해서 데이터를 콘솔 화면에 출력할 때 상수와 함수를 사용하여 출력하는 데이터의 포맷을 지정하는 몇 가지 방법들을 배워보겠습니다. 아래의 예제를 먼저 보겠습니다.

#include <iostream>
#include <iomanip>

//일자를 'xx/xx/xxxx' 포맷으로 콘솔 화면에 출력하는 함수
void showDate(int m, int d, int y)
{
	std::cout << std::setfill('0');          //문자 폭을 채울 수 없다면 0으로 채우라는 의미
	std::cout << std::setw(2) << m << '/'    //문자 폭을 2로 설정하고 데이터 m 출력
		<< std::setw(2) << d << '/'
		<< std::setw(4) << y << std::endl;
	std::cout << std::endl;
}

int main()
{
	//기본적으로 소숫점 이하 6자리를 반올림하여 출력
	double f = 3.141592653589793238462643383279502884197169;
	std::cout << f << std::endl;

	//std::fixed는 실수를 출력할 때 고정 소숫점 자리를 사용하도록 함
	//std::setprecision(2)는 소숫점 이하 2자리까지로 설정
	double x = 800000.0 / 81.0;
	std::cout << std::fixed << std::setprecision(2) << x << std::endl;

	x = 2.0 / 3.0;
	std::cout << std::fixed << std::setprecision(4) << x << std::endl;
	std::cout << std::endl;

	showDate(8, 5, 2021);    //showDate 함수 호출

	//std::showbase는 숫자를 출력할 때 진법을 표시하라는 의미
	//std::oct는 8진법으로 숫자 표시
	//std::hex는 16진법으로 숫자 표시
	unsigned long x1 = 64206;
	std::cout << x1 << std::showbase
		<< " 8진법은 \"" << std::oct << x1 << "\""
		<< " 16진법은 \"" << std::hex << x1 << "\"" << std::endl;

	return 0;
}

/*
실행 결과

3.14159
9876.54
0.6667

08/05/2021

64206 8진법은 "0175316" 16진법은 "0xface"

*/

 

std::setw() 함수, std::setfill() 함수

std::setw() 함수는 데이터의 출력 폭(바이트의 크기)을 입력받은 인수만큼 설정합니다. 예를 들어 std::setw(2)는 데이터의 출력 폭을 2바이트로 설정함을 의미합니다.

 

std::setfill() 함수는 숫자나 부호가 차지하지 않는 출력 폭의 나머지 영역을 std::setfill() 함수에 제공한 인수로 채워 넣습니다. 만약 std::setfill() 함수를 사용하지 않았다면 디폴트는 공백이 됩니다.

 

std::fixed 상수, std::setprecision() 함수

실수를 화면에 출력시키는 방법으로 부동 소수점 방식과 고정 소수점 방식이 존재합니다. std::fixed 상수는 실수를 화면에 출력할 때 고정 소수점 방식으로 출력하라는 의미로 사용합니다.

 

std::setprecision() 함수는 출력할 실수의 정밀도를 전달받은 인수만큼 설정합니다. 위의 예제에서는 2를 인수로 전달받아 소수점 이하 2자리까지로 설정하게 되었습니다.

 

std::showbase, std::dec, std::oct, std::hex

std::showbase는 10진법이 아닌 8진법이나 16진법을 콘솔 화면이나 파일로 출력할 때 숫자 앞에 '0'이나 '0x'와 같이 진법을 표시하라는 의미로 사용됩니다. 그리고 std::dec은 10진법, std::oct는 8진법, std::hex는 16진법으로 출력하라는 의미이며, 이들을 사용하지 않을 때 디폴트는 10진법이 됩니다.

 

std::left, std::right, std::internal

std::left는 출력할 숫자나 문자를 왼쪽으로 정렬합니다. std::setw() 함수와 함께 사용됩니다. std::right은 오른쪽 정렬, std::internal은 내부 폭 전체에 걸쳐서 정렬하도록 합니다. 아래는 예제입니다.

#include <iostream>
#include <iomanip>

int main()
{
	std::cout << "Left fill : \n" << std::left
		<< std::setw(12) << -1.23 << '\n'
		<< std::setw(12) << std::showbase << std::hex << 42 << std::endl;
	std::cout << std::endl;

	std::cout << "Internal fill : \n" << std::internal
		<< std::setw(12) << -1.23 << '\n'
		<< std::setw(12) << std::showbase << std::hex << 42 << std::endl;
	std::cout << std::endl;

	std::cout << "Right fill : \n" << std::right
		<< std::setw(12) << -1.23 << '\n'
		<< std::setw(12) << std::showbase << std::hex << 42 << std::endl;
	std::cout << std::endl;

	return 0;
}

/*
실행 결과

Left fill :
-1.23
0x2a

Internal fill :
-       1.23
0x        2a

Right fill :
       -1.23
        0x2a
        
*/

 

std::scientific, std::hexfloat, std::defaultfloat

std::scientific은 지수를 이용한 실수를 부동 소수점 방식으로 출력하도록 합니다. std::hexfloat은 실수를 16진법의 부동 소수점 방식으로 출력합니다. std:defaultfloat은 실수를 디폴트 방식으로 출력합니다. 아래는 예제입니다.

#include <iostream>
#include <iomanip>

int main()
{
	double a = 3.1415926535;
	double b = 2006.0;
	double c = 1.0e-10;

	std::cout << "scientific : \n" << std::scientific
		<< a << '\n' << b << '\n' << c << '\n' << std::endl;

	std::cout << "hexfloat : \n" << std::hexfloat
		<< a << '\n' << b << '\n' << c << '\n' << std::endl;

	std::cout << "defaultfloat : \n" << std::defaultfloat
		<< a << '\n' << b << '\n' << c << '\n' << std::endl;

	return 0;
}

/*
실행 결과

scientific :
3.141593e+00
2.006000e+03
1.000000e-10

hexfloat :
0x1.921fb54411744p+1
0x1.f580000000000p+10
0x1.b7cdfd9d7bdbbp-34

defaultfloat :
3.14159
2006
1e-10

*/

 

 

 

'공부 일지 > CPP 공부 일지' 카테고리의 다른 글

C++ | 새로운 자료형 bool  (0) 2021.07.31
C++ | 네임스페이스(namespace)  (0) 2021.07.31
C++ | 인라인(inline) 함수  (0) 2021.07.31
C++ | 매개변수의 디폴트 값  (0) 2021.07.31
C++ | 함수 오버로딩  (0) 2021.07.31
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함