안녕하세요, katte입니다.
이번 글에서는 cout의 출력 형식을 지정하는 방법에 대해 알아보겠습니다.
출력 형식은 setf 함수를 통해서도 변경할 수 있지만, 조정자나 다른 간편한 함수를 사용할 수 있는 경우에는 해당 방식을 사용하는 것이 더 간편하니 최대한 활용할 수 있는 만큼 활용하는 것이 좋습니다.
따라서 setf에 대해서는 다음 글에서 알아보도록 하고, 이번 글에서는 출력 형식을 지정할 수 있는 몇가지 조정자와 함수에 대해서 알아보겠습니다.
ios_base 클래스는 출력 형식을 관장하는 비트마스크 멤버들을 가지고 있습니다. 이러한 비트들은 조정자 혹은 ios_base의 멤버함수를 사용하여 제어할 수 있습니다.
1) 진법
진법은 setf 함수를 통해 제어할 수 있지만, 좀 더 간편한 방식인 조정자로도 제어할 수 있도록 지원하고 있습니다.
10진법 | dec |
16진법 | hex |
8진법 | oct |
이러한 조정자들은 다음과 같은 방법으로 사용할 수 있습니다.
std::cout << std::hex; //16진법
std::oct(std::cout); //8진법, 함수 호출(멤버함수가 아니다)
조정자를 통해 진법을 설정한 후에는, 다시 다른 진법으로 변경하지 않는 이상 출력 형식을 그대로 유지합니다.
또한 두 번째와 같이 함수를 호출하여 진법을 변경하는 경우, 리턴값이 ios_base의 객체 레퍼런스이므로 setf, clear와 같은 ios_base 클래스의 멤버함수를 연달아서 호출할 수 있습니다.
2) 필드 폭 조정
필드 폭은 ios_base의 멤버함수인 width 함수를 통해 조정할 수 있습니다.
매개변수가 없는 width(void) 함수는 현재 설정되어있는 필드폭을 리턴하고,
width(int i)와 같이 int형 매개변수를 갖는 width 함수는 필드폭을 i로 변경하고 변경 이전의 필드폭을 리턴합니다. 따라서 변경 이전의 필드폭을 저장해뒀다가 다시 되돌리기 위해 사용할 수 있습니다.
width 함수는 함수 호출 이후 바로 다음에 오는 출력에만 변경 내용이 적용됩니다.
따라서 다음과 같은 코드에서는,
std::cout.width(12);
std::cout << 12 << '#' << 24;
width 함수 호출 이후에 출력하는 12에만 변경 내용이 적용되므로, 12개의 문자를 출력할 수 있는 필드에 숫자 12가 출력되고 잇따라서 디폴트 필드폭에 문자 #과 숫자 24가 출력됩니다.
또한 C++은 데이터의 보존을 더 중요시하므로, 지정한 필드폭이 데이터의 자릿수보다 작을 경우 자동으로 자릿수에 맞추어 필드폭을 넓힙니다. (ex. 지정한 필드폭은 2이나, 출력할 데이터가 1234인 경우 필드폭을 자동으로 4로 넓힘)
참고로 C++의 디폴트 필드폭은 0으로, 출력할 데이터의 자릿수에 맞추어 필드폭을 넓히는 방식으로 출력합니다.
3) 채움 문자
2에서와 같이 필드폭을 조정하여 남는 필드폭이 생기는 경우 그 필드를 빈칸으로 채우는 것이 디폴트이지만, fill 함수를 사용하면 우리가 따로 채움 문자를 지정할 수도 있습니다.
fill 함수는 ios 클래스의 멤버함수로, char형 문자를 매개변수로 받아 채움 문자를 변경한 후, 변경하기 전의 채움 문자를 char형으로 리턴합니다.
또한 채움 문자를 한번 지정하면 다시 새로 지정하기 전까지 그 설정을 유지합니다.
4) 출력 정밀도(precision)
출력 정밀도는 소수를 표기할 때, 소수점 아래 몇자리까지 표기되는가를 결정하는 요인으로 precision 함수를 사용해 변경할 수 있습니다.
C++에서 소수를 표기하기 위한 방법으로는 부동 소수점 방식과 고정 소수점 방식, 과학적 표기법 이렇게 세가지가 있습니다.
일단 과학적 표기법은 이공계생이라면 1학년 때 전공기초를 들으며 질리도록 봤을 것이라고 생각합니다.(유효숫자의 악몽)
수의 크기와 관계없이 x.xx * 10^n 와 같이 10의 지수승으로 표기하는 것이 과학적 표기법인데, C++을 포함한 몇몇 프로그램들에서는 이 지수를 e(또는 E)로 표기하고 x.xxE(+-)n와 같이 출력합니다.
고정 소수법 방식의 경우엔 수의 크기와 관계 없이 x.xxx와 같이 출력합니다.
부동 소수점 방식은 수의 크기에 따라 고정 소수점 방식 또는 과학적 소수점 방식을 차용하는 것으로, 지수가 6 이상이거나 -5 이하이면 과학적 표기법을 사용하고 그 외에는 고정 소수점 방식을 사용합니다.
소수의 표기 방법에 따라 정밀도(precision)의 정의가 달라집니다.
디폴트 모드인 부동 소수점 방식의 경우에는 출력되는 총 자릿수의 개수를 정밀도로 정의합니다.
즉, 12.345의 숫자가 출력되고, 부동 소수점 모드라면 정밀도는 5가 되는 것입니다.
반면 고정 소수점 방식과 과학적 표기법의 경우 소수점 아래 자릿수가 정밀도가 됩니다.
또한 부동 소수점 방식의 경우 정밀도와 관계없이 뒤에 오는 0들은 생략하는 것이 디폴트이나, 고정 소수점 방식과 과학적 표기법은 뒤에 오는 0들을 생략하지 않습니다.
C++의 경우 디폴트는 정밀도 6인 부동 소수점 방식이며, 뒤에 오는 0을 생략합니다.
설명이 길었는데, 밑에서 표로 다시 한번 정리하도록 하겠습니다.
아무튼, 이러한 정밀도는 ios_base의 멤버함수인 precision 함수를 통해 제어할 수 있습니다.
매개변수가 없는 precision 함수는 현재의 정밀도를 리턴하며,
int형의 매개변수(streamsize형)를 갖는 precision 함수는 전달받은 매개변수의 값으로 정밀도를 변경한 후, 변경 전의 정밀도를 리턴합니다.
또한 한번 정밀도를 변경하면 다시 변경하기 전까지 그 설정이 유지됩니다.
부동 소수점 방식 | 고정 소수점 방식 | 과학적 표기법 | |
표기 방식 | 크기에 따라 다름 | x.xx | x.xxE(+-)n |
정밀도 | 총 자릿수 | 소수점 아래 자릿수 | 소수점 아래 자릿수 |
0 생략 여부 | 뒤에 오는 0 생략이 디폴트 | 0 생략 안함 | 0 생략 안함 |
이 외에도 출력형식을 조정할 수 있는 조정자는 많습니다. 또한 setf를 통해 직접 플래그들을 조정할 수도 있습니다.
이에 대해서는 다음 글에서 다루도록 하고, 이번 글은 여기서 마치도록 하겠습니다.
첨언하자면, 사실 이 부분 기초플러스를 읽으면서 오역이 꽤 있다고 느꼈습니다.
기초플러스 17장 읽으실 땐 원서랑 같이 보시는 편이 좋을 것 같습니다.
* 해당 글은 'C++ 기초플러스 6판'을 참고하여 작성되었습니다.
'Computer > C++' 카테고리의 다른 글
[C++] 함수 포인터 정리 (0) | 2022.11.11 |
---|---|
[C++] 배열 포인터 정리 (0) | 2022.11.11 |
[C++] cout 관련(2) - 출력 버퍼 비우기 (0) | 2022.11.06 |
[C++] cout 관련(1) - write, put 출력 멤버함수 (0) | 2022.11.06 |
[C++] 입출력과 스트림, 버퍼 (0) | 2022.10.26 |