프로그래밍/C++

[C++] cout 의 모든 것. [setf(), 조정자, 형식변환]

K_Coder 2012. 2. 17. 02:21

cout 소수점 출력하기, cout 16진수 출력하기, cout 공백 조절하기, cout setf() 사용하기, cout 조정자 사용하기
cout 소수점 출력하기, cout 16진수 출력하기, cout 공백 조절하기, cout setf() 사용하기, cout 조정자 사용하기 
cout 소수점 출력하기, cout 16진수 출력하기, cout 공백 조절하기, cout setf() 사용하기, cout 조정자 사용하기 
 


 
목차.
 

cout 의 기본 사용방법
형식 지정방법. ( cout 의 setf() 멤버함수 사용 1)
형식 지정방법. ( cout 의 setf() 멤버함수 사용 2) 
형식 지정방법 (조정자 사용) 

C와 C++의 출력 형식 비교 표





첫번째.  cout 의 기본 사용 방법  

cout << 변수명 ;


printf() 와는 다르게 형식 지정문자(%d, %c..) 가 필요 없어져서 편하고 간단히 쓸 수 있다.

cout << 'a' ;        또는      cout << "test"  ;

그냥 써주면 알아서 변수의 타입이 뭔지에 따라서 맞춰 출력해 준다. 굉장히 편리하긴 하다...

여러개를 사용할 때는 , 대신 << 을 사용해서 구분한다. cout << a << b ;

그렇다고, 16진수 혹은 소수점 조절을 못하면 말이 안되겠죠?

바로 다음에 설명 들어갑니다 ㅎㅎ


이건 개인적인거지만.. cout 문자들과 섞어 사용할 때 불편합니다.

예를 들어 printf("%d 와 ary[%d]의 값은 같습니다.\n", a, i);

이렇게 섞여 있는 내용을 출력 하려면

cout << a << "와 ary [" << i << "]의 값은 같습니다." << endl;

<< 요놈으로 계속 구분 지어줘야 하고 " " 를 계속 써줘야 한다;;

지금은 별 차이 못 느낄 수 있지만. 짜증나는 경우가 발생합니다; (사실 단지 익숙하지 않아서 그런것일 수도 있음);;



두번째. 
형식 지정 방법 cout의 setf() 멤버함수 사용

cout 의 self() 라는 형식을 지정해주는 멤버함수가 있는데, set flag 의 줄임말로
함수 오버로딩으로 인해 2가지 타입이 있죠


1개의 인자 값을 받는 함수
2개의 인자 값을 받는 함수 입니다.


cout.self(전달인자);

 1번째 전달인자  의미
 ios::showbase  출력에 진법 표시 접두어(0, 0x)를 표시
 ios::showpoint   소수점 표시(.) 과 생략된 0 들을 모두 출력 (기본 6자리)
 ios::uppercase   16진수와 과학적 표기에 대문자 표시 (1.2+E3)
 ios::showpos   양수 앞에 + 부호를 표시. (+30)



cout.self(전달인자, 전달인자); 

 1번째 전달인자  2번째 전달인자   결과
 ios::dec
 ios::hax
 ios::oct 
 ios::basefield  
 10진법
 16진법
   8진법
 ios::fixed
 ios::scientific
 ios::floatfield
 고정 소수점 표기
 과학적 E 표기(지수표기법)
 ios::left
 ios::right
 ios::internal 
ios::adjustfield 
 왼쪽 정렬
 오른쪽 정렬
 [부호,진법] 왼쪽, 값은 오른쪽 정렬





cout.self(전달인자) 예제 소스


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

int main()
{
	int num = 2012;

	double d_num1 = 10;
	double d_num2 = 12.345;
	

	cout << "그냥 출력" << endl;
	cout << "10진수 num = " << num << endl;
	cout << "16진수 num = " << hex << num << endl;
	cout << " 8진수 num = " << oct << num << endl;
	cout << dec;
	cout << "d_num1 = " << d_num1 << endl;
	cout << "d_num2 = " << d_num2 << endl << endl;

	cout << "부호 표시" << endl;
	cout.setf(ios::showpos);
	cout << "num = " << num << endl;
	cout << "d_num1 = " << d_num1 << endl;
	cout << "d_num2 = " << d_num2 << endl << endl;

	cout << "접두어(0,0x) 표시 " << endl;
	cout.setf(ios::showbase);
	cout << "접두어 표시 10진수 num = " << num << endl;
	cout << "접두어 표시 16진수 num = " << hex << num << endl;
	cout << "접두어 표시  8진수 num = " << oct << num << endl << endl;

	cout << "16진수 대문자 표시 " << endl;
	cout.setf(ios::uppercase);
	cout << "접두어 표시 10진수 num = " << dec << num << endl;
	cout << "접두어 표시 16진수 num = " << hex << num << endl;
	cout << "접두어 표시  8진수 num = " << oct << num << endl << endl;

	cout << "소수점 생략 안함 " << endl;
	cout.setf(ios::showpoint);
	cout << "소수점 생략 안하는 num = " << num << endl;
	cout << "소수점 생략 안하는 d_num1 = " << d_num1 << endl;
	cout << "소수점 생략 안하는 d_num2 = " << d_num2 << endl << endl;

	return 0;
}
※ oct, hex, dec 를 원래 설명한 방식대로 사용하지 않고 있지요? 이 부분은 아래 "조정자" 파트에서 설명하겠습니다.
 
    지금은 전달인자 1개짜리 .setf( ~ ); 의 사용 방법과 결과를 확인하세요 ^^




