문자열 객체 생성부터 연산까지 관장하는 String class를 만들어 보기
#pragma once
#include<iostream>
using namespace std;
class String
{
private:
// 문자열의 길이, 문자열 포인터
int len;
char * str;
public:
/*생성자, 복사생성자, 대입연산자, 연산자 오버로딩함수 **선언부***/
// 생성자1(디폴트, 인자x)
String();
// 생성자2(문자형 포인터 인자)
String(const char * Str);
// 복사생성자
String(const String & scopy);
// 대입 연산자
String & operator=(const String & scopy);
// '+'연산 오버로드
String operator+(const String & str2);
// '+='연산 오버로드
String & operator +=(const String & str2);
// '=='연산 오버로드
bool operator==(const String & str2);
// '<< , >>'연산 오버로드(멤버 외 오버로딩)
friend ostream & operator<<(ostream & cout , const String & str);
friend istream & operator>>(istream & cin , const String & str);
};
#include "string.h" // 직속 헤더파일 참조
#include <iostream>
#include <cstring> // 문자열 기능관련
#include <cstdlib> // exit함수
using namespace std;
/*정의부*/
// 무인자 생성 시
String::String()
{
len =0;
str = NULL;
}
// 생성자 str 동적할당
String::String(const char * Str)
{
len = strlen(Str) + 1; // Str을 복사하려면 Str원 길이 + NULL(1) 의 공간을 갖춰야함
str = new char[len];
strcpy(str, Str);
}
// 복사 생성자 동적할당
String::String(const String & scopy)
{
len = scopy.len+1;
str = new char[len];
strcpy(str, scopy.str);
}
// 대입 연산자 동적할당
String & String::operator=(const String & scopy)
{
len = scopy.len+1;
str = new char[len];
strcpy(str, scopy.str);
return *this;
}
// '+'operator overload
String String::operator+(const String & str2)
{
if(str==NULL)
{
exit(1); // 디폴트 생성 객체를 피연산자로 활용할 수 없음.
}
int len2 = len + str2.len -1;
// 각 길이에 중복되어 포함되어있는 NULL을 위한 자리를 한자리 뺀다. -1
char * tempstr = new char[len2];
strcpy(tempstr, str); // str1 복사
strcat(tempstr, str2.str); // str2 이어붙임
String temps(tempstr); // 두번째 생성자 호출
return temps; // 새로운 객체 temps 반환
}
String & String::operator +=(const String & str2)
{
if(str==NULL)
{
exit(1);
}
*this = *this + str2;
// 멤버 내 '+'연산자 함수를 이용하여 좌측 피연산자 초기화까지 진행
return *this;
}
// True or False 값을 반환하는 bool형
bool String::operator==(const String & str2)
{
if(str==NULL)
{
exit(1);
}
// 두 문자열 비교
if(strcmp(str, str2.str)==0) // 동일하다면 0, 아니라면 0 이외의 값
return true;
else
return false;
}
// header file : iostream, namespace : std, class : o / i stream, object : cout, cin
ostream & operator<<(ostream & cout ,const String & str1)
// 여기서 cout 말고 어떤 문자가 와도 무방하다.
{
cout << str1.str << endl;
return cout;
}
istream & operator>>(istream & cin , String & str1)
{
char temp[100];
cin >> temp;
str1 = String(temp);
return cin;
}
#include "string.h"
#include<iostream>
int main()
{
String str1 = "I love you";
String str2 = " babe";
String str3=str1; // 복사생성자 호출
String str4;
str4 = str2; // 대입연산자 호출
if(str1 == str3) // '=='연산자 함수 호출(boolean)
{
cout << "same string" << endl;
}
else
{
cout << "not same string" << endl;
}
cout << str1 + str2; // '+'연산자 함수 호출
// str1 + str2 -> str3역시 String & 형태
cout << str1;
str1 += str2; // '+=' 연산자 함수 호출
cout << str1; // '<<' 연산자 함수 호출
cout << "str1 재초기화 : "; cin << str1; // '>>'연산자 함수 호출
cout << str1;
return 0;
}
앞으로 문자열을 멤버변수로 갖는 클래스에서 일일히 동적할당, 각종 기능함수 를 생성할 필요 없이 String 클래스 객체를 생성하자.