前言:因为模拟实现string中途修修改改了很多代码,所以建议大家先复制总代码在自己的vs下,然后再来一步一步看
目录
第一步:将"hello world"赋值给自定义的string
第二步:打印出hello world在屏幕上
第三步:用下标可以修改字符串的任意字符
第四步:通过下标遍历string的每个字符
第五步:浅拷贝和深拷贝字符串
第六步:=运算符的重载
第七步:实现增删查改——修改基础private
第八步:增删查改——添加字符和字符串(resize和reserve,push_back和append)
第十步:三种遍历方式
第十一步:增删查改——指定插入和指定删除(insert和erase的实现)
第十二步:实现增删查改——查找find函数实现
总代码:
string.h:
test.cpp:
------------------------开始------------------------
为了模拟string,我们需要自己命名一个新的空间,我这里是’bit’,以方便和库中的string作区分
然后创建两个,一个是头文件’string.h’,另一个是.cpp文件"test.cpp"
文章图片
第一步:将"hello world"赋值给自定义的string
我这里自己定义了一个空间名字为”bit”,然后定义了一个String类。对于我们定义的新字符串_str,
我们需要定义出他的大小,因为原本的字符串中有’\0’,所以在进行字符串拷贝的时候,我们需要在原本的空间大小上+1,然后利用strcpy进行拷贝。
最后再加入一个析构函数
namespace bit
{
class String
{
public:
String(const char* str)//因为有’\0’,所以需要在原有的基础上+1个空间
:_str(new char[strlen(str) + 1])//比如'hello world',实际上是'hello world\0'
{
strcpy(_str, str);
//拷贝字符串
}
~String()//析构函数,将资源还给内存
{
if (_str)
{
delete[] _str;
}
}
private:
char* _str;
//自定义一个自己的新指针,指向一个只有'\0'的字符串空间
};
}
将上述代码放入string.h中,然后我们在test.cpp调用以下代码进行测试
#include
#include"string.h"
using namespace std;
//上面是头文件,下面才是代码
void test_string1()
{
bit::String s1("hello world");
}
int main()
{
test_string1();
return 0;
}
在监视窗口中我们可以看到,我们已经将hello world赋予了,我们自己创建的string的s1中
文章图片
第二步:打印出hello world在屏幕上 因为我们还没有重载流插入和流提取的运算符,所以如果我们要输出hello world,这里可以使用一个函数c_str.
在string.h的public中加入这段代码
const char* c_str()const
{
return _str;
}
然后就可以在test.app中使用了
void test_string1()
{
bit::String s1("hello world");
cout << s1.c_str() << endl;
//加入这句话
}
然后我们在屏幕上就可以看到这段话
文章图片
注:如果不了解c_str的小伙伴可以看看我的这篇文章
C++:什么是c_str_幻荼的博客-CSDN博客
第三步:用下标可以修改字符串的任意字符 对于修改字符,我们就需要对[]进行运算符重载
在string.h的public放入
char& operator[](size_t pos)
{
assert(pos < strlen(_str));
//记得在前面加头文件
return _str[pos];
}
然后在test.cpp中修改字符
void test_string1()
{
bit::String s1("hello world");
cout << s1.c_str() << endl;
s1[0] = 'X';
//加入这句话
cout << s1.c_str() << endl;
//加入这句话
}
文章图片
我们可以看到hello world的第一个字符h被替换成了X。
文章图片
备注:如果对运算符重载有问题的小伙伴可以观看我的这篇文章C++:运算符重载简介_幻荼的博客-CSDN博客
第四步:通过下标遍历string的每个字符
一共是有三种方式:
1.下标+[]
2.迭代器
3. 范围for
因为是从零开始模拟,我们这里先讲解第一种,下标+[]。
我们首先在string.h的public中加入size函数,以便求得下标的整体范围.
size_t size()
{
return strlen(_str);
}
有了这个函数,我们就能再test中遍历每个字符了
void test_string1()
{
bit::String s1("hello world");
cout << s1.c_str() << endl;
s1[0] = 'X';
cout << s1.c_str() << endl;
for (size_t i = 0;
i < s1.size();
i++)//加入这段话
{
cout << s1[i] << ' ';
}
cout << endl;
//加入这段话
}
会有以下结果
文章图片
我们可以看到我们就遍历出了每个字符。
备注:如果对strlen不了解的小伙伴可以看我写的这篇文章
strlen简介,和sizeof的区别_幻荼的博客-CSDN博客
第五步:浅拷贝和深拷贝字符串 我们以前使用string的时候,喜欢把一个字符串直接赋值给另一个字符串,即
string s1("123456");
string s2(s1);
那么如何模拟实现呢?
我们先看看直接在test.cpp中试试能不能做到
void test_string2()//这里为了演示深浅拷贝,我重新创立了一个test_string2,前面是1,请将这段代码全部打到test.cpp中
{
bit::String s1("hello world");
bit::String s2(s1);
cout << s1.c_str() << endl;
cout << s2.c_str() << endl;
}
然后就会出现这个结果:
文章图片
文章图片
结果就是,拷贝是拷贝过去了,但是编译器会报错,这是为什么呢?
这个就和我们的深浅拷贝有关了
简单来说就是p2通过浅拷贝,和p1指向了同一个空间
文章图片
由于栈区的规则是先进后出,当执行完拷贝构造函数的时候,我们程序就会先执行p2的析构函数,导致释放堆区开辟的数据,然后这个已经释放的内存又要再被p1释放,这样就会报错
就是说同一块内存数据被释放了两次,这是编译器所不允许的
文章图片
所以我们需要进行深拷贝。
深拷贝简单来说就是开一个和p1一样大的空间,然后将p1的数据存放到新空间,然后自己指向新空间
文章图片
这样解析的时候,就各自解析各自的了。
为了实现深拷贝,我们只需要加入这段代码:
String(const String& s)这个隐藏了一个this指针,实际上是s2(s1)
:_str(new char[strlen(s._str) + 1])//开辟(new)一个新空间和s1一样大,来存放数据,+1是因为有’\0’
{
strcpy(_str, s._str);
//拷贝数据
}
备注:不了解深浅拷贝的小伙伴可以看看我的这篇文章
C++:浅拷贝和深拷贝简析_幻荼的博客-CSDN博客
第六步:=运算符的重载 为了实现’+=’'+''-'各种运算符的重载,我们首先来实现最简单的’=’符号,即赋值。
我们设定一个场景
void test_string3()//这里是运算符重载,所以重新开了一个test3
{
bit::String s1("hello world");
bit::String s2(s1);
bit::String s3 ("ni hao");
s1 = s3;
//通过’=’,将s3赋值给s1
cout << s1.c_str() << endl;
cout << s2.c_str() << endl;
cout << s3.c_str() << endl;
}
有些同学可能会说,直接用strcpy将s3复制给s1不就行了吗?
但是对于赋值,我们有三种情况
s1空间 s1空间=s3空间
s1空间>s3空间
如果我们直接用strcpy复制,s1空间 列如:
文章图片
如果这么多个1通过strcpy,s1的空间是肯定放不下的,就会造成越界访问。
那么如果s1空间>s3空间是不是可以了呢?
答案是:可以,但是会造成浪费
列如:
文章图片
如果我S1开了一个1000个字节的空间,结果只用来存放s3这样一个字符’1’,那么是不是会造成很严重的浪费呢?
所以说为了避免越界访问和内存浪费,我们就要使得s1的空间大小和s3一模一样。
所以我们进行三步
第一步:删除s1原有内存
第二步:创建一个和s3一样大的内存
第三步:复制数据
这段代码加入到string.h的public中
String& operator=(const String& s)//这里有隐藏的this指针s3(s1)
{
if(this!=&s)//防止有人自己给自己赋值,列如s1=s1,这样会导致乱码
{
delete[]_str;
//删除s1空间
_str = new char[strlen(s._str) + 1];
//创建和s3一样大的空间
strcpy(_str, s._str);
//复制数据
return *this;
//返回数据
}
}
然后运行结果如下
文章图片
就可以看到s1被s3赋值了
第七步:实现增删查改——修改基础private 通过前面六步,实际上一个最基础的string已经完成了,为了丰富我们的string,我们就要实现增删查改的功能。
为了实现这些功能,一个_str肯定已经不够了,我们需要size和capacity,即容量和已存储数据的大小
private:
char* _str;
//自定义一个自己的新字符串接受
size_t _size;
//容量(新加入)
size_t _capacity;
//目前大小(新加入)
};
然后加入新的capacity函数
size_t capacity()const
{
return _capacity;
}
同时我们一系列的函数就需要调整
构造函数
String(const char* str="")//这里全缺省,加入一个空字符串,空字符串中有'\0',防止默认构造出错
:_size(strlen(str))//新加入
,_capacity(_size)//新加入
{
_str = new char[_capacity + 1];
//将开空间调到这里
strcpy(_str, str);
}
因为编译器是根据private的顺序进行定义,我们这里_str的初始化使用了capacity,而capacity在privat的最后面,所以为了方便,我们就直接把他在里面初始化了。
然后是 拷贝
String(const String& s)
:_size(strlen(s._str))
,_capacity(_size)
{
_str = new char[_capacity + 1];
strcpy(_str, s._str);
}
最后是’=’的重载
String& operator=(const String& s)
{
if (this != &s)
{
delete[]_str;
_str = new char[s._capacity + 1];
strcpy(_str, s._str);
_size = s._size;
_capacity = s._capacity;
}
return *this;
}
这些修改实际上就是增加了我们新加入的size和capacity,然后把原先用strlen求有效字符串长度用capacity替换。(capacity是有效字符串个数,不包括'\0')
第八步:增删查改——添加字符和字符串(resize和reserve,push_back和append) push_back(添加字符)append(添加字符串)
push_back:
添加字符实际上很简单,只需要考虑扩容,如果容量够直接在末尾添加一个字符,再补一个'\0'即可
void push_back(char ch)
{
if (_size == _capacity)//查看是否容量已满
{
char* tmp = new char[_capacity * 2 + 1];
//new一个新的大空间,+1是因为有'\0'
strcpy(tmp, _str);
//内容复制给新空间
delete[]_str;
//删除旧空间
_str = tmp;
//将旧空间指向新空间
_capacity *= 2;
//'\0'不是有效字符所以*2就可以了
}
_str[_size] = ch;
//尾插
++_size;
_str[_size] = '\0';
//最后补一个'\0'
}
如下图所示:
文章图片
然后我们就可以测试一下
void test_string5()//这里是5了
{
bit::String s1("hello world");
s1.push_back('1');
s1.push_back('X');
cout << s1.c_str() << endl;
}
文章图片
可以看到1和X就被尾插了。
然后接下来是append:
append和push_back几乎一模一样,都是扩容+尾插,却别在于append的扩容不太好直接扩二倍。
假如
string s("123");
s.append("12345678910");
如果我们只是单纯的扩容2倍,那么可以看到s*2的capacity=6,也不够10个。
所以在这里我们需要计算一共有多少个字符,再根据字符数量来扩容
void append(const char* str)
{
size_t len = _size + strlen(str);
//原本字符数+需要添加的字符数
if (len > _capacity)
{
reserve(len);
//扩容
}
strcpy(_str + _size, str);
//拷贝数值
_size = len;
//拷贝空间
}
小伙伴们可能发现了, 我们这里的扩容运用了一个函数reserve(),而没有像之前push_back一样写一串,这是因为我把扩容,重新用reserve包装了一下
其实和上面扩容一模一样
void reserve(size_t n)
{
if (n > _capacity)//如果需要扩容
{
char* tmp = new char[n + 1];
//创建一个和n一样大的空间防止浪费和越界访问
strcpy(tmp, _str);
//复制数据
delete[]_str;
//删除旧空间
_str = tmp;
//指向新空间
_capacity = n;
//把n给capacity
}
}
然后我们也可以吧reserve给push_back使用一下
void push_back(char ch)
{
if (_size == _capacity)
{
reserve(reserve(_capacity == 0 ? 4 : _capacity * 2);
);
//这里扩容二倍刚好合适,因为是只插入单个字符
}
_str[_size] = ch;
++_size;
_str[_size] = '\0';
}
在一些特殊的情况下,我们也会使用resize对数据进行插入和初始化。
列如:
string s1("123456");
s1.resize(10,'9')
这样打印出来的结果是"1234569999".
这里就模拟实现一下resize
void resize(size_t n,char ch='\0')
{
if (n < _size)//n _capacity)//capacity不够进行扩容
{
reserve(n);
}
for (size_t i = _size;
i < n;
i++)//对空余进行初始化操作
{
_str[i] = ch;
}
_size = n;
_str[_size] = '\0';
}
}
至于为什么用reserve,以及什么是resize,不明白的小伙伴可以看我这篇文章
c++:reserve和resize简介和区别_幻荼的博客-CSDN博客
但是————我们平时都不这么用
我们平时插入一个字符串或者字符直接用"+="
例如
string s1("123");
s1+='X';
s1+="686";
【c++|C++(从零开始,万字模拟实现string(超详细))】s1就成为了"123X686";
所以说,这里我们需要对+=进行运算符重载
因为我们已经实现了单个字符的插入和字符串的插入,所以套过去就好
String& operator+=(const char* str)//字符串的插入,记得隐藏的this指针
{
append(str);
return *this;
}
String& operator+=(char ch)//字符的插入,记得隐藏的this指针
{
push_back(ch);
return *this;
}
然后我们就可以在test.cpp中测试看看
void test_string5()//这里是用来测试插入字符和字符串的test5
{
bit::String s1("hello world");
s1.push_back('1');
s1.push_back('X');
s1.append("www");
s1 += 'y';
s1 += "abc";
cout << s1.c_str() << endl;
}
结果如下
文章图片
第九步:各类运算符重载
有不懂运算符的小伙伴,我在前面已经放了链接,可以自行查看,这里因为太简单所以直接贴上代码
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 strcmp(s1.c_str(), s2.c_str()) == 0;
}
bool operator<=(const String& s1, const String& s2)
{
return s1(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 !(s1 == s2);
}
如果不知道什么是strcmp的小伙伴可以看我的这篇文章
c:strcmp函数()比较两个字符串是否相等_幻荼的博客-CSDN博客_如何比较两个字符串内容是否一样
第十步:三种遍历方式这一段我自己了解的还不是很深刻,只能先讲解我知道的部分,等后面学习了再来补充吧...
我们已经在最开始利用了下标+[]的方式遍历了每个字符
void test_string6()//这里是专门用来测试三种遍历的test6
{
bit::String s1("hello world");
for (size_t i;
i < s1.size();
i++)
{
cout << s1[i] << " ";
}
cout << endl;
}
这里我们使用第二种方式迭代器
对于迭代器,我们首先需要begin和end两个自定义函数
typedef char* iterator;
iterator begin()//指向首地址
{
return _str;
}
iterator end()//指向末尾元素的下一个元素
{
return _str + _size;
}
然后就可以和指针一样遍历整个字符串
bit::String::iterator it = s1.begin();
//将字符串第一个字符给it
while (it != s1.end())//it不为最后一个字符,就继续循环
{
cout << *it << " ";
it++;
}
cout << endl;
实际上就是这么个情况
文章图片
第三种方式范围for(不会,等会面学了再来补充)
for (auto& ch : s1)//实际上底层被替换成了迭代器,这里ch实际上是s1的拷贝
{
//ch-=1;
大家可以试着把这段话加上看看,因为这里是引用传参所以可以改变,如果只是auto ch,那么这段代码就没有作用
cout << ch << " ";
}
cout << endl;
第十一步:增删查改——指定插入和指定删除(insert和erase的实现) 不明白这两个函数是什么的小伙伴可以看看我的这篇文章
c++:insert函数和erase函数的简介_幻荼的博客-CSDN博客
我们刚才已经实现了push_back,和append,以及+=,那么我们算是把尾部的增加给搞定了,但是很多情况下,我们是需要在数据的中间进行增删查改的,所以就需要我们实现指定位置的插入和删除。
insert(指定位置的插入):
对于指定位置的插入,我们一般是插入字符和字符串两种情况。
我们先来实现插入字符
String& insert(size_t pos, char ch)
{
assert(pos <= _size);
if (_size == _capacity)//扩容
{
reserve(_capacity == 0 ? 4 : _capacity * 2);
}
size_t end = _size+1;
while (end > pos)
{
_str[end] = _str[end-1];
--end;
}
_str[pos] = ch;
_size++;
return *this;
}
实际上是这么个情况,end指向字符串结尾'\0'的下一个位置,然后依次挪动数据,等到pos和end相等的时候,先判断是否扩容,如果不用扩容就直接在pos这个位置插入这个数据,然后size++
文章图片
接下来是字符串:
String& insert(size_t pos,const char* str)
{
assert(pos <= _size);
size_t len = strlen(str);
if (len == 0)
{
return* this;
}
if (_size + len >= _capacity)//扩容
{
reserve(_size + len);
}
size_t end = _size + len;
while (end >pos+len-1 )
{
_str[end] = _str[end-len];
--end;
}
strncpy(_str + pos, str, len);
_size += len;
return *this;
}
实际上是这么个情况:假如我要插入"XXX",的字符在S[0]处,那么我的end就是目前的size+"XXX"字符串的长度,只要当我们pos+”XXX”字符串的长度-1(有"\0")=end,那么我们就停止,然后在pos处用strncpy()函数插入这个字符串
文章图片
好,我们下面来进行调试
void test_string7()//这里是用来调试insert和erase的test7
{
bit::String s("hello world");
s.insert(1, 'x');
s.insert(0, "XXX");
cout << s.c_str() << endl;
}
结果如下:
文章图片
下面我们来实现指定位置删除erase:
String& earse(size_t pos, size_t len)
{
assert(pos < _size);
if (len == npos || pos + len >= _size)//pos+len>=size
{
_str[pos] = '\0';
_size = pos;
}
else//pos+len
意思如下:
假如,我有一个字符串hello world,我从W(pos)向后删除len个字符,有三种情况
pos+len pos+len=size
pos+len>size
一旦我的pos+len>=size,我们就可以直接在s[pos]处赋值一个'\0',然后把size变为pos,因为字符串遇到'\0'就终止
如果pos+len 就是w=l,然后o=d,然后r='\0',然后此时=size,赋值结束。然后把size-=len,就完成了。
文章图片
第十二步:实现增删查改——查找find函数实现 这一步很简单,没有什么需要讲解的
size_t find(char ch, size_t pos = 0)
{
for (;
pos < _size;
pos++)//遍历字符串
{
if (_str[pos] == ch)//如果等于就返回该字符
{
return pos;
}
}
return npos;
}
size_t find(const char* str, size_t pos = 0)
{
const char* p = strstr(_str + pos, str);
//用strstr函数进行字符串查找
if (p == nullptr)
{
return npos;
}
else
{
return p - _str;
}
}
总代码: string.h:
#pragma once
#include
#include
using namespace std;
namespace bit
{
class String
{
public:
typedef char* iterator;
typedef char* const const_iterator;
const_iterator begin()const
{
return _str;
}
const_iterator end()const
{
return _str + _size;
}
iterator begin()
{
return _str;
}
iterator end()
{
return _str + _size;
}
String()
:_size(0)
,_capacity(0)
{
_str = new char[1];
_str[0] = '\0';
}
String(const char* str)//
:_size(strlen(str))
,_capacity(_size)
{
_str = new char[_capacity + 1];
strcpy(_str, str);
}
String(const String& s)
:_size(strlen(s._str))
,_capacity(_size)
{
_str = new char[_capacity + 1];
strcpy(_str, s._str);
}
~String()//析构函数,将资源还给内存
{
if (_str)
{
delete[] _str;
_str = nullptr;
_size = _capacity = 0;
}
}
String& operator=(const String& s)
{
if (this != &s)
{
delete[]_str;
_str = new char[s._capacity + 1];
strcpy(_str, s._str);
_size = s._size;
_capacity = s._capacity;
}
return *this;
}
const char* c_str()const
{
return _str;
}
char& operator[](size_t pos)
{
assert(pos < strlen(_str));
return _str[pos];
}
const char& operator[](size_t pos)const
{
assert(pos < strlen(_str));
return _str[pos];
}
void push_back(char ch)
{
/*if (_size == _capacity)
{
reserve(_capacity == 0 ? 4 : _capacity * 2);
}
_str[_size] = ch;
++_size;
_str[_size] = '\0';
*/
insert(_size, ch);
}
void resize(size_t n,char ch='\0')
{
if (n < _size)
{
_size = n;
_str[_size] = '\0';
}
else
{
if (n > _capacity)
{
reserve(n);
}
for (size_t i = _size;
i < n;
i++)
{
_str[i] = ch;
}
_size = n;
_str[_size] = '\0';
}
}
String& operator+=(const char* str)
{
append(str);
return *this;
}
String& operator+=(char ch)
{
push_back(ch);
return *this;
}
void reserve(size_t n)
{
if (n > _capacity)
{
char* tmp = new char[n + 1];
strcpy(tmp, _str);
delete[]_str;
_str = tmp;
_capacity = n;
}
}
void append(const char* str)
{
/*size_t len = _size + strlen(str);
if (len > _capacity)
{
reserve(len);
}
strcpy(_str + _size, str);
_size = len;
*/
insert(_size, str);
}
size_t size()const
{
return strlen(_str);
}
size_t capacity()const
{
return _capacity;
}
String& insert(size_t pos, char ch)
{
assert(pos <= _size);
if (_size == _capacity)
{
reserve(_capacity == 0 ? 4 : _capacity * 2);
}
size_t end = _size+1;
while (end > pos)
{
_str[end] = _str[end-1];
--end;
}
_str[pos] = ch;
_size++;
return *this;
}
String& insert(size_t pos,const char* str)
{
assert(pos <= _size);
size_t len = strlen(str);
if (len == 0)
{
return* this;
}
if (_size + len >= _capacity)
{
reserve(_size + len);
}
size_t end = _size + len;
while (end >pos+len-1 )
{
_str[end] = _str[end-len];
--end;
}
strncpy(_str + pos, str, len);
_size += len;
return *this;
}
String& earse(size_t pos, size_t len)
{
assert(pos < _size);
if (len == npos || pos + len >= _size)
{
_str[pos] = '\0';
_size = pos;
}
else
{
size_t begin = pos + len;
while (begin <= _size)
{
_str[begin - len] = _str[begin];
begin++;
}
_size -= len;
}
return *this;
}
size_t find(char ch, size_t pos = 0)
{
for (;
pos < _size;
pos++)
{
if (_str[pos] == ch)
{
return pos;
}
}
return npos;
}
size_t find(const char* str, size_t pos = 0)
{
const char* p = strstr(_str + pos, str);
if (p == nullptr)
{
return npos;
}
else
{
return p - _str;
}
}
private:
char* _str;
//自定义一个自己的新指针,指向一个只有'\0'的字符串空间
size_t _size;
size_t _capacity;
const static size_t npos;
};
const size_t String::npos = -1;
ostream& operator<<(ostream& out, const String& s)
{
for (auto ch : s)
{
out << ch;
}
return out;
}
istream& operator>>(istream& in, String& s)
{
char ch;
ch = in.get();
while (ch != ' ' && ch != '\n')
{
s += ch;
ch = in.get();
}
return in;
}
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 strcmp(s1.c_str(), s2.c_str()) == 0;
}
bool operator<=(const String& s1, const String& s2)
{
return s1(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 !(s1 == s2);
}
}
test.cpp:
#define _CRT_SECURE_NO_WARNINGS 1
using namespace std;
#include"string.h"
void test_string1()
{
bit::String s1("hello world");
cout << s1.c_str() << endl;
s1[0] = 'X';
cout << s1.c_str() << endl;
for (size_t i = 0;
i < s1.size();
i++)
{
cout << s1[i] << ' ';
}
cout << endl;
}
void test_string2()
{
bit::String s1("hello world");
bit::String s2(s1);
cout << s1.c_str() << endl;
cout << s2.c_str() << endl;
}
void test_string3()
{
bit::String s1("hello world");
bit::String s2(s1);
bit::String s3("ni hao");
s1 = s3;
cout << s1.c_str() << endl;
cout << s2.c_str() << endl;
cout << s3.c_str() << endl;
}
void test_string4()
{
bit::String s1("hello world");
cout << s1.c_str() << endl;
}
void test_string5()
{
bit::String s1("hello world");
s1.push_back('1');
s1.push_back('X');
s1.append("www");
s1 += 'y';
s1 += "abc";
cout << s1.c_str() << endl;
}
void test_string6()//这里是专门用来测试三种遍历的test6
{
//1.下标+[]
bit::String s1("hello world");
for (size_t i=0;
i < s1.size();
i++)
{
cout << s1[i] << " ";
}
cout << endl;
//2.迭代器
bit::String::iterator it = s1.begin();
while (it != s1.end())
{
cout << *it << " ";
it++;
}
cout << endl;
//3.范围for
for (auto ch : s1)
{
cout << ch << " ";
}
cout << endl;
}void test_string7()//这里是用来调试insert和erase的test7
{
bit::String s("hello world");
s.insert(1, 'x');
s.insert(0, "XXX");
cout << s.c_str() << endl;
}
void test_string9()
{
bit::String s("hello world");
cout << s << endl;
}
int main()
{
try
{
test_string9();
}
catch (const exception& e)
{
cout << e.what() << endl;
}
return 0;
}
--------------------------完结----------------------------
推荐阅读
- 学习|C++ 练习3 [牛客]
- js 比较两个数组,并进行替换掉
- 新程序员|justjavac(从辍学到成为Deno核心代码贡献者,我的十年编程生涯)
- LeetCode高频面试题|LeetCode 416. 分割等和子集 【c++/java详细题解】
- LeetCode高频面试题|剑指 Offer 59 - I. 滑动窗口的最大值 【c++/java详细题解】
- LeetCode高频面试题|LeetCode 213. 打家劫舍 II【c++/java详细题解】
- C++入门
- 极客日报|极客头条(小米全球第二,雷军签发内部嘉奖令;亚马逊因违反数据隐私被欧盟处以创纪录的 8.88 亿美元罚款)
- 数据结构与算法(c++)|【20. 滑动窗口】