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

动态字符串 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.

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

祝你好运!

相关文章:

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

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

【深度学习】实验05 构造神经网络示例

文章目录 构造神经网络1. 导入相关库2. 定义一个层3. 构造数据集4. 定义基本模型5. 变量初始化6. 开始训练 构造神经网络 注明&#xff1a;该代码用来训练一个神经网络&#xff0c;网络拟合y x^2-0.5noise&#xff0c;该神经网络的结构是输入层为一个神经元&#xff0c;隐藏层…...

用了这么久SpringBoot却还不知道的一个小技巧

前言 你可能调第三方接口喜欢启动application&#xff0c;修改&#xff0c;再启动&#xff0c;再修改&#xff0c;顺便还有个不喜欢写JUnitTest的习惯。 你可能有一天想要在SpringBoot启动后&#xff0c;立马想要干一些事情&#xff0c;现在没有可能是你还没遇到。 那么SpringB…...

Websocket、SessionCookie、前端基础知识

目录 1.Websocket Websocket与HTTP的介绍 不同使用场景 Websocket链接过程 2.Session&Cookie Cookie的工作原理 Session的工作原理 区别 3.前端基础知识 1.Websocket Websocket与HTTP的介绍 HTTP&#xff1a; 1.HTTP是单向的&#xff0c;客户端发送请求&#xff0…...

【云原生进阶之PaaS中间件】第一章Redis-2.4缓存更新机制

1 缓存和数据库的数据一致性分析 1.1 Redis 中如何保证缓存和数据库双写时的数据一致性&#xff1f; 无论先操作db还是cache&#xff0c;都会有各自的问题&#xff0c;根本原因是cache和db的更新不是一个原子操作&#xff0c;因此总会有不一致的问题。想要彻底解决这种问题必须…...

Qt——事件处理详解

Qt事件处理 一、事件基础 事件是Qt应用程序中的基本构建块&#xff0c;它们代表了一些特定的行为或状态变化。事件可以是鼠标点击、键盘输入、窗口大小改变、定时器事件等。每个事件都是一个对象&#xff0c;继承自QEvent类。 二、事件常见类型 Qt中的事件分为多种类型&…...

基于位置管理的企业员工考勤打卡系统设计 微信小程序

员工考勤打卡系统设计app是针对员工必不可少的一个部分。在公司发展的整个过程中&#xff0c;员工考勤打卡系统设计app担负着最重要的角色。为满足如今日益复杂的管理需求&#xff0c;各类员工考勤打卡系统设计app程序也在不断改进。本课题所设计的 MVC基于HBuilder X的员工考勤…...

adb 查找应用包名,应用 Activity 等信息

列出设备上的包 不使用参数&#xff1a;adb shell pm list packages&#xff0c;打印设备/模拟器上的所有软件包 根据包名查看应用的activity 命令&#xff1a; dumpsys package 包名 adb shell dumpsys package 包名 petrel-cv96d:/data/app # dumpsys package com.instal…...

八、SpringBoot集成Kafka

目录 一、添加依赖二、SpringBoot 生产者三、SpringBoot 消费者 一、添加依赖 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><depend…...

联网智能实时监控静电离子风机的工作流程

联网智能实时监控静电离子风机是通过将静电离子风机与互联网连接&#xff0c;实现对其状态和性能的远程监控和管理。 具体实现该功能的方法可以包括以下几个步骤&#xff1a; 1. 传感器安装&#xff1a;在静电离子风机上安装适当的传感器&#xff0c;用于感知相关的参数&…...

第12章 微信支付

mini商城第12章 微信支付 一、课题 微信支付 二、回顾 1、分布式事务 2、分布式事务理论 3、掌握分布式事务解决方案模型 4、能基于Seata解决强一致性分布式事务 5、能基于RocketMQ解决柔性事务 三、目标 1、密码安全学 摘要加密 Base64 对称加密 2、微信支付 微信支…...

Java基础二十二(对集合元素排序比较)

