苏州学习网站建设,志鸿优化设计,网站报价详情,高唐建筑公司网站前言#xff1a;大家都知道在C语言里面的有 char 类型#xff0c;我接下来要讲的 string 类功能是使用 char 类型写的类#xff0c;当然这个是C官方写的#xff0c;接下来我们将会学会使用它#xff0c;我们会发现原来 char 这种类型是还能这么好用#xff0c;授人以…前言大家都知道在C语言里面的有 char 类型我接下来要讲的 string 类功能是使用 char 类型写的类当然这个是C官方写的接下来我们将会学会使用它我们会发现原来 char 这种类型是还能这么好用授人以鱼不如授人以渔接下来我将会讲不少干货不仅仅是教会我们使用还会教我们如何模拟实现一个 string 类我也会教大家如何去读英文文档话不多说正文开始。
一string 类初识
1英文文档的查找和阅读
想要了解一个语言里面的一个语法有什么比直接去它的官网看原汁原味的英文文档更加得劲呢我现在贴出C的官网cplusplus.com/reference/
打开之后我们会看到这个页面 因为新版本不具有搜索功能为了我们方便使用我们切回老版本点击图上的这个 之后我们就能在上面的reserch进行搜索了 我们搜索 string 就会显示 string 类的提供的所有接口和功能我们先看它对string类的描述也就是第一大段 这上面明确说明了string类是一串char字符并且提供了一系列的接口在下面是它的接口或者成员函数让我们来看看如何查看成员函数的功能使用方法。 我们阅读英文文献不一定要全部明白意思我们可以从上面的四个方面入手就能大概理解功能和使用方法碰到不会的单词我们可以用搜索引擎但不建议使用翻译软件直接翻译因为这样即不准确也不利用我们的成长以后我们还会阅读不少的英文文献只有自身硬才能笑到最后。
2string类初步使用
string 如何创建对象
在使用时我们首先可以把它定义的对象当作一个字符串但是这个对象拥有很多C语言字符串没有的特性比如不需要我们考虑它的空间够不够我们可以使用运算符对它进行操作也就是进行等操作并且提供了许多接口帮助我们减少手搓的代码量
话不多说我们先定义一个string 对象吧
string c1; //里面只有一个\0
string c2(wzdhxhn); //里面是wzdxhn\0
string c3(wzdxhn); //里面是wzdxhn\0
string c4c3; //里面也是wzdxhn\0
string c5(c4); //里面还是wzdxhn\0
c1c5c4; //里面可是wzdxhnwzdxhn\0哦
c5c5; //里面是wzdxhnwzdxhn\0哦
for(int i0;i7;i)
c2[i]6; //c2里面的内容将会全部变成6
coutc1;
cinc1; //支持输入输出流
没错真的是一场酣畅淋漓的初始化和赋值string都支持这种操作并且拷贝都是深拷贝哦如果在C里面我们就需要循坏进行赋值了刚开始是不是就感受到了它的便利。编译器最终还是我承受了一切。
string 成员函数的使用
前提知识size_t npos -1这个是C库里面的代表整形的最大值如果它是默认参数代表知道\0等结束标志结尾
1size()
sizehttps://legacy.cplusplus.com/reference/string/string/size/ 没有函数参数这个函数可以获取string里面字符串的长度不包括\0然后返回
string s(hello);
couts.size(); //输出s的长度5
2) length()
string::length - C Referencehttps://legacy.cplusplus.com/reference/string/string/length/ 功能类似size,没有参数也是返回字符串长度不包括\0
string s(hello);
couts.length(); //输出s的长度5
3) max_size() string::max_size - C Referencehttps://legacy.cplusplus.com/reference/string/string/max_size/ 没有参数返回字符串里面ASCLL码值的最大值这个可以改变字符串的大小
4resize
string::resize - C Referencehttps://legacy.cplusplus.com/reference/string/string/resize/ 只有一个参数就是字符串调整后的大小以\0为标注没有返回值可以扩大和缩小字符串长度扩大可以指定一个参数填充,也可以选择不指定这个参数有默认参数,但要注意这个如果指定大小小于字符串的大小则会将数据覆盖
string s(hello);
couts.resize(10,6); //输出hello66666
couts.resize(2); //输出he 5) capacity()
string::capacity - C Referencehttps://legacy.cplusplus.com/reference/string/string/capacity/
没有参数返回一个无符号整形代表调整后储存字符串空间的大小这个会返回string类的字符串空间的容量要注意的是字符串空间的容量不等于长度可能有一些空间存在但是我们没使用相当于多开了空间
6) reserve()
string::reserve - C Referencehttps://legacy.cplusplus.com/reference/string/string/reserve/一个参数没有返回值这个可以重新定义容量但是要注意只能扩大不能缩小容量因为编译器会做判断如果重定义的容量小于之前的字符串空间的容量就不会进行任何操作也不会报错。只有一个参数就是你再次定义的容量大小
7) clear()
string::clear - C Referencehttps://legacy.cplusplus.com/reference/string/string/clear/没有参数没有返回值顾名思义清理数据大小和长度。但是不会改变开的空间大小也就是字符串空间大小
8) at()
string::at - C Referencehttps://legacy.cplusplus.com/reference/string/string/at/这个相当于下标访问只有一个参数就是你要访问的字符串位置 最后返回你要的下标元素的引用
string s(hello);
s.at(2); //等价于s[2]
9) back() /front() string::back - C Referencehttps://legacy.cplusplus.com/reference/string/string/back/ 没有参数返回最后一个字符,front()则是返回第一个字符
string s(hello);
couts.back(); //输出o 10append() string::append - C Referencehttps://legacy.cplusplus.com/reference/string/string/append/ 这个有两个函数参数一个是插入的字符串或者字符第二个参数有默认参数0代表插入的位置返回类型是插入后的string类
string s(hello);
s.append( world);
couts; //输出hello world
11) push_back()
string::push_back - C Referencehttps://legacy.cplusplus.com/reference/string/string/push_back/这个成员函数有一个参数没有返回值是要注意插入的只能是字符或者ASCLL码值而且是尾插插入字符串请使用append
string s(nihao);
s.push_back(h);
couts; //输出nihaoh
10) insert()
string::insert - C Referencehttps://legacy.cplusplus.com/reference/string/string/insert/
这个函数支持的参数很多 从图什么我们能知道返回类型是插入后的string类或者迭代器这个insert功能强大不仅支持插入字符也支持字符串支持各种各样的插入方式即带来了遍历也变得复杂了
13erase
string::erase - C Referencehttps://legacy.cplusplus.com/reference/string/string/erase/ 这个函数功能很明确了就是删除字符串没有参数返回值是删除后的string类或者迭代器因此不做举例了
14c_str()
string::c_str - C Referencehttps://legacy.cplusplus.com/reference/string/string/c_str/这个会将string类型 转化为C语言的char* 类型返回类型是 const char* 但要注意返回类型是const类型只读不写
15find/rfind
string::find - C Referencehttps://legacy.cplusplus.com/reference/string/string/find/
这个函数的作用就是查找字符或者字符串里面的字符返回它在字符串里面的位置注意找字符串的时候不是找子字符串而是找属于这个子串里面的字符 find()是从前往后找rfind()则是从后往前找参数差不多
string s(hello,world);
couts.find(l,5); 结果是10返回为world里面的l,因为的从5 o开始查找的
16substr()
string::substr - C Referencehttps://legacy.cplusplus.com/reference/string/string/substr/这个函数的作用就是返回原字符串中的一个子字符串返回参数为char* 参数很简单应该是子字符串的位置一个是长度如果不指定长度默认到\0
string s(hello world);
couts.substr(0,5); //输出hello
17getline()
getline (string) - C Referencehttps://legacy.cplusplus.com/reference/string/string/getline/这个函数的作用就是cin的一个拓展没有参数和没有返回值众所周知cin输入字符串碰到空白会暂停但是getline要碰到\0才会停止
string s;
cins; //输入jascsahjas jscasjbsnc但最后只有jascsahjas成功输出了
s.getline(); //输入jascsahjas jscasjbsnc s里面是jascsahjas jscasjbsnc
二模拟实现
备注博主想偷懒了答应大家的模拟实现不能再给大家做详细的解释了但我会贴出源码供大家参考里面只有一点点的注释如果大家有不懂的可以评论区我我会给大家一一解答大家记得先看下面的私有成员不要直接从头看到尾哦
namespace bit //使用命名空间防止于库的string类型冲突{class string{public:typedef char* iterator; //string类的迭代器可以使用这个代替public:string(const char* str ) //当无参数时默认只有一个\0{_size strlen(str);_capacity _size;_str new char[_capacity1];strcpy(_str, str);}string(const string s): _str(nullptr), _size(0), _capacity(0) //初始化列表{string tmp(s._str);this-swap(tmp);}string operator(const string s){if(this ! s){string temp(s);this-swap(temp);}return *this;}~string(){if (_str){delete[] _str;_str nullptr;}}//// iteratoriterator begin(){return _str; //通过地址可以判断迭代器的位置}iterator end(){return _str _size;}/// modifyvoid push_back(char c){if (_size _capacity)reserve(_capacity*2);_str[_size] c;_str[_size] \0;}string operator(char c){push_back(c); //嘻嘻复用已有的功能偷懒return *this;}void append(const char* str);string operator(const char* str);void clear() //清除数据但空间不变尽量减少开空间的频率{_size 0;_str[_size] \0;}void swap(string s){std::swap(_str, s._str); //官方库的swap函数又是一个偷懒小技巧std::swap(_size, s._size);std::swap(_capacity, s._capacity);}const char* C_Str()const //哈哈是不是很简单{return _str;}/// capacitysize_t size()const //有手就行{return _size;}size_t capacity()const{return _capacity;}bool empty()const{return _size 0;}void resize(size_t newSize, char c \0){if (newSize _size){// 如果newSize大于底层空间大小则需要重新开辟空间if (newSize _capacity){reserve(newSize);}memset(_str _size, c, newSize - _size); //调用C官方库初始化不懂参考我以前的博客}_size newSize;_str[newSize] \0;}void reserve(size_t newCapacity){// 如果新容量大于旧容量则开辟空间if (newCapacity _capacity){char* str new char[newCapacity 1];strcpy(str, _str);// 释放原来旧空间,然后使用新空间delete[] _str;_str str;_capacity newCapacity;}}/// accesschar operator[](size_t index)//很容易实现吧{assert(index _size);return _str[index];}const char operator[](size_t index)const //要记住const类型要单独处理{assert(index _size);return _str[index];}///relational operatorsbool operator(const string s)const{int res strcmp(_str, s._str); //C官方库以前博客有这种函数的模拟实现和讲解if(res 0)return true;return false;}bool operator(const string s)const{return !(*this s);}bool operator(const string s)const{int res strcmp(_str, s._str);if(res 0)return true;return false;}bool operator(const string s)const{return !(*this s);}bool operator(const string s)const{int res strcmp(_str, s._str);if(res 0)return true;return false;}bool operator!(const string s)const{return !(*this s);}// 返回c在string中第一次出现的位置size_t find (char c, size_t pos 0) const //只读不改最好const同时支持非const类型{for (size_t i pos; i _size; i){if (_str[i] c)return i;//找到返回下标}return -1;//未找到}// 返回子串s在string中第一次出现的位置size_t find (const char* s, size_t pos 0) const{assert(s); //断言如果条件为假就报错结束程序并报错assert(pos _size);const char* src _str pos;while (*src){const char* match s;//如果不匹配返回子串起始处重新查找const char *cur src;while (*match *match*cur)//结束条件{match;cur;}if (*match \0)//找到子串{return src - _str;//返回下标}else{src;}}return -1;//未找到}// 在pos位置上插入字符c/字符串str并返回该字符的位置string insert(size_t pos, char c){assert(pos _size);if (_size _capacity){//扩容char *newstr new char[_capacity * 2 1];//开空间strcpy(newstr, _str);delete[] _str;_str newstr;_capacity * 2;//Expand(_capacity * 2);}//移数据for (int i _size; i (int)pos; --i){_str[i 1] _str[i];}_str[pos] c;_size;return *this;}string insert(size_t pos, const char* str){size_t len strlen(str);if (_size len _capacity)//扩容{//扩容char *newstr new char[_capacity * 2 1];//开空间strcpy(newstr, _str);delete[] _str;_str newstr;_capacity * 2;//Expand(_size len);}//后移数据for (int i _size; i (int)pos; --i){_str[len i] _str[i];}//拷贝字符串while (*str ! \0){_str[pos] *str;}_size len;return *this;}// 删除pos位置上的元素并返回该元素的下一个位置string erase(size_t pos, size_t len){assert(pos _size);if (pos len _size)//pos位置之后全为0{_str[pos] \0;_size pos;}else{strcpy(_str pos, _str pos len);_size - len;}return *this;}private:friend ostream operator(ostream _cout, const bit::string s);friend istream operator(istream _cin, bit::string s);private:char* _str;size_t _capacity;size_t _size;};};//输入流重载istream bit::operator(istream _cin, bit::string s){//预分配100个空间char *str (char *)malloc(sizeof(char)*100);char *buf str; //buf可以防止频繁开空间int i 1;//预处理跳过流里面的所有空格和回车while ((*buf getchar()) || (*buf \n));for ( ; ; i){if (*buf \n) //回车跳出{*buf \0;break;}else if (*buf ) //空格跳出{*buf \0;break;}else if (i % 100 0) //空间不足{i 100; //追加100个空间str (char *)realloc(str,i);}else //每次getchar()一个值{buf (stri);//为了避免realloc返回首地址改变不使用buf而是用str加上偏移.//每次读取一个字符*buf getchar();}}//输入完成,更新ss._str str;s._capacity s._size i;return _cin;}//输出流重载ostream bit::operator(ostream _cout, const bit::string s){for (size_t i 0; i s.size(); i){_cout s[i];}return _cout;}