#9. [모던 C++ STL] 문자열
- (C++11~) u16string이 추가되어 UTF-16 인코딩 문자열을 지원합니다.
 - (C++11~) u32string이 추가되어 UTF-32 인코딩 문자열을 지원합니다.
 - (C++11~) isblank()가 추가되었습니다.
 - (C++11~) atoll(), strtoll(), strtoull(), strtoimax(), strtoumax()가 추가되었습니다.
 - (C++11~) mbrtoc16(), mbrtoc32(), c32rtomb()가 추가되었습니다.
 - (C++11~)
 __STDC_UTF_16__,__STDC_UTF_32__가 추가되었습니다.- (C++11~) 숫자 변환이 추가되었습니다.
 - (C++17~) 숫자와 문자열간의 변환을 위한 to_chars(), from_chars() 함수가 제공되며, 기존 C스타일(atoi(), strtol()등) 보다 안전합니다.
 - (C++17~) chars_format이 추가되었습니다.
 - (C++20~) u8string이 추가되어 UTF-8 인코딩 문자열을 지원합니다.
 - (C++20~) starts_with(), ends_with()가 추가되어 접두사와 접미사를 검사할 수 있습니다.
 - (C++20~) mbrtoc8(), c8rtomb()가 추가되었습니다.
 
개요
문자열을 처리하는 기본 클래스는 basic_string입니다. char_traits를 사용하여 각 문자 타입별로 문자열을 처리합니다.
| 항목 | 내용 | 
|---|---|
| basic_string | 문자열의 기본 클래스입니다. | 
char_traits | 
      basic_string에서 각 문자를 처리하는 타입 특성입니다. | 
basic_string은 각 타입 별로 별칭을 사용합니다.
| 항목 | 내용 | 정의 | 
|---|---|---|
| string | 바이트 문자열 | basic_string<char> | 
    
| wstring | 와이드 문자열 | basic_string<wchar_t> | 
    
| u16string (C++11~) | UTF-16 인코딩 문자열 | basic_string<char16_t> | 
    
| u32string (C++11~) | UTF-32 인코딩 문자열 | basic_string<char32_t> | 
    
| u8string (C++20~) | UTF-8 인코딩 문자열 | basic_string<char8_t> | 
    
C++11 부터 UTF-16 인코딩을 지원하는 u16string과 UTF-32 인코딩을 지원하는 u32string이 추가되었습니다. 각 요소당 문자 1개를 저장합니다.
1
2
3
4
5
6
7
8
9
std::u16string u16str{u"abc가나다"};
EXPECT_TRUE(u16str == u"abc가나다");
EXPECT_TRUE(u16str.length() == 6);
EXPECT_TRUE(u16str[3] == u'가'); // 각 요소는 문자 1개 입니다.
std::u32string u32str{U"abc가나다"};  
EXPECT_TRUE(u32str == U"abc가나다");
EXPECT_TRUE(u32str.length() == 6);
EXPECT_TRUE(u32str[3] == U'가'); // 각 요소는 문자 1개 입니다. 
Windows의 경우 와이드 문자열은 내부적으로 UTF-16 인코딩으로 저장되므로(와이드 문자열 참고), u16string과 동일한 코드값을 가지고 있습니다.(Linux는 와이드 문자열이 UTF-32 인코딩을 사용하므로 u32string과 같을 겁니다. 확인해 보지는 않았습니다.)
1
2
3
std::wstring wstr{L"abc가나다"}; // windows에서는 와이드 문자열이 UTF-16으로 저장됩니다.
std::u16string u16str{reinterpret_cast<const char16_t*>(wstr.c_str())}; // 강제적으로 형변환하면 UTF-16과 동일한 형태로 저장되어 있습니다.
EXPECT_TRUE(u16str == u"abc가나다");
C++20 부터는 UTF-8 인코딩을 사용하는 u8string이 추가되었습니다.
wstring, u16string, u32string은 요소 1개당 문자 1개를 저장하지만, u8string은 그렇지 않습니다.
UTF-8 인코딩에서는 문자의 종류에 따라 1 ~ 4byte를 사용하며, 문자가 한글과 같이 3yte인 경우에는 char8_t 타입(적어도 1byte)인 요소 3개로 저장합니다. 따라서 length()가 문자의 갯수가 아니라 byte의 갯수가 됩니다.
1
2
3
4
5
6
7
std::u8string u8str{u8"abc가나다"}; 
EXPECT_TRUE(u8str == u8"abc가나다"); 
EXPECT_TRUE(u8str.length() == 12); // UTF8에서 영문자는 1byte, 한글은 3byte입니다. 한글 1글자를 3개로 처리합니다.
                                   // abc : 3byte, 가 : 3byte, 나 : 3byte, 다 : 3byte
