Dairy

String 클래스의 디자인

OKOK 2017. 8. 1. 17:51

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 클래스를 사용한 것이 유일한 차이점입니다.