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

[C++String]接口解读,深拷贝和浅拷贝,string的模拟实现

💖💖💖欢迎来到我的博客,我是anmory💖💖💖
又和大家见面了
欢迎来到C++探索系列
作为一个程序员你不能不掌握的知识
先来自我推荐一波
个人网站欢迎访问以及捐款
推荐阅读
如何低成本搭建个人网站
专栏:动画详解leetcode算法题
C语言知识
玉桂狗呀呼

String常用接口解读

String类

string是代表了一串字符串的序列
标准string类通过类似于标准字节容器的接口为此类对象提供支持,但添加了专门设计用于处理单字节字符字符串的功能
字符串类是一个实例使用 char(即字节)作为其字符类型的basic_string类模板,其默认char_traits和分配器类型
此类处理字节与所使用的编码无关:如果用于处理多字节或可变长度字符(如 UTF-8)的序列,则此类的所有成员(如长度或大小)及其迭代器仍将根据字节(而不是实际编码字符)进行操作

成员函数

(Constructor):构造函数
string():构造一个空的字符串,长度为0
string(const char* str):拷贝构造一个字符串,参数由函数传递进来
string(const char* str,size_t pos,size_t len = npos):拷贝一个字符串的字串,从pos位置开始拷贝len个,如果len过长那么就从pos位置拷贝全部字符串
string(const char* s):复制以\0结尾的C字符串
string(const char* s,size_t n):拷贝字符串中的前n个字符
string(size_t n,char c):用n个连续的c填充string
更多请参考string构造函数

案例

// string constructor
#include <iostream>
#include <string>int main ()
{std::string s0 ("Initial string");// constructors used in the same order as described above:std::string s1;std::string s2 (s0);std::string s3 (s0, 8, 3);std::string s4 ("A character sequence");std::string s5 ("Another character sequence", 12);std::string s6a (10, 'x');std::string s6b (10, 42);      // 42 is the ASCII code for '*'std::string s7 (s0.begin(), s0.begin()+7);std::cout << "s1: " << s1 << "\ns2: " << s2 << "\ns3: " << s3;std::cout << "\ns4: " << s4 << "\ns5: " << s5 << "\ns6a: " << s6a;std::cout << "\ns6b: " << s6b << "\ns7: " << s7 << '\n';return 0;
}

迭代器

begin:返回迭代器到开始位置
end:返回迭代器到结束位置
rbegin:将迭代器指向字符串的末尾
rend:将迭代器指向字符串的开头
cbegin:返回const迭代器到开始位置
cend:返回const迭代器到结束位置
crbegin:将迭代器指向字符串的末尾
crend:将const迭代器指向字符串的开头
更多内容请访问迭代器

容量

size:返回字符串的长度
length:返回字符串的长度
max_size:返回字符串的最大尺寸
capacity:返回字符串的容量
resize:重新为字符串分配大小
reserve:为字符串预留一定空间
clear:清除字符串内容
更多请访问字符串

元素访问

operator[]:获取字符串的字符
更多请访问元素访问

修改操作

operator+=:在字符串末尾添加字符或字符串
append:在字符串末尾添加字符或字符串
push_back:在字符串末尾添加字符
insert:在字符串中插入字符或字符串
erase:在字符串中清除字符或字符串
swap:交换字符串的值
更多请访问修改操作

string操作

c_str:等效的C字符串
find:找到字符串中的内容
find_first_of:找到字符串中的字符
substr:找到字符串中的子串

非成员函数重载

operator+:连接字符串
relational operator:字符串的比较
swap:交换两个字符串的内容
operator>>:流插入,用于输入
operator<<:流提取,用于输出
getline:将流中的行转换为字符串

String常用接口的模拟实现

