728x90

C++에는 조금 더 보기 좋게 출력하게 하기 위해 스트림 조종자(manipulator)가 있다.

스트림 조종자는 <iomanip>과 <iostream> 헤더파일을 포함하면 사용할 수 있다.

사실 boolalpha, showbase, showpoint, dec, hex, oct는 <ios>에 있는 함수들인데 iostream은 ios의 자식 클래스이기 때문에 우리가 C++로 코드를 짤 때 거의 항상 포함하는 <iostream>을 포함해도 사용할 수가 있기 때문에 <iostream>이 있는데 굳이 <ios>를 따로 포함해줄 필요는 없다.

 

이 표는 manipulator와 그 기능이다.

setprecision(int n) 실수의 정밀도 설정
setw(int n) 출력되는 영역의 폭 설정
setfill(char c) 출력하고 남은 부분을 c로 채움
fixed 실수를 고정된 부동소수점 형식으로
showpoint 실수의 소수점 부분이 없어도 소수점 아래에 0을 표시
left 왼쪽 정렬
right 오른쪽 정렬
boolalpha bool 값을 1, 0이 아닌 true, false로 출력
showbase 진법기호(16진수의 경우 0x, 8진수의 경우 0)도 출력
dec 정수를 10진수로 출력
hex 정수를 16진수로 출력
oct 정수를 8진수로 출력

다음 코드를 실행하면

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
	double a = 3.14159265358979323;
	double b = 31.4159265358979323;
	double c = 314.159265358979323;
	double d = 3141.59265358979323;
	double e = 31415.9265358979323;
	double f = 314159.265358979323;
	double g = 3141592.65358979323;
	cout << a << endl;
	cout << b << endl;
	cout << c << endl;
	cout << d << endl;
	cout << e << endl;
	cout << f << endl;
	cout << g << endl;
	return 0;
}

이런 결과가 나온다. 즉 실수는 기본적으로 소수점의 위치와는 상관 없이 6자리까지만 표기된다.

그리고 6자리가 넘어가면 3141592.65358979323처럼 3.14159e+06 이렇게 과학적 표기법으로 표기되는데 이게 싫다면 fixed를 이용하면 된다.

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
	double a = 3.14159265358979323;
	double b = 31.4159265358979323;
	double c = 314.159265358979323;
	double d = 3141.59265358979323;
	double e = 31415.9265358979323;
	double f = 314159.265358979323;
	double g = 3141592.65358979323;
	cout << fixed << a << endl;
	cout << b << endl;
	cout << c << endl;
	cout << d << endl;
	cout << e << endl;
	cout << f << endl;
	cout << g << endl;
	return 0;
}

이렇게 fixed만 한 번 써주면

e를 사용한 과학적 표기법이 아니라 우리가 일상에서 쓰는 소수점 표현으로 출력된다. 그리고 fixed를 사용해주니 전체 자리수가 6자리까지가 아니라 소수점 아래 6자리까지 출력된다. fixed는 기본이 소수점 아래 6자리이다.

 

그런데 실제로 내가 저장한 숫자보다 출력된 숫자가 소수점 아래가 잘려서 정확도가 너무 떨어진다면 setprecision 함수를 사용해서 몇 자리를 표기할지 정해주면 된다.

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
	double a = 3.14159265358979323;
	double b = 31.4159265358979323;
	double c = 314.159265358979323;
	double d = 3141.59265358979323;
	double e = 31415.9265358979323;
	double f = 314159.265358979323;
	double g = 3141592.65358979323;
	cout << setprecision(18) << a << endl;
	cout << b << endl;
	cout << c << endl;
	cout << d << endl;
	cout << e << endl;
	cout << f << endl;
	cout << g << endl;
	return 0;
}

 

이렇게 setprecision() 함수로 정해주면 18자리가 모두  나타난 것을 볼 수 있다. setprecision() 함수는 한 번만 써주면 setprecision() 함수로 다시 바꾸기 전까지는 계속 유효하다.

하지만 소수점 아래쪽으로 갈수록 정확도가 떨어지는 것을 볼 수 있다.

 

그럼 setprecision() 함수를 fixed와 같이 써보자.

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
	double a = 3.14159265358979323;
	double b = 31.4159265358979323;
	double c = 314.159265358979323;
	double d = 3141.59265358979323;
	double e = 31415.9265358979323;
	double f = 314159.265358979323;
	double g = 3141592.65358979323;
	cout << fixed << setprecision(18) << a << endl;
	cout << b << endl;
	cout << c << endl;
	cout << d << endl;
	cout << e << endl;
	cout << f << endl;
	cout << g << endl;
	return 0;
}

내가 저장했던 숫자인 314159265358979323까지는 모두 아주 정확하게 출력된 것을 볼 수 있다. 그 아래 자리는 아무 숫자나 출력되었다.

fixed를 사용하고 setprecision() 함수를 사용하면 소수점 아래 몇 번째 자리까지 나타낼 것인지를 정해주는 것이다. 그냥 setprecision() 함수를 사용했을 때에는 소수점과 상관없이 숫자 몇 개를 나타낼지를 정해주는 거였다. 둘의 차이를 기억하자.

그리고 setprecision()을사용할 때에는 원래 숫자의 자릿수보다 더 큰 숫자를 넣으면 저렇게 이상한 숫자가 출력될 수도 있다. 실수는 정수와 달리 저장할 때 정확도가 떨어진다. 모든 정수는 모두 정확한 이진수로 바꿀 수 있지만 실수는 소수점 아래를 정확한 이진수로 표현하기 힘든 경우가 있기 때문이다.

 