EXPECT_TRUE(u8str[3] == 0xEA); // 한글 '가'는 UTF-8에서 3byte. 0xEA, 0xB0, 0x80
EXPECT_TRUE(u8str[4] == 0xB0);
EXPECT_TRUE(u8str[5] == 0x80);
(C++14~) 표준 사용자 정의 리터럴이 추가되어
operator ""s,operator ""min,operator ""if, 등 문자열, 날짜 / 시간, 복소수 관련 표현이 간편해 졌습니다.
basic_string
대부분 vector와 동일하며, string에 필요한 기능이 추가되었습니다.(basic_string의 멤버 함수들의 자세한 사용 방법은 레거시 C++ STL의 문자열을 참고하시기 바랍니다.)
정적 멤버 변수
| 항목 | 내용 | 
|---|---|
npos | 
      “찾을 수 없음”이나 “나머지 모든 문자”를 나타내는 의미로 사용합니다. | 
1
static const size_type npos = -1;
생성자
| 항목 | 내용 | 
|---|---|
basic_string() | 
      빈 string 개체를 생성합니다. | 
basic_string(const string& other) | 
      복사 생성합니다. | 
basic_string(const value_type* ptr) | 
      C 언어 스타일의 문자열로부터 문자들을 복사하여 string 개체를 생성합니다. | 
basic_string(const string& other, size_type, offset, size_type count = npos)basic_string(const value_type* ptr, size_type count) | 
      offset 위치 부터 count 갯수만큼 문자들을 복사하여 string개체를 생성합니다. | 
    
basic_string(size_type count, value_type char_value) | 
      char_value를 count만큼 채운string을 생성합니다. | 
    
basic_string(const_iterator first, const_iterator last) | 
      first부터 last 직전까지의 요소(반개방 구조)를 복사하여 string 개체를 생성합니다. | 
    
연산자
| 항목 | 내용 | 
|---|---|
operator =(const basic_stiring& other) | 
      other를 복사 대입합니다. | 
    
operator =(const basic_stiring&& other) noexcept (C++11~) | 
      other를 이동 대입합니다. | 
    
+ | 
      두 문자열을 연결하여 새로운 문자열을 만듭니다. | 
+= | 
      문자열에 문자나 문자열을 추가합니다. | 
==!= (~C++20) | 
      두 문자열이 같은지, 다른지 검사합니다. 단순히 포인터 비교하는게 아니라 실제 문자들을 비교합니다. | 
<, <=, >, >= (~C++20)<=> (C++20~) | 
      두 문자열을 대소 비교합니다. | 
<<, >> | 
      출력 스트림에 출력하거나, 입력 스트림에서 문자열을 추출합니다. | 
할당과 문자열 관리
| 항목 | string 특화 | 내용 | 
|---|---|---|
| assign() | string의 기존 내용을 지우고 새로운 문자열을 복사합니다. | |
assign_range() (C++11~) | 
      (작성중) | |
get_allocator() (C++23~) | 
      (작성중) | |
resize() | 
      string의 새 크기를 지정하며, 필요에 따라 문자를 추가하거나 지웁니다. | |
| size() length()  | 
      O | string의 문자 갯수를 리턴합니다. string에서는 length를 추가로 제공합니다. | 
    
