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

embedded/2024/10/21 9:17:20/

个人主页:仍有未知等待探索-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.ppmy.cn/embedded/10621.html

相关文章

精进质量管理:必读的六本书籍推荐

想精进质量管理&#xff0c;深入了解质量管理的理论与实践至关重要。质量管理领域不断演进&#xff0c;涌现了众多经典著作&#xff0c;为我们提供了丰富的知识资源和实际操作指导。今天优思学院将快速介绍六本在质量管理和精益六西格玛方法方面极具影响力的书籍&#xff0c;帮…

使用ERNIE SDK和Comate开发AI“划拳”游戏!

作者晓飞好&#xff0c;飞桨星河社区开发者&#xff0c;金融行业软件开发工程师&#xff0c;对大模型应用开发比较感兴趣。个人主页链接&#xff1a;https://aistudio.baidu.com/personalcenter/thirdview/48323 技术的迅速发展为我们带来了无限的创新可能&#xff0c;大模型技…

图像处理基础知识

图像处理基础知识 图像 1、模拟图像 模拟图像&#xff0c;又称连续图像&#xff0c;是指在二维坐标系中连续变化的图像&#xff0c;即图像的像点是无限稠密的&#xff0c;同时具有灰度值&#xff08;即图像从暗到亮的变化值&#xff09;。 2、数字图像 数字图像&#xff0…

asp.net core rabbitmq的基本使用

要在 .NET Core 应用程序中实现使用 RabbitMQ 发送和接收消息的简单示例&#xff0c;首先需要在开发机器上安装 RabbitMQ 服务器并运行它。接下来&#xff0c;我们将创建两个控制台应用程序&#xff1a;一个用于发送消息&#xff08;生产者&#xff09;&#xff0c;另一个用于接…

oracle_申明与赋值

1.格式 --1.程序块结构 declare --申明部分 begin --执行部分 end&#xff1b; 2.写一个空的程序块 --1.程序块结构 declare --申明部分 begin --执行部分 null&#xff1b; end&#xff1b; 在控制台输出【hello world】 --2.简单的程序输入 DECLARE --申明部分 BEGIN --…

公开征集 | 2024年区块链创新大赛赛题有奖征集正式启动

为进一步提升区块链作为信任基础设施在数据流通、实体经济、社会治理等方面的应用支撑作用&#xff0c;在国家区块链技术创新中心的指导下&#xff0c;长安链开源社区联合多所国内知名学会协会、高等院校共同筹办2024年区块链创新大赛。 赛题公开征集 区块链是实现数据可信共享…

浅谈Java NIO

Java NIO&#xff08;New Input/Output&#xff09;是Java平台上一种全新的IO API&#xff0c;相较于传统的Java I/O&#xff08;也称为BIO&#xff0c;阻塞I/O&#xff09;&#xff0c;NIO引入了非阻塞I/O和通道&#xff08;Channel&#xff09;的概念&#xff0c;以及缓冲区&…

南京邮电大学数学实验A 作业1 Matlab基础 答案 | 《MATLAB数学实验》第三版 第一章 课后习题答案

若要获得更好的阅读体验&#xff0c;请前往 链接。 1(课本习题1) 执行下列命令&#xff0c;观察其运算结果&#xff0c;理解其意义: (1) [1 2; 3 4]10-2i; (2) [1 2; 3 4].*[0.1 0.2; 0.3 0.4]; (3) [1 2; 3 4].[20 10; 9 2]; (4) [1 2; 3 4].^2; (5) exp([1 2; 3 4]); …