C/C++ 入门(7)string类(STL)

个人主页:仍有未知等待探索-CSDN博客

专题分栏:C++

                                                        请多多指教!

目录

一、标准库中的string

1、了解

2、string类常用接口说明

1、常见的构造函数

2、容量操作 ​编辑

3、访问及遍历操作

4、修改操作

5、非成员函数

 二、string类实现

1、string类的大体框架

2、构造和析构函数 

3、迭代器 

4、成员函数 

5、非成员函数

 三、问题

1、深拷贝和浅拷贝问题

2、strcpy,memcpy

四、总代码


一、标准库中的string

1、了解

1、string是表示字符串的字符串类
2、该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。

2、string类常用接口说明

下面的函数都可以去下面的网址进行查文档,来看函数的功能。(接下来我会实现这个string类)

string - C++ Reference

1、常见的构造函数

string类对象的常见构造
函数名称功能说明
string()        构造空的string类,即空字符串
string(const char*s)

用c_str()来构造string类对象

string(size_t n, char c)string类对象中包含n个字符c
string(const string& s)拷贝构造函数

2、容量操作
 

3、访问及遍历操作

4、修改操作

5、非成员函数

 二、string类实现

实现string类能让我们更好的明白模板的使用,函数重载等等。

1、string类的大体框架

#include <iostream>
#include <cstring>
#include <assert.h>
using namespace std;class string
{
public:private:char* _str; // string存的字符串size_t _size; // string中字符串的长度 size_t _capacity; // string的容量
};

2、构造和析构函数 

string():_str(nullptr),_size(0),_capacity(0)
{}
string(const char* str):_size(strlen(str)),_capacity(_size)
{_str = new char[_capacity + 1];strcpy(_str, str);
}
string(const string& str):_str(new char[str._capacity + 1]),_size(str._size),_capacity(str._capacity)
{strcpy(_str, str._str);
}
~string()
{delete[] _str;_str = nullptr;_size = 0;_capacity = 0;
}

3、迭代器 

typedef char* iterator;
iterator begin()
{return _str;
}
iterator end()
{return _str + _size;
}

4、成员函数 