| empty() | string이 비었는지 확인합니다. | |
| capacity() | 메모리를 더 할당하지 않고 string에 저장할 수 있는 문자 갯수를 리턴합니다.(string은 vector와 동일하게 메모리 할당이 빈번히 발생하지 않도록 실제 문자 갯수보다 큰 크기를 할당하기도 하고, 삽입/삭제에 따라 실제 문자 갯수보다 더 많은 메모리를 관리할 수 있습니다.) | |
shrink_to_fit() | 
      (작성중) | |
| reserve() | string의 메모리 공간을 최소한 count 갯수 만큼 문자를 저장할 수 있도록 예약합니다. | 
    |
max_size() | 
      string이 저장할 수 있는 최대 문자 갯수를 리턴합니다. | |
swap() | 
      두 string의 내부 데이터를 바꿔치기 합니다. | 
문자 검색
| 항목 | string 특화 | 내용 | 
|---|---|---|
[] | 
      요소에 접근합니다. | |
| at() | position위치의 요소 참조자를 리턴합니다. position이 잘못된 위치이면 [] 과 달리 예외가 발생하며, 검사 코드가 추가되어 상대적으로 속도 부하가 있습니다. | 
    |
begin(), end() | 
      순방향 이터레이터를 리턴합니다. | |
rbegin(), rend() | 
      역방향 이터레이터를 리턴합니다. | |
cbegin(), cend() | 
      순방향 이터레이터를 리턴합니다. 이때 요소를 수정할 수 없습니다. | |
crbegin() crend() | 
      역방향 이터레이터를 리턴합니다. 이때 요소를 수정할 수 없습니다. | |
| data() | 컨테이너가 관리하는 메모리 블록을 리턴합니다. STL 구현에 따라 끝에 널문자(정수 0인 문자, '\0')가 있을 수도 있지만, 표준이 아니기 때문에 널종료 문자열을 구할 때는 c_str()을 이용해야 합니다. | 
    |
| c_str() | O | c 스타일의 널종료 문자열을 리턴합니다.(끝에 널문자(정수 0인 문자, '\0')가 있습니다.) | 
    
front() | 
      첫번째 요소의 참조자를 리턴합니다. string이 비었다면 아무 생각없이 실행되어 오동작 합니다. | |
back() | 
      마지막 요소의 참조자를 리턴합니다. string이 비었다면 아무 생각없이 실행되어 오동작 합니다. | |
find()rfind() | 
      O | 지정된 문자 시퀀스와 일치하는 첫번째 인덱스를 찾습니다. | 
find_first_of()find_first_not_of() | 
      O | 지정된 문자들중 일치하는 문자가 있는 첫번째 인덱스를 찾습니다. | 
find_last_of()find_last_not_of() | 
      O | 지정된 문자들중 일치하는 문자가 있는 마지막 인덱스를 찾습니다. | 
operator basic_string_view() (C++17~) | 
      O | (작성중) | 
요소 삽입/삭제/비교/추출
| 항목 | string 특화 | 내용 | 
|---|---|---|
| clear() | 모든 요소를 지웁니다. 이때 메모리 영역은 그대로 입니다. | |
| erase() | position위치의 요소를 삭제하거나 first와 last 직전까지의 요소(반개방 구조)를 삭제합니다. 이터레이터가 유효하지 않다면, 아무 생각없이 실행되어 오동작 합니다. | 
    |
erase_if() (C++20~) | 
      (작성중) | |
pop_back() | 
      마지막 요소를 삭제합니다. string이 비었다면 아무 동작 안합니다. | |
| push_back() | string끝에 요소를 추가합니다. | |
| insert() | position으로 지정한 위치 앞에 삽입합니다. | 
    |
insert_range() (C++23~) | 
      (작성중) | |
| append() | O | 문자열에 문자나 문자열을 추가합니다. | 
append_range() (C++23~) | 
      (작성중) | |
| compare() | O | 문자열을 대소 비교합니다. | 
| starts_with() (C++20~) | O | 주어진 부분 문자열로 시작하는지 검사합니다. | 
| ends_with() (C++20~) | O | 주어진 부분 문자열로 끝나는지 검사합니다. | 
contains() (C++23~) | 
      O | (작성중) | 