#pragma once#include <iostream>
#include <string>
#include <assert.h>
using namespace std;namespace anmory
{class string{friend ostream& operator<<(ostream& out, const string& s);//friend istream& operator>>(istream& in, const string& s);public:const size_t npos = -1;// iterator的定义和实现typedef char* iterator;typedef const char* const_iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}const_iterator begin() const{return _str;}const_iterator end() const{return _str + _size;}//你现在是在string这个类中,我重载的operator++也是stirng的,而不是迭代器的void clear(){_str[0] = '\0';_size = 0;}string(const char* str = "")// 这里不希望能够修改str的值,因此需要使用const{_size = strlen(str);_capacity = _size;_str = new char[_capacity + 1];// 预留\0的位置strcpy(_str, str);}// 构造函数string(const string& s){// 防止自我赋值导致错误if (this != &s){// 行赋值操作_size = s._size;_capacity = _size;_str = new char[_capacity + 1];strcpy(_str, s._str);}}// 析构函数~string(){delete[] _str;_size = 0;_capacity = 0;}const char* c_str() const{return _str;}size_t size(){return _size;}size_t capacity(){return _capacity;}void swap(string& s){std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}// 重载=,+=string& operator=(const string& s);string& operator=(string s);string& operator+=(const char* str);string& operator+=(char ch);void push_back(char ch);void append(const char* str);void reserve(size_t n);size_t resize(size_t n);size_t resize(size_t n, char c);void insert(size_t pos, char c);void insert(size_t pos, const char* str);void erase(size_t pos, size_t len);size_t find(char ch, size_t pos);size_t find(const char* str, size_t pos,size_t len);private:char* _str = 0;size_t _size = 0;size_t _capacity = 0;};bool operator>(const string& s1, const string& s2);bool operator>=(const string& s1, const string& s2);bool operator<(const string& s1, const string& s2);bool operator<=(const string& s1, const string& s2);bool operator==(const string& s1, const string& s2);bool operator!=(const string& s1, const string& s2);
}
#define _CRT_SECURE_NO_WARNINGS 1#include "string.h"namespace anmory
{const size_t npos = -1;/*istream& operator>>(istream& in, string& s){char ch;in >> ch;while (ch != ' ' && ch != '\n'){s += ch;in >> ch;}return in;}*/string& string::operator=(const string& s){{// 防止自我赋值if (this != &s){delete[] _str;// 先删去原有的字符串内容// 再进行赋值操作_size = strlen(s._str);_capacity = _size;_str = new char[_capacity + 1];strcpy(_str, s._str);}return *this;}}string& string::operator=(string s){swap(s);return *this;}string& string::operator+=(char ch){push_back(ch);return *this;}string& string::operator+=(const char* str){append(str);return *this;}ostream& operator<<(ostream& out,const string& s){//for (size_t i = 0; i < s._size; i++)//{//	out << s._str[s._size];//}for (auto ch : s){out << ch;}//for (string::iterator iter = s.begin(); iter != s.end(); ++iter)//{//	out << *iter;//}return out;}void string::reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = n;}}void string::push_back(char ch){if (_size == _capacity){reserve(_capacity == 0 ? 4 : _capacity * 2);}_str[_size] = ch;_size++;_str[_size] = '\0';// 为字符串最后手动加上\0}void string::append(const char* str){size_t len = strlen(str);if (_size + len > _capacity){size_t newcapacity = _size + len > _capacity * 2 ? _size + len : _capacity * 2;char* tmp = new char[newcapacity + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = newcapacity;}strcat(_str, str);_size += len;}size_t string::resize(size_t n){if (n > _capacity){size_t newcapacity = n > _capacity * 2 ? n : _capacity * 2;_size = n;char* tmp = new char[_capacity + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = newcapacity;}if (n <= _size){_size = n;}return _size;}bool operator>(const string& s1, const string& s2){return strcmp(s1.c_str(), s2.c_str())>0;}bool operator>=(const string& s1, const string& s2){return s1 == s2 || s1 > s2;}bool operator<(const string& s1, const string& s2){return !(s1 >= s2);}bool operator<=(const string& s1, const string& s2){return !(s1 > s2);}bool operator==(const string& s1, const string& s2){return strcmp(s1.c_str(), s2.c_str()) == 0;}bool operator!=(const string& s1, const string& s2){return !(s1 == s2);}size_t string::resize(size_t n, char c){if (n <= _size){_size = n;_str[_size] = '\0';}if(n>_capacity){size_t newcapacity = n > _capacity * 2 ? n : _capacity * 2;char* tmp = new char[newcapacity + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = newcapacity;}if (n > _size){for (size_t i = _size; i < n; i++){_str[i] = c;}_str[_size] = '\0';_size = n;}return _size;}void string::insert(size_t pos, char c){assert(pos < _size);if (_size == _capacity){reserve(_capacity == 0 ? 4 : _capacity * 2);}size_t end = _size + 1;while (end>=pos){_str[end+1] = _str[end];end--;}_str[pos] = c;_size++;_str[_size + 1] = '\0';}void string::insert(size_t pos, const char* str){assert(pos < _size);size_t len = strlen(str);if (_size == _capacity){reserve(_capacity == 0 ? 4 : _capacity * 2);}size_t end = _size + 1;size_t end2 = end + len;while (end >= pos){_str[end + len] = _str[end];end--;}_size += len;for (size_t i = 0; i < len; i++){_str[pos + i] = str[i];}}void string::erase(size_t pos, size_t len){assert(pos < _size);size_t end = pos + len;while (_str[end] != '\0'){_str[pos++] = _str[end++];}_size -= len;_str[_size] = '\0';}size_t string::find(char ch, size_t pos){while (_str[pos] != '\0'){if (_str[pos] == ch){return ch;}}return string::npos;}size_t string::find(const char* str, size_t pos,size_t len){char* ptr = strstr(_str+pos, str);if (ptr == nullptr){return npos;}return ptr - _str;}
}
#define _CRT_SECURE_NO_WARNINGS 1#include "string.h"void test_c_str()
{anmory::string s("hello world");cout << "test_c_str:> " << s.c_str() << endl;
}void test_operator()
{anmory::string s("hello world");char ch = '*';s += ch;cout << "test+= :> " << s << endl;string tmp;//tmp = s;cout << "test= :> " << tmp << endl;
}void test_push_back()
{anmory::string s("hello world");s.push_back('x');cout << "test_push_back:> " << s << endl;
}void test_append()
{anmory::string s1("hello world");s1.append("xxxxx");cout << "test_append:> " << s1 << endl;
}void test_clear()
{anmory::string s1("hello world");s1.clear();cout << "test_clear:> " << s1 << endl;
}void test_reserve()
{anmory::string s("hello world");s.reserve(100);cout << "test_reserve:> " << s.size() << " " << s.capacity() << endl;
}void test_resize()
{anmory::string s("hello world");s.resize(19,'c');cout << "test_resize:> " << s << endl;
}void test_size()
{anmory::string s("hello");cout << "test_size:> " << s.size() << endl;
}void test_insert()
{anmory::string s("helloworld");s.insert(4, 'x');cout << "test_insert:> " << s << endl;anmory::string s1("hello world");s1.insert(5, "xxx");cout << "test_insert:> " << s1 << endl;
}void test_erase()
{anmory::string s("hello world");s.erase(5, 3);cout << "test_erase:> " << s << endl;
}int main()
{test_c_str();test_operator();test_push_back();test_append();test_clear();test_reserve();test_resize();test_size();test_insert();test_erase();return 0;
}

模拟实现中的深拷贝和浅拷贝的问题

#define _CRT_SECURE_NO_WARNINGS 1#include <iostream>
#include <vector>
#include <string>
using namespace std;class string
{
public:void swap(string s){std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}string(const char* str = ""){_size = strlen(str);_capacity = _size;}string(const string& s){string tmp(s);swap(tmp);}/*string& operator=(const string& s){string tmp(s);swap(tmp);return *this;}*/string& operator=(string tmp){swap(tmp);return *this;}~string(){delete[] _str;_size = 0;}
private:char* _str = nullptr;size_t _size = 0;size_t _capacity = 0;
};int main()
{/*vector<int> v1;vector<int> v2(10, 1);vector<int>::iterator it = v2.begin();while (it != v2.end()){cout << *it << " ";it++;}cout << endl;*/return 0;
}

结语

💖💖💖非常感谢各位的支持💖💖💖
我们共同进步
本系列持续更新,关注我,带你了解更多C++知识
下期再见
玉桂狗呀呼

相关文章:

[C++String]接口解读,深拷贝和浅拷贝,string的模拟实现

&#x1f496;&#x1f496;&#x1f496;欢迎来到我的博客&#xff0c;我是anmory&#x1f496;&#x1f496;&#x1f496; 又和大家见面了 欢迎来到C探索系列 作为一个程序员你不能不掌握的知识 先来自我推荐一波 个人网站欢迎访问以及捐款 推荐阅读 如何低成本搭建个人网站…...

理性看待、正确理解 AI 中的 Scaling “laws”

编者按&#xff1a;LLMs 规模和性能的不断提升&#xff0c;让人们不禁产生疑问&#xff1a;这种趋势是否能一直持续下去&#xff1f;我们是否能通过不断扩大模型规模最终实现通用人工智能&#xff08;AGI&#xff09;&#xff1f;回答这些问题对于理解 AI 的未来发展轨迹至关重…...

【OCR 学习笔记】二值化——全局阈值方法

二值化——全局阈值方法 固定阈值方法Otsu算法在OpenCV中的实现固定阈值Otsu算法 图像二值化&#xff08;Image Binarization&#xff09;是指将像素点的灰度值设为0或255&#xff0c;使图像呈现明显的黑白效果。二值化一方面减少了数据维度&#xff0c;另一方面通过排除原图中…...

Java - IDEA开发

使用IDEA开发Java程序步骤&#xff1a; 创建工程 Project&#xff1b;创建模块 Module&#xff1b;创建包 Package&#xff1b;创建类&#xff1b;编写代码&#xff1b; 如何查看JDK版本 Package介绍: package是将项目中的各种文件,比如源代码、编译生成的字节码、配置文件、…...

Oracle(62)什么是内存优化表(In-Memory Table)?

内存优化表&#xff08;In-Memory Table&#xff09;是指将表的数据存储在内存中&#xff0c;以提高数据访问和查询性能的一种技术。内存优化表通过利用内存的高速访问特性&#xff0c;显著减少I/O操作的延迟&#xff0c;提升数据处理的速度。这种技术在需要高性能数据处理的应…...

#window家庭版安装hyper-v#

由于window 11 家庭版没有hyper-v虚拟机服务&#xff0c;则需要安装一下&#xff0c;使用如下操作 1:新建一个txt文件&#xff0c;拷贝如下脚本到里面 pushd "%\~dp0" dir /b %SystemRoot%\servicing\Packages\*Hyper-V*.mum >hyper-v.txt for /f %%i in (findst…...

【云原生】Pass容器研发基础——汇总篇

云原生基础汇总 系列综述&#xff1a; &#x1f49e;目的&#xff1a;本系列是个人整理为了云计算学习的&#xff0c;整理期间苛求每个知识点&#xff0c;平衡理解简易度与深入程度。 &#x1f970;来源&#xff1a;每个知识点的修正和深入主要参考各平台大佬的文章&#xff0c…...

【Py/Java/C++三种语言详解】LeetCode743、网络延迟时间【单源最短路问题Djikstra算法】

可上 欧弟OJ系统 练习华子OD、大厂真题 绿色聊天软件戳 od1441了解算法冲刺训练&#xff08;备注【CSDN】否则不通过&#xff09; 文章目录 相关推荐阅读一、题目描述二、题目解析三、参考代码PythonJavaC 时空复杂度 华为OD算法/大厂面试高频题算法练习冲刺训练 相关推荐阅读 …...

交替输出

交替输出 题目&#xff1a;线程 1 输出 a 5 次&#xff0c;线程 2 输出 b 5 次&#xff0c;线程 3 输出 c 5 次。现在要求输出 abcabcabcabcabc wait notify 版 public class SyncWaitNotify {private volatile int flag;private volatile int loopNumber;public SyncWaitNo…...

JS(三)——更改html内数据

获取 DOM 元素&#xff0c;然后修改其属性或内容。使用 getElementById 方法获取特定 ID 的元素&#xff1a; <p id"myParagraph">这是初始的文本</p> const paragraph document.getElementById(myParagraph); paragraph.innerHTML 这是修改后的文本…...

CSS小玩意儿:文字适配背景

一&#xff0c;效果 二&#xff0c;代码 1&#xff0c;搭个框架 添加一张背景图片&#xff0c;在图片中显示一行文字。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" conte…...

C++:平衡二叉搜索树之红黑树

一、红黑树的概念 红黑树&#xff0c; 和AVL都是二叉搜索树&#xff0c; 红黑树通过在每个节点上增加一个储存位表示节点的颜色&#xff0c; 可以是RED或者BLACK&#xff0c; 通过任何一条从根到叶子的路径上各个节点着色方式的限制&#xff0c;红黑树能够确保没有一条路径会比…...

CentOS 7 系统优化

CentOS 7 系统优化 1、配置YUM源 阿里云的YUM源配置&#xff1a; CentOS 7使用以下命令&#xff1a; sudo wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repoCentOS 8使用以下命令&#xff1a; sudo wget -O /etc/yum.repos.d/CentOS…...

扫雷游戏——附源代码

扫雷游戏的源代码比较简单&#xff0c;不设计比较复杂的代码&#xff0c;主要是多个函数的组合&#xff0c;每个函数执行自己的功能&#xff0c;最终支持游戏的完成。 1.菜单 我们需要一个提醒信息来让用户进行选择。 void menu() {printf("***********************\n&…...

Vue3列表(List)

效果如下图&#xff1a;在线预览 APIs List 参数说明类型默认值bordered是否展示边框booleanfalsevertical是否使用竖直样式booleanfalsesplit是否展示分割线booleantruesize列表尺寸‘small’ | ‘middle’ | ‘large’‘middle’loading是否加载中booleanfalsehoverable是否…...

HarmonyOS NEXT - Navigation组件封装BaseNavigation

demo 地址: https://github.com/iotjin/JhHarmonyDemo 代码不定时更新&#xff0c;请前往github查看最新代码 在demo中这些组件和工具类都通过module实现了&#xff0c;具体可以参考HarmonyOS NEXT - 通过 module 模块化引用公共组件和utils 官方介绍 组件导航 (Navigation)(推…...

浅看MySQL数据库

有这么一句话&#xff1a;“一个不会数据库的程序员不是合格的程序员”。有点夸张&#xff0c;但是确是如此。透彻学习数据库是要学习好多知识&#xff0c;需要学的东西也是偏难的。我们今天来看数据库MySQL的一些简单基础东西&#xff0c;跟着小编一起来看一下吧。 什么是数据…...

Pytorch常用训练套路框架(CPU)

文章目录 1. 数据准备示例&#xff1a;加载 CIFAR-10 数据集 2. 模型定义示例&#xff1a;定义一个简单的卷积神经网络 3. 损失函数和优化器示例&#xff1a;定义损失函数和优化器 4. 训练循环示例&#xff1a;训练循环 5. 评估和测试示例&#xff1a;评估模型 6. 保存和加载模…...

C++ | Leetcode C++题解之第338题比特位计数

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<int> countBits(int n) {vector<int> bits(n 1);for (int i 1; i < n; i) {bits[i] bits[i & (i - 1)] 1;}return bits;} };...

智慧校园云平台电子班牌系统源码,智慧教育一体化云解决方案

智慧校园云平台电子班牌系统&#xff0c;利用先进的云计算技术&#xff0c;将教育信息化资源和教学管理系统进行有效整合&#xff0c;实现生态基础数据共享、应用生态统一管理&#xff0c;为智慧教育建设的统一性&#xff0c;稳定性&#xff0c;可扩展性&#xff0c;互通性提供…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎&#xff1a;品融电商&#xff0c;一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中&#xff0c;品牌如何破浪前行&#xff1f;自建团队成本高、效果难控&#xff1b;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

#Uniapp篇:chrome调试unapp适配

chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器&#xff1a;Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

第7篇:中间件全链路监控与 SQL 性能分析实践

7.1 章节导读 在构建数据库中间件的过程中&#xff0c;可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中&#xff0c;必须做到&#xff1a; &#x1f50d; 追踪每一条 SQL 的生命周期&#xff08;从入口到数据库执行&#xff09;&#…...

为什么要创建 Vue 实例

核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...

学习一下用鸿蒙​​DevEco Studio HarmonyOS5实现百度地图

在鸿蒙&#xff08;HarmonyOS5&#xff09;中集成百度地图&#xff0c;可以通过以下步骤和技术方案实现。结合鸿蒙的分布式能力和百度地图的API&#xff0c;可以构建跨设备的定位、导航和地图展示功能。 ​​1. 鸿蒙环境准备​​ ​​开发工具​​&#xff1a;下载安装 ​​De…...

鸿蒙(HarmonyOS5)实现跳一跳小游戏

下面我将介绍如何使用鸿蒙的ArkUI框架&#xff0c;实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...

【深尚想】TPS54618CQRTERQ1汽车级同步降压转换器电源芯片全面解析

1. 元器件定义与技术特点 TPS54618CQRTERQ1 是德州仪器&#xff08;TI&#xff09;推出的一款 汽车级同步降压转换器&#xff08;DC-DC开关稳压器&#xff09;&#xff0c;属于高性能电源管理芯片。核心特性包括&#xff1a; 输入电压范围&#xff1a;2.95V–6V&#xff0c;输…...