Standard format specification (since C++20)
기본 타입과 문자열 타입의 경우, 형식 지정은 Python의 형식 지정 을 기반으로 합니다.
형식 지정의 구문은 다음과 같습니다:
채움 및 정렬
(선택 사항)
부호
(선택 사항)
#
(선택 사항)
0
(선택 사항)
너비
(선택 사항)
정밀도
(선택 사항)
L
(선택 사항)
타입
(선택 사항)
|
|||||||||
sign
,
#
및
0
옵션은 정수 또는 부동 소수점 표현 유형이 사용될 때만 유효합니다.
목차 |
채우기 및 정렬
fill-and-align
는 선택적
fill
문자(
{
또는
}
를 제외한 모든 문자)와 그 뒤에 오는
align
옵션 중 하나(
<
,
>
,
^
)로 구성됩니다.
채우기 문자가 지정되지 않은 경우 기본적으로 공백 문자로 설정됩니다. 유니코드 인코딩의 형식 지정에서 채우기 문자는 단일 유니코드 스칼라 값에 해당해야 합니다.
align 옵션의 의미는 다음과 같습니다:
-
<: 서식이 지정된 인수를 사용 가능한 공간의 시작 부분에 정렬하도록 강제합니다. 서식이 지정된 인수 뒤에 n 개의 채움 문자를 삽입합니다. 이는 정수형이 아닌 비부동소수점 표현 유형이 사용될 때의 기본값입니다. -
>: 서식이 지정된 인수를 사용 가능한 공간의 끝 부분에 정렬하도록 강제합니다. 서식이 지정된 인수 앞에 n 개의 채움 문자를 삽입합니다. 이는 정수형 또는 부동소수점 표현 유형이 사용될 때의 기본값입니다. -
^: 서식이 지정된 인수를 사용 가능한 공간의 중앙에 배치하도록 강제합니다. 서식이 지정된 인수 앞에 ⌊
⌋ 개의 문자와 뒤에 ⌈n 2
⌉ 개의 문자를 삽입합니다.n 2
각 경우에, n 은 최소 필드 너비( width 로 지정됨)와 서식이 지정된 인수의 예상 너비 의 차이이거나, 차이가 0보다 작을 경우 0입니다.
#include <cassert> #include <format> int main() { char c = 120; assert(std::format("{:6}", 42) == " 42"); assert(std::format("{:6}", 'x') == "x "); assert(std::format("{:*<6}", 'x') == "x*****"); assert(std::format("{:*>6}", 'x') == "*****x"); assert(std::format("{:*^6}", 'x') == "**x***"); assert(std::format("{:6d}", c) == " 120"); assert(std::format("{:6}", true) == "true "); }
부호, #, 및 0
sign 옵션은 다음 중 하나일 수 있습니다:
-
+: 양수와 음수 모두에 부호를 사용해야 함을 나타냅니다.+기호는 음수가 아닌 숫자의 출력 값 앞에 삽입됩니다. -
-: 음수에만 부호를 사용해야 함을 나타냅니다(이는 기본 동작입니다). - space: 음수가 아닌 숫자에는 앞에 공백을 사용하고, 음수에는 마이너스 기호를 사용해야 함을 나타냅니다.
음의 영은 음수로 취급됩니다.
sign 옵션은 부동 소수점 무한대 및 NaN에 적용됩니다.
#include <cassert> #include <format> #include <limits> int main() { double inf = std::numeric_limits<double>::infinity(); double nan = std::numeric_limits<double>::quiet_NaN(); assert(std::format("{0:},{0:+},{0:-},{0: }", 1) == "1,+1,1, 1"); assert(std::format("{0:},{0:+},{0:-},{0: }", -1) == "-1,-1,-1,-1"); assert(std::format("{0:},{0:+},{0:-},{0: }", inf) == "inf,+inf,inf, inf"); assert(std::format("{0:},{0:+},{0:-},{0: }", nan) == "nan,+nan,nan, nan"); }
#
옵션은 변환에
대체 형식(alternate form)
이 사용되도록 합니다.
-
정수형(integral types)의 경우, 2진수, 8진수 또는 16진수 표현 형식이 사용될 때 대체 형식(alternate form)은 부호 문자(공백일 수 있음)가 있는 경우 이를 출력 값 뒤에 접두사(
0b,0, 또는0x)를 삽입하고, 그렇지 않으면 출력 값 앞에 추가합니다. -
부동 소수점형(floating-point types)의 경우, 대체 형식은 유한 값(finite values)의 변환 결과에 항상 소수점 문자를 포함하도록 합니다. 일반적으로 이러한 변환 결과에는 숫자가 뒤따를 때만 소수점 문자가 나타납니다. 또한
g및G변환의 경우, 결과에서 후행 제로(trailing zeros)가 제거되지 않습니다.
0
옵션은 무한대 또는 NaN에 적용되는 경우를 제외하고, 필드 너비까지 선행하는 0들로(부호 또는 진법 표시 뒤에) 필드를 채웁니다. 만약
0
문자와
align
옵션이 모두 나타나면,
0
문자는 무시됩니다.
#include <cassert> #include <format> int main() { char c = 120; assert(std::format("{:+06d}", c) == "+00120"); assert(std::format("{:#06x}", 0xa) == "0x000a"); assert(std::format("{:<06}", -42) == "-42 "); // '<' 때문에 0은 무시됨 }
너비와 정밀도
width
는 양의 십진수이거나 중첩된 치환 필드(
{}
또는
{
n
}
)입니다. 존재할 경우 최소 필드 너비를 지정합니다.
precision
은 점(
.
) 뒤에 음수가 아닌 십진수 또는 중첩된 치환 필드가 오는 형태입니다. 이 필드는 정밀도 또는 최대 필드 크기를 나타냅니다. 부동 소수점 및 문자열 타입에서만 사용할 수 있습니다.
- 부동 소수점 타입의 경우, 이 필드는 서식 지정 정밀도를 나타냅니다.
- 문자열 타입의 경우, 출력에 복사될 문자열 접두사의 예상 너비 상한값을 제공합니다( 아래 참조 ). 유니코드 인코딩 문자열의 경우, 출력에 복사될 텍스트는 예상 너비가 정밀도를 초과하지 않는 전체 확장 자소 클러스터의 가장 긴 접두사입니다.
중첩된 치환 필드가 width 또는 precision 에 사용되고, 해당 인수가 integral type (until C++23) standard signed or unsigned integer type (since C++23) 가 아니거나 음수인 경우, std::format_error 타입의 예외가 발생합니다.
float pi = 3.14f; assert(std::format("{:10f}", pi) == " 3.140000"); // 너비 = 10 assert(std::format("{:{}f}", pi, 10) == " 3.140000"); // 너비 = 10 assert(std::format("{:.5f}", pi) == "3.14000"); // 정밀도 = 5 assert(std::format("{:.{}f}", pi, 5) == "3.14000"); // 정밀도 = 5 assert(std::format("{:10.5f}", pi) == " 3.14000"); // 너비 = 10, 정밀도 = 5 assert(std::format("{:{}.{}f}", pi, 10, 5) == " 3.14000"); // 너비 = 10, 정밀도 = 5 auto b1 = std::format("{:{}f}", pi, 10.0); // 예외 발생: 너비가 정수형이 아님 auto b2 = std::format("{:{}f}", pi, -10); // 예외 발생: 너비가 음수임 auto b3 = std::format("{:.{}f}", pi, 5.0); // 예외 발생: 정밀도가 정수형이 아님
문자열의 너비는 터미널에서 표시하기에 적합한 예상 열 위치 수로 정의됩니다.
너비 계산을 목적으로, 문자열은 구현에서 정의된 인코딩으로 간주됩니다. 너비 계산 방법은 명시되지 않지만, 유니코드 인코딩의 문자열에 대해서는 구현체가 문자열의 너비를 해당 문자열의 확장 자소 클러스터 에서 첫 번째 코드 포인트들의 예상 너비 합으로 추정해야 합니다. 다음 코드 포인트들에 대해서는 예상 너비가 2이며, 그 외의 경우에는 1입니다:
-
유니코드 속성
East_Asian_Width값이 전각(F) 또는 광각(W)인 모든 코드 포인트 - U+4DC0 - U+4DFF (역경 헥사그램 기호)
- U+1F300 – U+1F5FF (기타 기호 및 픽토그램)
- U+1F900 – U+1F9FF (보조 기호 및 픽토그램)
#include <cassert> #include <format> int main() { assert(std::format("{:.^5s}", "🐱") == ".🐱.."); assert(std::format("{:.5s}", "🐱🐱🐱") == "🐱🐱"); assert(std::format("{:.<5.5s}", "🐱🐱🐱") == "🐱🐱."); }
L (로케일별 서식 지정)
L
옵션은 로케일별 형식을 사용하도록 합니다. 이 옵션은 산술 타입에만 유효합니다.
- 정수형(integral types)의 경우, 로케일별 형식은 컨텍스트의 로케일에 따라 적절한 숫자 그룹 구분자 문자를 삽입합니다.
- 부동소수점형(floating-point types)의 경우, 로케일별 형식은 컨텍스트의 로케일에 따라 적절한 숫자 그룹 및 기수 구분자 문자를 삽입합니다.
-
bool의 텍스트 표현의 경우, 로케일별 형식은 std::numpunct::truename 또는 std::numpunct::falsename 으로 얻은 것과 같은 적절한 문자열을 사용합니다.
타입
type 옵션은 데이터가 어떻게 표시되어야 하는지를 결정합니다.
사용 가능한 문자열 표현 유형은 다음과 같습니다:
-
none,
s: 문자열을 출력에 복사합니다.
|
(C++23부터) |
char , wchar_t , 그리고 bool 를 제외한 정수형(integral types)에 사용 가능한 정수 표현 형식(integer presentation types)은 다음과 같습니다:
-
b: 이진 형식. std:: to_chars ( first, last, value, 2 ) 을 호출한 것처럼 출력을 생성합니다. 진법 접두사는0b입니다. -
B:b와 동일하지만, 진법 접두사가0B인 점이 다릅니다. -
c: 문자 static_cast < CharT > ( value ) 을 출력에 복사합니다. 여기서CharT는 형식 문자열의 문자 타입입니다. 값이CharT의 표현 가능한 범위에 있지 않으면 std::format_error 를 발생시킵니다. -
d: 십진 형식. std:: to_chars ( first, last, value ) 을 호출한 것처럼 출력을 생성합니다. -
o: 팔진 형식. std:: to_chars ( first, last, value, 8 ) 을 호출한 것처럼 출력을 생성합니다. 진법 접두사는 해당 인수 값이 0이 아닌 경우0이고, 그렇지 않으면 비어 있습니다. -
x: 십육진 형식. std:: to_chars ( first, last, value, 16 ) 을 호출한 것처럼 출력을 생성합니다. 진법 접두사는0x입니다. -
X:x와 동일하지만, 9보다 큰 숫자에 대문자 알파벳을 사용하고 진법 접두사가0X인 점이 다릅니다. -
지정 없음:
d와 동일합니다.
사용 가능한 char 및 wchar_t 표현 유형은 다음과 같습니다:
-
none,
c: 문자를 출력에 복사합니다. -
b,B,d,o,x,X: 정수 표현 타입을 사용하며 값은 각각 static_cast < unsigned char > ( value ) 또는 static_cast < std:: make_unsigned_t < wchar_t >> ( value ) 입니다.
|
(C++23부터) |
사용 가능한 bool 표현 형식은 다음과 같습니다:
-
none,
s: 텍스트 표현(true또는false, 또는 지역별 형식)을 출력에 복사합니다. -
b,B,d,o,x,X: 값 static_cast < unsigned char > ( value ) 을 사용하여 정수 표현 타입을 사용합니다.
사용 가능한 부동 소수점 표현 유형은 다음과 같습니다:
-
a: precision 이 지정된 경우, 지정된 precision 을 사용하여 std:: to_chars ( first, last, value, std :: chars_format :: hex , precision ) 을 호출한 것처럼 출력을 생성합니다. 그렇지 않으면 std:: to_chars ( first, last, value, std :: chars_format :: hex ) 을 호출한 것처럼 출력을 생성합니다. -
A:a와 동일하지만, 9보다 큰 숫자에 대해 대문자를 사용하고 지수를 나타내기 위해P를 사용합니다. -
e: 지정된 precision 을 사용하여 (지정되지 않은 경우 6) std:: to_chars ( first, last, value, std :: chars_format :: scientific , precision ) 을 호출한 것처럼 출력을 생성합니다. -
E:e와 동일하지만, 지수를 나타내기 위해E를 사용합니다. -
f,F: 지정된 precision 을 사용하여 (지정되지 않은 경우 6) std:: to_chars ( first, last, value, std :: chars_format :: fixed , precision ) 을 호출한 것처럼 출력을 생성합니다. -
g: 지정된 precision 을 사용하여 (지정되지 않은 경우 6) std:: to_chars ( first, last, value, std :: chars_format :: general , precision ) 을 호출한 것처럼 출력을 생성합니다. -
G:g와 동일하지만, 지수를 나타내기 위해E를 사용합니다. - none: precision 이 지정된 경우, 지정된 precision 을 사용하여 std:: to_chars ( first, last, value, std :: chars_format :: general , precision ) 을 호출한 것처럼 출력을 생성합니다. 그렇지 않으면 std:: to_chars ( first, last, value ) 을 호출한 것처럼 출력을 생성합니다.
소문자 표현 형식의 경우, 무한대와 NaN은 각각
inf
와
nan
으로 포맷됩니다.
대문자 표현 형식의 경우, 무한대와 NaN은 각각
INF
와
NAN
으로 포맷됩니다.
| std::format 지정자 | std::chars_format | 해당 std::printf 지정자 |
|---|---|---|
a
,
A
|
std::chars_format::hex |
a
,
A
(단
std::format
은 선행
0x
또는
0X
를 출력하지 않음)
|
e
,
E
|
std::chars_format::scientific |
e
,
E
|
f
,
F
|
std::chars_format::fixed |
f
,
F
|
g
,
G
|
std::chars_format::general |
g
,
G
|
| 없음 | std::chars_format::general (정밀도가 지정된 경우), 그렇지 않으면 최단 라운드트립 형식 |
g
(정밀도가 지정된 경우). 그렇지 않으면 해당 지정자가 없음.
|
사용 가능한 포인터 표현 유형(또한 std::nullptr_t 에 사용됨)은 다음과 같습니다:
-
none,
p: 만약 std::uintptr_t 가 정의되어 있다면, std:: to_chars ( first, last, reinterpret_cast < std:: uintptr_t > ( value ) , 16 ) 를 호출한 것과 같은 출력을 생성하며, 출력 앞에0x접두사를 추가합니다; 그렇지 않으면 출력은 구현에 따라 정의됩니다.
|
(C++26부터) |
이스케이프된 문자와 문자열 형식 지정문자나 문자열은 디버깅이나 로깅에 더 적합하도록 이스케이프된 형식으로 지정될 수 있습니다. 이스케이프는 다음과 같이 수행됩니다:
문자열의 이스케이프된 문자열 표현은 위에서 설명한 대로 문자열의 코드 단위 시퀀스를 이스케이프하고 결과를 큰따옴표로 묶어 구성됩니다. 문자의 이스케이프된 표현은 위에서 설명한 대로 이스케이프하고 결과를 작은따옴표로 묶어 구성됩니다.
이 코드 실행
#include <print> int main() { std::println("[{:?}]", "h\tllo"); // prints: ["h\tllo"] std::println("[{:?}]", "Спасибо, Виктор ♥!"); // prints: ["Спасибо, Виктор ♥!"] std::println("[{:?}] [{:?}]", '\'', '"'); // prints: ['\'', '"'] // The following examples assume use of the UTF-8 encoding std::println("[{:?}]", std::string("\0 \n \t \x02 \x1b", 9)); // prints: ["\u{0} \n \t \u{2} \u{1b}"] std::println("[{:?}]", "\xc3\x28"); // invalid UTF-8 // prints: ["\x{c3}("] std::println("[{:?}]", "\u0301"); // prints: ["\u{301}"] std::println("[{:?}]", "\\\u0301"); // prints: ["\\\u{301}"] std::println("[{:?}]", "e\u0301\u0323"); // prints: ["ẹ́"] } |
(C++23부터) |
참고 사항
대부분의 경우 구문은 기존
%
-포맷팅과 유사하며,
{}
의 추가와 함께
:
가
%
대신 사용됩니다. 예를 들어,
"%03.2f"
는
"{:03.2f}"
로 변환될 수 있습니다.
| 기능 테스트 매크로 | 값 | 표준 | 기능 |
|---|---|---|---|
__cpp_lib_format_uchar
|
202311L
|
(C++20)
(DR) |
코드 유닛의 부호 없는 정수 형식 지정 |
결함 보고서
다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.
| DR | 적용 대상 | 게시된 동작 | 올바른 동작 |
|---|---|---|---|
| LWG 3721 | C++20 |
표준 형식 지정에서 너비 필드에
zero가 허용되지 않음 |
대체 필드를 통해 지정된 경우
zero가 허용됨 |
| P2909R4 | C++20 |
char
또는
wchar_t
가 범위를 벗어난
부호 없는 정수 값으로 포맷될 수 있음 |
해당 부호 없는 타입으로 변환된 후
코드 유닛이 포맷됨 |