하지만 위의 예처럼 소수점 아래가 매우 많은 숫자 말고 이 정도 숫자는 정확하게 출력한다.

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
	double a = 3.14;
	double b = 3.1415;
	double c = 3.1415926;
	cout << setprecision(5) << a << endl;
	cout << b << endl;
	cout << c << endl;
	return 0;
}

그리고 setprecision() 함수를 사용해서 잘린 부분은 그 뒤의 수에서 반올림해서 출력된다.

 

그런데 만약 모든 수의 소수점 아래 자리가 동일하고 3.14와 같 소수점 아래 숫자가 짧은 것들은 0으로 채우고 싶다면? 그러면 showpoint를 사용하면 된다.

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
	double i = 3.0;
	double a = 3.14;
	double b = 3.1415;
	double c = 3.1415926;
	cout << i << endl;
	cout << showpoint << setprecision(7) << i << endl;
	cout << a << endl;
	cout << b << endl;
	cout << c << endl;
	return 0;
}

showpoint를 사용하면 이렇게 3.0과 같은 소수점 아래가 없는 숫자도 내가 정해준 만큼 0을 출력할 수 있다.

 

그러면 이제 다른 조종자를 배워보자.

#include <iostream>
using namespace std;

int main() {
	int arr[10][10];
	int num = 1;
	for (int i = 0; i < 6; i++) {
		for (int j = 0; j < 6; j++) {
			arr[i][j] = num;
			num++;
		}
	}
	for (int i = 0; i < 6; i++) {
		for (int j = 0; j < 6; j++) {
			cout << arr[i][j] << " ";
		}
		cout << endl;
	}
	return 0;
}

이 코드를 실행하면

이렇게 줄이 안 맞아서 보기 안 좋게 출력된다.

이 때 setw()를 사용하면 줄 맞춰서 예쁘게 출력할 수 있다.

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
	int arr[10][10];
	int num = 1;
	for (int i = 0; i < 6; i++) {
		for (int j = 0; j < 6; j++) {
			arr[i][j] = num;
			num++;
		}
	}
	for (int i = 0; i < 6; i++) {
		for (int j = 0; j < 6; j++) {
			cout << setw(3) << arr[i][j];
		}
		cout << endl;
	}
	return 0;
}

setw()를 이용했더니 이렇게 줄맞춰서 예쁘게 출력되었다.

setw(n)은 n칸을 확보해놓는다는 것이다. 확보해놓고 그 안에서 내가 출력하고 싶은 것을 출력하는 것이다. 확보해놓은 칸보다 내가 출력하고 싶은 것이 더 많은 칸을 차지한다면 자동으로 칸이 증가되기 때문에 잘릴 걱정은 하지 않아도 된다.

setw()를 쓸 때 주의해야 할 것은 setw()를 쓴 직후의 출력에만 유효하다는 것이다.

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
	cout << setw(7) << "orange" << "cat" << "peach" << endl;
	return 0;
}

이렇게 setw(7)을 orange 직전에 써주면

이렇게 orange에만 유효하다.

따라서 이렇게 출력하기 전에 매번 써줘야 한다.

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
	cout << setw(7) << "orange" << setw(7) << "cat" << setw(7) << "peach" << endl;
	return 0;
}

showpoint, fixed, setprecision과는 달리 딱 한 번만 유효하다는 거 기억하자.

 

그런데 setw()를 쓰면 자동으로 오른쪽으로 정렬이 되었는데 왼쪽으로 정렬하고 싶다면?

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
	int arr[10][10];
	int num = 1;
	for (int i = 0; i < 6; i++) {
		for (int j = 0; j < 6; j++) {
			arr[i][j] = num;
			num++;
		}
	}
	cout << left;
	for (int i = 0; i < 6; i++) {
		for (int j = 0; j < 6; j++) {
			cout << setw(3) << arr[i][j];
		}
		cout << endl;
	}
	return 0;
}

이렇게 left를 써주면 왼쪽으로 정렬되어 출력된다.

오른쪽으로 정렬하고 싶다면 left 대신 right를 써주면 된다. (right가 기본값이다.)

left도 setprecision, showpoint, fixed처럼 한 번만 써주면 right로 바꾸기 전까지는 유효하다.

(딱 한 번만 유효한 것은 setw()이다.)

 

그런데 setw()로 확보하느라 생기는 공백을 다른 문자로 채우고 싶다면?

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
	int arr[10][10];
	int num = 1;
	for (int i = 0; i < 6; i++) {
		for (int j = 0; j < 6; j++) {
			arr[i][j] = num;
			num++;
		}
	}
	for (int i = 0; i < 6; i++) {
		for (int j = 0; j < 6; j++) {
			cout << setfill('#') << setw(3) << arr[i][j];
		}
		cout << endl;
	}
	return 0;
}

이렇게 setw 전에 setfill(채우고 싶은 문자)를 써주면 된다.

주의할 것은 문자열은 안 되고 char형 문자를 써줘야 한다.

 

표에 있지만 설명하지 않은 것들은 그냥 보면 어떻게 쓰면 되는지 간단하기 때문에 누구나 쉽게 쓸 수 있다.

이 외에도 더 많은 조종자를 알고 싶다면

http://www.cplusplus.com/reference/ios/

 

- C++ Reference

header Input-Output base classes Header providing base classes and types for the IOStream hierarchy of classes: Types Class templates basic_iosBase class for streams (type-dependent components) (class template )fposStream position class template (class tem

www.cplusplus.com

http://www.cplusplus.com/reference/iomanip/

 

- C++ Reference

 

www.cplusplus.com

여기에 들어가서 보는 것을 추천한다.

728x90

+ Recent posts