Coding Memo
[C++] 여러가지 출력 방법 (스트림 서식화) 본문
C++에서
출력을 표처럼 간격에 맞춰서 깔끔하게 출력하고 싶다.
double이나 float 타입의 숫자를 특정 자릿수까지 출력하고 싶다.
특정 숫자를 16진수, 8진수로 바로 출력하고 싶다.
double을 출력했는데 자릿수가 얼마 안나온다.
...
int main()
{
double pi = 3.1415926535;
cout << pi << endl;
return 0;
}
// output
// 3.14159
어떻게 해야 할까?
C++에는 이를 위해 다양한 서식화(formatting) 기능이 있다.
입출력 스트림(키보드, 파일 등)에는 입출력 조작자(I/O Manipulator)가 사용된다. 이 입출력 조작자로 출력 형식을 지정할 수 있다.
입출력 조작자에는 어떤 것이 있는지 알아보고 테스트 해보자.
참고: iomanip 헤더를 미리 추가하자.
#include <iomanip>
precision
정밀도를 설정하여 유효숫자를 더 많이 출력하게 해준다.
예를 들어 precision을 10으로 설정하였다면, 출력되는 숫자를 10자리로 하여 출력한다.
precision 사용 시 주의해야 할 점은 2가지이다.
1. precision을 한번 설정하면 다시 값을 넣어주기 전까지 그 값이 계속 유지된다.
2. precision은 전체 자릿수에 대한 값으로, 정수부와 소수부를 합친 자릿수가 그 값이 된다.
#define _USE_MATH_DEFINES
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
int main()
{
double pi = M_PI;
double pi2 = 3.1415926535;
float f = 12.345f;
cout << "Before precision" << endl;
cout << "pi: " << pi << endl;
cout << "pi2: " << pi2 << endl;
cout << "f: " << f << endl;
cout << '\n';
cout.precision(10);
cout << "After cout.precision(10)" << endl;
cout << "pi: " << pi << endl;
cout << "pi2: " << pi2 << endl;
cout << "f: " << f << endl;
return 0;
}
/* output
Before precision
pi: 3.14159
pi2: 3.14159
f: 12.345
After cout.precision(10)
pi: 3.141592654
pi2: 3.141592654
f: 12.34500027
*/
참고: f의 값은 12.345인데 왜 12.34500027로 출력이 되었을까 생각해보자.
물론, 소수점 아래 숫자의 길이만 설정하여 출력도 가능하다.
precision를 설정해주기 전에 "cout << fixed"를 넣어주면 된다.
"cout << fixed" 이후에 precision에 값을 넣으면 그 값만큼 소수점 아래 숫자가 출력이 된다.
int main()
{
double pi = M_PI;
double pi2 = 3.1415926535;
cout << fixed; // = cout.setf(ios_base::fixed);
cout.precision(5);
cout << pi << endl;
cout << pi2 << endl;
return 0;
}
/* output
3.14159
3.14159
*/
cout.precision()으로 값을 설정할 수도 있지만 cout << setprecision()으로도 값을 넣어 줄 수 있다.
(마찬가지로 계속 설정한 값이 유지된다.)
int main()
{
double pi = M_PI;
double pi2 = 3.1415926535;
cout << "setprecision(20) pi: " << setprecision(20) << pi << endl;
cout << "setprecision(10) pi2: " << setprecision(10) << pi2 << endl;
return 0;
}
/* output
setprecision(20) pi: 3.141592653589793116
setprecision(10) pi2: 3.141592654
*/
width
출력의 너비를 설정할 수 있다. (숫자 뿐만 아니라 출력하는 모든 것에 영향을 미친다.)
표를 출력할 때나, 결과값을 한쪽에 정렬하여 출력하고 싶을 때 유용하다.
width에 관해서도 주의해야 할 점이 두가지 있다.
1. width값이 변하면 바로 다음 출력의 너비만 바꾼다. (이후 출력은 width와 관계가 없다.)
2. 지정한 너비는 출력의 최소너비란 의미로, 출력이 이 길이를 넘어가게 될 수 있다. (출력 너비를 강제하는 것이 아니다.)
즉, 여러개를 정렬하여 출력하고 싶으면, 출력할 때 마다 설정을 해주어야한다.
int main()
{
double pi = M_PI;
double pi2 = 3.1415926535;
cout.width(5);
cout << "pi: ";
cout.width(20);
cout << pi << endl;
cout.width(5);
cout << "pi2: ";
cout.width(20);
cout << pi2 << endl;
return 0;
}
/* output
pi: 3.14159
pi2: 3.14159
*/
fill
설정된 width에 맞게 출력하고 남은 공간을 설정한 값으로 채울 수 있다.
마찬가지로 fill 또한 한번 설정하면 precision과 동일하게 계속 유지된다.
int main()
{
double pi = M_PI;
double d = 1.23456789;
cout.fill('-');
cout.width(5);
cout << "pi: ";
cout.width(20);
cout << pi << endl;
cout.width(5);
cout << "d: ";
cout.width(20);
cout << d << endl;
return 0;
}
/* output
-pi: -------------3.14159
--d: -------------1.23457
*/
left, right
width 설정 후 값을 어느 쪽을 기준으로 정렬할 건지 설정 할 수 있다.
마찬가지로 플레그 자체를 변경하는 것이기 때문에 계속 옵션이 유지된다.
setf로 right나 left를 직접 넣어 설정하거나 cout << right 나 cout << left와 같이 사용하여도 된다.
int main()
{
double pi = M_PI;
double d = 1.23456789;
cout.setf(ios_base::left); // cout << left
cout.fill('-');
cout.width(5);
cout << "pi: ";
cout.width(20);
cout << pi << endl;
cout.width(5);
cout << "d: ";
cout.width(20);
cout << d << endl;
return 0;
}
/* output
pi: -3.14159-------------
d: --1.23457-------------
*/
8진수, 10진수, 16진수
숫자를 별다른 변환 없이 8진수, 10진수, 16진수로 바로 출력할 수 있다.
int main()
{
int a = 1000;
cout << "octal: " << oct << a << endl;
cout << "decimal: " << dec << a << endl;
cout << "hex: " << hex << a << endl;
return 0;
}
/* output
octal: 1750
decimal: 1000
hex: 3e8
*/
bool
우리 C++는 다른 언어와 달리 bool 값을 출력할 때 0 (false) 또는 1 (true) 값으로 표시해 준다. true/false가 아니라 숫자로...
다른 언어 처럼 true/false를 출력하기 위해서는 cout.setf(ios_base::boolalpha)를 해주거나 cout << boolalpha를 넣어주면 된다.
int main()
{
bool a = 1 < 3;
bool b = 1 > 3;
cout << a << endl;
cout << b << endl;
cout.setf(ios_base::boolalpha);
cout << "After set boolalpha" << endl;
cout << a << endl;
cout << b << endl;
return 0;
}
/* output
1
0
After set boolalpha
true
false
*/
서식화
이미 눈치챈분들도 있겠지만, 서식화 옵션은 flag로 되어 있으며, cout.setf()함수로 플레그를 지정할 수 있다.
(반대로 cout.unsetf() 함수로 플레그를 해제할 수 있다.)
플레그가 설정된 값은 해제 전까지 계속 유효하다. (boolalpha, fixed 등)
각 서식화 옵션들은 비트로 표현되는 플레그 값을 가지고 있다.
따라서 OR 연산을 통해 여러 개의 옵션을 동시에 활성화 하거나 비활성화 시킬 수 있다.
여전히 width 설정은 매번 해주어야 한다는 것 잊지말자.
#define _USE_MATH_DEFINES
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
int main()
{
double pi = M_PI;
double d = 1.23456789;
bool a = 1 < 3;
auto old_precision = cout.precision(); // std::streamsize = long long
auto old_fill = cout.fill();
cout.setf(ios_base::boolalpha | ios_base::fixed | ios_base::left);
cout << setfill('_');
cout.precision(10);
cout << setw(5) << "pi: " << setw(20) << pi << endl;
cout << setw(5) << "d: " << setw(20) << d << endl;
cout << setw(5) << "a: " << setw(20) << a << endl;
cout << "\nClean all manipulators" << endl;
cout.unsetf(ios_base::boolalpha | ios_base::fixed | ios_base::left);
cout.precision(old_precision);
cout.fill(old_fill);
cout << setw(5) << "pi: " << setw(20) << pi << endl;
cout << setw(5) << "d: " << setw(20) << d << endl;
cout << setw(5) << "a: " << setw(20) << a << endl;
return 0;
}
/* output
pi: _3.1415926536________
d: __1.2345678900________
a: __true________________
Clean all manipulators
pi: 3.14159
d: 1.23457
a: 1
*/
위에 소개한 입출력 조작자 외에도 더 많은 조작자들이 있다. (showpos, scientific, basefield 등등...)
?: dec, hex, oct는 flag에 넣어도 적용이 안된다... 이유가 뭘까...
'Language > C++' 카테고리의 다른 글
[C++] 상수 (define, constexpr) (0) | 2023.07.25 |
---|---|
[C++] 컨테이너(자료구조) 사용법 간단요약 (0) | 2023.07.21 |
C++ 리터럴 표기법 및 팁 (0) | 2023.01.07 |
VS 템플릿 클래스 사용 시 빌드 오류 (LNK2019, LNK1120) (0) | 2023.01.07 |
소켓 IO 모델 장단점 정리 (0) | 2022.11.29 |