코드 설명 : 문자열을 다루기 위한 MyString 클래스를 정의하고 사용하는 방법
MyString()
{
cout << "MyString()" << endl;
size_ = 1;
str_ = new char[size_];
}
MyString(const char *init_str)
{
cout << "MyString(const char *init_str)" << endl;
// 1. 글자 수 먼저 확인
size_ = 0; // 글자수를 size에 저장
while (init_str[size_] != '\0')
{
size_++;
}
// 2. 글자 수가 0이 아니면 메모리 할당
if (size_ > 0)
{
str_ = new char[size_]; // 동적할당으로 딱 받을만큼만 받고있음
}
// 3. 복사 (글자 개수만큼만 복사, 사이즈를 알고있기 때문에 널캐릭터를 복사하지 않아도된다)
for (int i = 0; i < size_; i++)
{
str_[i] = init_str[i];
}
// memcpy() 사용 가능
}
~MyString()
{
cout << "Destructor" << endl;
size_ = 0;
// 만약 동적할당 받은 메모리가 있다면, 메모리가 0이 아니라면 메모리를 반납!
if (str_)
delete[] str_;
}
void Resize(int new_size) // 새로운 사이즈가 입력으로 들어오면
{
char *new_str = new char[new_size]; // 새로 할당을 받고
// memcpy() 사용 가능 // 원래갖고있던 데이터를 복사하고
for (int i = 0; i < (new_size < size_ ? new_size : size_); i++)
{
new_str[i] = str_[i];
}
// 기존 데이터를 삭제
delete[] str_;
str_ = new_str;
size_ = new_size;
}
void Print()
{
for (int i = 0; i < size_; i++)
{
cout << str_[i];
// 한글자한글자 일일히 출력해야함. 마지막에 널 캐릭터가 항상 들어있다는 보장이 없기 때문에
}
cout << endl;
}
void Append(MyString *app_str)
{
int old_size = size_; // 원래 몇글자였는지 기억하기 위해 임시로 사이즈를 저장해놓음
Resize(size_ + app_str->size_); // 다른 멤버 함수 호출 가능
for (int i = old_size; i < size_; i++)
{
cout << i << " " << i - old_size << endl;
str_[i] = app_str->str_[i - old_size];
}
}
MyString str1("ABCDE");
MyString str2("123");
str1.Print();
str1.Append(&str2);
/*
홍정모 연구소 https://honglab.co.kr/
*/
#include <iostream>
#include <cstring>
using namespace std;
// public, private 접근 권한 안내
class MyString
{
public:
MyString()
{
// 호출 시점 확인
cout << "MyString()" << endl;
size_ = 1;
str_ = new char[size_];
}
MyString(const char *init_str) // init_str이 유효한 메모리라고 가정, 생성자에서는 널포인트를 제외한 글자수를 세고있음
{
cout << "MyString(const char *init_str)" << endl;
// 1. 글자 수 먼저 확인
size_ = 0; // 글자수를 size에 저장
while (init_str[size_] != '\0')
{
size_++; // ++ 연산자 안내
}
// 2. 글자 수가 0이 아니면 메모리 할당
if (size_ > 0)
{
str_ = new char[size_]; // 동적할당으로 딱 받을만큼만 받고있음
}
// 3. 복사 (글자 개수만큼만 복사, 사이즈를 알고있기 때문에 널캐릭터를 복사하지 않아도된다)
for (int i = 0; i < size_; i++)
{
str_[i] = init_str[i];
}
// memcpy() 사용 가능
}
~MyString() // 소멸자(변수들이 메모리에 공간을 차지하지 못하고 사라질 때 알아서 호출됨, 끝나기 전에 메모리 반납하는 역할)
{
// 호출 시점 확인
cout << "Destructor" << endl;
size_ = 0;
if (str_) // 만약 동적할당 받은 메모리가 있다면, 메모리가 0이 아니라면 메모리를 반납!
delete[] str_;
}
void Resize(int new_size) // 새로운 사이즈가 입력으로 들어오면
{
char *new_str = new char[new_size]; // 새로 할당을 받고
// memcpy() 사용 가능 // 원래갖고있던 데이터를 복사하고
for (int i = 0; i < (new_size < size_ ? new_size : size_); i++)
{
new_str[i] = str_[i];
}
// 기존 데이터를 삭제
delete[] str_;
str_ = new_str;
size_ = new_size;
// new_str 지우면 안되요!
}
void Print()
{
for (int i = 0; i < size_; i++)
{
cout << str_[i]; // 한글자한글자 일일히 출력해야함. 마지막에 널 캐릭터가 항상 들어있다는 보장이 없기 때문에
}
cout << endl;
}
void Append(MyString *app_str) // 같은 타입을 매개변수로 사용 가능
{
int old_size = size_; // 원래 몇글자였는지 기억하기 위해 임시로 사이즈를 저장해놓음
// 다른 멤버 함수 호출 가능
Resize(size_ + app_str->size_);
// 중요한 개념
for (int i = old_size; i < size_; i++)
{
cout << i << " " << i - old_size << endl;
str_[i] = app_str->str_[i - old_size];
}
}
private:
int size_ = 0; // m_size
char *str_ = nullptr; // m_str (여기서는 구글 스타일)
};
int main()
{
// 클래스 기본 문법 안내
MyString str1("ABCDE"); // 생성자 이용
MyString str2("123");
str1.Print();
str1.Append(&str2); // 주소 넣어줌
str1.Print();
str1.Append(&str2);
str1.Print();
MyString str3("Hello, World!");
str3.Append(&str1);
str3.Print();
return 0;
}
MyString(const char *init_str)
MyString(const char *init_str)
ABCDE
5 0
6 1
7 2
ABCDE123
8 0
9 1
10 2
ABCDE123123
MyString(const char *init_str)
13 0
14 1
15 2
16 3
17 4
18 5
19 6
20 7
21 8
22 9
23 10
Hello, World!ABCDE123123
Destructor
Destructor
Destructor
출처 : 홍정모 유튜브