| replace() | O | string의 요소를 지정한 문자나 다른 시퀀스로 바꿉니다. | 
replace_with_range() (C++23~) | 
      O | (작성중) | 
| substr() | O | string에서 부분 문자열을 복사하여 리턴합니다. | 
| copy() | O | string에서 부분 문자열을 문자 배열에 복사합니다. | 
getline() | 
      O | IO 스트림으로부터 데이터를 읽습니다. | 
C스타일 문자열 함수
문자 분류
| 바이트 문자열 | 와이드 문자열 | 내용 | 
|---|---|---|
isalnum() | 
      iswalnum() | 
      (작성중) | 
isalpha() | 
      iswalpha() | 
      (작성중) | 
islower() | 
      iswlower() | 
      (작성중) | 
islower() | 
      iswupper() | 
      (작성중) | 
isupper() | 
      (작성중) | |
isdigit() | 
      iswdigit() | 
      (작성중) | 
isxdigit() | 
      iswxdigit() | 
      (작성중) | 
iscntrl() | 
      iswcntrl() | 
      (작성중) | 
isgraph() | 
      iswgraph() | 
      (작성중) | 
isspace() | 
      iswspace() | 
      (작성중) | 
isblank() (C++11~) | 
      iswblank() (C++11~) | 
      (작성중) | 
isprint() | 
      iswprint() | 
      (작성중) | 
ispunct() | 
      iswpunct() | 
      (작성중) | 
iswctype() | 
      (작성중) | |
wctype() | 
      (작성중) | |
locale() | 
      (작성중) | 
문자 조작
| 바이트 문자열 | 와이드 문자열 | 내용 | 
|---|---|---|
tolower() | 
      towlower() | 
      (작성중) | 
toupper() | 
      towupper() | 
      (작성중) | 
towctrans() | 
      (작성중) | |
wctrans() | 
      (작성중) | 
문자열 조작
| 바이트 문자열 | 와이드 문자열 | 내용 | 
|---|---|---|
strcpy() | 
      wcscpy() | 
      (작성중) | 
strncpy() | 
      wcsncpy() | 
      (작성중) | 
strcat() | 
      wcscat() | 
      (작성중) | 
strncat() | 
      wcsncat() | 
      (작성중) | 
strxfrm() | 
      wcsxfrm() | 
      (작성중) | 
문자열 검사
| 바이트 문자열 | 와이드 문자열 | 내용 | 
|---|---|---|
strlen() | 
      wcslen() | 
      (작성중) | 
strcmp() | 
      wcscmp() | 
      (작성중) | 
strncmp() | 
      wcsncmp() | 
      (작성중) | 
strcoll() | 
      wcscoll() | 
      (작성중) | 
strchr() | 
      wcschr() | 
      (작성중) | 
strrchr() | 
      wcsrchr() | 
      (작성중) | 
strspn() | 
      wcsspn() | 
      (작성중) | 
strcspn() | 
      wcscspn() | 
      (작성중) | 
strpbrk() | 
      wcspbrk() | 
      (작성중) | 
strstr() | 
      wcsstr() | 
      (작성중) | 
strtok() | 
      wcstok() | 
      (작성중) | 
메모리 조작
| 바이트 문자열 | 와이드 문자열 | 내용 | 
|---|---|---|
memchr() | 
      wmemchr() | 
      (작성중) | 
memcmp() | 
      wmemcmp() | 
      (작성중) | 
memset() | 
      wmemset() | 
      (작성중) | 
| memcpy() | wmemcpy() | 
      (작성중) | 
memmove() | 
      wmemmove() | 
      (작성중) | 
숫자 포맷
| 바이트 문자열 | 와이드 문자열 | 내용 | 
|---|---|---|
atof() | 
      (작성중) | |
atoi()atol()atoll() (C++11~) | 
      (작성중) | |
strtol()strtoll() (C++11~) | 
      wcstol()wcstoll() | 
      (작성중) | 
