String class

#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;

class MyString {
char* string_content; // 문자열 데이터를 가리키는 포인터
int string_length; // 문자열 길이
int memory_capacity; // 현재 할당된 용량 

public:
MyString(char c); // 문자 하나로 생성
MyString(const char* str); // 문자열로 부터 생성
MyString(const MyString& str); // 복사 생성자
~MyString();  // 소멸자

// 함수가 클래스의 멤버함수인 경우 const 키워드를 뒤에 삽입가능 
// 이 경우 함수에 속해있는 객체의 멤버변수를 변경할 수 없다
int length() const;  // 문자의 길이
int capacity() const;  // 현재 할당된 메모리 공간 크기 
void reserve(int size); // 할당할 문자열의 크기를 미리 예약해놓음

void print() const; // 문자 출력 
void println() const; // 문자열 출력 

MyString& assign(const MyString& str); // 기존의 문자열 대신 새로운 문자열 삽입 
MyString& assign(const char* str);

char at(int i) const; // 특정 위치의 문자 리턴

MyString& insert(int loc, const MyString& str); // 특정 위치에 문자 삽입
MyString& insert(int loc, const char* str);
MyString& insert(int loc, char c);

MyString& erase(int loc, int num); // 문자열을 지우는 함수

int find(int find_from, MyString& str) const; // 특정 문자열을 찾아주는 함수
int find(int find_from, const char* str) const;
int find(int find_from, char c) const;

int compare(MyString& str); // 크기를 비교해주는 함수
bool operator==(MyString& str);  // == 연산자 오버로딩
};

 

// 문자 c를 받았을떄 생성자

MyString::MyString(char c) {
string_content = new char[1];
string_content[0] = c;
memory_capacity = 1;
string_length = 1;
}

 

// 문자열 str의 시작주소를 받았을떄 생성자
MyString::MyString(const char* str) {
string_length = strlen(str);
memory_capacity = string_length;
string_content = new char[string_length];

for (int i = 0; i != string_length; i++)
string_content[i] = str[i];
}

 

// MyString객체의 문자열 str을 받았을때 생성자 
MyString::MyString(const MyString& str) {
string_length = str.string_length;
memory_capacity = str.string_length;
string_content = new char[string_length];

for (int i = 0; i != string_length; i++)
string_content[i] = str.string_content[i];
}

 

// 소멸자

MyString::~MyString() {

delete[] string_content;
}

 

// 문자열의 길이 반환
int MyString::length() const {
return string_length;
}

 

문자 출력
void MyString::print() const {
for (int i = 0; i != string_length; i++)
cout << string_content[i];
}

 

// 문자열 출력 
void MyString::println() const {
for (int i = 0; i != string_length; i++)
cout << string_content[i];
cout << endl;
}

 

// 메모리 사용공간 반환
int MyString::capacity() const {
return memory_capacity;
}

 

// 메모리 공간 예약
void MyString::reserve(int size) {
if (size > memory_capacity) {
char* prev_string_content = string_content;

string_content = new char[size];
memory_capacity = size;

for (int i = 0; i != string_length; i++)
string_content[i] = prev_string_content[i];

delete[] prev_string_content;
}
// 예약할려는 size가 현재 capacity보다 작으면 
// 아무것도 하지 않아도 된다 
}

MyString& MyString::assign(const MyString& str) {
if (str.string_length > string_length) {
delete[] string_content;
string_content = new char[str.string_length];
}
for (int i = 0; i != str.string_length; i++) {
string_content[i] = str.string_content[i];
}
string_length = str.string_length;
return *this;
}

// 문자열을 통째로 받아오는 것이 아닌 주소의 시작점으로 
// 받아오는 것이기 떄문에 문자열의 길이를 알려주는 
// strlen()을 이용해 문자열의 길이를 정수형 변수에 저장
MyString& MyString::assign(const char* str) {
int str_length = strlen(str);

if (str_length > string_length) {
delete[] string_content;

string_content = new char[str_length];
}
for (int i = 0; i != str_length; i++) {
string_content[i] = str[i];
}
string_length = str_length;
return *this;
}


 
char MyString::at(int i) const {
if (i >= string_length || i < 0)
return 0;
else
return string_content[i];
}