对集合元素排序比较 1. 使用 Comparable 接口实现默认排序 Comparable 是 Java 中的一个接口&#xff0c;用于定义对象之间的排序规则。 实现了 Comparable 接口的类可以比较其对象的大小&#xff08;包装类都实现了该接口&#xff09;&#xff0c;从而可以在集合类&#xf…...

(15)线程的实例认识:同步,异步,并发,并发回调,事件,异步线程,UI线程

参看&#xff1a;https://www.bilibili.com/video/BV1xA411671D/?spm_id_from333.880.my_history.page.click&vd_source2a0404a7c8f40ef37a32eed32030aa18 下面是net framework版本 一、文件构成 1、界面如下。 (1)同步与异步有什么区别&#xff1f; …...

长胜证券:华为“黑科技”点燃A股炒作激情

8月29日&#xff0c;在未举行相关发布会的情况下&#xff0c;华为新款手机Mate60Pro悄然上线开售&#xff0c;并在一小时内售罄。 金融出资报记者注意到&#xff0c;跟着商场对新机重视的继续发酵&#xff0c;其中的各种技能打破也愈加受到重视&#xff0c;其影响很快扩散到资…...

Kubernetes(k8s)上部署redis5.0.14

Kubernetes上部署redis 环境准备创建命名空间 准备PV和PVC安装nfs准备PV准备PVC 部署redis创建redis的配置文件部署脚本挂载数据目录挂载配置文件通过指定的配置文件启动redis 集群内部访问外部链接Redis 环境准备 首先你需要一个Kubernetes环境&#xff0c;可参考我写的文章&…...

frida动态调试入门01——定位关键代码

说明 frida是一款Python工具可以方便对内存进行hook修改代码逻辑在移动端安全和逆向过程中常用到。 实战 嘟嘟牛登录页面hook 使用到的工具 1&#xff0c;jadx-gui 2&#xff0c;frida 定位关键代码 使用jadx-gui 进行模糊搜索&#xff0c;例如搜索encyrpt之类的加密关键…...

ASP.NET Core 8 的配置类 Configuration

Configuration Configuration 可以从两个途径设置&#xff1a; WebApplication创建的对象app.Configuration 属性WebApplicationBuilder 创建的 builder.Configuration 属性 app的Configuration优先级更高&#xff0c;host Configuration作为替补配置&#xff0c;因为app运行…...

MySql增量恢复

一、 使用二进制日志的时间点恢复 注意 本节和下一节中的许多示例都使用mysql客户端来处理mysqlbinlog生成的二进制日志输出。如果您的二进制日志包含\0&#xff08;null&#xff09;字符&#xff0c;那么mysql将无法解析该输出&#xff0c;除非您使用--binary模式选项调用它。…...

设计模式--装饰者模式(Decorator Pattern)

一、什么是装饰者模式&#xff08;Decorator Pattern&#xff09; 装饰者模式&#xff08;Decorator Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许你在不修改现有对象的情况下&#xff0c;动态地将新功能附加到对象上。这种模式通过创建一个包装类&#xff0c;…...

Spring三级缓存解决循环依赖

Spring三级缓存解决循环依赖 一 Spring bean对象的生命周期 二 三级缓存解决循环依赖 实现原理解析 spring利用singletonObjects, earlySingletonObjects, singletonFactories三级缓存去解决的&#xff0c;所说的缓存其实也就是三个Map 先实例化的bean会通过ObjectFactory半…...

Commit Mono版本管理指南:如何优雅地升级和回滚字体版本

Commit Mono版本管理指南&#xff1a;如何优雅地升级和回滚字体版本 【免费下载链接】commit-mono Commit Mono is an anonymous and neutral programming typeface. 项目地址: https://gitcode.com/gh_mirrors/co/commit-mono Commit Mono是一款匿名且中性的编程字体&a…...

告别复制粘贴!用Python+GoBot Pro 1.0,5分钟搞定Excel数据自动录入网页表单