strtoul()strtoull() (C++11~) | 
      wcstoul()wcstoull() | 
      (작성중) | 
strtof()strtod()strtold() | 
      wcstof()wcstod()wcstold() | 
      (작성중) | 
strtoimax() (C++11~)strtoumax() (C++11~) | 
      wcstoimax() (C++11~)wcstoumax() (C++11~) | 
      (작성중) | 
와이드 문자열
타입
| 항목 | 내용 | 
|---|---|
wctrans_t | 
      (작성중) | 
wctype_t | 
      (작성중) | 
wint_t | 
      (작성중) | 
매크로
| 항목 | 내용 | 
|---|---|
WEOF | 
      (작성중) | 
WCHAR_MIN | 
      (작성중) | 
WCHAR_MAX | 
      (작성중) | 
멀티 바이트
다국어 처리는 와이드 문자열, UTF-16 인코딩 문자열, UTF-32 인코딩 문자열, UTF-8 인코딩 문자열을 사용하면 되므로 멀티 바이트를 사용할 일은 별로 없습니다. 비권고되기도 하고요. 이제 구버전 호환 용도 정도로만 사용하면 될 듯 하네요.(사용법은 멀티바이트 문자열을 참고하시기 바랍니다.)
멀티 바이트 문자열과 와이드 문자열간 변환
| 항목 | 내용 | 
|---|---|
| mblen(str) | str 주소의 멀티 바이트 문자가 몇 바이트 크기인지 구합니다. | 
    
mbtowc() | 
      멀티 바이트 문자를 와이드 문자로 변환합니다. | 
wctomb() | 
      와이드 문자를 멀티 바이트 문자로 변환합니다. | 
| mbstowcs() | 멀티 바이트 문자열를 와이드 문자열로 변환합니다. | 
wcstombs() | 
      와이드 문자열을 멀티 바이트 문자열로 변환합니다. | 
mbsinit() | 
      (작성중) | 
btowc() | 
      (작성중) | 
wctob() | 
      (작성중) | 
mbrlen() | 
      멀티 바이트 문자가 몇 바이트 크기인지 구합니다. 이때 mbstate_t를 이용하여, 멀티 바이트 문자의 변환 상태를 저장하고 사용합니다. | 
    
mbrtowc() | 
      mbtowc()와 같습니다. 이때 mbstate_t를 이용하여, 멀티 바이트 문자의 변환 상태를 저장하고 사용합니다. | 
    
wcrtomb() | 
      wctomb()와 같습니다. 이때 mbstate_t를 이용하여, 멀티 바이트 문자의 변환 상태를 저장하고 사용합니다. | 
    
mbsrtowcs() | 
      mbstowcs()와 같습니다. 이때 mbstate_t를 이용하여, 멀티 바이트 문자의 변환 상태를 저장하고 사용합니다. | 
    
wcsrtombs() | 
      wcstombs()와 같습니다. 이때 mbstate_t를 이용하여, 멀티 바이트 문자의 변환 상태를 저장하고 사용합니다. | 
    
mbrtoc16() (C++11~) | 
      멀티 바이트 문자를 UTF-16 인코딩 문자로 변환합니다. 이때 mbstate_t를 이용하여, 멀티 바이트 문자의 변환 상태를 저장하고 사용합니다. | 
    
c16rtomb() (C++11~) | 
      UTF-16 인코딩 문자를 멀티 바이트 문자로 변환합니다. 이때 mbstate_t를 이용하여, 멀티 바이트 문자의 변환 상태를 저장하고 사용합니다. | 
    
mbrtoc32() (C++11~) | 
      멀티 바이트 문자를 UTF-32 인코딩 문자로 변환합니다. 이때 mbstate_t를 이용하여, 멀티 바이트 문자의 변환 상태를 저장하고 사용합니다. | 
    
c32rtomb() (C++11~) | 
      UTF-32 인코딩 문자를 멀티 바이트 문자로 변환합니다. 이때 mbstate_t를 이용하여, 멀티 바이트 문자의 변환 상태를 저장하고 사용합니다. | 
    