소수점 생략 안하는 num 을 보시면 8진수로 나옴을 알 수 있죠?
바로 위에 접두어 표시에서 사용한 oct 적용이 다음번 cout 에도 계속 유지 됩을 알 수 있습니다.






cout.self(전달인자, 전달인자) 예제 소스 

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

int main()
{
	int num = 2012;

	double d_num1 = 10;
	double d_num2 = 12.345;

	cout << "소수점 생략 안함 " << endl;
	cout.setf(ios::showpoint);
	cout << "소수점 생략 안하는 num = " << num << endl;
	cout << "소수점 생략 안하는 d_num1 = " << d_num1 << endl;
	cout << "소수점 생략 안하는 d_num2 = " << d_num2 << endl << endl;

	cout << "소수점 생략 안함 + 고정 소수점 표기 " << endl;
	cout.setf(ios::fixed, ios::floatfield);
	cout << "소수점 2째 자리 num = "  num << endl;
	cout << "소수점 2째 자리 d_num1 = " << d_num1 << endl;
	cout << "소수점 2째 자리 d_num2 = " << d_num2 << endl << endl;

	cout << "소수점 생략 안함 + 지수표기법(과학적 표기법) " << endl;
	cout.setf(ios::scientific, ios::floatfield);
	cout << "소수점 2째 자리 num = " << num << endl;
	cout << "소수점 2째 자리 d_num1 = " << d_num1 << endl;
	cout << "소수점 2째 자리 d_num2 = " << d_num2 << endl << endl;

	return 0;
}



전달인자 2개짜리 .setf( ~, ~ ); 의 사용 방법과 결과를 확인하세요 ^^





 세번째.  형식 지정 방법 조정자를 이용한 방법.


조정자 (or 조절자) 라는 출력 양식을 조절하는게 있습니다.
위에서 몇개가 잠깐 나왔었죠?ㅎㅎ

위에서 봤던 .setf() 함수의 번거로움을 해결하고자 만들어진거 같네요.

.setf() 없이 바로 내용만 작성하면 되지요. ^^

단, 조정자를 사용하기 위해서는 #include <iomanip> 를 반드시 해주어야 해요.

그리고.. 아주 중요한 부분이 하나 있는데,
%d 같이 1회성이 아닌 유지형(지속형) 입니다.
[ setw() 제외 ]


한번 hex를 사용해서 16진수를 출력하면
그 다음엔 hex를 사용하지 않아도 계속 16진수가 출력 되지요.
사용 후에는 원상복귀 시켜줘야 하는 번거로움이 있어요 ㅠㅠ

그리고 부호, 소수점, 대문자 표시 같은 표시 유형들은. 중복되서 사용되기 때문에

unsetf() 를 사용해서 해제 하거나, no조정자 를 사용해서 해제 하셔야 합니다. (표시 유형의 조정자)



조정자.
 
조정자  원래 사용 방식
 dec  setf(ios::dec, ios::basefield)
 hex  setf(ios::hex, ios::basefield)
 oct  setf(ios::oct, ios::basefield)
 showbase  setf(ios::showbase)
 noshowbase  unsetf(ios::showbase)
 showpos  setf(ios::showpos)
 noshowpos  unsetf(ios::showpos)
 uppercase  setf(ios::uppercase)
 nouppercase  unsetf(ios::uppercase)
 showpoint  setf(ios::showpoint)
 noshowpoint  unsetf(ios::showpoint)
 fixed  setf(ios::fixed, ios::floatfield)
 scientfific  setf(ios::scientific, ios::floatfield)
 left   setf(ios::left, ios::adjustfield)   
 right  setf(ios::right, ios::adjustfield) 
 internal    setf(ios::internal, ios::adjustfield)  


조정자의 사용결과는 cout.setf() 시와 동일 합니다.

각 조정자의 의미 설명은 위의 setf() 부분에서 확인 하시구
결과와 예제는 아래에서 확인 하시면 됩니다. ^^



