본문 바로가기
Dairy

String 클래스의 디자인

by OKOK 2017. 8. 1.

string 클래스를 모델로 삼아서 연산자가 어떠한 형태로 오보러딩 되어 있는지 보고, 이와 유사한 문자열 처리 클래스를 직접 구현해 보는데 목적이 있습니다. 이는 표준 string 클래스를 사용하는 것 이상의 의미가 있다고 생각합니다. 


#pragma warning(disable:4996)


#include <iostream>

#include <string>

using namespace std;


int main(void)

{

string str1 = "I like ";

string str2 = "string class";

string str3 = str1 + str2;


cout << str1 << endl;

cout << str2 << endl;

cout << str3 << endl;


str1 += str2;

if (str1 == str3)

cout << "same" << endl;

else

cout << "not same" << endl;


string str4;

cout << "charcter string input: ";

cin >> str4;

cout << "string output: " << str4 << endl;

return 0;


string 객체간 덧셈연산이 가능함을 알 수 있습니다. 이는 operator + 연산자의 오버로딩으로 인해 가능합니다. string 클래스가 << 연산자에 대해서도 오버로딩 되어있음을 확인 할 수 있습니다. 


문자열 처리 클래스의 정의

요구사항들에 대해서 정의해보도록 하겠습니다. 문자열을 인자로 전달받는 생성자의 정의. 생성자, 소멸자 복사 생성자 그리고 대입 연산자의 정의가 필요합니다. 결합된 문자열로 초기화된 객체를 반환하는 + 연산자의 오버로딩 + 연산자의 반환 값은 다음 두 가지입니다. 문자열의 주소 값(str1고 str2가 지니고 있는 무자열을 합한 문자열의 주소 값) 그리고 string 객체(str1과 str2가 지니고 있는 문자열을 합한 문자열을 저장하고 있는 객체입니다.) 내용비교를 진행하는 == 연산자의 오버로딩. 


문자열을 입력 받을 목적으로, 다음의 형태로 객체를 생성할 수 있게 하기 위해서 정의된 생성자입니다. String emptystr; 때문에 멤버변수 str에는 NULL이 저장될 수도 있습니다. 그래서 멤버변수 str을 대상으로 delete 연산을 하기에 앞서, str에 저장된 값이 NULL인지를 검사하는 코드를 소멸자를 포함해서 곳곳에서 확인할 수 있습니다. 


#pragma warning(disable:4996)


#include <iostream>

#include <cstring>

using namespace std;


class String

{

private:

int len;

char * str;

public:

String();

String(const char * s);

String(const String& s);

~String();

String& operator = (const String& s);

String& operator+= (const String& s);

bool operator== (const String& s);

String operator+ (const String& s);


friend ostream& operator<< (ostream& os, const String& s);

friend istream& operator >> (istream& is, String& s);

};


String::String()

{

len = 0;

str = NULL;

}


String::String(const char* s)

{

len - strlen(s) + 1;

str = new char[len];

strcpy(str, s);

}


String::String(const String& s)

{

len = s.len;

str = new char[len];

strcpy(str, s.str);

}


String::~String()

{

if (str != NULL)

delete[]str;

}


String& String::operator= (const String& s)

{

if (str != NULL)

delete[]str;

len = s.len;

str = new char[len];

strcpy(str, s.str);

return *this;

}



String& String::operator+= (const String& s)

{

len += (s.len - 1);

char* tempstr = new char[len];

strcpy(tempstr, str);

strcat(tempstr, s.str);


if (str != NULL)

delete[]str;

str = tempstr;

return *this;

}


bool String::operator == (const String& s)

{

return strcmp(str, s.str) ? false : true;

}


String String::operator+ (const String& s)

{

char* tempstr = new char[len + s.len - 1];

strcpy(tempstr, str);

strcat(tempstr, s.str);


String temp(tempstr);

delete[]tempstr;

return temp;

}


ostream& operator<< (ostream& os, const String& s)

{

os << s.str;

return os;

}


istream& operator >> (istream& is, String& s)

{

char str[100];

is >> str;

s = String(str);

return is;

}


int main(void)

{

String str1 = "I like ";

String str2 = "string class";

String str3 = str1 + str2;


cout << str1 << endl;

cout << str2 << endl;

cout << str3 << endl;


str1 += str2;

if (str1 == str3)

cout << "same" << endl;

else

cout << "not same" << endl;


String str4;

cout << "Input: ";

cin >> str4;

cout << "Output: " << str4 << endl;

return 0;


main 함수는 앞소 소개한 예제의 main 함수와 동일합니다. 다만 표준 string 클래스를 대신해서 우리가 정의한  String 클래스를 사용한 것이 유일한 차이점입니다.