본문 바로가기
my_lesson/_C++

CPP - C++ 출력 자리수

by boolean 2014. 9. 25.
728x90

가. 폭 지정, fill 지정

출력되는 데이터가 화면상에 차지하는 폭은 별다른 지정을 하지 않고 데이터
를 출력했을 때 데이터의 길이에 맞추어진다. cout << 123;하면 3칸, cout <<
"korea"; 하면 5칸이 화면상에 할당되어 데이터가 출력된다. 만약 데이터 고유
길이 외의 특정 길이의 폭에 맞추어주고 싶다면 ios의 멤버 함수 width를 사용
하면 된다. 또한 데이터를 출력하고 나머지 남은 부분을 채우는 fill 문자를 f
ill 함수를 사용해서 지정할 수 있다. 예컨대 숫자 앞에 선행 0(zero)를 붙인
다거나 하는 등을 말한다. 폭과,fill 문자의 지정은 다음 두 함수에 의해 이루
어진다.

cout.width(지정하고자 하는 폭);
cout.fill(fill 문자);

예제와 출력 결과를 보이면 아래와 같다.

#include <iostream>
#include <iomanip>
void main()
{
int i=3;
char c='C';
clrscr();
cout << c << endl;
cout.width(5); // 폭을 5로 지정
cout.fill('*'); // 채움 문자는 '*'
cout << c;
cout << endl;
cout << i << endl;
cout.width(10); // 폭을 10으로 지정
cout.fill('0'); // 채움 문자는 '0'
cout << i;
}

출력 결과

C
****C
3
0000000003

printf를 쓸 줄 아는 사람이라면 쉽게 이해가 갈 것이다. 위 예제에서 사용된
endl은 개행을 시키는 역할을 하며 '\n'을 출력시키는 것과 동일하다. width와
fill을 사용할 때 다음 두 가지 사항에 주의해야 한다.
첫째, width와 fill에 의해 지정되는 폭과, fill 문자는 일회적이다. 한번 지
정한다고 해서 그 폭과 fill 문자가 계속 유효한 것은 아니라는 얘기다. 하나
의 데이터를 출력할 때마다 계속 폭과 fill 문자를 다시 지정해 주어야 한다.

cout.width(10);
cout << "echo";
cout << "off";

이러한 출력에 의해 문자열 "echo"는 과연 화면상에 10칸의 공간을 차지하지
만 "off"는 자기 자신의 길이인 3칸밖에 차지하지 못한다.
둘째, width가 지정하는 폭이란 강제적으로 그 폭에 맞추어라는 뜻이 아니라
최소한 그 폭은 되어야 함을 의미한다. 즉 출력할 데이터의 길이가 지정한 폭
보다 짧으면 지정한 폭이 할당되지만 데이터가 지정한 폭보다 더 길면 폭지정
은 무시되고 데이터의 길이에 맞추어진다.

cout.width(8);
cout << "ethics";
cout.width(8);
cout << "economics";

이런 경우 "ethics"는 지정한 폭대로 8칸을 차지하게 되며 economics는 9자이
기 때문에 지정한 폭 8칸에 맞추어질 수가 없기 때문에 폭지정을 무시하고 9칸
을 차지하게 된다. 지정한 폭에 맞추느라 데이터를 잘라 버리는 것 보다는 폭
을 조금 어기더라도 데이터를 다 출력하는 것이 더 중요하지 않은가? width 함
수는 폭을 지키기 위해 데이터를 잘라 버리는 어리석은 짓은 하지 않는다(no
truncation).


나. 진법 지정

진법 지정이란 printf문의 서식 %d, %o, %h에 해당하는 I/O 스트림의 출력 형
식 제어 방법이다. 같은 수라도 진법에 따라 출력이 달라진다. 다음 예제를 보
면 진법 지정에 대해 쉽게 이해할 수 있을 것이다.

#include <iostream>
#include <iomanip>
void main()
{
int i=32;
clrscr();
cout << i << endl;
cout << "dec= " << dec << i << endl; // 10진 지정
cout << "hex= " << hex << i << endl; // 16진 지정 
cout << "oct= " << oct << i << endl; // 8진 지정
}

출력 결과

32
dec= 32
hex= 20
oct= 40

진법에 대한 아무런 지정이 없다면 10진수로 출력이 이루어진다. 위 예제에서
나타난 dec, hex, oct의 문법적 의미는 함수 포인터이며 바로 다음에 구경하게
될 manipulator의 일종이다.

다. manipulator

manipulator란 입출력 형식을 조작하는 함수들이다. manipulator는 일부 iost
ream.h에 정의되어 있는 것도 있지만 대부분은 iomanip.h에 정의되어 있으므로
반드시 iomanip.h를 포함시키도록 한다.
manipulator의 종류에는 다음과 같은 것들이 있다.