추가로 함수형태로 전달인자를 받는 조정자를 몇개 소개 하겠습니다.
아주아주 꼭꼭 필요한 놈들이지요 ㅎㅎ
  
함수형(?)의 조정자.

조정자 함수  사용 결과
 setfill (char c)  c 문자로 여백을 채움
 setw (int n)  n 만큼 필드폭을 지정
 setprecision(int n)  소수점 n 자리까지 표시 



특이 사항으로는 유일하게 setw() 만 일회성 입니다.

자세한 사용법과 결과는 아래 예제와 결과로 확인해 주세요 ^^

#include <iostream>
#include <iomanip>                      // 조정자 사용을 위한 include.  필수 !!
using namespace std;

int main()
{
	int num = 2012;
	double d_num1 = 10;
	double d_num2 = 123.456;
	

	cout << "그냥 출력" << endl;
	cout << "num = " << num << endl;
	cout << "d_num1 = " << d_num1 << endl;
	cout << "d_num2 = " << d_num2 << endl << endl;


	cout << "조정자 사용 " << endl;
	cout << "10진수 num = " << num << endl;
	cout << "16진수 num = " << oct << num << endl;
	cout << " 8진수 num = " << hex << num << endl << endl;

	cout << dec ;                       //다시 10진수로 변경.
	cout << "필드폭 10인 d_num1 = " << setw(10) << d_num1 << endl;
	cout << "필드폭 10인 d_num2 = " << setw(10) << d_num2 << endl << endl;

	cout << "필드폭 10에 여백을 #으로 채움d_num1 = " << setw(10) << setfill('#') << d_num1 << endl;
	cout << "필드폭 10에 여백을 #으로 채움d_num2 = " << setw(10) << d_num2 << endl << endl;

	cout << "고정 소수점 표기 + 소수점 2째까지 출력 " << endl;
	cout << fixed << setprecision(2);
	cout << d_num1 << endl; 
	cout << d_num2 << endl;

	return 0;
}


※ fixed 는 scientfific 와 상반되는 표현입니다.

 
10,16,8진수(basefiled)에게는 영향을 끼치지 않으며,
 
fixed를 썼다고 10진 출력하기 위해 다시 뭔가 해줘야 하는 것은 아닙니다.

31라인에서 fixed 썻다고 10진수 찍기 위해 복귀시켜야 하는거 그런거 아닙니다 ㅎㅎ  

23라인에서 10진수를 찍기위해 다시 dec 를 사용해 줘야 하구요,
27라인에서 setfill('#') 적용으로 인해. 
28 라인에서는 따로 적을 필요 없이
계속 유지 됩니다.
setprecision(2) 도 마찬가지구요

보시면 아시겠지만, setw(10)은 매번있죠?
이놈만 유지성이 없습니다. 앞부분에서 설명했죠?ㅎㅎ 







C언와 C++의 출력 형식 비교표
 

C 언어 C ++
printf("%3d", num);   cout << setw(3) << num ; 
  printf("%.3lf", d_num);   cout << fixed << setprecision(3) << d_num ;  
printf("%x", num); cout << hex << num;
printf("%X", num); cout << uppercase << hex << num ;
printf("%#x\n", num); cout << showbase << hex << num ;
printf("%+d", num); cout << showpos << num;
printf("%.2s", str); cout.write(str,2);
printf("%*d", cnt, num); cout << setw(변수) << num ; 
printf("%.3lf", cnt,  d_num);   cout << fixed << setprecision(변수) << d_num ;  
printf("%-10d", num); cout << setw(10) << left << num ;
printf("%.3d", num);  cout << setw(3) << setfill('0') << num ; 

# 참고로. %3d 와 %.3d의 차이는 
%.3d 는 앞쪽 여백을 0 으로 채우고, %3d는 앞쪽 여백을 공백으로 채움
둘다 3자리가 넘는 값이 들어가면 무효되고, 값의 길이 만큼 출력 됨

다음에 순서대로 다시 정리해야지 ㅠㅠ

setprecision(n), precision(n) fixed로 잡아준 경우에는 소수점 몇째 자리까지 표시.
소수점이 짤리는 경우 fixed 지정이면 반올림되며,  

아무런 지정없이 사용해서 짤리면 지수표기법으로 나타남.

123.456을 fixed 없이  setprecision(n), precision(n) 로 잡으면 소수점에서 2자리가 아닌,
전체 숫자에서 2자리부터 짜르고 1.2e+002 가 출력됨.
123.456 에서 12까지 하고 소수가 아닌 3이 짤리므로 지수형 표기법으로 나타남.

10.5의 경우 10까지 되고 0.5가 짤리므로 반올림.