Language/C++

📌 Chapter 11 - string

e-cko 2025. 10. 11. 20:28
반응형
반응형

1. string 클래스

  • string C++ 표준 라이브러리에서 제공하는 문자열 처리 클래스이다.
  • 문자열을 사용하기 위해서는 반드시 **#include <string>**을 포함해야 한다.
  • 문자열을 객체로 다루므로, C 언어의 char 배열보다 훨씬 직관적이고 안전하다.
  • 주요 특징
    ·
    문자열 결합: + 연산자로 문자열을 합칠 수 있다.
    ·
    문자열 누적: += 연산자로 기존 문자열에 이어 붙일 수 있다.
    ·
    비교 연산자 지원: ==, !=, <, > 연산으로 문자열 비교가 가능하다.
    ·
    대입 연산자 지원: =를 사용하여 문자열을 쉽게 복사할 수 있다.
    ·
    길이 확인: .size() 또는 .length() 멤버 함수를 사용한다.

예시

string a = "hello";

string b = "world";

string c = a + b;   // "helloworld"

⚠️ 주의

  • string은 객체이므로 C 스타일 문자열(char*)과 달리 포인터 연산을 직접 사용할 수 없다.
  • 문자열의 끝을 '\0'으로 관리하는 방식은 내부적으로 처리되므로, 사용자가 신경 쓸 필요가 없다.

💻 표준 string 클래스 사용 예제

#include <iostream>

#include <string> // 표준 string 클래스 사용

using namespace std;

 

int main() {

    string str1 = "apple";     // "apple"로 초기화

    string str2 = "banana";    // "banana"로 초기화

 

    string str3 = str1 + str2; // "applebanana"

    cout << "str3: " << str3 << endl;

 

    str1 += str2;              // str1 "applebanana"

    cout << "str1: " << str1 << endl;

 

    if (str1 == str3) {

        cout << "str1 str3는 같다." << endl;

    } else {

        cout << "str1 str3는 다르다." << endl;

    }

 

    return 0;

}

실행 결과

str3: applebanana

str1: applebanana

str1 str3는 같다.


2. 사용자 정의 String 클래스

  • 경우에 따라 표준 string 클래스 대신 직접 구현한 사용자 정의 String 클래스를 사용할 수 있다.
  • 보통 표준 클래스와 구분하기 위해 첫 글자를 대문자(String) 으로 작성한다.
  • 구현 시 필수 구성 요소
    ·
    생성자: 문자열을 인자로 받아 객체를 초기화한다.
    ·
    소멸자: 동적 할당된 메모리를 해제한다.
    ·
    복사 생성자: 깊은 복사를 통해 새로운 객체를 생성한다.
    ·
    대입 연산자 오버로딩(=): 객체 간 대입 시 얕은 복사가 아닌 깊은 복사가 이루어지도록 한다.
    · +
    연산자 오버로딩: 문자열을 결합할 수 있도록 한다.

반드시 고려할 점
1️
문자열의 길이는 가변적이므로 **동적 메모리 할당(new, delete)**을 사용해야 한다.
2️
단순히 포인터를 복사하면 얕은 복사(shallow copy) 문제가 발생한다.
3️
메모리 해제 시 중복 해제(double free) 오류가 발생하지 않도록 소멸자를 정의해야 한다.


💻 사용자 정의 String 클래스 예제

#include <iostream>

#include <cstring> // strlen, strcpy 사용

using namespace std;

 

class String {

private:

    char* data;   // 문자열을 저장할 동적 메모리

    int length;   // 문자열 길이

 

public:

    // 생성자

    String(const char* str = "") {

        length = strlen(str);

        data = new char[length + 1]; // '\0' 공간 포함

        strcpy(data, str);

    }

 

    // 복사 생성자 (깊은 복사)

    String(const String& other) {

        length = other.length;

        data = new char[length + 1];

        strcpy(data, other.data);

    }

 

    // 대입 연산자 오버로딩

    String& operator=(const String& other) {

        if (this != &other) { // 자기 자신에 대한 대입 방지

            delete[] data; // 기존 메모리 해제

            length = other.length;

            data = new char[length + 1];

            strcpy(data, other.data);

        }

        return *this;

    }

 

    // + 연산자 오버로딩 (문자열 결합)

    String operator+(const String& other) const {

        int newLen = length + other.length;

        char* newData = new char[newLen + 1];

        strcpy(newData, data);

        strcat(newData, other.data);

        String temp(newData);

        delete[] newData; // 임시 버퍼 해제

        return temp;

    }

 

    // 소멸자

    ~String() {

        delete[] data;

    }

 

    // 출력 함수

    void print() const {

        cout << data << endl;

    }

};

 

int main() {

    String s1("apple");

    String s2("banana");

    String s3 = s1 + s2; // applebanana

 

    cout << "s1: "; s1.print();

    cout << "s2: "; s2.print();

    cout << "s3: "; s3.print();

 

    return 0;

}

실행 결과

s1: apple

s2: banana

s3: applebanana


마무리 정리

1️ string 클래스는 <string>에 정의되어 있으며, 문자열 결합, 비교, 대입, 길이 확인 등을 지원한다.
2️
string은 객체이므로, C 스타일 문자열과 달리 포인터 연산을 직접 사용할 수 없다.
3️
사용자 정의 String 클래스를 구현할 때는 생성자, 소멸자, 복사 생성자, 대입 연산자, + 연산자 오버로딩을 반드시 작성해야 한다.
4️
문자열은 가변적이므로 동적 메모리 관리가 핵심이며, 얕은 복사로 인한 오류를 방지해야 한다.

반응형