728x90

1. 출력

1.1. class 분석

class 관련 자료 확인 검색 시 다음의 자료를 볼 수 있었다. 현재 C++20 버전의 구조를 보기 편하게 정리된 자료입니다.
(참고: https://www3.ntu.edu.sg/home/ehchua/programming/cpp/cp10_IO.html)

1.1.1. Iosb

ios_base의 base class

1.1.2. ios_base

ios를 위한 base class

- 멤버변수

class ios_base

1.1.3. _Locbase

locale클래스 의 base class

1.1.4. locale

문자의 출력 방식 등 나라에 따라 달라지는 설정을 저장하기 위한 class

- 멤버변수

- 내부 추가 class

(1) id: 멤버 클래스는 locale의 패싯을 조회하기 위한 인덱스로 사용되는 고유한 패싯 ID 제공을 위한 클래스

(identifier stamp, unique for each distinct kind of facet)

(2) _Locimp: 참조 카운트 된 locale의 실제 구현이 이뤄지는 클래스 (reference-counted actual implementation of a locale)

(3) facet: locale이 구현하는 패싯에 대한 포인터를 단일 인덱스 컨테이너에 저장할 수 있도록 지원하는 클래스

내부에 facet 관련 구조체로 자신을 가리키는 포인터와 참조 카운터를 갖고 있는다.

(4) _Ptr: 로케일 구현 객체에 대한 포인터

1.1.3. basic_ios

basic_istream/basic_ostream을 위한 base class

- 멤버 변수: basic_ios는 ostream과 stream buffer를 멤버변수로 갖고 있는다.

 

1.1.4. ostream

- 멤버변수 정리

(1) ios_base

(2) basic_ios

(3) ostream

class 내 멤버변수 미포함

 

1.2. Output formatting

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

int main()
{
	// 1. 상태 저장 및 초기화
	std::ios state(NULL);
	state.copyfmt(std::cout);
	std::cout.copyfmt(std::ios(NULL));

	// 2. showpos/noshowpos
	// int
	cout << showpos << 12 << endl;				        // +12
	cout << noshowpos << 12 << endl;					// 12
	// float
	cout << showpos << 12.3 << endl;					// +12.3
	cout << noshowpos << 12.3 << endl;					// 12.3
	// string  
	cout << showpos << "12" << endl;					// 12
	cout << noshowpos << "12" << endl;					// 12

	// 3. dec/hex/oct
	std::cout.copyfmt(std::ios(NULL));
	// int
	cout << hex << 12 << endl;							// c  (c = 12)
	cout << dec << 12 << endl;							// 12
	cout << oct << 12 << endl;							// 14 (8 + 4 = 12)
	// float
	cout << hexfloat << 12.3 << endl;					// 0x1.899999999999ap+3
	// string
	cout << hex << "12" << endl;						// 12
	cout << dec << "12" << endl;						// 12
	cout << oct << "12" << endl;						// 12

	// 4. uppercase/nouppercase
	std::cout.copyfmt(std::ios(NULL));
	// int
	cout << hex << uppercase << 12 << endl;				// C
	cout << hex << nouppercase << 12 << endl;			// c
	// float
	cout << hexfloat << uppercase << 12.3 << endl;		// 0X1.899999999999AP+3
	cout << hexfloat << nouppercase << 12.3 << endl;	// 0x1.899999999999ap+3
	// string
	cout << uppercase << "abcd" << endl;				// abcd
	cout << nouppercase << "abcd" << endl;				// abcd

	// 5. showbase/noshowbase
	std::cout.copyfmt(std::ios(NULL));
	// int (hex)
	cout << hex << showbase << 12 << endl;				// 0xb
	cout << hex << noshowbase << 12 << endl;			// b
	// int (dec)
	cout << dec << showbase << 12 << endl;				// 12
	cout << dec << noshowbase << 12 << endl;			// 12
	// int (oct)
	cout << oct << showbase << 12 << endl;				// 014
	cout << oct << noshowbase << 12 << endl;			// 14

	// 6. setw()
	std::cout.copyfmt(std::ios(NULL));
	// int
	cout << setw(4) << 12 << endl;						// __12
	cout << setw(4) << 12345 << endl;					// 12345
	// float
	cout << setw(4) << 12.345 << endl;					// 12.345
	cout << setw(4) << 12.3 << endl;					// 12.3
	// string
	cout << setw(4) << "12" << endl;					// __12
	cout << setw(4) << "12345" << endl;					// 12345

	// 7. setfill()
	std::cout.copyfmt(std::ios(NULL));
	// int
	cout << setw(4) << setfill('*') << 12 << endl;		// **12
	cout << setw(4) << setfill('*') << 12345 << endl;	// 12345
	cout << setw(4) << 12 << endl;						// __12
	// float
	cout << setw(4) << setfill('*') << 12.345 << endl;	// 12.345
	cout << setw(4) << setfill('*') << 12.3 << endl;	// 12.3
	// string
	cout << setw(4) << setfill('*') << "12" << endl;	// **12
	cout << setw(4) << setfill('*') << "12345" << endl;	// 12345

	// 8. left/right/internal
	std::cout.copyfmt(std::ios(NULL));
	// int
	cout << hex << showbase << showpos << left;
	cout << setw(5) << 12 << endl;						// 0xc
	cout << setw(5) << 12345 << endl;					// 0x3039
	cout << dec;
	cout << setw(5) << 12 << endl;						// +12
	cout << setw(5) << 12345 << endl;					// +12345
	cout << hex << right;
	cout << setw(5) << 12 << endl;						// __0xc
	cout << setw(5) << 12345 << endl;					// 0x3039
	cout << dec;		
	cout << setw(5) << 12 << endl;						// __+12
	cout << setw(5) << 12345 << endl;					// +12345
	cout << hex << internal;
	cout << setw(5) << 12 << endl;						// 0x__c
	cout << setw(5) << 12345 << endl;					// 0x3039
	cout << dec;
	cout << setw(5) << 12 << endl;						// +__12
	cout << setw(5) << 12345 << endl;					// +12345
	// float
	cout << showbase << showpos << left;
	cout << setw(6) << 1.2 << endl;						// +1.2
	cout << setw(6) << 1. << endl;						// +1
	cout << setw(6) << 1.2345 << endl;					// +1.2345
	cout << right;
	cout << setw(6) << 1.2 << endl;						// __+1.2
	cout << setw(6) << 1. << endl;						// ____+1
	cout << setw(6) << 1.2345 << endl;					// +1.2345
	cout << internal;
	cout << setw(6) << 1.2 << endl;						// +__1.2
	cout << setw(6) << 1. << endl;						// +____1
	cout << setw(6) << 1.2345 << endl;					// +1.2345
	// string
	cout << left;
	cout << setw(5) << "12" << endl;					// 12
	cout << setw(5) << "123456" << endl;				// 123456
	cout << right;
	cout << setw(5) << "12" << endl;					// ___12
	cout << setw(5) << "123456" << endl;				// 123456
	cout << internal;
	cout << setw(5) << "12" << endl;					// ___12
	cout << setw(5) << "123456" << endl;				// 123456

	// 9. setprecision
	std::cout.copyfmt(std::ios(NULL));
	// float
	cout << setprecision(6) << 12.345678 << endl;		// 12.3457
	cout << setprecision(6) << 12.3456 << endl;			// 12.3456
	cout << setprecision(6) << 12.345 << endl;			// 12.345

	// 10. showpoint/noshowpoint
	std::cout.copyfmt(std::ios(NULL));
	// int
	cout << showpoint << 123 << endl;					// 123
	cout << noshowpoint << 123 << endl;					// 123
	// float
	cout << showpoint << 12.3 << endl;					// 12.3000
	cout << noshowpoint << 12.3 << endl;				// 12.3
	// string
	cout << showpoint << "123" << endl;					// 123
	cout << noshowpoint << "123" << endl;				// 123

	// 11. scienantific/fixed
	std::cout.copyfmt(std::ios(NULL));
	// float
	cout << 12.34 << endl;								// 12.34
	cout << scientific << 12.34 << endl;				// 1.234000e+01
	cout << fixed << 12.34 << endl;						// 12.340000
	cout << fixed << setprecision(4) << 12.34 << endl;	// 12.3400

	// 12. boolalpha/noboolalpha
	std::cout.copyfmt(std::ios(NULL));
	// bool
	cout << boolalpha << true << endl;					// true
	cout << noboolalpha << true << endl;				// 1
	cout << boolalpha << false << endl;					// false
	cout << noboolalpha << false << endl;				// 0

	std::cout.copyfmt(std::ios(NULL));
	cout.setf(ios_base::hex);
	cout << 12 << endl;								// 12
	cout.setf(ios_base::hex, ios_base::basefield);
	cout << 12 << endl;								// c
	

	return 0;
}

 

1.2.1. manipulator

'ostream'의 부모클래스인 ' ios_base' 내 fmtflags를 설정하여 출력 방식을 제어한다.

이때, fmtflags는 int형으로 bitmask 방식으로 동작이 이뤄진다. (mask에 대한 동작 방식은 '_Iosb' class 내에 정의되어있다.)

1.2.1.1. 상태 저장 및 초기화

상태 저장: ios_base에 설정된 옵션을 가져온다. (참고: https://cplusplus.com/reference/ios/ios/copyfmt/)

초기화: copyfmt을 응용하여 초기화 ios 값 복사를 통해 초기화를 적용한다.

// 상태 저장
std::ios state(NULL);
state.copyfmt(std::cout);

// 초기화
std::cout.copyfmt(std::ios(NULL));

1.2.1.2. showpos/noshowpos

'ios_base' 내 멤버변수 중 '_Fmtfl'에 flag 정보 추가 (showpos = 0x0020)

showpos: 양수에 부호를 표시한다.

noshowpos: 양수에 부호를 표시하지 않는다.

// int
cout << showpos << 12 << endl;		// +12
cout << noshowpos << 12 << endl;	// 12
// float
cout << showpos << 12.3 << endl;	// +12.3
cout << noshowpos << 12.3 << endl;	// 12.3
// string  
cout << showpos << "12" << endl;	// 12
cout << noshowpos << "12" << endl;	// 12

1.2.1.3. dec/hex/oct

'ios_base' 내 멤버변수 중 '_Fmtfl'에 flag 정보 추가 (dec/oct/hex = 0x0200/0x0400/0x0800)

dec: 10진수 표기법을 사용한다.

hex: 16진수 표기법을 사용한다.

oct: 8진수 표기법을 사용한다.

// int
cout << hex << 12 << endl;		// c  (c = 12)
cout << dec << 12 << endl;		// 12
cout << oct << 12 << endl;		// 14 (8 + 4 = 12)
// float
cout << hexfloat << 12.3 << endl;	// 0x1.899999999999ap+3
// string
cout << hex << "12" << endl;		// 12
cout << dec << "12" << endl;		// 12
cout << oct << "12" << endl;		// 12

basefield: setf 동작 시 bitmask를 위한 구간 지정 (basefield = 0x0x0E00 //dec | oct | hex)

 

1.2.1.4. uppercase/nouppercase

'ios_base' 내 멤버변수 중 '_Fmtfl'에 flag 정보 추가 (uppercase = 0x0004)

uppercase: 16진수 출력 시 대문자로 출력한다.

nouppercase: 16진수 출력 시 소문자로 출력한다.

// int
cout << hex << uppercase << 12 << endl;			// C
cout << hex << nouppercase << 12 << endl;		// c
// float
cout << hexfloat << uppercase << 12.3 << endl;		// 0X1.899999999999AP+3
cout << hexfloat << nouppercase << 12.3 << endl;	// 0x1.899999999999ap+3
// string
cout << uppercase << "abcd" << endl;			// abcd
cout << nouppercase << "abcd" << endl;			// abcd

1.2.1.5. showbase/noshowbase

'ios_base' 내 멤버변수 중 '_Fmtfl'에 flag 정보 추가 (showbase = 0x0008)

showbase: 16진수, 8진수 출력 시 포멧에 따른 접두사를 붙여준다.

1) 16진수 출력: '0x' 추가

2) 8진수 출력: '0' 추가

noshowbase: 접두사를 붙이지 않는다.

// int (hex)
cout << hex << showbase << 12 << endl;				// 0xb
cout << hex << noshowbase << 12 << endl;			// b
// int (dec)
cout << dec << showbase << 12 << endl;				// 12
cout << dec << noshowbase << 12 << endl;			// 12
// int (oct)
cout << oct << showbase << 12 << endl;				// 014
cout << oct << noshowbase << 12 << endl;			// 14

1.2.1.6. setw()

setw: 'ios_base' 내 멤버변수 중 '_Wide' 변경 (default: 0)을 통해 출력할 문자의 길이 제어

특이사항: 매 출력 시 설정 필요

// int
cout << setw(4) << 12 << endl;		// __12
cout << setw(4) << 12345 << endl;	// 12345
// float
cout << setw(4) << 12.345 << endl;	// 12.345
cout << setw(4) << 12.3 << endl;	// 12.3
// string
cout << setw(4) << "12" << endl;	// __12
cout << setw(4) << "12345" << endl;	// 12345

 

1.2.1.7. setfill()

setfill: 'basic_ios' 내 멤버변수 중 '_Fillch' 변경 (default: 32, ' ')을 통해 공백을 채울 문자 결정

// int
cout << setw(4) << setfill('*') << 12 << endl;		// **12
cout << setw(4) << setfill('*') << 12345 << endl;	// 12345
// float
cout << setw(4) << setfill('*') << 12.345 << endl;	// 12.345
cout << setw(4) << setfill('*') << 12.3 << endl;	// 12.3
// string
cout << setw(4) << setfill('*') << "12" << endl;	// **12
cout << setw(4) << setfill('*') << "12345" << endl;	// 12345

1.2.1.8. left/right/internal

'ios_base' 내 멤버변수 중 '_Fmtfl'에 flag 정보 추가 (left/right/internal = 0x0040/0x0080/0x0100)

left: 좌측 정렬

right: 우측 정렬

internal: 접두사-좌측 정렬 / 데이터-우측 정렬

// int
cout << hex << showbase << showpos << left;
cout << setw(5) << 12 << endl;						// 0xc
cout << setw(5) << 12345 << endl;					// 0x3039
cout << dec;
cout << setw(5) << 12 << endl;						// +12
cout << setw(5) << 12345 << endl;					// +12345
cout << hex << right;
cout << setw(5) << 12 << endl;						// __0xc
cout << setw(5) << 12345 << endl;					// 0x3039
cout << dec;		
cout << setw(5) << 12 << endl;						// __+12
cout << setw(5) << 12345 << endl;					// +12345
cout << hex << internal;
cout << setw(5) << 12 << endl;						// 0x__c
cout << setw(5) << 12345 << endl;					// 0x3039
cout << dec;
cout << setw(5) << 12 << endl;						// +__12
cout << setw(5) << 12345 << endl;					// +12345
// float
cout << showbase << showpos << left;
cout << setw(6) << 1.2 << endl;						// +1.2
cout << setw(6) << 1. << endl;						// +1
cout << setw(6) << 1.2345 << endl;					// +1.2345
cout << right;
cout << setw(6) << 1.2 << endl;						// __+1.2
cout << setw(6) << 1. << endl;						// ____+1
cout << setw(6) << 1.2345 << endl;					// +1.2345
cout << internal;
cout << setw(6) << 1.2 << endl;						// +__1.2
cout << setw(6) << 1. << endl;						// +____1
cout << setw(6) << 1.2345 << endl;					// +1.2345
// string
cout << left;
cout << setw(5) << "12" << endl;					// 12
cout << setw(5) << "123456" << endl;					// 123456
cout << right;
cout << setw(5) << "12" << endl;					// ___12
cout << setw(5) << "123456" << endl;					// 123456
cout << internal;
cout << setw(5) << "12" << endl;					// ___12
cout << setw(5) << "123456" << endl;					// 123456

adjustfield: setf 동작 시 bitmask를 위한 구간 지정 (basefield = 0x0x01C0 //left | right | internal)

1.2.1.9. setprecision()

setprecision: 'ios_base' 내 멤버변수 중 '_Prec' 변경 (default: 6)을 통해 출력할 유효 자릿수 결정

// float
cout << setprecision(6) << 12.345678 << endl;		// 12.3457
cout << setprecision(6) << 12.3456 << endl;		// 12.3456
cout << setprecision(6) << 12.345 << endl;		// 12.345

1.2.1.10. showpoint/noshowpoint

'ios_base' 내 멤버변수 중 '_Fmtfl'에 flag 정보 추가 (showpoint = 0x0010)

showpoint: 소수 부분이 0인 경우에도 표현

noshowpoint: 소수 부분이 0인 경우 생략

// int
cout << showpoint << 123 << endl;	// 123
cout << noshowpoint << 123 << endl;	// 123
// float
cout << showpoint << 12.3 << endl;	// 12.3000
cout << noshowpoint << 12.3 << endl;	// 12.3
// string
cout << showpoint << "123" << endl;	// 123
cout << noshowpoint << "123" << endl;	// 123

1.2.1.11. scienantific/fixed

'ios_base' 내 멤버변수 중 '_Fmtfl'에 flag 정보 추가 (scientific/fixed = 0x2000/0x1000)

scientific: 과학적 표기법을 활용하여 부동 소수점 표현

fixed: 기본 표현을 활용하여 부동 소수점 표현

// float
cout << 12.34 << endl;					// 12.34
cout << scientific << 12.34 << endl;			// 1.234000e+01
cout << fixed << 12.34 << endl;				// 12.340000
cout << fixed << setprecision(4) << 12.34 << endl;	// 12.3400

floatfield: setf 동작 시 bitmask를 위한 구간 지정 (floatfield = 0x0x3000 // scientific | fixed)

1.2.1.12. boolalpha/noboolalpha

'ios_base' 내 멤버변수 중 '_Fmtfl'에 flag 정보 추가 (boolalpha = 0x4000)

boolalpha: bool 값을 문자로 표시 (false/true)

noboolalpha: bool 값을 정수로 표시 (0/1)

// bool
cout << boolalpha << true << endl;		// true
cout << noboolalpha << true << endl;		// 1
cout << boolalpha << false << endl;		// false
cout << noboolalpha << false << endl;		// 0

1.2.2. setf(), unsetf()

fmtflag를 직접 제어하는 함수

cout.setf(ios_base::hex);
cout << 12 << endl;								// 12
cout.setf(ios_base::hex, ios_base::basefield);
cout << 12 << endl;								// c

(1) setf(flag) / unsetf(flag)

(2) setf(flag, flag)

- dec/oct/hex basefield

- fixed/scientific floatfield

- left/right/internal adjustfield

 

1.3. 출력 동작 분석

실제 응용은 아래의 구문을 진행하며, 출력이 이뤄진다.

1.3.1. operator<<(int _Val) (in 'basic_ostream' class)

int형 출력 시 facet을 활용하고, fmtflag 중 basefield를 사용한다.

1.3.1.1. rdbuf() (in 'basic_ios' class)

stream buffer의 포인터 위치를 반환함.

1.3.1.2. fill() (in 'basic_ios' class)

빈 공간을 채울 character를 반환함. (이때, _Elem은 char가 활용된다. 예외적인 상황은 추후 고민해보자.)

1.3.1.3. put (in 'num_put' class)

1.3.1.3.1. do_put (in 'num_put' class)

 

1.3.1.3.1.1. _Ifmt (in 'num_put' class)

int형 출력을 위한 format

+) _Ffmt (in 'num_put' class)

floating-point 출력을 위한 포멧

1.3.1.3.1.2. sprintf_s (global, in 'stdio.h' class)

_Buffer에 _Format에 따라 변경된 문자열을 저장

1.3.1.3.1.3. _Iput (in 'num_put' class)

Integer 형식의 출력을 위한 구현부

+) Fput (in 'num_put' class)

Floating-point 형식의 출력을 위한 구현부

1.3.1.3.1.3.1. getloc() (in 'ios_base' class)

locale을 활용

1.3.1.3.1.3.2. widen() (in 'ctype' class)

char 형식의 문자를 locale에서 사용하는 ctype 형태의 문자로 변환

1.3.1.3.1.3.3. _Put (in 'num_put' class)

[_Ptr, _Prt + _Count] 범위의 값을 _Dest 메모리로 복사

1.3.1.3.1.3.4. _Rep (in 'num_put' class)

'_Count' 횟수만큼 '_Ch' 데이터를  _Dest 메모리로 복사

 

1.3.2. endl (in 'basic_ostream' class)

 

1.3.2.1. put (in 'basic_ostream' class)

1.3.2.2. flush (in 'basic_ostream' class)

1.3.2.2.1. rdbuf (in 'basic_ios' class)

stream buffer 포인터 반환

1.3.2.2.2. pubsync, sync (in 'basic_streambuf' class)

(참고: https://learn.microsoft.com/ko-kr/cpp/standard-library/basic-streambuf-class?view=msvc-170)

외부 스트림과 동기화

+ Recent posts