告别复制粘贴&#xff01;用PythonGoBot Pro 1.0&#xff0c;5分钟搞定Excel数据自动录入网页表单 在数据驱动的时代&#xff0c;重复性劳动正成为效率的最大杀手。每天面对成百上千条Excel数据需要手动录入网页表单的场景&#xff0c;从市场调研、活动报名到用户注册&#xff…...

STR71X中断服务程序定位与Keil MDK配置详解

1. STR71X中断服务程序定位问题解析在基于ARM7架构的STR71X系列微控制器开发过程中&#xff0c;中断服务程序(ISR)的定位是一个关键但容易被忽视的技术细节。STR71X采用增强型中断控制器(EIC)&#xff0c;其硬件设计要求所有中断服务例程必须位于同一个64KB内存段内。这个限制源…...

One API 部署教程(下):使用指南

导读:前面两篇讲了本地和线上部署,现在 One API 已经跑起来了,接下来就是真正的使用环节! 理解核心概念 在开始之前,咱们先搞清楚几个关键概念,不然后面容易晕。 渠道(Channel):就是你的各个 AI 平台的 API Key。比如你有 DeepSeek 的 Key、OpenAI 的 Key、通义千问…...

普通人如何从零开始搭建自己的AI标题助手?低成本实战指南

就在今天&#xff0c;我刷到了一篇爆文&#xff0c;其标题乃是“用AI制作标题&#xff0c;短短3分钟就能产出100个爆款&#xff0c;而我的阅读量竟翻了5倍之多”&#xff0c;随后我点了进去&#xff0c;看过之后&#xff0c;又将其关掉&#xff0c;此时心里略微有那么点儿不是滋…...

ArcGIS 10.2也能用天地图!手把手教你用WMTS服务和lyr文件搞定低版本兼容

ArcGIS 10.2兼容天地图WMTS服务的工程级解决方案 在GIS项目实施过程中&#xff0c;我们常常会遇到软件版本滞后于服务更新的尴尬局面。天地图作为国内权威的地理信息服务&#xff0c;自2019年起仅支持ArcGIS 10.6及以上版本直接加载&#xff0c;这对仍在使用ArcGIS 10.2/10.3等…...

Perplexity财经数据查询失效的4个致命信号,第3个95%用户仍在踩坑——附权威校验脚本(Python版)

更多请点击&#xff1a; https://kaifayun.com 第一章&#xff1a;Perplexity财经数据查询失效的4个致命信号&#xff0c;第3个95%用户仍在踩坑——附权威校验脚本&#xff08;Python版&#xff09; 信号一&#xff1a;HTTP状态码非200但响应体含“success”: true Perplexit…...

别再只用K-Means了!用DBSCAN搞定非球形数据聚类(附Python代码实战)

突破K-Means局限&#xff1a;DBSCAN在复杂数据聚类中的实战指南 当数据科学家面对那些"不听话"的非球形分布数据集时&#xff0c;传统K-Means算法往往会束手无策。想象一下这样的场景&#xff1a;你的客户分群数据呈现出笑脸形状的分布&#xff0c;或者市场调研数据形…...

别再死记硬背了!用Vivado 2022.1和Vitis搭建ZYNQ工程,这份避坑清单帮你省下3小时

ZYNQ开发实战&#xff1a;从Vivado到Vitis的高效避坑指南 当第一次打开Vivado和Vitis的开发者&#xff0c;往往会被复杂的界面和繁琐的配置流程所困扰。本文将以"按键控制LED"这一经典案例为主线&#xff0c;揭示ZYNQ开发中最容易踩中的12个深坑&#xff0c;并提供经…...

混合AI路由器架构:实现高效智能任务分发

1. 混合AI路由器架构解析 在当今AI技术快速发展的背景下&#xff0c;超级代理系统正逐渐从理论走向实践。这类系统面临的核心挑战是如何在保证响应质量的同时&#xff0c;实现高效、低成本的规模化部署。混合AI路由器架构通过分层决策机制&#xff0c;巧妙地解决了这一难题。 …...