mbrtoc8() (C++20~) | 
      멀티 바이트 문자를 UTF-8 인코딩 문자로 변환합니다. 이때 mbstate_t를 이용하여, 멀티 바이트 문자의 변환 상태를 저장하고 사용합니다. | 
    
c8rtomb() (C++20~) | 
      UTF-8 인코딩 문자를 멀티 바이트 문자로 변환합니다. 이때 mbstate_t를 이용하여, 멀티 바이트 문자의 변환 상태를 저장하고 사용합니다. | 
    
타입
| 항목 | 내용 | 
|---|---|
mbstate_t | 
      (작성중) | 
매크로
| 항목 | 내용 | 
|---|---|
MB_LEN_MAX | 
      (작성중) | 
| MB_CUR_MAX | 현재 locale()에서 멀티 바이트 문자의 최대 크기입니다. | 
__STDC_UTF_16__ (C++11~) | 
      (작성중) | 
__STDC_UTF_32__ (C++11~) | 
      (작성중) | 
strerror()
errorno를 문자열로 출력해 줍니다.
(C++11~) 숫자 변환
| 항목 | 내용 | 
|---|---|
stoi(), stol(), stoll() (C++11~) | 
      부호 있는 정수를 문자열로 바꿉니다. | 
stoul(), stoull() (C++11~) | 
      부호 없는 정수를 문자열로 바꿉니다. | 
stof(), stod(), stold() (C++11~) | 
      실수를 문자열로 바꿉니다. | 
to_string() (C++11~) | 
      string을 정수 또는 실수로 바꿉니다. | 
to_wstring() (C++11~) | 
      wstring을 정수 또는 실수로 바꿉니다. | 
(C++17~) 숫자/문자열 변환
C++17 부터 숫자와 문자열간의 변환을 위한 to_chars(), from_chars() 함수가 제공되며, 기존 C스타일(atoi(), strtol()등) 보다 안전합니다.
| 항목 | 내용 | 
|---|---|
| to_chars() (C++17~) | 정수, 실수를 문자열로 변환합니다. | 
to_chars_result (C++17~) | 
      to_chars()의 리턴값입니다. 변환된 문자열을 끝 포인터(ptr)와 에러 코드(ec, errc 타입)로 구성됩니다. | 
    
| from_chars() (C++17~) | 문자열을 정수, 실수로 변환합니다. | 
from_chars_result (C++17~) | 
      from_chars()의 리턴값입니다. 인자로 전달된 문자열에서 숫자로 해석할 수 없는 위치(ptr)와 에러 코드(ec, errc 타입)로 구성됩니다. | 
    
chars_format (C++17~) | 
      scientific, fixed, hex, general(fixed 와 scientific) 옵션을 제공합니다. | 
    
to_char()와 from_char()는 데이터와 에러 코드를 함께 리턴하는데요, 구조화된 바인딩을 사용하면 좀더 간결하게 코딩할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
char buf[10];
{      
    // 11을 10진수 문자열로 변환    
    auto [ptr, ec]{std::to_chars(buf, buf + sizeof(buf), 11, 10)}; // 구조화된 바인딩. std::to_chars_result result{std::to_chars()} 와 동일
    if (ec == std::errc{}) {
        EXPECT_TRUE(std::string(buf, ptr - buf) == "11");
    }
}
{
    // 11을 16진수 문자열로 변환
    auto [ptr, ec]{std::to_chars(buf, buf + sizeof(buf), 11, 16)};
    EXPECT_TRUE(std::string(buf, ptr - buf) == "b");
}
{
    char str[]{"11year"}; // 숫자와 일반 문자로 구성됩니다.
    int result{0};
    auto [ptr, ec]{std::from_chars(str, str + sizeof(str), result)};
    if (ec == std::errc{}) {
        EXPECT_TRUE(result == 11); // 숫자 부분만 잘 변환합니다.
    }
    EXPECT_TRUE(ptr == &str[2]); // ptr은 숫자 다음 위치입니다. 즉, 'y' 위치입니다.
}
댓글남기기