news 2026/4/26 21:28:46

C++ 类设计实践(一):自定义 String 类与顺序栈

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++ 类设计实践(一):自定义 String 类与顺序栈

引言

在学完 C++ 的类、构造函数、析构函数、拷贝控制、运算符重载、模板等核心知识后,动手设计一个完整的类是最好的巩固方式。

今天,我将通过两个实践项目来检验这些知识的掌握程度:

  1. 自定义 String 类:模拟标准库std::string的核心功能

  2. 顺序栈 Stack 类模板:实现一个通用的栈容器,并完成括号匹配检测

这两个项目涵盖了深拷贝、运算符重载、模板编程、动态内存管理等重要知识点。


第一部分:自定义 String 类

一、设计目标

实现一个类似std::string的字符串类String,支持以下功能:

  • 构造与析构

  • 深拷贝(拷贝构造)

  • 下标访问[]

  • 字符串追加append+=

  • 字符串查找find/rfind

  • 字符串插入insert

  • 输出流运算符<<

二、类设计

#include <iostream> #include <cstring> using namespace std; #define BUF_SIZE 8192 class String final { private: char* buffer; // 字符缓冲区 int len; // 字符串长度 public: // 1. 默认构造函数 String() { buffer = new char[BUF_SIZE]{0}; len = 0; } // 2. 带参构造函数(C风格字符串) String(const char* s) { buffer = new char[BUF_SIZE]{0}; memcpy(buffer, s, strlen(s)); len = strlen(s); } // 3. 拷贝构造函数(深拷贝) String(const String& o) { buffer = new char[BUF_SIZE]{0}; memcpy(buffer, o.buffer, o.len); len = o.len; } // 4. 析构函数 ~String() { delete[] buffer; } // 5. 获取长度 int length() const { return len; } // 6. 下标访问运算符(可修改) char& operator[](int index) { static char nochar = '\0'; if (index < 0 || index >= len) return nochar; return buffer[index]; } // 7. 追加字符串 String& append(const char* s) { int s_len = strlen(s); if (len + s_len >= BUF_SIZE) { // 扩容逻辑(可优化) return *this; } memcpy(buffer + len, s, s_len); len += s_len; return *this; } String& operator+=(const char* s) { return append(s); } // 8. 插入字符串 String insert(int pos, const char* ns) const { String result; int ns_len = strlen(ns); // 复制 pos 之前的内容 memcpy(result.buffer, buffer, pos); // 插入新字符串 memcpy(result.buffer + pos, ns, ns_len); // 复制剩余内容 memcpy(result.buffer + pos + ns_len, buffer + pos, len - pos); result.len = len + ns_len; return result; } // 9. 查找子串(从左到右) int find(const char* s) const { int s_len = strlen(s); if (s_len == 0 || s_len > len) return -1; for (int i = 0; i <= len - s_len; i++) { if (buffer[i] == s[0]) { bool found = true; for (int j = 1; j < s_len; j++) { if (buffer[i + j] != s[j]) { found = false; break; } } if (found) return i; } } return -1; } // 10. 查找子串(从右到左) int rfind(const char* s) const { int s_len = strlen(s); if (s_len == 0 || s_len > len) return -1; for (int i = len - s_len; i >= 0; i--) { if (buffer[i] == s[0]) { bool found = true; for (int j = 1; j < s_len; j++) { if (buffer[i + j] != s[j]) { found = false; break; } } if (found) return i; } } return -1; } // 11. 输出运算符重载(成员函数版本) ostream& operator<<(ostream& cout) const { cout << buffer; return cout; } }; // 12. 全局输出运算符重载 ostream& operator<<(ostream& cout, const String& s) { return s.operator<<(cout); }

三、测试代码

