1. 하이레벨 숫자 변환
std 네임스페이스는 숫자와 string을 쉽게 변환할 수 있도록 다양한 헬퍼(편의) 함수를 제공한다.
숫자 타입을 string으로 변환하는 함수는 다음과 같다.
<string> 헤더 파일을 불러와야 한다.
- string to_string(int val);
- string to_string(long val);
- string to_string(float val);
- ... 등등
예를 들어 long double 값을 string으로 변환하려면 다음과 같이 작성한다.
long double d = 3.14L;
string s = to_string(d);
이와 반대로 변환하는 함수도 다음과 같이 std 네임스페이스에 정의돼 있다.
이 함수의 프로토타입에서 str은 변환하려는 원본 string 값을 의미하고,
idx는 아직 변환되지 않은 부분의 맨 앞에 있는 문자의 인덱스를 가리키는 포인터고,
base는 변환할 수의 밑(기수, 기저)이다.
idx 포인터를 널 포인터로 지정하면 이 값을 무시한다.
- int stoi(const string& str, size_t *idx=0, int base=10);
- long stol(const string& str, size_t *idx=0, int base=10);
- unsigned long stoul(const string& str, size_t *idx=0, int base=10);
- float stof(const string& str, size_t, *idx=0);
- ... 등등
예를 들면 다음과 같다.
const string toParse = " 123USED";
size_t index = 0;
int value = stoi(toParse, &index);
cout << "Parsed value: " << value << endl;
cout << "First non-parsed character: '" << toParse[index] << "'" << endl;
이 코드의 실행 결과는 다음과 같다.
2. 로우레벨 숫자 변환
C++17부터 로우 레벨 숫자 변환에 대한 함수도 다양하게 제공된다. 이 함수는 <charconv> 헤더에 정의돼 있다.
이 함수는 메모리 할당에 관련된 작업은 전혀 해주지 않기 때문에 호출한 측에서 버퍼를 할당하는 방식으로 사용해야 한다.
정수를 문자로 변환하려면 다음과 같은 함수를 사용한다.
to_chars_result to_chars(char* first, char* last, IntegerT value, int base =10);
여기서 IntegerT 자리에 부호 있는 정수나 부호 없는 정수 또는 char 타입이 나올 수 있다.
결과는 to_chars_result 타입으로 리턴되며, 다음과 같이 정의돼 있다.
struct to_chars_result {
char* ptr;
errc ec;
}
정상적으로 변환됐다면 ptr 멤버는 끝에서 두 번째 문자를 가리키고, 그렇지 않으면 last 값과 같다
예를 들면 다음과 같다.
std::string out(10, ' ');
auto result = std::to_chars(out.data(), out.data() + out.size(), 12345);
if (result.ec == std::errc()) { /* 제대로 변환된 경우 */ }
앞에서 소개한 구조적 바인딩을 적용하면 다음과 같이 표현할 수 있다.
string out(10, ' ');
auto [ptr = ec] = std::to_chars(out.data(), out.data() + out.size(), 12345);
if(ec == std::errc()) { /* 제대로 변환된 경우 */ }
구조적 바인딩 이란?
또한 다음과 같이 부동소수점 타입에 대한 변환 함수도 제공한다.
- to_chars_result to_chars(char* first, char* last, FloatT value);
- to_chars_result to_chars(char* first, char* last, FloatT value, chars_format format);
- to_chars_result to_chars(char* first, char* last, FloatT value, chars_format format, int precision);
여기서 FloatT 자리에 float, double, long double이 나올 수 있다.
구체적인 포맷은 다음과 같이 정의된 chars_format 플래그를 조합해서 지정할 수 있다.
enum class chars_format {
scientific, // 스타일: (-)d.ddde±dd
fixed, // 스타일: (-)ddd.ddd
hex, // 스타일: (-)h, hhhp±d(주의 :0x는 적지 않는다)
general = fixed | scientific // 다음 문단 참조
};
기본 포맷인 chars_format::general을 적용하면 to_chars()는 부동소수점 값을 십진수 표기법인 (-)ddd.ddd와
십진수 지수 표기법인 (-)d.ddde±dd 중에서 소수점 왼쪽에 나오는 숫자를 표기할 때
전체 길이가 가장 짧은 형태로 변환된다.(예: 100.001보다는 1.0e+6 선택)
반대 방향, 즉 스트링을 숫자로 변환하는 함수도 있다.
from_chars_result from_chars(const char* first, const char* last, IntegerT& value, int base = 10_;
from_chars_result from_chars(const char* first, const char* last, FloatT& value,
chars_format format = chars_format::general);
from_chars_result 타입은 다음과 같이 정의돼 있다.
struct from_chars_result {
const char* ptr;
errc ec;
};
여기서 ptr 멤버는 변환에 실패할 경우 첫 번째 문자에 대한 포인터가 되고, 제대로 변환될 때는 last와 같다.
변환된 문자가 하나도 없다면 ptr는 first와 같으며, 에러 코드는 errc::invalid_argment가 된다.
파싱된 값이 너무 커서 지정된 타입으로 표현할 수 없다면 에러 코드의 값은 errc::result_out_of_range가 된다.
from_chars()는 앞에 나온 공백 문자를 무시하지 않는다.
'💻프로그래밍 내용 정리 > C++17' 카테고리의 다른 글
[C++ 7.1.1] 동적 메모리 작동 과정 살펴보기 (0) | 2022.08.22 |
---|---|
[C++ 2.1.4] std::string_view 클래스 (1) | 2022.08.20 |
[C++ 2.1.3-1] C++std::string 클래스, 표준 사용저 정의 리터럴's' (0) | 2022.08.20 |
[C++ 2.1.2] 스트링 리터럴(리터럴 폴링, 로 스트링 리터럴, 확장 로스트링 리터럴) (0) | 2022.08.19 |
[C++ 2.1.1] 동적 스트링(C 스타일 스트링), strlen, strcpy, strcat (0) | 2022.08.19 |