이이프
IeF 제멋대로 세상
이이프
전체 방문자
오늘
어제

공지사항

  • ✔ Info
  • 전체 글보기 (56)
    • 💻프로그래밍 내용 정리 (55)
      • C (0)
      • C++17 (55)
    • 💻게임메이커 (0)
    • 💻언리얼엔진 (0)
    • 💻유니티 (0)
    • 🎈[팀&자작]게임소개 (0)
    • 📃게임제작기술 (0)
    • 🎨그림놀이 (0)
    • 📒대학생활 (0)
    • 😃잡담 (1)
    • 🕹게임성과 (0)
    • 💷자격증 (0)

블로그 메뉴

  • 방명록

최근 글

최근 댓글

티스토리

hELLO · Designed By 정상우.
이이프

IeF 제멋대로 세상

[C++ 2.1.3-2] 하이레벨 숫자 변환(to_string, stoi), 로우레벨 숫자 변환(to_chars, from_chars)
💻프로그래밍 내용 정리/C++17

[C++ 2.1.3-2] 하이레벨 숫자 변환(to_string, stoi), 로우레벨 숫자 변환(to_chars, from_chars)

2022. 8. 20. 20:38
728x90

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()) { /* 제대로 변환된 경우 */ }

구조적 바인딩 이란?

https://iefef.tistory.com/16

 

또한 다음과 같이 부동소수점 타입에 대한 변환 함수도 제공한다.

- 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
    '💻프로그래밍 내용 정리/C++17' 카테고리의 다른 글
    • [C++ 7.1.1] 동적 메모리 작동 과정 살펴보기
    • [C++ 2.1.4] std::string_view 클래스
    • [C++ 2.1.3-1] C++std::string 클래스, 표준 사용저 정의 리터럴's'
    • [C++ 2.1.2] 스트링 리터럴(리터럴 폴링, 로 스트링 리터럴, 확장 로스트링 리터럴)
    이이프
    이이프
    게임 프로그래머 지망생 / Since 2022.08.14

    티스토리툴바