/ C

자료구조 정복하기 with C++ (2)String(문자열) 자료구조

자료구조 정복하기 with C++ (2)String(문자열) 자료구조

직접 코딩하면서 자료구조 공부하기

개요

자료구조와 알고리즘은 프로그램을 구성하는 가장 핵심적인 요소입니다. 프로그램 개발을 집을 짓는 것에 비유한다면 흙이나 모래, 시멘트, 목재와 같은 자재들이 바로 ‘자료구조’에 해당되고, 이러한 자재들을 이용해서 집을 짓는 것이 ‘알고리즘’에 해당됩니다. 자료구조는 가장 기본적이고 중요한 부분이기 때문에 복습하는 겸해서 직접 여러가지 자료구조를 코딩하면서 공부하기로 했습니다.

String 문자열

C언어에서는 큰따옴표(““)를 사용해 표현되는 문자열을 문자열 상수(string constant)라고 합니다. 상수라고 표현하는 이유는 해당 문자열이 이름을 가지고 있지 않으며, 문자열의 내용 또한 변경할 수 없기 때문입니다. C언어에서 문자열(string)은 메모리에 저장된 일련의 연속된 문자(character)들의 집합을 의미합니다. 따라서 문자형 배열을 선언하면 이 배열이 곧 문자열 변수가 됩니다. 이러한 문자열을 이용하기 위해 C에서는 대표적으로 string.h 헤더파일을 제공합니다.

따라서 이러한 문자열 관련 자료구를 C++로 직접 구현하겠습니다.

String Class 기능

String 클래스의 기능은

  1. 문자열 생성
  2. 문자열 결합(concat)
  3. 문자열 비교(== 연산자 operator 재지정)
  4. 공백 검사(! 연산자 재지정)
  5. 길이 반환
  6. 특정 인덱스 문자열 출력
  7. 특정 문자열 위치 반환 및 이동

String.h

String헤더파일

#pragma once
class String
{
private:
	char* buffer;
	int length;
	int size;

public:
	String();
	String(int m);
	String(String& s);
	String(char* init, int m);			//길이 m인 string으로 초기화
	~String();
	String& operator=(const String&);
	bool operator==(String t);			//동일 비교
	bool operator!();					//공백이면 true, 아니면 false
	int Length();						//문자수 반환
	String Concat(String t);			//연결된 스트링 반환
	String Substr(int i, int j);		//i~j 사이의 스트링 반환
	int Find(String pat);				//스트링에서 pat스트링 찾아서 위치 반환

	void print();
};

String.cpp

Strinig 소스코드

#include "String.h"
#include <iostream>

using namespace std;

String::String() : String(10)
{

}

String::String(String& s) : String(s.length + 1)
{
	for (int i = 0; i < s.length; i++)
		buffer[i] = s.buffer[i];
	buffer[s.length] = '\0';
	length = s.length;

}

String::~String()
{
	delete[] buffer;
}

String::String(int m)
{
	size = m;
	buffer = new char[m];
	length = 0;
}

String::String(char* init, int m) : String(m + 1)	// <-- cat 3 (실제 버퍼까지 길이 4)
{
	for (int i = 0; i < m; i++)
		buffer[i] = init[i];
	buffer[m] = '\0';
	length = m;
}

String String::Concat(String t)
{
	String result(length + t.length + 1);

	for (int i = 0; i < length; i++)
		result.buffer[i] = buffer[i];
	for (int i = 0; i < t.length; i++)
		result.buffer[length + i] = t.buffer[i];

	result.buffer[length + t.length] = '\0';
	result.length = length + t.length;

	return result;
}

String& String::operator=(const String& s)
{
	delete[] buffer;
	buffer = new char[s.length + 1];
	for (int i = 0; i < s.length; i++)
		buffer[i] = s.buffer[i];
	buffer[s.length] = '\0';
	length = s.length;

	return *this;
}

bool String::operator==(String t)
{
	int i = 0;
	if (length != t.length)
		return false;
	while (i < length)
	{
		if (buffer[i] != t.buffer[i])
			return false;
		i++;
	}
	return true;
}

bool String::operator!()
{
	int i = 0;
	while (i < length)
	{
		if (buffer[i] != ' ')
			return false;
		i++;
	}
	return true;
}

int String::Length()
{
	return length;
}

String String::Substr(int i, int j)
{
		String result(j - i + 2);
		int m = i;
		for (int k = 0; k < j - i + 1; k++)
		{
			result.buffer[k] = buffer[m-1];
			m++;	
		}
		result.buffer[j - i + 1] = '\0';
		result.length = j - i + 1;

		return result;
}

int String::Find(String pat)
{
	int i = 0;
	int num = 0;

	while (i < length + 1)
	{
		if (buffer[i] == pat.buffer[num])
		{
			i++;
			num++;
		}
		else
		{
			i = i - num + 1;
			num = 0;
		}
		
		if (pat.length == num)
			return i - num + 1;
	}

	return -99999;
}

void String::print()
{
	int i = 0;
	while (i < length)
	{
		cout << buffer[i];
		i++;
	}
	cout << endl;
}

결과

main.cpp

#include <iostream>
#include "String.h"

using namespace std;

int main()
{
	//String 생성
	String a((char*)"hello", 5);
	String b((char*)"world", 5);
	String c;
	String d((char*)"     ", 5);

	//a와 b 합치기
	cout << "Concat Func: \"hello\" + \"world\"" << endl;
	c = a.Concat(b);
	c.print();

	//a와 c 비교 맞으면 1 틀리면 0
	cout << "\n\"hello\"\"hellowordl\" 비교하기" << endl;
	cout << (a == c) << endl;
	cout << "\n\"hello\"\"hello\" 비교하기" << endl;
	cout << (a == a) << endl;

	//b가 공백이면 1 아니면 0
	cout << "\n\"world\" 공백 검사하기" << endl;
	cout << (!b) << endl;
	cout << "\n\"     \" 공백 검사하기" << endl;
	cout << (!d) << endl;

	//c의 길이 반환 함수
	int length = c.Length();
	cout << "\nC \"helloworld\"의 길이: " << length << endl;

	//str 스트링 3~8 값 출력
	String str;
	str = c.Substr(3, 8);
	cout << "\n\"hellowordl\" 에서 3~8번 값 출력하기" << endl;
	str.print();

	//c에서 "lowo" 찾아서 위치 반환하기
	String pat((char*)"lowo", 4);
	String pat2((char*)"loo", 3);
	int num = c.Find(pat);
	int num2 = c.Find(pat2);
	cout << "\n\"helloworld\"에서 \"lowo\"의 시작 위치: " << num << endl;
	cout << "\n\"helloworld\"에서 \"loo\"의 시작 위치: " << num2 << endl;

	return 0;
}

이것으로 String 클래스의 작성을 마칩니다.