std::string 클래스
C-스타일 문자열은 수동적인 메모리 관리, 버퍼 오버플로우의 위험, 그리고 불편한 연산자 사용 등 여러 가지 한계를 가지고 있었습니다.
이러한 문제점들을 해결하고 문자열 처리를 훨씬 더 안전하고 효율적이며 편리하게 만들기 위해 C++ 표준 라이브러리에서는 std::string
클래스를 제공합니다.
이 장에서는 std::string
이 무엇인지, 어떻게 사용하는지, 그리고 C-스타일 문자열에 비해 어떤 장점을 가지는지 상세히 알아보겠습니다.
std::string
클래스란 무엇인가?
std::string
은 C++ 표준 라이브러리(STL: Standard Template Library)의 일부로 제공되는 문자열 전용 클래스입니다.
이 클래스는 문자열 데이터를 객체 지향적인 방식으로 다룰 수 있게 해주며, C-스타일 문자열의 많은 단점을 보완합니다.
주요 특징
- 동적 크기 조절:
std::string
은 문자열의 길이에 따라 필요한 만큼 자동으로 메모리를 할당하고 해제합니다. 문자열이 길어지면 메모리를 확장하고, 짧아지면 축소하여 효율적으로 관리합니다. 프로그래머가 직접 메모리 크기를 신경 쓸 필요가 없습니다. - 안전한 문자열 처리: 버퍼 오버플로우와 같은 메모리 관련 오류로부터 훨씬 더 안전합니다. 문자열 복사나 이어 붙이기 시에도 자동으로 메모리 크기를 조절하여 안전하게 처리합니다.
- 직관적인 연산자 오버로딩: C-스타일 문자열에서는 사용할 수 없었던 대입 연산자(
=
), 비교 연산자(==
,!=
,<
,>
), 이어 붙이기 연산자(+
,+=
) 등을 문자열 객체에 직접 사용할 수 있습니다. - 풍부한 멤버 함수: 문자열 길이, 검색, 부분 문자열 추출, 삽입, 삭제 등 다양한 문자열 조작을 위한 편리한 멤버 함수들을 제공합니다.
- 객체 지향: 문자열을
char
배열이 아닌 하나의 객체로 다루므로, 객체 지향 프로그래밍 패러다임에 더 잘 맞습니다.
std::string
클래스를 사용하려면 프로그램에 <string>
헤더 파일을 포함해야 합니다.
#include <string> // std::string을 사용하기 위해 포함
std::string
객체 선언 및 초기화
std::string
객체는 일반 변수를 선언하듯이 선언하고 다양한 방법으로 초기화할 수 있습니다.
1. 기본 생성 (빈 문자열)
#include <string>
#include <iostream>
int main() {
std::string s1; // 빈 문자열로 초기화 (길이 0)
std::cout << "s1: " << s1 << std::endl; // 출력: (빈 줄)
std::cout << "s1의 길이: " << s1.length() << std::endl; // 출력: 0
return 0;
}
2. 문자열 리터럴로 초기화
std::string s2 = "Hello C++"; // 가장 일반적인 방법
std::string s3("Another string"); // 괄호 초기화 (생성자 호출)
3. 다른 std::string
객체로 초기화 (복사 초기화)
std::string s4 = s2; // s2의 내용을 s4로 복사
std::string s5(s3); // s3의 내용을 s5로 복사
4. 특정 문자나 문자열의 일부로 초기화
std::string s6(5, 'A'); // 'A' 문자 5개로 초기화 -> "AAAAA"
std::string s7(s2, 6, 3); // s2의 6번 인덱스부터 3개 문자 -> "C++" (s2는 "Hello C++")
std::string
의 기본 연산자 사용
std::string
은 연산자 오버로딩 덕분에 문자열 처리가 매우 직관적입니다.
1. 대입 연산자 (=
): 문자열을 다른 문자열에 할당합니다.
std::string text = "Initial Text";
text = "New Text Value"; // 기존 문자열 덮어쓰기
std::cout << text << std::endl; // 출력: New Text Value
2. 이어 붙이기 (+
, +=
): 문자열을 연결합니다 (concatenation).
std::string str_hello = "Hello";
std::string str_world = "World";
std::string full_string = str_hello + " " + str_world + "!"; // + 연산자로 연결
std::cout << full_string << std::endl; // 출력: Hello World!
str_hello += " Everyone!"; // += 연산자로 기존 문자열에 이어 붙이기
std::cout << str_hello << std::endl; // 출력: Hello Everyone!
3. 비교 연산자 (==
, !=
, <
, <=
, >
, >=
): 문자열의 내용을 사전순으로 비교합니다.
std::string fruit1 = "apple";
std::string fruit2 = "banana";
std::string fruit3 = "apple";
if (fruit1 == fruit3) {
std::cout << "fruit1과 fruit3는 같습니다." << std::endl; // 실행됨
}
if (fruit1 != fruit2) {
std::cout << "fruit1과 fruit2는 다릅니다." << std::endl; // 실행됨
}
if (fruit1 < fruit2) { // "apple"이 "banana"보다 사전적으로 앞섬
std::cout << "fruit1이 fruit2보다 사전적으로 빠릅니다." << std::endl; // 실행됨
}
4. 인덱스 접근 ([]
, .at()
): 특정 위치의 문자에 접근합니다.
std::string my_string = "Example";
std::cout << my_string[0] << std::endl; // 'E' (0번 인덱스 문자)
std::cout << my_string[2] << std::endl; // 'a'
my_string[0] = 'e'; // 문자 변경
std::cout << my_string << std::endl; // 출력: example
// .at() 함수: 범위 검사(range check)를 수행하여 안전한 접근 제공
try {
std::cout << my_string.at(6) << std::endl; // 'e' (유효한 인덱스)
std::cout << my_string.at(10) << std::endl; // 예외 발생 (std::out_of_range)
} catch (const std::out_of_range& e) {
std::cerr << "오류: " << e.what() << std::endl;
}
[]
연산자는 C-스타일 배열처럼 빠른 접근을 제공하지만, 인덱스 범위를 벗어나도 컴파일 에러를 발생시키지 않고 런타임 오류(예: 크래시)로 이어질 수 있습니다..at()
멤버 함수는 인덱스 범위를 검사하여, 유효하지 않은 인덱스에 접근하려 할 경우std::out_of_range
예외를 발생시킵니다. 따라서 더 안전한 접근을 원한다면.at()
을 사용하는 것이 좋습니다.
std::string
의 주요 멤버 함수
std::string
클래스는 문자열 조작을 위한 다양한 유용한 멤버 함수들을 제공합니다.
함수명 | 설명 | 예시 |
---|---|---|
.length() 또는 .size() | 문자열의 길이 (널 문자 제외)를 반환. | myString.length() |
.empty() | 문자열이 비어있는지 (길이가 0인지) 확인. true 또는 false 반환. | if (myString.empty()) |
.append(str) | 문자열 str 을 현재 문자열의 끝에 추가. += 연산자와 유사. | s.append(" World"); |
.insert(pos, str) | pos 위치에 str 을 삽입. | s.insert(6, "great "); |
.erase(pos, len) | pos 위치부터 len 길이만큼 문자열 삭제. | s.erase(0, 5); (앞 5개 문자 삭제) |
.replace(pos, len, str) | pos 위치부터 len 길이만큼을 str 로 교체. | s.replace(0, 5, "Hi"); |
.substr(pos, len) | pos 위치부터 len 길이만큼의 부분 문자열을 새로 생성하여 반환. | std::string sub = s.substr(0, 5); |
.find(str, pos) | str 이 현재 문자열에서 처음 나타나는 인덱스를 pos 부터 검색하여 반환. 없으면 std::string::npos 반환. | s.find("lo") |
.c_str() | std::string 의 내용을 널 종료된 C-스타일 문자열(const char* )로 반환. (C-스타일 함수와 호환성을 위해) | printf("%s", myString.c_str()); |
.clear() | 문자열의 모든 내용을 지우고 빈 문자열로 만듦. | myString.clear(); |
#include <iostream>
#include <string> // std::string을 위해
#include <cstdio> // printf를 위해 (c_str() 사용 예시)
int main() {
std::string text = "Programming in C++ is fun.";
// 길이와 비어있는지 확인
std::cout << "길이: " << text.length() << std::endl; // 27
std::cout << "비어있는가? " << std::boolalpha << text.empty() << std::endl; // false
// 부분 문자열 추출
std::string sub = text.substr(14, 5); // 14번 인덱스부터 5글자 ("C++ i")
std::cout << "부분 문자열: " << sub << std::endl; // C++ is
// 문자열 검색
size_t pos_cpp = text.find("C++");
if (pos_cpp != std::string::npos) { // 찾지 못하면 npos 반환
std::cout << "'C++' 발견 위치: " << pos_cpp << std::endl; // 14
}
// 문자열 삽입
text.insert(10, "with "); // 10번 인덱스에 "with " 삽입
std::cout << "삽입 후: " << text << std::endl; // Programming with in C++ is fun.
// 문자열 교체
text.replace(0, 11, "Coding"); // 0번부터 11글자를 "Coding"으로 교체
std::cout << "교체 후: " << text << std::endl; // Coding with in C++ is fun.
// C-스타일 문자열로 변환 (필요 시)
const char* c_str_ptr = text.c_str();
printf("C-스타일 문자열로 출력: %s\n", c_str_ptr);
// 문자열 지우기
text.clear();
std::cout << "지운 후 길이: " << text.length() << std::endl; // 0
std::cout << "지운 후 비어있는가? " << text.empty() << std::endl; // true
return 0;
}
C-스타일 문자열과 std::string
의 변환
-
C-스타일 문자열을
std::string
으로:std::string
은 C-스타일 문자열 리터럴이나char*
포인터를 인자로 받는 생성자를 제공하므로, 직접 대입하거나 생성 시 인자로 넘겨주면 됩니다.C-스타일 문자열을 std::string으로 변환 const char* c_str_data = "Hello from C-style!"; std::string s = c_str_data; // 자동 변환 std::string s_another(c_str_data); // 생성자 호출
-
std::string
을 C-스타일 문자열로:std::string
객체의 내용을 C-스타일 문자열(const char*
)로 얻으려면.c_str()
멤버 함수를 사용합니다. 이 함수는 문자열의 널 종료된 내부 버퍼에 대한 포인터를 반환합니다. 이 포인터는std::string
객체가 살아있는 동안에만 유효하며,std::string
객체가 변경되거나 소멸되면 무효화될 수 있습니다.std::string을 C-스타일 문자열로 변환 std::string my_cpp_string = "This is C++ string."; const char* my_c_string = my_cpp_string.c_str(); // const char*로 변환 std::cout << my_c_string << std::endl; // 출력: This is C++ string.
결론: std::string
사용의 강력한 권장
C++에서 문자열을 다룰 때는 특별한 C 언어와의 호환성 요구사항이 없는 한, 반드시 std::string
클래스를 사용하는 것이 좋습니다.
std::string
은 C-스타일 문자열이 가진 모든 단점을 보완하고, 훨씬 더 안전하고 편리하며 효율적인 문자열 처리 기능을 제공합니다.
현대 C++ 프로그래밍에서 std::string
은 문자열을 다루는 표준이자 최선의 방법입니다.