챕터6. 실습 문제
2025. 3. 28. 08:46ㆍProgramming Languages/C++
6.6 실습 문제
문제 1: 동적 메모리를 사용한 간단한 문자열 클래스
#include <iostream>
#include <cstring>
class MyString {
private:
char* buffer;
size_t length;
public:
// 기본 생성자
MyString() : buffer(nullptr), length(0) {
buffer = new char[1];
buffer[0] = '\0';
}
// 매개변수가 있는 생성자
MyString(const char* str) : buffer(nullptr), length(0) {
if (str) {
length = strlen(str);
buffer = new char[length + 1];
strcpy(buffer, str);
} else {
buffer = new char[1];
buffer[0] = '\0';
}
}
// 복사 생성자
MyString(const MyString& other) : buffer(nullptr), length(other.length) {
buffer = new char[length + 1];
strcpy(buffer, other.buffer);
}
// 이동 생성자
MyString(MyString&& other) noexcept : buffer(nullptr), length(0) {
// 리소스 이동
buffer = other.buffer;
length = other.length;
// 원본 객체 무효화
other.buffer = nullptr;
other.length = 0;
}
// 소멸자
~MyString() {
delete[] buffer;
}
// 복사 대입 연산자
MyString& operator=(const MyString& other) {
if (this != &other) {
// 기존 리소스 해제
delete[] buffer;
// 새 리소스 할당
length = other.length;
buffer = new char[length + 1];
strcpy(buffer, other.buffer);
}
return *this;
}
// 이동 대입 연산자
MyString& operator=(MyString&& other) noexcept {
if (this != &other) {
// 기존 리소스 해제
delete[] buffer;
// 리소스 이동
buffer = other.buffer;
length = other.length;
// 원본 객체 무효화
other.buffer = nullptr;
other.length = 0;
}
return *this;
}
// 문자열 길이 반환
size_t getLength() const {
return length;
}
// C 스타일 문자열 반환
const char* getCString() const {
return buffer;
}
// 두 문자열 연결
MyString concat(const MyString& other) const {
size_t newLength = length + other.length;
char* newBuffer = new char[newLength + 1];
strcpy(newBuffer, buffer);
strcat(newBuffer, other.buffer);
MyString result;
delete[] result.buffer;
result.buffer = newBuffer;
result.length = newLength;
return result;
}
// 문자열 출력
void print() const {
std::cout << buffer << std::endl;
}
};
int main() {
// 기본 생성자
MyString str1;
std::cout << "str1 (빈 문자열): ";
str1.print();
// 매개변수가 있는 생성자
MyString str2("Hello, World!");
std::cout << "str2: ";
str2.print();
std::cout << "str2 길이: " << str2.getLength() << std::endl;
// 복사 생성자
MyString str3 = str2;
std::cout << "str3 (str2 복사): ";
str3.print();
// 대입 연산자
str1 = str3;
std::cout << "str1 = str3: ";
str1.print();
// 문자열 연결
MyString str4 = str1.concat(MyString(" C++ is fun!"));
std::cout << "연결된 문자열: ";
str4.print();
// 이동 생성자 및 이동 대입 연산자 테스트
MyString str5 = std::move(str4);
std::cout << "str5 (str4에서 이동): ";
str5.print();
// str4는 이제 비어 있어야 함
std::cout << "이동 후 str4 길이: " << str4.getLength() << std::endl;
std::cout << "이동 후 str4: ";
str4.print();
return 0;
}
문제 2: 링크드 리스트 구현
#include <iostream>
// 노드 구조체
struct Node {
int data;
Node* next;
// 생성자
Node(int value) : data(value), next(nullptr) {}
};
// 연결 리스트 클래스
class LinkedList {
private:
Node* head;
public:
// 기본 생성자
LinkedList() : head(nullptr) {}
// 소멸자
~LinkedList() {
clear();
}
// 리스트의 앞에 노드 추가
void pushFront(int value) {
Node* newNode = new Node(value);
newNode->next = head;
head = newNode;
}
// 리스트의 끝에 노드 추가
void pushBack(int value) {
Node* newNode = new Node(value);
// 빈 리스트인 경우
if (head == nullptr) {
head = newNode;
return;
}
// 마지막 노드 찾기
Node* current = head;
while (current->next != nullptr) {
current = current->next;
}
// 마지막 노드에 새 노드 연결
current->next = newNode;
}
// 특정 위치에 노드 삽입
bool insertAt(int position, int value) {
// 위치가 0보다 작으면 실패
if (position < 0) {
return false;
}
// 위치가 0이면 앞에 추가
if (position == 0) {
pushFront(value);
return true;
}
// 삽입 위치의 이전 노드 찾기
Node* current = head;
for (int i = 0; i < position - 1; i++) {
if (current == nullptr) {
return false; // 위치가 범위를 벗어남
}
current = current->next;
}
// 현재 노드가 nullptr이면 위치가 범위를 벗어남
if (current == nullptr) {
return false;
}
// 새 노드 생성 및 연결
Node* newNode = new Node(value);
newNode->next = current->next;
current->next = newNode;
return true;
}
// 리스트의 앞에서 노드 제거
bool popFront() {
if (head == nullptr) {
return false; // 빈 리스트
}
Node* temp = head;
head = head->next;
delete temp;
return true;
}
// 리스트의 끝에서 노드 제거
bool popBack() {
if (head == nullptr) {
return false; // 빈 리스트
}
// 리스트에 노드가 하나만 있는 경우
if (head->next == nullptr) {
delete head;
head = nullptr;
return true;
}
// 마지막 노드의 이전 노드 찾기
Node* current = head;
while (current->next->next != nullptr) {
current = current->next;
}
// 마지막 노드 삭제
delete current->next;
current->next = nullptr;
return true;
}
// 특정 위치의 노드 제거
bool removeAt(int position) {
if (head == nullptr || position < 0) {
return false;
}
// 첫 번째 노드 제거
if (position == 0) {
return popFront();
}
// 제거할 노드의 이전 노드 찾기
Node* current = head;
for (int i = 0; i < position - 1; i++) {
if (current->next == nullptr) {
return false; // 위치가 범위를 벗어남
}
current = current->next;
}
// 제거할 노드가 없는 경우
if (current->next == nullptr) {
return false;
}
// 노드 제거
Node* temp = current->next;
current->next = temp->next;
delete temp;
return true;
}
// 특정 값 검색
bool contains(int value) const {
Node* current = head;
while (current != nullptr) {
if (current->data == value) {
return true;
}
current = current->next;
}
return false;
}
// 특정 값의 첫 번째 인덱스 찾기
int indexOf(int value) const {
Node* current = head;
int index = 0;
while (current != nullptr) {
if (current->data == value) {
return index;
}
current = current->next;
index++;
}
return -1; // 값을 찾지 못함
}
// 모든 노드 제거
void clear() {
while (head != nullptr) {
Node* temp = head;
head = head->next;
delete temp;
}
}
// 리스트가 비어 있는지 확인
bool isEmpty() const {
return head == nullptr;
}
// 리스트 출력
void print() const {
if (isEmpty()) {
std::cout << "빈 리스트" << std::endl;
return;
}
Node* current = head;
while (current != nullptr) {
std::cout << current->data;
if (current->next != nullptr) {
std::cout << " -> ";
}
current = current->next;
}
std::cout << std::endl;
}
};
int main() {
LinkedList list;
// 노드 추가
std::cout << "노드 추가(1, 2, 3): ";
list.pushBack(1);
list.pushBack(2);
list.pushBack(3);
list.print();
// 앞에 노드 추가
std::cout << "앞에 노드 추가(0): ";
list.pushFront(0);
list.print();
// 특정 위치에 노드 삽입
std::cout << "위치 2에 노드 삽입(10): ";
list.insertAt(2, 10);
list.print();
// 앞에서 노드 제거
std::cout << "앞에서 노드 제거: ";
list.popFront();
list.print();
// 끝에서 노드 제거
std::cout << "끝에서 노드 제거: ";
list.popBack();
list.print();
// 특정 위치의 노드 제거
std::cout << "위치 1의 노드 제거: ";
list.removeAt(1);
list.print();
// 값 검색
int searchValue = 1;
std::cout << searchValue << "이 리스트에 "
<< (list.contains(searchValue) ? "있습니다." : "없습니다.") << std::endl;
// 값의 인덱스 찾기
int findValue = 2;
int index = list.indexOf(findValue);
if (index != -1) {
std::cout << findValue << "의 인덱스: " << index << std::endl;
} else {
std::cout << findValue << "을 찾을 수 없습니다." << std::endl;
}
// 모든 노드 제거
std::cout << "모든 노드 제거 후: ";
list.clear();
list.print();
return 0;
}
'Programming Languages > C++' 카테고리의 다른 글
| 클래스 템플릿 기초 (0) | 2025.03.28 |
|---|---|
| 템플릿 (0) | 2025.03.28 |
| 고급 포인터 주제 (0) | 2025.03.28 |
| 참조 (0) | 2025.03.28 |
| 동적 메모리 할당 (0) | 2025.03.28 |