全flash网站模板,活动营销方案,装修设计软件免费版下载,网站收录是怎么回事#x1f308;个人主页#xff1a;秋风起#xff0c;再归来~#x1f525;系列专栏#xff1a;C从入门到起飞 #x1f516;克心守己#xff0c;律己则安
目录 1、多文件之间的关系
2、模拟实现常用的构造函数
2.1 无参构造函数
2.2 有参的构造函数 2.3 析构函… 个人主页秋风起再归来~系列专栏C从入门到起飞 克心守己律己则安
目录 1、多文件之间的关系
2、模拟实现常用的构造函数
2.1 无参构造函数
2.2 有参的构造函数 2.3 析构函数顺便实现
3、size()、capacity()、[]运算符重载
4、模拟实现简单的正向迭代器
5、reserve、push_back、append
6、operator、insert、erase
7、find、substr
8、非成员函数operator比较系列
9、非成员函数operator、operator
10. 完结散花 1、多文件之间的关系
string.h
在string.h中我们用来包含各种头文件以及定义我们的string类和非成员函数的声明
注意在string.h中string类的定义和非成员函数的声明放到我们自己定义的命名空间my_string中原因就是为了和库里面的std:string类进行区分 string.cpp
在string.cpp中我们来完成string类中一些类里面短小频繁调用的函数声明和定义不用分离成员函数和非成员函数的定义!
注意在string.cpp中我们要包含“string.h”并且要在命名空间域中完成成员函数和非成员函数的定义 test.cpp
这个文件用来测试我们的接口是否有bug 2、模拟实现常用的构造函数
这里我们实现的是简单的string类没有搞vs下用buff数组来存放字符串那一套所以我们就只有三个成员变量
private:char* _str;//指向字符串的指针size_t _size;//有效字符个数不包含\0size_t _capacity;//空间大小不包含\0
注意这里的有效字符个数_size和空间大小_capacity都不包含\0但我们实际开空间时都会多开一个来存放’\0‘
2.1 无参构造函数
声明以下实现的函数都是直接在类里面定义短小频繁调用在类里面直接默认为inline
有误的无参构造函数 string():_str(nullptr)//有问题标准库里面的是可以输出空字符串的, _size (0),_capacity (0)
{}
在写构造函数时一般我们都是建议显示写初始化列表的于是我们上来可能就会写出如上的代码不过上面的代码并不符合C标准规定当我们空参构造时库里面输出的是一个空字符串而上面写的构造函数却是不能直接访问的空指针
在测试代码前因为我们还没有重载流提取和流插入函数那我们就先实现一个简单的c_str()函数来帮助我们实现打印输出
返回C字符串(c_str())
//返回C字符串
const char* c_str() const
{return _str;
}
指定命名空间使用库里面的string
std::string s1;//指定命名空间用的是库里面的string
cout s1.c_str() endl; 通过调试我们发现库里面的string空参构造一个string对象s1时 s1里面存放的是一个’\0‘并输出一个空字符串
未指定命名空间在命名空间my_string内,优先使用自己实现的string
//未指定命名空间在命名空间my_string内,优先使用自己实现的string
string s1;
cout s1.c_str() endl; 通过调试我们发现我们模拟实现的string空参构造一个string对象s1时 s1里面存放的是一个nullptr所以我们在输出时程序就直接崩溃了 正确的无参构造函数
那我们就按照标准库的规定来写在走初始化列表时开一个空间来存放’\0‘即可
string():_str(new char[1]{\0})//实际的空间大小要比capacity大1来存放\0, _size (0),_capacity (0)
{}
2.2 有参的构造函数
走初始化列表通过计算str的长度来开辟空间并确定_size和_capacity的大小然后在函数体内将str的值拷贝到_str中,我们就完成了带参数的构造函数
string(const char* str):_str(new char[strlen(str) 1]), _size(strlen(str)),_capacity(strlen(str))
{strcpy(_str, str);
} 不过这里并不建议走初始化列表因为每次都要调用strlen有性能和效率的消耗。
建议写下面这一种版本
string(const char* str)//加上缺省值合二为一
{_size strlen(str);_capacity _size;_str new char[_capacity 1];//记住开空间时多开一个strcpy(_str, str);//会把str的\0拷贝进来
}
当然我们还可以将无参构造函数和带参构造函数合二为一
string(const char* str)//加上缺省值合二为一
{_size strlen(str);_capacity _size;_str new char[_capacity 1];//记住开空间时多开一个strcpy(_str, str);//会把str的\0拷贝进来
} 注意合二为一之后我们就要将之前写的无参构造函数屏蔽掉不然编译器不知道调用谁就会报错一个类中只能有一个默认构造函数即可以无参调用的构造函数 2.3 析构函数顺便实现
因为有资源的申请所以我们要显示实现我们的析构函数
~string()
{delete[] _str;_str nullptr;_capacity _size 0;
}
3、size()、capacity()、[]运算符重载
声明以下实现的函数都是直接在类里面定义短小频繁调用在类里面直接默认为inline
这些接口都比较简单我就不赘述了
//返回size和capacity
size_t size() const
{return _size;
}
size_t capacity() const
{return _capacity;
}
//[]运算符重载
char operator[](size_t pos)
{assert(pos _size);return _str[pos];
}
//const版本
const char operator[](size_t pos) const
{assert(pos _size);return _str[pos];
}
好啦到这里我们配合一下前面实现的一些接口测试一下有没有什么问题
string s1(hello world);
for (size_t i 0; i s1.size(); i)
{cout s1[i];
}
cout endl;
for (size_t i 0; i s1.size(); i)
{s1[i] 2;cout s1[i];
} 好这里看到结果也是没有任何问题的呢
4、模拟实现简单的正向迭代器
声明以下实现的函数都是直接在类里面定义短小频繁调用在类里面直接默认为inline
上面用下标访问遍历了我们的string对象范围for这么方便那我们也来尝试用它来遍历一下吧
string s1(hello world);
for (auto ch :s1 )
{cout ch;
} 完蛋了一写出来就给我们报了一大堆的错误
不过我在上一篇博客里写到了范围for的底层就是迭代器我们冷静下来思考并结合报错就会发现原来我们自己实现的string类中目前还没有迭代器所以我们不能用范围for来遍历s1
那我们怎么来实现string类的迭代器呢
这里我就直接告诉大家所有的迭代器iterator都是typedef出来的在这里迭代器其实就是典型的封装的一种体现所有的容器链表队列树等都有迭代器并且使用他们的迭代器的方式都是一样的即迭代器给我们提供了统一的接口但其底层的实现并不相同不过我们在使用时并不关心它底层的细节我们只要掌握了迭代器的使用方式就会对所有容器进行操作。这种封装的方式大大方便了我们对容器的使用
好啦到这里我们就来实现一下string类里面简单的一个迭代器吧
我们上篇文章就说过在string中正向迭代器的使用就可以把它当做指针来看不一定是指针那我们在实现时不就可以参考使用原始指针的方式来实现我们的简单迭代器呢
1. 我们将char*重新命名为iterator即iterator就是char* 的类型
2. 然后我们再实现begin()和end()俩个接口来返回_str的开头和结尾
typedef char* iterator;
//正向迭代器
iterator begin()const
{return _str;
}
iterator end() const
{return _str_size;
}
好啦到这里我们就实现好了一个简单的正向迭代器我们来测试一下 string s1(hello world);for (auto ch :s1 ){cout ch;}cout endl; 我们再简单的实现一下正向常量迭代器
//正向常量迭代器
typedef const char* const_iterator;
const_iterator cbegin() const
{return _str;
}
const_iterator cend() const
{return _str _size;
} 这里我们就不实现反向迭代器了用原始指针已经解决不了了因为它要用到一个叫适配器的东西目前我也不知道那是啥玩意还挺复杂的~
5、reserve、push_back、append
reserve
标准库里面的reserve只有在预留空间大于容量时才会扩容并且决不改变有效字符个数strcpy会拷贝到\0 void string::reserve(size_t n){//标准库里面的reserve只有在预留空间大于容量时才会扩容//并且决不改变有效字符if (n _capacity){char* tmp new char[n 1];//开新空间记得加一strcpy(tmp, _str);//拷贝数据到新空间delete[] _str;//释放旧空间_str tmp;//_str指向新空间_capacity n;}return;} 好啦写到这里我们来测试一下上面的接口是否有问题
string s1(hello world);
cout capacity: s1.capacity() endl;
//reserve
s1.reserve(20);
cout capacity: s1.capacity() endl endl; string s1(hello world);
cout capacity: s1.capacity() endl;
//reserve
s1.reserve(10);
cout capacity: s1.capacity() endl endl; 好啦 也是没有任何问题的
push_back
先判断是否需要扩容空间为0则开4个空间否则二倍扩记得要手动放一个\0
void string::push_back(char c)
{//先判断是否需要扩容if (_size _capacity){ //空间为0则开4个空间否则二倍扩reserve(_capacity 0 ? 4 : _capacity * 2);}_str[_size] c;//有效字符已经更新_str[_size] \0;//记得要手动放一个\0
} 好啦写到这里我们来测试一下上面的接口是否有问题
string s1(hello world);
cout s1.c_str() endl;
s1.push_back(x);
cout s1.c_str() endlendl; OK啊也是没有任何问题的
append
先判断是否需要扩容原字符串与追加的字符串总长度大于2 * _capacity就开len _size,否则二倍扩不要忘了更新_sizestrcpy会拷贝到\0 string string::append(const char* s){size_t len strlen(s);if (len _size _capacity){//原字符串与追加的字符串总长度大于2 * _capacity就开len _size,否则二倍扩reserve(len _size 2 * _capacity ? len _size : 2 * _capacity);}strcpy(_str _size, s);_size len;//不要忘了更新_sizereturn *this;} 好啦写到这里我们来测试一下上面的接口是否有问题
string s1(hello world);
cout s1.c_str() endl;
s1.append(test append );
cout s1.c_str() endl endl; 6、operator、insert、erase
operator
直接复用push_back即可 string string::operator(char c){push_back(c);return *this;}
因为是复用的代码就不测试了
insert(任意位置前插入一个字符)
//任意位置前插入一个字符
string string::insert(size_t pos, char c)
{assert(pos _size);//先判断是否需要扩容if (_size _capacity){ //空间为0则开4个空间否则二倍扩reserve(_capacity 0 ? 4 : _capacity * 2);}for (size_t i _size; i pos; i--){//把pos位置开始 的字符全部后移一个位置_str[i 1] _str[i];}_str[pos] c;_size;return *this;
} 好啦写到这里我们来测试一下上面的接口是否有问题
我们先尾插一个字符
string s1(hello world);
cout s1.insert(s1.size(), *).c_str() endl endl; 没有什么问题
我们再头插一个字符
string s1(hello world);
cout s1.insert(0, ).c_str() endl endl; 我的发坏了程序直接崩溃了。我们程序员最害怕的就是自己写的程序测试出bug来不过我们不要慌我们调试一下来解决问题 按照我们的挪动逻辑循环结束前后i的位置应该如下 我们来调试检查检查一下哪里出了问题 通过调试我们发现头插前 i 的值雀氏为11 所有的数据都按我们的想法挪 动到后面去了不过i的值却不是-1而是一个非常大的数值
好了这里我们就大概明白哪里出问题了这里其实就是C语言遗留下来的一个坑i的类型是size_t是无符号的整型当i的值为-1时其在内存中的补码是全一的序列而它又是无符号的整型正数因此这全一的序列会被认为是该值的原码 即这是整型的最大值
解决这个问题的方法有很多比如可以用int来解决不过我这里就直接改变一下挪动的逻辑啦
for (size_t i _size1; i pos; i--)
{//把pos位置开始 的字符全部后移一个位置_str[i] _str[i-1];
}
这样挪i就不会到-1
insert(任意位置前插入一个字符串)
注释很详细啦友友们认真看哦~
//任意位置前插入一个字符串
string string::insert(size_t pos, const char* s)
{assert(pos _size);size_t len strlen(s);if (len _size _capacity){//原字符串与追加的字符串总长度大于2 * _capacity就开len _size,否则二倍扩reserve(len _size 2 * _capacity ? len _size : 2 * _capacity);}//把pos位置开始 的字符全部后移len个位置//1、用库函数memmove一个一个字节的拷贝挪动注意一定要多挪动一个字节把\0也挪动到后面去memmove(_str pos len, _str pos, (len1) * sizeof(char));//2、手动挪/*for (size_t i _size len; i poslen-1; i--){_str[i] _str[i - len];}*///一个一个字符拷贝for (size_t i 0; i len ; i){_str[posi] s[i];}_size len;return *this;
}
erase
string erase(size_t pos, size_t lennpos);
上面的代码是类里面的成员函数声明有缺省值npos这是在类里面声明的一个静态的常量成员
static const size_t npos;
注意
//static const size_t npos-1; //特殊的可以在声明(类内部)处定义的static成员变量 //而且只有整形可以 //static const double d 1.1;报错const double类型不能包含类内初始值设定项
不过我们这里还是建议让静态成员变量定义到类外中不过我们要注意定义一定不要在头文件中不然我们在test.cpp和string.cpp中包含了俩次npos的定义这时在链接时编译器就找不到重复定义的成员从而发生链接错误 所以我们在string.cpp中定义npos! 声明处给了缺省值定义处就不能显示写缺省值了先判断pos的有效性再判断从pos位置开始的字符够不够删如果不够直接在pos位置放\0,并更新有效字符的个数为pos。如果够删就走挪动的逻辑
从任意位置开始删除len个字符string string::erase(size_t pos, size_t len){assert(pos _size);if (len _size - pos){_str[pos] \0;_size pos;}else{//把poslen位置开始的字符全部前移len个位置//1、用库函数memmove一个一个字节的挪动注意一定要多挪动一个字节把\0也挪动到后前 //面去//memmove(_str pos, _str pos len, (_size -pos1) * sizeof(char));//2、手动挪for (size_t i pos len; i _size; i){_str[i-len] _str[i];}_size - len;}return *this;}
7、find、substr
find(从pos位置开始找字符c)
循环遍历查找即可没什么好说的但要注意如果没有找到返回npos
//从pos位置开始找字符c
size_t string::find(char c, size_t pos )
{assert(pos _size);for (size_t i pos; i _size; i){if (_str[i] c){return i;}}return npos;
} find从(pos位置开始找字符串s)
找子串问题可以用kmp算法但该算法在实际应用中用的并不多C语言中strstr用的就不是该算法而BM算法就用的较多不过BM算法较为复杂有兴趣的小伙伴可以自己去查阅一下资料哦我们下面就直接使用库里面的函数来匹配子串了
//从pos位置开始找字符串s
size_t string::find(const char* s, size_t pos )
{assert(pos _size);char* retstrstr(_str pos, s);if (ret nullptr){return npos;}return ret - _str;
}
substr(从pos位置开始取子串)
//从pos位置开始取子串
string string::substr(size_t pos, size_t len)
{if (len _size-pos){len _size - pos;}string sub;sub.reserve(len);for (size_t i pos; i _size; i){sub _str[i];}return sub;
}
测试代码
string s1(hello world);
string s2 s1.substr(6);
cout s2.c_str() endl;
这里我就直接说结论我们上面的代码还是有问题的我们在vs2022debug版本上测试倒不会出现什么问题但vs2019或更早一点的版本就会有运行时错误。因为我还没有安装更早的版本这里就没办法演示了。
那到底是哪里出了问题呢我们在函数里面创建了一个局部变量sub来暂时存放取到的子串并传值返回在传值返回时函数还会先调用拷贝构造来拷贝一个临时的string对象然后再用临时的string对象来拷贝构造我们在函数外面用来接收返回值的string对象s2 不过编译器默认的拷贝构造是浅拷贝即将对象一个一个字节的拷贝构造另一个对象 通过调试我们发现s2的_str和sub的_str指向的是同一块空间当sub出函数的局部作用域时sub对象就会调用析构函数而销毁而其所指向的空间也同时被释放 所以当一个类里面有成员向内存申请资源时我们就不能使用编译器默认生成的拷贝构造了必须自己显示生成拷贝构造进行深拷贝
//拷贝构造(深拷贝)
string(const string s)
{_str new char[s._capacity 1];strcpy(_str, s._str);_size s._size;_capacity s._capacity;
}
那为什么在vs2022debug版本上测试倒不会出现什么问题呢这里简单的说一下在进行传值拷贝构造时编译器可能不会进行sub对象的创建直接用临时对象拷贝构造s2而在这里编译器的优化更为激进直接和三为一sub和临时对象都不创建了直接拷贝构造s2所以也就不存在同一块空间被多次析构的问题了
8、非成员函数operator比较系列
这个系列比较简单大家看看代码就明白了
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);
}
9、非成员函数operator、operator operator
ostream operator(ostream out, const string s)
{for (auto ch : s){out ch;}return out;
}operator
istream operator(istream in, string s)
{s.clear();//先清理有效字符char ch;in ch;//将流里面的字符插入到ch中while (ch ! ch ! \n){s ch;in ch;}s \0;//末尾记得加上\0return in;
}
上面的代码看似没问题其实这样写in读取不到缓冲区里面的换行和空格与scanf一样cin在读取字符时默认将空格和换行视为字符分割符不进行读取记住就行所以我们就可以用in.get()来读取每一个字符作用和getc一样
istream operator(istream in, string s)
{s.clear();//先清理有效字符char ch;ch in.get();//将流里面的字符插入到ch中while (ch ! ch ! \n){s ch;ch in.get();}s \0;//末尾记得加上\0return in;
}
如果字符串很长会有频繁的扩容消耗可以优化一下
istream operator(istream in, string s)
{s.clear();//先清理有效字符const size_t N 256;int i 0;char buff[N];//用一个buff数组做我们的缓冲char ch in.get();while (ch ! ch ! \n){buff[i] ch;if (i N - 1)//数组满了再把字符加进s中避免频繁扩容{buff[i] \0;i 0;s buff;}ch in.get();}if (i 0)//把最后一组没有满的也加上{buff[i] \0;s buff;}return in;
}
10、完整代码
string.h
#pragma once#includeiostream
#includeassert.h
using namespace std;namespace my_string
{class string{public://类里面短小频繁调用的函数声明和定义不用分离//1、无参构造函数//string()// :_str(new char[1]{\0})//实际的空间大小要比capacity大1来存放\0// , _size (0)// ,_capacity (0)//{}// string()// :_str(nullptr)//有问题标准库里面的是可以输出空字符串的// , _size (0)// ,_capacity (0)//{}//2、有参的构造函数string(const char* str)//加上缺省值合二为一{_size strlen(str);_capacity _size;_str new char[_capacity 1];//记住开空间时多开一个strcpy(_str, str);//会把str的\0拷贝进来}/** 不建议走初始化列表每次都要调用strlenstring(const char* str):_str(new char[strlen(str) 1]), _size(strlen(str)),_capacity(strlen(str)){strcpy(_str, str);}*///3、析构函数~string(){delete[] _str;_str nullptr;_capacity _size 0;}//4、返回C字符串const char* c_str() const{return _str;}//5、返回size和capacitysize_t size() const{return _size;}size_t capacity() const{return _capacity;}//6、[]运算符重载char operator[](size_t pos){assert(pos _size);return _str[pos];}//const版本const char operator[](size_t pos) const{assert(pos _size);return _str[pos];}//7、实现两个简单的迭代器typedef char* iterator;//正向迭代器iterator begin()const {return _str;}iterator end() const{return _str_size;}//正向常量迭代器typedef const char* const_iterator;const_iterator cbegin() const{return _str;}const_iterator cend() const{return _str _size;}//拷贝构造(深拷贝)string(const string s){_str new char[s._capacity 1];strcpy(_str, s._str);_size s._size;_capacity s._capacity;}//显示赋值运算符重载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;}void clear(){_str[0] \0;_size 0;}//下面的成员函数声明和定义分离//0、预留空间void reserve(size_t n);//1、尾插一个字符void push_back(char c);//2、追加一个字符串string append(const char* s);//3、一个字符string operator(char s);//4、一个字符串string operator(const char* s);//5、任意位置插入一个字符string insert(size_t pos, char c);//6、任意位置插入一个字符串string insert(size_t pos,const char* s);//7、从任意位置删除len个字符string erase(size_t pos, size_t lennpos);//8、从pos位置开始找字符csize_t find(char c, size_t pos 0);//9、从pos位置开始找字符串ssize_t find(const char* s, size_t pos 0);//10、从pos位置开始取子串string substr(size_t pos 0, size_t len npos);private:char* _str;//指向字符串的指针size_t _size;//有效字符个数不包含\0size_t _capacity;//空间大小不包含\0static const size_t npos;//static const size_t npos-1;//特殊的可以在声明(类内部)处定义的static成员变量//而且只有整形可以//static const double d 1.1;报错const double类型不能包含类内初始值设定项friend ostream operator(ostream out, const string s);};//const size_t string::npos -1;//非成员函数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);ostream operator(ostream out, const string s);istream operator(istream in, string s);
}
string.cpp
#define _CRT_SECURE_NO_WARNINGS#includestring.hnamespace my_string
{const size_t string::npos -1;void string::reserve(size_t n){//标准库里面的reserve只有在预留空间大于容量时才会扩容//并且决不改变有效字符if (n _capacity){char* tmp new char[n 1];//开新空间记得加一strcpy(tmp, _str);//拷贝数据到新空间delete[] _str;//释放旧空间_str tmp;//_str指向新空间_capacity n;}return;}void string::push_back(char c){//先判断是否需要扩容if (_size _capacity){ //空间为0则开4个空间否则二倍扩reserve(_capacity 0 ? 4 : _capacity * 2);}_str[_size] c;_str[_size] \0;//记得要手动放一个\0}string string::append(const char* s){size_t len strlen(s);if (len _size _capacity){//原字符串与追加的字符串总长度大于2 * _capacity就开len _size,否则二倍扩reserve(len _size 2 * _capacity ? len _size : 2 * _capacity);}strcpy(_str _size, s);_size len;//不要忘了更新_sizereturn *this;}string string::operator(char c){push_back(c);return *this;}string string::operator(const char* s){append(s);return *this;}//5、任意位置前插入一个字符string string::insert(size_t pos, char c){assert(pos _size);//先判断是否需要扩容if (_size _capacity){ //空间为0则开4个空间否则二倍扩reserve(_capacity 0 ? 4 : _capacity * 2);}//for (size_t i _size; i pos; i--)//{// //把pos位置开始 的字符全部后移一个位置// _str[i 1] _str[i];// //这种写法有bug//}for (size_t i _size1; i pos; i--){//把pos位置开始 的字符全部后移一个位置_str[i] _str[i-1];}_str[pos] c;_size;return *this;}//6、任意位置前插入一个字符串string string::insert(size_t pos, const char* s){assert(pos _size);size_t len strlen(s);if (len _size _capacity){//原字符串与追加的字符串总长度大于2 * _capacity就开len _size,否则二倍扩reserve(len _size 2 * _capacity ? len _size : 2 * _capacity);}//把pos位置开始 的字符全部后移len个位置//1、用库函数memmove一个一个字节的拷贝挪动注意一定要多挪动一个字节把\0也挪动到后面去memmove(_str pos len, _str pos, (len1) * sizeof(char));//2、手动挪/*for (size_t i _size len; i poslen-1; i--){_str[i] _str[i - len];}*/for (size_t i 0; i len ; i){_str[posi] s[i];}_size len;return *this;}//7、从任意位置开始删除len个字符string string::erase(size_t pos, size_t len){assert(pos _size);if (len _size - pos){_str[pos] \0;_size pos;}else{//把poslen位置开始的字符全部前移len个位置//1、用库函数memmove一个一个字节的挪动注意一定要多挪动一个字节把\0也挪动到后前面去//memmove(_str pos, _str pos len, (_size -pos1) * sizeof(char));//2、手动挪for (size_t i pos len; i _size; i){_str[i-len] _str[i];}_size - len;}return *this;}//8、从pos位置开始找字符csize_t string::find(char c, size_t pos ){assert(pos _size);for (size_t i pos; i _size; i){if (_str[i] c){return i;}}return npos;}//9、从pos位置开始找字符串ssize_t string::find(const char* s, size_t pos ){assert(pos _size);char* retstrstr(_str pos, s);if (ret nullptr){return npos;}return ret - _str;}//10、从pos位置开始取子串string string::substr(size_t pos, size_t len){if (len _size-pos){len _size - pos;}string sub;sub.reserve(len);for (size_t i pos; i _size; i){sub _str[i];}//注意一定要自己实现拷贝构造sub是局部的return sub;}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);}ostream operator(ostream out, const string s){for (auto ch : s){out ch;}return out;}//1、这样写有问题读取不到换行和\0//istream operator(istream in, string s)//{// s.clear();//先清理有效字符// char ch;// in ch;//将流里面的字符插入到ch中// while (ch ! ch ! \n)// {// s ch;// in ch;// }// s \0;//末尾记得加上\0// return in;//}//2、如果字符串很长会有频繁的扩容消耗可以优化一下//istream operator(istream in, string s)//{// s.clear();//先清理有效字符// char ch;// ch in.get();//将流里面的字符插入到ch中// while (ch ! ch ! \n)// {// s ch;// ch in.get();// }// s \0;//末尾记得加上\0// return in;//}istream operator(istream in, string s){s.clear();//先清理有效字符const size_t N 256;int i 0;char buff[N];//用一个buff数组做我们的缓冲char ch in.get();while (ch ! ch ! \n){buff[i] ch;if (i N - 1)//数组满了再把字符加进s中避免频繁扩容{buff[i] \0;i 0;s buff;}ch in.get();}if (i 0)//把最后一组没有满的也加上{buff[i] \0;s buff;}return in;}
}
test.cpp #includestring.h
using namespace my_string;
namespace my_string
{void test_my_string1(){string s1;cout s1.c_str() endl;/*string s2(hello world);cout s2.c_str() endl;*/}void test_my_string2(){/* string s1(hello world);for (size_t i 0; i s1.size(); i){cout s1[i];}cout endl;for (size_t i 0; i s1.size(); i){s1[i] 2;cout s1[i];}cout endl;*///string::const_iterator it s1.cbegin();//while (it ! s1.cend())//{// //*it 2;报错表达式必须是可修改的左值// cout *it;// it;//}//cout endl;string s1(hello world);for (auto ch :s1 ){cout ch;}cout endl;}void test_my_string3(){//string s1(hello world);//cout capacity: s1.capacity() endl;reserve//s1.reserve(10);//cout capacity: s1.capacity() endl endl;//push_back/*string s1(hello world);cout s1.c_str() endl;s1.push_back(x);cout s1.c_str() endlendl;*///cout s1.c_str() endl;//s1 ;//cout s1.c_str() endl endl;//append/*string s1(hello world);cout s1.c_str() endl;s1.append(test append );cout s1.c_str() endl endl;*///append//cout s1.c_str() endl;//s1test ;//cout s1.c_str() endl endl;}void test_my_string4() {//Test insert/*string s1(hello world);cout s1.insert(s1.size(), *).c_str() endl endl;*/string s1(hello world);cout s1.insert(0, ).c_str() endl endl;//cout s1.insert(s1.size(), test insert s).c_str() endl endl;/*string s2(hello world);s2.erase(6,2);cout s2.c_str()endl;s2.erase(0,8);cout s2.c_str() endl;*/}void test_my_string5(){//Test findstring s1(hello world);/*size_t ret s1.find(llo);cout ret endl;*/string s2 s1.substr(6);cout s2.c_str() endl;}void test_my_string6(){//Test string s1hello world;cout s1 endl;cin s1;cout s1;}
}int main()
{test_my_string5();
}
11. 完结散花
好了这期的分享到这里就结束了~
如果这篇博客对你有帮助的话可以用你们的小手指点一个免费的赞并收藏起来哟~
如果期待博主下期内容的话可以点点关注避免找不到我了呢~
我们下期不见不散~~
文章转载自: http://www.morning.wchcx.cn.gov.cn.wchcx.cn http://www.morning.twmp.cn.gov.cn.twmp.cn http://www.morning.fxqjz.cn.gov.cn.fxqjz.cn http://www.morning.nzwp.cn.gov.cn.nzwp.cn http://www.morning.hwtb.cn.gov.cn.hwtb.cn http://www.morning.gjmll.cn.gov.cn.gjmll.cn http://www.morning.ypbp.cn.gov.cn.ypbp.cn http://www.morning.mzydm.cn.gov.cn.mzydm.cn http://www.morning.ywgrr.cn.gov.cn.ywgrr.cn http://www.morning.mztyh.cn.gov.cn.mztyh.cn http://www.morning.jjxxm.cn.gov.cn.jjxxm.cn http://www.morning.rzmlc.cn.gov.cn.rzmlc.cn http://www.morning.ntqqm.cn.gov.cn.ntqqm.cn http://www.morning.qbwyd.cn.gov.cn.qbwyd.cn http://www.morning.tsnq.cn.gov.cn.tsnq.cn http://www.morning.nxbkw.cn.gov.cn.nxbkw.cn http://www.morning.trkl.cn.gov.cn.trkl.cn http://www.morning.nkddq.cn.gov.cn.nkddq.cn http://www.morning.tlnbg.cn.gov.cn.tlnbg.cn http://www.morning.tbbxn.cn.gov.cn.tbbxn.cn http://www.morning.cbndj.cn.gov.cn.cbndj.cn http://www.morning.lthgy.cn.gov.cn.lthgy.cn http://www.morning.qfgxk.cn.gov.cn.qfgxk.cn http://www.morning.xtrzh.cn.gov.cn.xtrzh.cn http://www.morning.wgtr.cn.gov.cn.wgtr.cn http://www.morning.hlhqs.cn.gov.cn.hlhqs.cn http://www.morning.stxg.cn.gov.cn.stxg.cn http://www.morning.srkzd.cn.gov.cn.srkzd.cn http://www.morning.tpssx.cn.gov.cn.tpssx.cn http://www.morning.hcszr.cn.gov.cn.hcszr.cn http://www.morning.wrlxy.cn.gov.cn.wrlxy.cn http://www.morning.qwmdx.cn.gov.cn.qwmdx.cn http://www.morning.rkkpr.cn.gov.cn.rkkpr.cn http://www.morning.mhmdx.cn.gov.cn.mhmdx.cn http://www.morning.gbtty.cn.gov.cn.gbtty.cn http://www.morning.kmqms.cn.gov.cn.kmqms.cn http://www.morning.nkdmd.cn.gov.cn.nkdmd.cn http://www.morning.gpmrj.cn.gov.cn.gpmrj.cn http://www.morning.jphxt.cn.gov.cn.jphxt.cn http://www.morning.wnzgm.cn.gov.cn.wnzgm.cn http://www.morning.hxfrd.cn.gov.cn.hxfrd.cn http://www.morning.kwqcy.cn.gov.cn.kwqcy.cn http://www.morning.pbzlh.cn.gov.cn.pbzlh.cn http://www.morning.jpnfm.cn.gov.cn.jpnfm.cn http://www.morning.skbbt.cn.gov.cn.skbbt.cn http://www.morning.rwlns.cn.gov.cn.rwlns.cn http://www.morning.sfphz.cn.gov.cn.sfphz.cn http://www.morning.kyfrl.cn.gov.cn.kyfrl.cn http://www.morning.ksbmx.cn.gov.cn.ksbmx.cn http://www.morning.qnbsx.cn.gov.cn.qnbsx.cn http://www.morning.rqxtb.cn.gov.cn.rqxtb.cn http://www.morning.hcqd.cn.gov.cn.hcqd.cn http://www.morning.fqnql.cn.gov.cn.fqnql.cn http://www.morning.ylklr.cn.gov.cn.ylklr.cn http://www.morning.mwrxz.cn.gov.cn.mwrxz.cn http://www.morning.jbxfm.cn.gov.cn.jbxfm.cn http://www.morning.tgtwy.cn.gov.cn.tgtwy.cn http://www.morning.wdhlc.cn.gov.cn.wdhlc.cn http://www.morning.gjqnn.cn.gov.cn.gjqnn.cn http://www.morning.gtxrw.cn.gov.cn.gtxrw.cn http://www.morning.bnlkc.cn.gov.cn.bnlkc.cn http://www.morning.ydnxm.cn.gov.cn.ydnxm.cn http://www.morning.lwgrf.cn.gov.cn.lwgrf.cn http://www.morning.pqwhk.cn.gov.cn.pqwhk.cn http://www.morning.xqltq.cn.gov.cn.xqltq.cn http://www.morning.tcxk.cn.gov.cn.tcxk.cn http://www.morning.ylpwc.cn.gov.cn.ylpwc.cn http://www.morning.rknsp.cn.gov.cn.rknsp.cn http://www.morning.bwygy.cn.gov.cn.bwygy.cn http://www.morning.kqwsy.cn.gov.cn.kqwsy.cn http://www.morning.dwrjj.cn.gov.cn.dwrjj.cn http://www.morning.thmlt.cn.gov.cn.thmlt.cn http://www.morning.ykgp.cn.gov.cn.ykgp.cn http://www.morning.btpll.cn.gov.cn.btpll.cn http://www.morning.wrtpk.cn.gov.cn.wrtpk.cn http://www.morning.wrwcf.cn.gov.cn.wrwcf.cn http://www.morning.lxyyp.cn.gov.cn.lxyyp.cn http://www.morning.xflzm.cn.gov.cn.xflzm.cn http://www.morning.nzqmw.cn.gov.cn.nzqmw.cn http://www.morning.hlxpz.cn.gov.cn.hlxpz.cn