当前位置: 首页 > news >正文

2.5 动态字符串 String (完整源码)

C++自学精简教程 目录(必读)

C++数据结构与算法实现(目录)

本文的实现基本上和 动态数组 vector 是一样的。

因为大部分接口都一样。

所以,本文就直接给出全部的源码和运行结果。

//------下面的代码是用来测试你的代码有没有问题的辅助代码,你无需关注------
#include <algorithm>
#include <cstdlib>
#include <iostream> 
#include <vector>
#include <utility>
using namespace std;
struct Record { Record(void* ptr1, size_t count1, const char* location1, int line1, bool is) :ptr(ptr1), count(count1), line(line1), is_array(is) { int i = 0; while ((location[i] = location1[i]) && i < 100) { ++i; } }void* ptr; size_t count; char location[100] = { 0 }; int line; bool is_array = false; bool not_use_right_delete = false; }; bool operator==(const Record& lhs, const Record& rhs) { return lhs.ptr == rhs.ptr; }std::vector<Record> myAllocStatistic; void* newFunctionImpl(std::size_t sz, char const* file, int line, bool is) { void* ptr = std::malloc(sz); myAllocStatistic.push_back({ ptr,sz, file, line , is }); return ptr; }void* operator new(std::size_t sz, char const* file, int line) { return newFunctionImpl(sz, file, line, false); }void* operator new [](std::size_t sz, char const* file, int line)
{return newFunctionImpl(sz, file, line, true);
}void operator delete(void* ptr) noexcept { Record item{ ptr, 0, "", 0, false }; auto itr = std::find(myAllocStatistic.begin(), myAllocStatistic.end(), item); if (itr != myAllocStatistic.end()) { auto ind = std::distance(myAllocStatistic.begin(), itr); myAllocStatistic[ind].ptr = nullptr; if (itr->is_array) { myAllocStatistic[ind].not_use_right_delete = true; } else { myAllocStatistic[ind].count = 0; }std::free(ptr); } }void operator delete[](void* ptr) noexcept { Record item{ ptr, 0, "", 0, true }; auto itr = std::find(myAllocStatistic.begin(), myAllocStatistic.end(), item); if (itr != myAllocStatistic.end()) { auto ind = std::distance(myAllocStatistic.begin(), itr); myAllocStatistic[ind].ptr = nullptr; if (!itr->is_array) { myAllocStatistic[ind].not_use_right_delete = true; } else { myAllocStatistic[ind].count = 0; }std::free(ptr); } }
#define new new(__FILE__, __LINE__)
struct MyStruct { void ReportMemoryLeak() { std::cout << "Memory leak report: " << std::endl; bool leak = false; for (auto& i : myAllocStatistic) { if (i.count != 0) { leak = true; std::cout << "leak count " << i.count << " Byte" << ", file " << i.location << ", line " << i.line; if (i.not_use_right_delete) { cout << ", not use right delete. "; }	cout << std::endl; } }if (!leak) { cout << "No memory leak." << endl; } }~MyStruct() { ReportMemoryLeak(); } }; static MyStruct my;
//------上面的代码是用来测试你的代码有没有问题的辅助代码,你无需关注------//------check用来检查有没有bug begin------
#include <iostream> 
using namespace std;
void check_do(bool b, int line = __LINE__) { if (b) { cout << "line:" << line << " Pass" << endl; } else { cout << "line:" << line << " Ohh! not passed!!!!!!!!!!!!!!!!!!!!!!!!!!!" << " " << endl; exit(0); } }
#define check(msg)  check_do(msg, __LINE__);
//------check用来检查有没有bug end------class String
{friend std::ostream& operator<<(std::ostream& os, const String& str);
public:String(void);String(const char* data, int length);String(const char* data);String(const String& from);//1 复制构造String& operator = (const String& from);//2 赋值操作符size_t size(void) const { return m_length; }bool empty(void) const { return m_length == 0; }~String();//3 析构函数bool operator == (const String& other);bool operator != (const String& other) { return !(*this == other); }String operator+(const String& other);void push_back(char c);void clear(void);protected:void copy(const char* data, size_t length);
private:char* m_data;size_t m_length;int m_capacity = 0;
};
void String::push_back(char c)
{if (m_capacity > m_length)//直接追加到最后一个{m_data[m_length++] = c;}else//只有满了的那一瞬间,才翻倍开辟新空间{m_capacity = (m_capacity == 0 ? 10 : m_capacity + m_capacity);auto pNewArray = new char[m_capacity];//拷贝老数据for (size_t i = 0; i < m_length; i++){pNewArray[i] = m_data[i];}//追加最新的末尾元素pNewArray[m_length++] = c;delete[] m_data;m_data = pNewArray;}
}
std::ostream& operator<<(std::ostream& os, const String& str)
{for (size_t i = 0; i < str.m_length; ++i){os << str.m_data[i];}return os;
}
String::String(void) :m_data(nullptr), m_length(0)
{
}
String::~String()
{clear();
}
bool String::operator==(const String& other)
{if (other.m_length != this->m_length){return false;}for (size_t i = 0; i < m_length; i++){auto c1 = m_data[i];auto c2 = other.m_data[i];if (c1 != c2){return false;}}return true;
}
String String::operator+(const String& other)
{if (other.empty()){return *this;}String result;result.m_length = m_length + other.m_length;result.m_data = new char[result.m_length];for (size_t i = 0; i < m_length; i++){result.m_data[i] = m_data[i];}for (size_t i = 0; i < other.m_length; i++){result.m_data[m_length + i] = other.m_data[i];}return result;
}
String::String(const char* data, int _length) :m_data(nullptr), m_length(0)
{copy(data, _length);
}
String::String(const char* data) : m_data(nullptr), m_length(0)
{int stringLength = 0;auto p = data;while (*p != '\0'){++stringLength;++p;}copy(data, stringLength);
}
String::String(const String& from) : m_data(nullptr), m_length(0)
{if (from.m_data != m_data){copy(from.m_data, from.m_length);}
}
String& String::operator=(const String& from)
{if (&from != this){copy(from.m_data, from.m_length);}return *this;
}void String::clear(void)
{if (nullptr != m_data){delete[] m_data;m_data = nullptr;m_length = 0;}
}
void String::copy(const char* data, size_t length)
{clear();m_data = new char[length];for (size_t i = 0; i < length; ++i){m_data[i] = data[i];}m_length = length;
}String GetLeftValue(void)
{String s("String");return s;
}
void Test0(void)
{auto leftValue1 = GetLeftValue();String left2;left2 = (left2 = leftValue1);std::vector<String> arrStr(2);left2 = (arrStr[0]);String arr[2];left2 = (arr[0]);auto p = arr;left2 = (*p);arrStr.push_back(left2);
}
void Test_empty(void)
{String s("");check(s.empty());check(s.size() == 0);check(s == "");
}
void Test_clear(void)
{String s2;{String s("123");check(s == "123");s2 = s;s.clear();s.clear();check(s.size() == 0);check(s.empty());check(s == "");check(s2 != s);}check(s2 == "123");
}
void Test_copy(void)
{{String s1("Hello World!");//constructorString s2(s1);//copy constructorcout << s2 << endl;//operator<<check(s1.size() == s2.size());//sizeString s3;s3 = s2;check(s3 == s1);check(!s3.empty());check(!s1.empty());s1 = s2 = s2 = s1;check(s1.size() == s2.size());//sizecheck(s3 == s1);check(!s3.empty());check(!s1.empty());check(s1 == "Hello World!");s1.clear();check(s1.empty());check(s1 != s2);check(s2 == s3);}{String s;check(s.empty());}// +{String s1("Hello World!");//constructorString s2("Hello World!");//constructorString s3(s1 + s2);check(s3.size() == s1.size() + s2.size());check(s3 == s1 + s2);check(s3 == "Hello World!Hello World!");}{const char* p = "Hello World !";String s(p);check(s == p);}//push_back{String s;check(s.size() == 0);check(s.empty());s.push_back('a');check(s == "a");for (size_t i = 0; i < 100; i++){s.push_back('a');}check(s.size() == 101);}
}String GetValue(void)
{String a;String b;b = a;return a;
}int main()
{Test0();Test_empty();Test_copy();Test_clear();return 0;
}

正确的运行结果:

line:194 Pass
line:195 Pass
line:196 Pass
Hello World!
line:220 Pass
line:223 Pass
line:224 Pass
line:225 Pass
line:227 Pass
line:228 Pass
line:229 Pass
line:230 Pass
line:231 Pass
line:233 Pass
line:234 Pass
line:235 Pass
line:239 Pass
line:246 Pass
line:247 Pass
line:248 Pass
line:253 Pass
line:258 Pass
line:259 Pass
line:261 Pass
line:266 Pass
line:203 Pass
line:207 Pass
line:208 Pass
line:209 Pass
line:210 Pass
line:212 Pass
Memory leak report:
No memory leak.

欢迎参考借鉴,如有问题欢迎评论指出!

祝你好运!

相关文章:

2.5 动态字符串 String (完整源码)

C自学精简教程 目录(必读) C数据结构与算法实现&#xff08;目录&#xff09; 本文的实现基本上和 动态数组 vector 是一样的。 因为大部分接口都一样。 所以&#xff0c;本文就直接给出全部的源码和运行结果。 //------下面的代码是用来测试你的代码有没有问题的辅助代码…...

Ansible之变量

一&#xff09;Ansible变量介绍 我们在PlayBook⼀节中&#xff0c;将PlayBook类⽐成了Linux中的shell。 那么它作为⼀⻔Ansible特殊的语⾔&#xff0c;肯定要涉及到变量定义、控 制结构的使⽤等特性。 在这⼀节中主要讨论变量的定义和使⽤ 二&#xff09;变量命名规则 变量的…...

自动化测试面试常见技术题目

1&#xff1a;一行代码实现1--100之和 print(sum(list(range(1,101)))) 2&#xff1a;如何在一个函数内部修改全局变量 global  修改全局变量 局部作用域只能调用全局作用域的变量&#xff0c;但是不熊修改全局作用域的变量&#xff0c;如果想要修改全局作用域的变量需要gl…...

aarch64 arm64 部署 stable diffusion webui 笔记 【2】继续安装其他依赖 gfpgan

接上篇 aarch64 arm64 部署 stable diffusion webui 笔记 【1】准备 venv 安装pytorch 验证cuda_hkNaruto的博客-CSDN博客 编辑requirements_versions.txt&#xff0c;注释掉torch 启动webui.sh (venv) [rootceph3 stable-diffusion-webui]# useradd yeqiang useradd&#xf…...

使用ECS和RDS部署WordPress,搭建个人博客并使用域名访问

目录 一、准备工作 1、准备ECS服务器 2、创建数据库账号和密码 二、部署环境 1、远程连接 2、安装Apache服务 3、部署WordPress 三、对博客的优化并使用域名访问 1、博客的设计优化 1.1 插件的使用 1.2 博客的设计介绍 2、使用域名访问 四、个人博客部署的心得 1…...

C# Winform 简单排期实现(DevExpress TreeList)

排期的需求在很多任务安排的系统中都有相应的需求&#xff0c;原生的Winform控件并未提供相应的控件&#xff0c;一般都是利用DataGridViewTreeView组合完成相应的需求&#xff0c;实现起来比较麻烦。用过DevExpress控件集的开发者应该知道&#xff0c;DevExpress WinForm提供了…...

2023高教社杯国赛数学建模C题思路+模型+代码(9.7晚开赛后第一时间更新)

目录 1.C题思路模型&#xff1a;9.7晚上比赛开始后&#xff0c;第一时间更新&#xff0c;获取见文末名片 2.竞赛注意事项&#xff1a;包括比赛流程&#xff0c;任务分配&#xff0c;时间把控&#xff0c;论文润色&#xff0c;已经发布在文末名片中 3.常用国赛数学建模算法 …...

QT6中添加串口模块SerialPort最简单方法

qt6.2.3以上版本已经开始支持SerialPort包了&#xff0c;不用在傻傻的自己去编译包了。 在安装的时候勾选SerialPort即可。 等着安装完即可。 如果已经安装完了的小伙伴&#xff0c;可以用 从新打开维护 选择增加或者删除组件 即可从新选择组件...

LeetCode每日一题:1123. 最深叶节点的最近公共祖先(2023.9.6 C++)

目录 1123. 最深叶节点的最近公共祖先 题目描述&#xff1a; 实现代码与解析&#xff1a; dfs 原理思路&#xff1a; 1123. 最深叶节点的最近公共祖先 题目描述&#xff1a; 给你一个有根节点 root 的二叉树&#xff0c;返回它 最深的叶节点的最近公共祖先 。 回想一下&…...

Oracle查看锁表和正在执行的Sql

查看当前被锁的表&#xff08;需要有管理员权限&#xff09;&#xff1a; --查看锁表进程SQL语句1&#xff1a; select sess.sid,sess.serial#,lo.oracle_username,lo.os_user_name,ao.object_name,lo.locked_modefrom v$locked_object lo, dba_objects ao, v$session sesswh…...

Linux centos 卸载 ceph

在CentOS上卸载Ceph的操作步骤&#xff1a; 1. 停止Ceph集群&#xff1a;首先&#xff0c;你需要停止Ceph集群中的所有服务。在每个节点上运行以下命令来停止所有服务 systemctl stop ceph.target 2. 卸载Ceph软件包&#xff1a;在每个节点上&#xff0c;使用yum包管理器卸载C…...

ElementUI浅尝辄止34:Radio 单选框

在一组备选项中进行单选 1.如何使用&#xff1f; 由于选项默认可见&#xff0c;不宜过多&#xff0c;若选项过多&#xff0c;建议使用 Select 选择器。 //要使用 Radio 组件&#xff0c;只需要设置v-model绑定变量&#xff0c;选中意味着变量的值为相应 Radio label属性的值&…...

开始MySQL之路——MySQL三大日志(binlog、redo log和undo log)概述详解

前言 MySQL实现事务、崩溃恢复、集群的主从复制&#xff0c;底层都离不开日志&#xff0c;所以日志是MySQL的精华所在。只有了解MySQL日志&#xff0c;才算是彻底搞懂MySQL。 日志是mysql数据库的重要组成部分&#xff0c;记录着数据库运行期间各种状态信息。mysql日志主要包…...

router基础使用

1.安装router npm i vue-router3 安装后 2.写出路由界面 接着 3.配置路由 import Vue from vue import VueRouter from vue-router import Home from "../views/Home.vue" import About from "../views/About.vue" Vue.use(VueRouter)const routes …...

亚马逊云科技人工智能内容审核服务:大大降低生成不安全内容的风险

生成式人工智能技术发展日新月异&#xff0c;现在已经能够根据文本输入生成文本和图像。Stable Diffusion是一种文本转图像模型&#xff0c;可以创建栩栩如生的图像应用。通过Amazon SageMaker JumpStart&#xff0c;使用Stable Diffusion模型轻松地从文本生成图像。 尽管生成式…...

2023年高教社杯数学建模思路 - 案例:最短时间生产计划安排

文章目录 0 赛题思路1 模型描述2 实例2.1 问题描述2.2 数学模型2.2.1 模型流程2.2.2 符号约定2.2.3 求解模型 2.3 相关代码2.4 模型求解结果 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 最短时…...

算法工程题(二叉树递归)

* 题意说明&#xff1a; * 给你两棵二叉树的根节点 p 和 q &#xff0c;编写一个函数来检验这两棵树是否相同。 * 如果两个树在结构上相同&#xff0c;并且节点具有相同的值&#xff0c;则认为它们是相同的。 * * 示例 1&#xff1a; * 输入&#xff1a;p [1,2,3]…...

“指针跃动”受邀参加全球贸易服务峰会

“指针跃动”受邀参加全球贸易服务峰会 有“服”同享 共赢未来 引子 在全球化日益盛行的今天&#xff0c;贸易不再仅仅是物质的交流&#xff0c;更涉及到服务、理念、文化和科技的共享。中国国际服务贸易交易会全球贸易服务峰会&#xff0c;就是这个趋势的集中体现。在这次峰会…...

Go Web开发的高级技巧和最佳实践

Go Web开发的高级技巧和最佳实践 欢迎来到Go语言Web开发的高级技巧和最佳实践指南。在这篇文章中&#xff0c;我们将深入探讨Go语言Web应用程序的高级主题&#xff0c;包括性能优化、安全性、部署和微服务架构。 性能优化 性能是Web应用程序的关键因素之一。Go语言以其出色的…...

Verilog 基础知识

1、数值种类 Verilog HDL 有下列四种基本的值来表示硬件电路中的电平逻辑&#xff1a; 0&#xff1a;逻辑 0 或 “假”1&#xff1a;逻辑 1 或 “真”x 或 X&#xff1a;未知 x 意味着信号数值的不确定&#xff0c;即在实际电路里&#xff0c;信号可能为 1&#xff0c;也可能…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist

现象&#xff1a; android studio报错&#xff1a; [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决&#xff1a; 不要动CMakeLists.…...

elementUI点击浏览table所选行数据查看文档

项目场景&#xff1a; table按照要求特定的数据变成按钮可以点击 解决方案&#xff1a; <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...

Axure 下拉框联动

实现选省、选完省之后选对应省份下的市区...

WEB3全栈开发——面试专业技能点P7前端与链上集成

一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染&#xff08;SSR&#xff09;与静态网站生成&#xff08;SSG&#xff09; 框架&#xff0c;由 Vercel 开发。它简化了构建生产级 React 应用的过程&#xff0c;并内置了很多特性&#xff1a; ✅ 文件系…...