string& operator=(const string& str)
{char* tmp = new char[str._capacity + 1];strcpy(tmp, str._str);delete[] _str;_str = tmp;_size = str._size;_capacity = str._capacity;return *this;
}
void reserve(int x)
{if (_capacity < x){char* tmp = new char[x + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = x;}
}
void swap(string& str)
{std::swap(_str, str._str);std::swap(_size, str._size);std::swap(_capacity, str._capacity);
}
const char* c_str() const
{return _str;
}
void clear()
{_str[0] = '\0';_size = 0;
}
void insert(int index, const string& str)
{int len = str._size;assert(index >= 0 && index < _size);if (_size + len >= _capacity){reserve(_capacity + len);}for (int i = _size - 1; i >= index; i -- ){_str[i + len] = _str[i];}for (int j = 0, i = index; j < str._size; j ++ ,i ++ ){_str[i] = str._str[j];}_size += len;
}
void insert(int index, char ch)
{assert(index >= 0 && index < _size);if (_size + 1 >= _capacity){reserve(2 * _capacity);_capacity *= 2;}for (int i = _size - 1; i >= index; i -- ){_str[i + 1] = _str[i];}_str[index] = ch;_size ++ ;}
void append(const string& str)
{int len = str._size;if (len + _size > _capacity){reserve(len + _size);_capacity = len * _size;}int end = _size;for (int i = 0; i < str._size; i ++ ,end ++ ){_str[end] = str._str[i];}_size += len;
}
string& operator+=(const string& str)
{append(str);return *this;
}
void push_back(const char ch)
{if (_size + 1 >= _capacity){reserve(2 * _capacity);}_capacity *= 2;_str[_size] = ch;_size ++ ;
}
int size() const
{return _size;
}
int capacity() const
{return _capacity;
}
bool empty() const
{return _size == 0;
}
void resize(int n, char ch = '\0')
{if (n < _size){for (int i = n; i < _size; i ++ ){_str[i] = '\0';}}else if (n + 1 < _capacity){for (int i = _size; i < n; i ++ ){_str[i] = ch;}}else{reserve(n);}
}
char& operator[](size_t index)
{assert(index < _size);return _str[index];
}
const char& operator[](size_t index)const
{assert(index < _size);return _str[index];
}
bool operator==(const string& str)
{int ret = strcmp(_str, str.c_str());return ret == 0;
}
bool operator!=(const string& str)
{return !(*this == str);
}
bool operator>(const string& str)
{int ret = strcmp(_str, str.c_str());return ret > 0;
}
bool operator<(const string& str)
{int ret = strcmp(_str, str.c_str());return ret < 0;
}
bool operator<=(const string& str)
{return *this < str || *this == str;
}
bool operator>=(const string& str)
{return *this > str || *this == str;
}
int find (char c, size_t pos = 0) const
{assert(pos < _size);for (int i = pos; i < _size; i ++ ){if (_str[i] == c) return i;}return npos;
}
int find (const char* s, size_t pos = 0) const
{char* p = strstr(_str + pos, s);if (p != nullptr){return p - _str;}return npos;
}
string& erase (size_t pos = 0, size_t len = npos)
{assert(pos < _size);if (len == npos || len >= _size - pos){_str[pos] = '\0';_size = pos;}else{int i = 0;for (i = pos + len; i < _size; i ++ ){_str[i - len] = _str[i];}_str[i] = '\0';_size -= len;}return *this;
}

5、非成员函数

    ostream& operator<<(ostream& out, const string& str){int len = str._size;for (int i = 0; i < len; i ++ ){out << str._str[i];}return out;}istream& operator>>(istream& in, string& str){str.clear();char ch = in.get();char buff[128];int i = 0;while (ch != ' ' && ch != '\n'){buff[i ++ ] = ch;if (i == 127){buff[i] = '\0';str += buff;i = 0;}ch = in.get();}if (i != 0){buff[i] = '\0';str += buff;}return in;}
}

 三、问题

1、深拷贝和浅拷贝问题

浅拷贝:也称位拷贝,编译器只是将对象中的值拷贝过来。如果对象中管理资源,最后就会导致多个对象共享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该资源已经被释放,以为还有效,所以当继续对资源进项操作时,就会发生发生了访问违规。


深拷贝:每个对象都有一份独立的资源,不要和其他对象共享。如果一个类中涉及到资源的管理,其拷贝构造函数、赋值运算符重载以及析构函数必须要显式给出。一般情况都是按照深拷贝方式提供。

2、strcpy,memcpy

通过下面的例子也能清晰的看出来,这两个拷贝函数都是浅拷贝。所以在用的时候需要小心谨慎。

四、总代码