-------------------------------------------------------------------------
manipulator 의 미
-------------------------------------------------------------------------
dec 숫자 데이터를 10진수로 출력한다.
oct 숫자 데이터를 8진수로 출력한다.
hex 숫자 데이터를 16진수로 출력한다.
endl '\n'을 출력하고 스트림을 비운다.
ends 문자열의 끝에 NULL 문자를 추가한다.
flush 스트림을 비운다. 
setbase(int n) 진법을 지정한다. n은 8,10,16이 가능하며 그 외의 나머지 숫
자가 오면 10진수로 가정한다.
resetiosflags(long n) n에서 지정한 비트를 reset한다.
setiosflags(liong n) n과 x_flags를 OR시켜 n에서 지정한 비트를 set한다.
setfill(int n) fill 문자를 지정한다.
setw(int n) 데이터가 출력될 화면의 폭을 n으로 지정한다.
setprecision(int n) 실수의 유효숫자 자리수를 지정한다. 지정한 유효숫자 자
리에서 반올림된다.
-------------------------------------------------------------------------

뭔가 복잡해보이지만 한번씩 사용해보면 어렵지 않다. manipulator 중에는 ios
의 멤버 함수와 기능면에서 중복되는 것들도 있다. setw는 ios::width와 같고
setfill은 ios::fill과 그 기능이 같다. 차이점이라면 width, fill은 개별적으
로 실행을 시켜야 하고 manipulator는 << 연산자의 피연산자로 사용될 수 있다
는 것이다. 다음에 manipulator를 사용하는 예제와 실행 결과를 보인다.

#include <iostream>
#include <iomanip>
#include 
void main()
{
double x=3.1415;
int i=16;
clrscr();
cout << x << endl;
cout << setw(10) << setfill('0') << x << endl;
cout << setprecision(3) << x << endl;
cout << "dec= " << setbase(10) << i << endl;
cout << "hex= " << setbase(16) << i << endl;
cout << "oct= " << setbase(8) << i << endl;
}

실행 결과

3.1415
00003.1415
3.142
dec= 16
hex= 10
oct= 20

실행 결과를 잘 살펴보고 예제에 사용된 manipulator를 직접 사용해 보아라.


라. 좌우 정렬

출력될 데이터가 차지할 폭이 데이터의 길이보다 더 길 경우는 데이터를 좌측
정렬할 것인지 우측 정렬할 것인지 두 가지를 선택해야 한다. 이러한 정렬 정
보는 ios 클래스의 데이터 멤버 x_flags에 보관되며 x_flags의 정보를 조작하
는 setiosflags와 resetiosflags가 준비되어 있다.

* setiosflags(long n);
n의 값이 1인 비트와 대응되는 x_flags의 비트를 1로 만들어 준다. 즉 그 비
트가 가진 의미를 활성화시킨다는 뜻이다. setiosflags(0x0014)는 x_flags의 b
2,b4를 1로 만들며 이때 출력 형식은 10진수의 오른쪽 정렬이 된다.
* resetiosflags(long n);
n의 값이 1인 비트와 대응되는 x_flags의 비트를 0으로 만들어 준다. 즉 그
비트가 가진 의미를 활성화시키지 않는다는 뜻이다.

setiosflags의 인수로 사용하기 위한 열거형이 iostream.h에 다음과 같이 정
의되어 있으며 이 열거형을 살펴보면 x_flags의 각 비트가 어떠한 의미인지 알
수 있다.

// formatting flags
enum {
skipws = 0x0001, // skip whitespace on input
left = 0x0002, // left-adjust output
right = 0x0004, // right-adjust output
internal = 0x0008, // padding after sign or base
indicatordec = 0x0010, // decimal conversion
oct = 0x0020, // octal conversion
hex = 0x0040, // hexadecimal conversion
showbase = 0x0080, // use base indicator on
outputshowpoint = 0x0100, // force decimal point (floating output)
uppercase = 0x0200, // upper-case hex output
showpos = 0x0400, // add '+' to positive
integersscientific = 0x0800, // use 1.2345E2 floating
notationfixed = 0x1000, // use 123.45 floating
notationunitbuf = 0x2000, // flush all streams after
insertionstdio = 0x4000 // flush stdout, stderr after insertion
};

다음 예제는 setiosflags를 사용해 문자열을 좌우로 정렬시켜 출력해본 것이
다.

#include <iostream>
#include <iomanip>
#include 
void main()
{
char str[]="string";
clrscr();
cout.setf(ios::left); // 좌측 정렬
cout << setw(10) << str << endl;
cout.setf(ios::right); // 우측 정렬
cout << setw(10) << str << endl;
cout.setf(ios::hex); // 16진 출력
cout.setf(ios::showbase); // 16진 표식을 보인다.
cout.setf(ios::left); // 좌측 정렬
cout.setf(ios::uppercase); // 16진수에 대문자 사용
cout << setw(10) << 12 << endl;
}

출력 결과

string
string
0XC

또한 showbase,uppercase 등을 사용해 숫자 데이터의 base(진법)를 출력하도
록 하고 16진수에 사용되는 영문자를 대문자로 출력되도록 하였다.

'my_lesson > _C++' 카테고리의 다른 글

CPP - Array _ For _ LottoGenerator 1.0  (0) 2019.04.04
CPP - Repeat While, RackPaperScissors_Game  (0) 2019.04.03
CPP - Condition If , Switch  (0) 2019.04.03
CPP - Operator  (0) 2019.04.03
CPP - DataType  (0) 2019.04.03

댓글