일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- Windows Forms
- 실습으로 다지는 c#
- 소스 코드
- 네트워크 프로그래밍
- 유튜브 동영상 강의
- C++
- 산책하기 좋은 곳
- 동영상 강의
- 언제나휴일
- c언어
- 클래스 다이어그램
- 표준 입출력
- 알고리즘
- 원격 제어 프로그램
- 소켓 통신
- 프로젝트
- 캡슐화
- 강의
- 언제나 휴일
- 안드로이드 앱 개발
- 파이썬
- c#
- 무료 동영상 강의
- 추천
- 표준 라이브러리 함수
- 실습
- 동영상
- 충남 천안
- 졸업 작품 소재
- 졸업 작품
- Today
- Total
프로그래밍 언어 및 기술 [언제나휴일]
[C++] 55~56. string 클래스 흉내내기 본문
55. string 클래스 흉내내기1
이번에는 연산자 중복 정의 문법으로 string 클래스와 비슷하게 사용할 수 있는 클래스를 만들어 보아요. 먼저 여기에서 구현할 범위를 정하기 위해 string 클래스를 사용하는 기본적인 사항을 확인하고 넘어갈게요.
string 형식은 기본 생성 및 문자열을 입력 인자로 받는 생성을 할 수 있어요.
string s;
string s2="hello";
string 형식은 비교 연산(==, !=, >, >=, <, <=)을 사용할 수 있어요.
if(s == s2)
{
cout<<"서로 같다."<<endl;
}
else
{
cout<<"서로 다르다."<<endl;
}
string 형식은 대입 연산(=)이 가능하고 개체 출력을 할 수 있어요.
s = s2;
cout<<s<<endl;
string 내부에 문자열을 보관한 버퍼의 위치를 알 수 있어요.
const char *buf = s.c_str();
cout<<"버퍼:"<<buf<<endl;
string 형식은 cin을 이용하여 입력받는 것이 가능해요.
cout<<"문자열:";
cin>>s;
cout<<"입력한 내용은 "<<s<<endl;
다음은 string 형식을 사용한 예제 코드입니다.
//STL에서 제공하는 string 클래스 사용
#include <string>
#include <iostream>
using namespace std;
int main()
{
string s;
string s2="hello";
if(s == s2)
{
cout<<"서로 같다."<<endl;
}
else
{
cout<<"서로 다르다."<<endl;
}
s = s2;
cout<<s<<endl;
if(s == s2)
{
cout<<"서로 같다."<<endl;
}
else
{
cout<<"서로 다르다."<<endl;
}
const char *buf = s.c_str();
cout<<"버퍼:"<<buf<<endl;
cout<<"문자열:";
cin>>s;
cout<<"입력한 내용은 "<<s<<endl;
return 0;
}
#include <string> 부분을 지우고 #include “mystring.h”로 변경한 후에 컴파일 오류가 없게 string 클래스를 정의하세요. using 구문도 using std::cout; using std::endl; using std::cin; 으로 수정하세요.
//string 클래스 흉내내기
#include "mystring.h"
#include <iostream>
using std::cout;
using std::endl;
using std::cin;
그리고 컴파일 오류를 하나 하나 지우면 다음과 같은 형태로 작성할 수 있을 거예요.
//mystring.h
#pragma once
#include <iostream>
using std::ostream;
using std::istream;
using std::cin;
using std::cout;
class string
{
char *buf;
public:
string(const char *buf=0);
bool operator==(const string &src)const;
bool operator!=(const string &src)const;
bool operator>(const string &src)const;
bool operator>=(const string &src)const;
bool operator<(const string &src)const;
bool operator<=(const string &src)const;
void view(ostream &os=cout) const;
const char *c_str()const;
friend ostream &operator<<(ostream &os,const string &src);
friend istream &operator>>(istream &is,string &src);
};
friend는 private으로 접근 지정한 멤버에 접근할 수 있게 하는 문법으로 정보 은닉을 무너트려 신뢰성을 떨어트릴 수 있는 문법입니다. friend 문법을 사용할 때는 매우 신중하게 사용하시고 다른 방법이 있다면 가급적 사용하지 마세요. 그리고 friend로 메서드를 지정하였을 때 이는 멤버 메서드가 아니라 전역 메서드이며 자신에 정의한 멤버에 접근하는 것을 허용하겠다는 약속일 뿐입니다.
현재 컴파일 오류를 해결한 상태로 구체적인 구현을 하지 않은 상태의 코드는 다음과 같습니다.
//mystring.cpp
#include "mystring.h"
string::string(const char *buf){ }
bool string::operator==(const string &src)const
{
return false;
}
bool string::operator!=(const string &src)const
{
return false;
}
bool string::operator>(const string &src)const
{
return false;
}
bool string::operator>=(const string &src)const
{
return false;
}
bool string::operator<(const string &src)const
{
return false;
}
bool string::operator<=(const string &src)const
{
return false;
}
void string::view(ostream &os)const
{
}
const char *string::c_str()const
{
return 0;
}
ostream &operator<<(ostream &os,const string &src)
{
return os;
}
istream &operator>>(istream &is,string &src)
{
return is;
}
사용하는 코드는 다음과 같습니다.
//string 클래스 흉내내기
#include "mystring.h"
#include <iostream>
using std::cout;
using std::endl;
using std::cin;
int main()
{
string s;
string s2="hello";
if(s == s2)
{
cout<<"서로 같다."<<endl;
}
else
{
cout<<"서로 다르다."<<endl;
}
s = s2;
cout<<s<<endl;
if(s == s2)
{
cout<<"서로 같다."<<endl;
}
else
{
cout<<"서로 다르다."<<endl;
}
const char *buf = s.c_str();
cout<<"버퍼:"<<buf<<endl;
cout<<"문자열:";
cin>>s;
cout<<"입력한 내용은 "<<s<<endl;
return 0;
}
이제 컴파일 오류를 하나 하나 해결하면서 STL에서 제공하는 string과 같은 형태로 동작하게 구현해 보세요.
이제 자신의 string 클래스의 멤버 메서드를 하나 하나 구현해 보기로 해요.
제일 먼저 생성자를 구현합시다.
string::string(const char *buf)
{
먼저 입력 인자가 0(널 포인터)일 때 빈 문자열을 보관할 버퍼를 생성해서 빈 문자열을 복사하세요.
if(buf==0)//입력 인자가 0(널 포인터)일 때
{
this->buf = new char[1];//크기가 1인 버퍼를 생성
strcpy_s(this->buf,1,""); //공백 문자를 대입
}
입력 인자가 0(널 포인터)가 아닐 때는 입력 문자열 길이를 구하여 버퍼를 생성하고 문자열을 복사하세요.
else//입력 인자가 0(널 포인터)가 아닐 때
{
int len_p1 = strlen(buf)+1; //입력 문자열의 길이 + 1 을 구함
this->buf = new char[len_p1]; //버퍼 생성
strcpy_s(this->buf,len_p1,buf); //문자열 복사
}
}
비교 연산자 중복 정의에서는 strcmp 함수를 이용하여 구현하세요.
bool string::operator==(const string &src)const
{
return strcmp(buf,src.buf)==0;
}
bool string::operator!=(const string &src)const
{
return strcmp(buf,src.buf)!=0;
}
bool string::operator>(const string &src)const
{
return strcmp(buf,src.buf)>0;
}
bool string::operator>=(const string &src)const
{
return strcmp(buf,src.buf)>=0;
}
bool string::operator<(const string &src)const
{
strcmp(buf,src.buf)<0;
}
bool string::operator<=(const string &src)const
{
strcmp(buf,src.buf)<=0;
}
개체 정보를 출력하는 view 메서드에서는 buf의 내용을 출력합니다.
void string::view(ostream &os)const
{
os<<buf;
}
문자열 버퍼의 주소를 반환하는 메서드에서는 buf를 반환하면 되겠죠.
const char *string::c_str()const
{
return buf;
}
개체 출력자를 위한 전역 <<연산자 중복 정의 메서드에서는 view 메서드를 호출합니다.
ostream &operator<<(ostream &os,const string &src)
{
src.view(os);
return os;
}
istream &operator>>(istream &is,string &src)
{
문자열 정보를 입력받는 전역>>연산자 중복 정의 메서드에서는 지역 변수로 문자열을 입력받을 버퍼를 선언하여 문자열을 입력받습니다.
char buf[256];
cin>>buf;
그리고 src 문자열의 버퍼는 메모리 해제하세요.
delete [] src.buf;
그리고 입력받은 버퍼의 문자열 길이를 계산하여 src 개체의 버퍼를 생성하고 문자열을 복사하세요.
int len_p1 = strlen(buf)+1; //입력 문자열의 길이 + 1 을 구함
src.buf = new char[len_p1]; //버퍼 생성
strcpy_s(src.buf,len_p1,buf); //문자열 복사
return is;
}
이제 테스트를 해 보세요. 다음은 전체 코드입니다.
//mystring.h
#pragma once
#include <iostream>
using std::ostream;
using std::istream;
using std::cin;
using std::cout;
class string
{
char *buf;
public:
string(const char *buf=0);
bool operator==(const string &src)const;
bool operator!=(const string &src)const;
bool operator>(const string &src)const;
bool operator>=(const string &src)const;
bool operator<(const string &src)const;
bool operator<=(const string &src)const;
void view(ostream &os=cout)const;
const char *c_str()const;
friend ostream &operator<<(ostream &os,const string &src);
friend istream &operator>>(istream &is,string &src);
};
//mystring.cpp
#include "mystring.h"
#include <string.h>
string::string(const char *buf)
{
if(buf==0)//입력 인자가 0(널 포인터)일 때
{
this->buf = new char[1];//크기가 1인 버퍼를 생성
strcpy_s(this->buf,1,""); //공백 문자를 대입
}
else//입력 인자가 0(널 포인터)가 아닐 때
{
int len_p1 = strlen(buf)+1; //입력 문자열의 길이 + 1 을 구함
this->buf = new char[len_p1]; //버퍼 생성
strcpy_s(this->buf,len_p1,buf); //문자열 복사
}
}
bool string::operator==(const string &src)const
{
return strcmp(buf,src.buf)==0;
}
bool string::operator!=(const string &src)const
{
return strcmp(buf,src.buf)!=0;
}
bool string::operator>(const string &src)const
{
return strcmp(buf,src.buf)>0;
}
bool string::operator>=(const string &src)const
{
return strcmp(buf,src.buf)>=0;
}
bool string::operator<(const string &src)const
{
return strcmp(buf,src.buf)<0;
}
bool string::operator<=(const string &src)const
{
return strcmp(buf,src.buf)<=0;
}
void string::view(ostream &os)const
{
os<<buf;
}
const char *string::c_str()const
{
return buf;
}
ostream &operator<<(ostream &os,const string &src)
{
src.view(os);
return os;
}
istream &operator>>(istream &is,string &src)
{
char buf[256];
cin>>buf;
delete [] src.buf;
int len_p1 = strlen(buf)+1; //입력 문자열의 길이 + 1 을 구함
src.buf = new char[len_p1]; //버퍼 생성
strcpy_s(src.buf,len_p1,buf); //문자열 복사
return is;
}
//Program.cpp
//string 클래스 흉내내기
#include "mystring.h"
#include <iostream>
using std::cout;
using std::endl;
using std::cin;
int main()
{
string s;
string s2="hello";
if(s == s2)
{
cout<<"서로 같다."<<endl;
}
else
{
cout<<"서로 다르다."<<endl;
}
s = s2;
cout<<s<<endl;
if(s == s2)
{
cout<<"서로 같다."<<endl;
}
else
{
cout<<"서로 다르다."<<endl;
}
const char *buf = s.c_str();
cout<<"버퍼:"<<buf<<endl;
cout<<"문자열:";
cin>>s;
cout<<"입력한 내용은 "<<s<<endl;
return 0;
}
▷ 실행 화면
서로 다르다.
hello
서로 같다.
버퍼:hello
문자열:yahoo
입력한 내용은 yahoo
이 외에도 STL의 string 클래스는 다양한 멤버를 제공하고 있습니다. 보다 비슷하게 만들다 보면 STL의 string 클래스를 이해할 수 있을 거예요.