#include <iostream>
#include <cstring>
#include <assert.h>
using namespace std;namespace my
{class string{public:string():_str(nullptr),_size(0),_capacity(0){}string(const char* str):_size(strlen(str)),_capacity(_size){_str = new char[_capacity + 1];strcpy(_str, str);}string(const string& str):_str(new char[str._capacity + 1]),_size(str._size),_capacity(str._capacity){strcpy(_str, str._str);}~string(){delete[] _str;_str = nullptr;_size = 0;_capacity = 0;}typedef char* iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}string& operator=(const string& str){char* tmp = new char[str._capacity + 1];strcpy(tmp, str._str);delete[] _str;_str = tmp;_size = str._size;_capacity = str._capacity;return *this;}void reserve(int x){if (_capacity < x){char* tmp = new char[x + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = x;}}void swap(string& str){std::swap(_str, str._str);std::swap(_size, str._size);std::swap(_capacity, str._capacity);}const char* c_str() const{return _str;}void clear(){_str[0] = '\0';_size = 0;_capacity = 0;}void insert(int index, const string& str){int len = str._size;assert(index >= 0 && index < _size);if (_size + len >= _capacity){reserve(_capacity + len);}for (int i = _size - 1; i >= index; i -- ){_str[i + len] = _str[i];}for (int j = 0, i = index; j < str._size; j ++ ,i ++ ){_str[i] = str._str[j];}_size += len;}void insert(int index, char ch){assert(index >= 0 && index < _size);if (_size + 1 >= _capacity){reserve(2 * _capacity);_capacity *= 2;}for (int i = _size - 1; i >= index; i -- ){_str[i + 1] = _str[i];}_str[index] = ch;_size ++ ;}void append(const string& str){int len = str._size;if (len + _size > _capacity){reserve(len + _size);_capacity = len * _size;}int end = _size;for (int i = 0; i < str._size; i ++ ,end ++ ){_str[end] = str._str[i];}_size += len;}string& operator+=(const string& str){append(str);return *this;}void push_back(const char ch){if (_size + 1 >= _capacity){reserve(2 * _capacity);}_capacity *= 2;_str[_size] = ch;_size ++ ;}int size() const{return _size;}int capacity() const{return _capacity;}bool empty() const{return _size == 0;}void resize(int n, char ch = '\0'){if (n < _size){for (int i = n; i < _size; i ++ ){_str[i] = '\0';}}else if (n + 1 < _capacity){for (int i = _size; i < n; i ++ ){_str[i] = ch;}}else{reserve(n);}}char& operator[](size_t index){assert(index < _size);return _str[index];}const char& operator[](size_t index)const{assert(index < _size);return _str[index];}bool operator==(const string& str){int ret = strcmp(_str, str.c_str());return ret == 0;}bool operator!=(const string& str){return !(*this == str);}bool operator>(const string& str){int ret = strcmp(_str, str.c_str());return ret > 0;}bool operator<(const string& str){int ret = strcmp(_str, str.c_str());return ret < 0;}bool operator<=(const string& str){return *this < str || *this == str;}bool operator>=(const string& str){return *this > str || *this == str;}int find (char c, size_t pos = 0) const{assert(pos < _size);for (int i = pos; i < _size; i ++ ){if (_str[i] == c) return i;}return npos;}int find (const char* s, size_t pos = 0) const{char* p = strstr(_str + pos, s);if (p != nullptr){return p - _str;}return npos;}string& erase (size_t pos = 0, size_t len = npos){assert(pos < _size);if (len == npos || len >= _size - pos){_str[pos] = '\0';_size = pos;}else{int i = 0;for (i = pos + len; i < _size; i ++ ){_str[i - len] = _str[i];}_str[i] = '\0';_size -= len;}return *this;}friend ostream& operator<<(ostream& out, const string& str);friend istream& operator>>(istream& in, string& str);private:char* _str; // string存的字符串size_t _size; // string中字符串的长度 size_t _capacity; // string的容量static const size_t npos = -1;};inline ostream& operator<<(ostream& out, const string& str){int len = str._size;for (int i = 0; i < len; i ++ ){out << str._str[i];}return out;}inline istream& operator>>(istream& in, string& str){str.clear();char ch = in.get();char buff[128];int i = 0;while (ch != ' ' && ch != '\n'){buff[i ++ ] = ch;if (i == 127){buff[i] = '\0';str += buff;i = 0;}ch = in.get();}if (i != 0){buff[i] = '\0';str += buff;}return in;}
}

谢谢大家! 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/641271.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

创享大会分会场—“职棱起来”《职业生涯画布工作坊》

会议主题&#xff1a;创享大会分会场—“职棱起来”《职业生涯画布工作坊》 会议时间&#xff1a;5月25日&#xff08;周六&#xff09;13:30—16:30 会议地点&#xff1a;北京希尔顿欢朋酒店&#xff08;大红门&#xff09; 特邀嘉宾&#xff1a;姚冬&#xff08;冬哥&…

5款制作表格的软件,一键帮你实现数据可视化

数据可视化是许多企业决定未来方向、产品研发和用户研究的关键。只有大量的数据支持才能做出最明智的决定&#xff0c;因此表格在可视化中逐渐发挥着不可替代的作用。可以看出&#xff0c;掌握表格制作技巧是多么重要。然而&#xff0c;不能制作表格的小型合作伙伴不必担心。国…

机器人实验室CNRS-AIST JRL, IRL介绍

一、背景 作为搞机器人方向的学生&#xff0c;必须时常关注国际上顶尖实验室的研究成果&#xff0c;以免自己做的方向out&#xff0c;除了大家耳熟能详的Boston Dynamics&#xff0c;还有许多非常厉害的机器人实验室值得我们关注&#xff0c;如日本的CNRS-AIST JRL, IRL实验室…

X-Spider媒体下载工具

软件介绍 X-Spider 是一个功能丰富的推特媒体下载器&#xff0c;它不仅可以帮助用户从推特上下载图片和视频&#xff0c;还提供了一些高级的过滤功能。例如&#xff0c;用户可以通过指定日期范围来筛选需要下载的媒体文件&#xff0c;并且可以跳过已下载的重复文件&#xff0c…

[第一届 帕鲁杯 CTF挑战赛 2024] Crypto/PWN/Reverse

被一个小题整坏了&#xff0c;后边就没认真打。赛后把没作的复盘一下。 比赛有52个应急响应&#xff0c;猜是取证&#xff0c;都是队友在干&#xff0c;我也不大关心。前边大多题是比赛的原题。这是后来听说的&#xff0c;可都没见过&#xff0c;看来打的比赛还是少了。 Cryp…

Java中的super

package day33; ​ public class Person {public String name;public int age; ​public Person() {System.out.println("调用了父类的无参构造");} } ​ package day33; ​ public class teacher extends Person{public teacher() {System.out.println("调用了…

Linux开机启动流程

Linux开机启动流程详细步骤如下图&#xff1a; 其中&#xff1a; POST:Power On Self Test --加电自检 BIOS: Basic Input Output System --基础输入输出系统 MBR: Master Boot Record --主引导记录 GRUB: GRand Uni…

pytorch安装(含cuda、cudnn安装教程)

pytorch安装&#xff08;含cuda、cudnn安装教程&#xff09; 一、创建python虚拟环境二、CUDA安装1、查看CUDA支持版本2、下载CUDA3、下载cuDNN4、安装CUDA5、安装cuDNN 三、pytorch安装1.使用命令安装2.手动安装 win10 64位 环境下安装CUDA 11.8和 cuDNN v8.9.0 一、创建pytho…

Linux:服务器硬件及RAID配置

Linux&#xff1a;服务器硬件及RAID配置 服务器 服务器是什么 服务器的英文名称为“ Server”&#xff0c;是指在网络上提供各种服务的高性能计算机。作为网络的节点&#xff0c;存储、处理网络上80&#xff05;的数据、信息&#xff0c;因此也被称为网络的灵魂。 服务器和…

【PCL】教程global_hypothesis_verification 通过验证模型假设来实现 3D 对象识别与位姿估计...

测试程序1 milk.pcd milk_cartoon_all_small_clorox.pcd 终端输出1&#xff1a; Model total points: 12575; Selected Keypoints: 193 Scene total points: 307200; Selected Keypoints: 7739 [pcl::SHOTEstimation::computeFeature] The local reference frame is not valid!…

应对电网挑战!lonQ与橡树岭国家实验室利用量子技术改善关键基础设施

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 文丨浪味仙 排版丨沛贤 深度好文&#xff1a;1800字丨6分钟阅读 摘要&#xff1a;美国电网正在面临需求增加和能源扩散的挑战&#xff0c;对能够应对优化和安全挑战的创新解决方案有着迫切需求…

Day4 商品管理

Day4 商品管理 这里会总结构建项目过程中遇到的问题&#xff0c;以及一些个人思考&#xff01;&#xff01; 学习方法&#xff1a; 1 github源码 文档 官网 2 内容复现 &#xff0c;实际操作 项目源码同步更新到github 欢迎大家star~ 后期会更新并上传前端项目 编写品牌服务 …