[ 공 부 ]/[ C + + ]

[ C++ ] STRING Class

HiStar__ 2019. 11. 13. 01:09

문 제

 

  • 간단하게 String Class 구현

 

소 스  코 드

// class(struct) 키워드로 사용자 정의 자료형을 만든다. 
// - 생성시 자원을 할당하였다면 ( 자원을 사용하지 않는다면 아무것도 할 필요 없다. ) 
// 1. 소멸자에서 자원 해제 
// 2. 깊은 복사를 코딩 해야 한다. 
// 3. 2번과 쌍인 Copy Assignment를 제대로 코딩해야 한다. 
//  
// 4. 최신 이동기능을 지원하려면 이동생성자를 코딩 
// 5. 4와 한 쌍인 이동할당연산자를 코딩해야 한다. 
//////////////////////////////////////////////////////////////////////////////////////////////// 
#include  <iostream>
#include  <random>
#include  <algorithm>
#include "SaveCode.h" 


std::default_random_engine dre; 
std::uniform_int_distribution<> uidINT{ 1 ,70 }; 
std::uniform_int_distribution<> uidCHAR{ 'a', 'z' }; 


class STRING { 
char *word; 
size_t length; // 저장한 글자수 


public: 
////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
// STRING() : word{ nullptr }, length{ 0 } {} 

STRING() { 
length = uidINT(dre); 
word = new char[length]; 
for (int i = 0; i < length; ++i) { 
word[i] = uidCHAR(dre); 
} 
} 

~STRING() { if(word != nullptr) delete[] word; } // 생성자에서 확보한 자원은 객체가 사라질 때 정리해야! 

STRING(const char* w) { 
length = strlen(w); 
word = new char[length]; 
memcpy(word, w, length); 
} 


////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

// 복사 생성자( 생성자에서 자원을 할당한 경우 ) 
STRING(const STRING& other) : length{ other.length } { 
word = new char[length]; 
// 깊은 복사의 경우 strcpy가 아니라 memcpy를 사용한다. 
// strcpy(word, other.word); 
memcpy(word, other.word, length); 
} 

// CopyAssignment 복사할당 연산자  b = a; 
STRING& operator=(const STRING & other) { 
if (this == &other) return *this; // 예외문 a = a; 무의미한 할당하는 행동을 제하는 코드 

if (length != 0) delete[] word; 

length = other.length; 
word = new char[length]; 

// 깊은 복사가 많이 생긴다면,  
// *this = other; // memcpy 대신 사용을 한다. 

memcpy(word, other.word, length); //  
return *this; 
} 

////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
// 자원을 이동하고 싶으면 (선택 사항) 
// 이동은 데이터 안정성 측면에서 위험할 수 있기 때문에  
// 안전하다는 보증을 프로그래머가 직접 해줘야함. 
// noexcept : 이 함수는 안정된 함 수 이다. 
// 

// && 아벨류 레퍼런스 
STRING(STRING&& other) noexcept : length{ other.length }, word{ other.word }  { 
// 이동 대상의 멤버를 잘 정리 
other.word = nullptr; 
other.length = 0; 
} 

// 이동 할당 연산자 move assignment  
STRING operator=(STRING&& other) noexcept { 
// 나를 나에게 할당 되지 않게 
if (this != &other) return *this; 

// 내가 잡은 메모리가 있다면 해제 
if (length != 0) delete[] word; 

// ohter의 자원을 가져오기 
word = other.word; 
length = other.length; 

other.length = 0; 
other.word = nullptr; 

return *this; 

} 



////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
// + 함수 

// 주의 임시 변수 이기 때문에  
// STRING &의 경우 메모리 주소를 가져오는 것이기 때문에 지역변수의 경우 삭제가 됨으로 제대로 된 값을 받을 수 없다. 
// const STRING &other 의 경우 인자 값이 변하지 않음 ) const { 나 자신도 변하지 않음. 
STRING operator+(const STRING & other) const { 

STRING stemp; 
stemp.length = length + other.length; 
stemp.word = new char[stemp.length]; 

memcpy(stemp.word, word, length); 
memcpy(stemp.word + length, other.word, other.length); 

return stemp; 
} 



////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
// [] 함수 
// 읽기 전용 
char operator [](const int& idx) const {  
if (length < idx) exit(1); 
else return *(word + idx); 
} 

// 쓰기 전용 
// char& 나 자신 
char& operator [](int idx) { 
return *(word + idx); 
} 

////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
// 범위 기반 for 루프를 위한 코드 
char* begin() const { 
return word; 
} 

char* end() const { 
return word + length; 
} 

////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
int GetLength()const { return length; } 


// ostream 입출력 연산자 
friend std::ostream& operator << (std::ostream&, const STRING&); 
}; 

std::ostream& operator << (std::ostream& os, const STRING& rhs) { 
os << "길이 : " << rhs.length << "\t"; 
for (int i = 0; i < rhs.length; ++i) { 
os << rhs.word[i]; 
} 

return os; 
} 

// [문제] STRING을 100개를 생성하라 
// 각 STRING의 길이를 random(1 ~ 70) , 각 글자를 random(a ~ z) 하게 만들어라. 
// 전체 STRING을 길이 오름차순으로 정렬하라. 
// 전체를 출력하라. 

int main() { 
// CodeSave("Main.cpp"); // 코드 저장용 함수 

// 생성자로 만들기 
STRING random[100]; 


std::sort(std::begin(random), std::end(random), [](const STRING& a, const STRING& b) {return a.GetLength() > b.GetLength(); }); 

for (const auto &a : random) { 
std::cout << a << std::endl; 
} 



return 0; 
}