int main() { // 1. 基本构造与输出 String s = "hello"; cout << s << endl; // hello cout << "长度: " << s.length() << endl; // 5 // 2. 下标修改 s[1] = 'i'; cout << "修改后: " << s << endl; // hillo // 3. 追加 s.append(", diyi").append(" and "); s += "lucy!"; cout << s << endl; // hillo, diyi and lucy! // 4. 插入 String s2 = s.insert(5, " everybody"); cout << s2 << endl; // hillo everybody, diyi and lucy! // 5. 查找 cout << "\"diyi\"位置: " << s2.find("diyi") << endl; // 17 s2[s2.find("diyi")] = 'j'; cout << "替换后: " << s2 << endl; // hillo everybody, jiyi and lucy! // 6. 反向查找 String s3 = "hi,diyi! what are you doing? diyi say sleep!"; cout << "\n原字符串: " << s3 << endl; cout << "第一次出现 diyi: " << s3.find("diyi") << endl; cout << "最后一次出现 diyi: " << s3.rfind("diyi") << endl; s3[s3.rfind("diyi")] = 'k'; cout << "替换后: " << s3 << endl; return 0; }

第二部分:顺序栈类模板

一、设计目标

实现一个通用的顺序栈(基于数组),支持任意数据类型,并完成括号匹配检测应用。

栈的特点:后进先出(LIFO,Last In First Out)

二、类模板设计

#define STACK_SIZE 128 template<class T> class Stack { private: T* data; // 动态数组 int last; // 栈顶索引(也是元素个数) int maxSize; // 最大容量 public: // 构造函数 Stack(int maxSize = -1) { this->maxSize = (maxSize == -1) ? STACK_SIZE : maxSize; data = new T[this->maxSize]{ T() }; last = 0; } // 禁止拷贝(栈通常不需要拷贝) Stack(const Stack& o) = delete; void operator=(const Stack& o) = delete; // 析构函数 ~Stack() { delete[] data; } // 入栈 void push(T item) { if (last < maxSize) { data[last++] = item; } } // 出栈 void pop() { if (last > 0) { data[last - 1] = T(); // 重置为默认值 last--; } } // 查看栈顶元素 T peek() const { if (last == 0) return T(); return data[last - 1]; } // 获取元素个数 int size() const { return last; } // 判断是否为空 bool isEmpty() const { return last == 0; } };

三、测试代码

1. 基本类型测试
int main() { Stack<int> s1; s1.push(10); s1.push(20); s1.push(100); cout << "栈大小: " << s1.size() << endl; // 3 cout << "栈顶: " << s1.peek() << endl; // 100 cout << "弹出顺序: "; while (s1.size() > 0) { cout << s1.peek() << " "; s1.pop(); } cout << endl; // 100 20 10 return 0; }
2. 自定义类型测试
class Person { private: string name; int pid; public: Person() : name(""), pid(0) {} Person(string name, int pid) : name(name), pid(pid) {} void show() const { cout << name << ", " << pid << endl; } }; int main() { Stack<Person> s2; s2.push(Person("dier", 1010)); s2.push(Person("Jack", 2010)); s2.push(Person("Lucy", 1030)); s2.push(Person("Mack", 5010)); while (s2.size() > 0) { s2.peek().show(); s2.pop(); } // 输出顺序(后进先出): // Mack, 5010 // Lucy, 1030 // Jack, 2010 // dier, 1010 return 0; }

第三部分:经典应用——括号匹配检测

一、问题描述

给定一个包含括号()[]{}的字符串,判断括号是否匹配。

合法示例()([]){([[]])}
非法示例(][)((()))

二、算法思路

三、代码实现

int main() { string s; cout << "请输入测试括号的字符串: "; cin >> s; string lefts = "([{"; string rights = ")]}"; Stack<char> stack(128); bool isValid = true; for (char ch : s) { // 1. 左括号:压栈 if (lefts.find(ch) != string::npos) { stack.push(ch); } // 2. 右括号:匹配检查 else if (rights.find(ch) != string::npos) { if (stack.isEmpty()) { isValid = false; break; } char top = stack.peek(); if ((top == '(' && ch == ')') || (top == '[' && ch == ']') || (top == '{' && ch == '}')) { stack.pop(); } else { isValid = false; break; } } } if (isValid && stack.isEmpty()) { cout << "括号合法!" << endl; } else { cout << "括号不合法!" << endl; } return 0; }
# 合法示例 请输入测试括号的字符串: ({[]}) 括号合法! # 非法示例 请输入测试括号的字符串: (] 括号不合法! # 左括号多余 请输入测试括号的字符串: ((() 括号不合法! # 右括号多余 请输入测试括号的字符串: ())) 括号不合法!

总结

一、自定义 String 类核心知识点

知识点应用
构造函数默认构造、带参构造、拷贝构造(深拷贝)
析构函数delete[]释放动态内存
运算符重载[]+=<<
访问控制private成员、public接口
const 成员函数length()find()rfind()

二、Stack 类模板核心知识点

知识点应用
类模板template<class T>支持任意类型
动态内存new[]/delete[]
拷贝控制禁用拷贝(= delete
LIFO 特性push/pop/peek

三、两个项目的关联

项目核心难点旁白
String 类深拷贝、运算符重载模拟标准库行为
Stack 类模板模板编程、泛型可存储任意类型,包括 String

这两个实践项目覆盖了 C++ 类的核心知识点:

  1. String 类:重点练习了深拷贝(拷贝构造函数)、运算符重载([]+=<<)、动态内存管理。

  2. Stack 类模板:重点练习了模板编程、泛型设计、后进先出的数据结构,并完成了括号匹配的经典应用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/26 21:25:21

Docker容器化部署Halo博客:开箱即用与生产级实践指南

1. 项目概述&#xff1a;一个快速上手的Halo博客容器镜像最近在折腾个人博客&#xff0c;想找一个既轻量又功能齐全的开源方案&#xff0c;Halo这个项目进入了我的视线。它是一个现代化的开源博客系统&#xff0c;用Java开发&#xff0c;但部署起来对新手来说可能有点门槛。就在…

作者头像 李华
网站建设 2026/4/26 21:21:27

3步解锁:让任天堂控制器在Windows上重获新生的终极兼容方案

3步解锁&#xff1a;让任天堂控制器在Windows上重获新生的终极兼容方案 【免费下载链接】WiinUPro 项目地址: https://gitcode.com/gh_mirrors/wi/WiinUPro 你是否曾有过这样的经历&#xff1f;刚买的Switch Pro控制器在电脑上毫无反应&#xff0c;只能无奈地看着它在抽…

作者头像 李华
网站建设 2026/4/26 21:20:23

终极解决方案:3分钟搞定Windows与iPhone网络共享驱动安装

终极解决方案&#xff1a;3分钟搞定Windows与iPhone网络共享驱动安装 【免费下载链接】Apple-Mobile-Drivers-Installer Powershell script to easily install Apple USB and Mobile Device Ethernet (USB Tethering) drivers on Windows! 项目地址: https://gitcode.com/gh_…

作者头像 李华