MyString& MyString::insert(int loc, const MyString& str) {
// i위치 바로 앞에 문자 삽입 

if (loc < 0 || loc > string_length) return *this;

// 현재 할당된 메모리 공간의 크기보다 새로 올 문자열의 크기가 
// 더 크므로 새로 할당해 주어야 함 
if (string_length + str.string_length > memory_capacity) {

// insert 작업은 잦은 할당/ 해제가 발생한다 
// 이를 피하기 위해 메모리를 할당해놓되, 많은 자원을 낭비하지 않도록 
// 메모리를 할당해야 한다. 
// 메모리를 미리 할당하는 경우, 현재 메모리 크기의 두 배 정도를 할당해 놓는 방법
if (memory_capacity * 2 > string_length + str.string_length) {
memory_capacity *= 2; 
} // 새로 할당해야 하는 메모리의 크기가 2배 이하라면 
// 필요한 크기의 2배를 할당 
else {
memory_capacity = string_length + str.string_length;
} // 2배를 넘는다면 그냥 크기만큼 할당

// 기존의 문자열은 내용은 다른 곳에 저장 
char* prev_string_content = string_content;
// 문자열에 새로운 동적할당 
string_content = new char[memory_capacity];

int i;
// insert 직전까지의 내용 복사 
for (i = 0; i < loc; i++) {
string_content[i] = prev_string_content[i];
}
// 새롭게 insert 되는 문자열 삽입
for (int j = 0; j != str.string_length; j++) {
string_content[i + j] = str.string_content[j];
}
// 다시 원 문자열의 나머지 부분 복사
for (; i < string_length; i++) {
string_content[str.string_length + i] = prev_string_content[i];
}
delete[] prev_string_content;

string_length = string_length + str.string_length;
return *this;
}
// 크기를 초과하지 않는다면 동적할당을 할 필요는 없다 
// 효율적인 insert를 위해서는 밀리는 부분을 먼저 뒤로 밀어버린다
// 크기가 충분하기 때문에 가능한 방법 

for (int i = string_length - 1; i >= loc; i--) {
string_content[i + str.string_length] = string_content[i];
}
for (int i = 0; i < str.string_length; i++)
string_content[i + loc] = str.string_length;
return *this;
}

// 문자열의 시작 주소로 받는 경우
MyString& MyString::insert(int loc, const char* str) {
MyString temp(str); 
// str 문자열을 가진 MyString 객체를 생성
return insert(loc, temp);
// 삽입 위치, 객체를 매개변수로 insert() 호출, 리턴 
}

MyString& MyString::insert(int loc, char c) {
MyString temp(c);
// c 문자를 가진 MyString 객체를 생성 
return insert(loc, temp);
// 삽입 위치, 객체를 매개변수로 insert() 호출, 리턴 
}

// loc는 해당하는 문자 앞, num은 지우는 문자의 수를 의미 
// 지운다는 의미는 뒤의 문자들을 앞으로 끌고 온다는 것
MyString& MyString::erase(int loc, int num) {
if (num < 0 || loc < 0 || loc > string_length) return *this;

// 예시 코드
for (int i = loc + num; i < string_length; i++) {
string_content[i - num] = string_content[i];
}
// 내 코드 
/*for (int i = loc; i <= num; i++) {
string_content[i - num] = string_content[i];
}*/
string_length -= num;
return *this;
}


int MyString::find(int find_from, MyString& str) const{
int i, j;
if (str.string_length == 0) return -1;
// 밑의 코드 이해X 나중에 다시 보기
for (i = find_from; i <= string_length - str.string_length; i++) {
for (j = 0; j < str.string_length; j++) {
if (string_content[i + j] != str.string_content[j]) break;
}
if (j == str.string_length) return i;
}
return -1;
}

int MyString::find(int find_from, const char* str) const {
MyString temp(str);
return find(find_from, temp);
}
int MyString::find(int find_from, char c) const {
MyString temp(c);
return find(find_from, temp);
}

int MyString::compare(MyString& str) {

// max(), min() -> 매개변수를 2개 받아 해당하는 값을 리턴
// 비교 가능한 것이라면 자료형은 상관 X
for (int i = 0; i < std::min(string_length, str.string_length); i++) {
if (string_content[i] > str.string_content[i])
return 1;
else if (string_content[i] < str.string_content[i])
return -1;
}
// (*this) - (str)을 수행해서 1, 0, -1 로 결과를 리턴
// 1 -> (*this)가 사전식으로 더 뒤에 온다는 의미 
// 0 -> 두 문자열이 같다는 의미 
// -1 -> (*this)가 사전식으로 더 앞에 온다는 의미

if (string_length == str.string_length) return 0;
else if (string_length > str.string_length) return 1;
return -1;
}

// str과 같으면 compare에서 0을 리턴 
bool MyString::operator==(MyString& str) {
return !compare(str);
}

 

int main() {

// 생략

}

'c++' 카테고리의 다른 글

템플릿 (Template)  (0) 2020.08.27
오버라이딩, 가상함수  (0) 2020.08.20
explicit, mutable  (0) 2020.08.18
초기화 리스트 (Initializer list)  (0) 2020.08.17
참조자 (레퍼런스 - reference)  (0) 2020.08.17
TAGS.

Comments