当前位置:首页 » 《休闲阅读》 » 正文

【C++】string类(1)

22 人参与  2024年10月21日 08:41  分类 : 《休闲阅读》  评论

点击全文阅读


?个人主页: 起名字真南
?个人专栏:【数据结构初阶】 【C语言】 【C++】

请添加图片描述

目录

引言1 string类的基础知识1.1 什么是string类1.2 string和STL 2 范围for2.1 范围for的语法 3 string类的主要功能和操作3.1 string类的构造3.2 string类对象空间容量操作3.3 string类对象的访问和遍历操作3.4 string类对象的修改操作3.5 string类对象的非成员函数

引言

在C++中,string类是标准库中的一个重要工具,用于处理字符串。与传统的C风格字符串(char数组)相比,C++的string类提供了更高的灵活性和安全性,并且能够自动处理内存管理。因此,掌握string类的使用对于编写高效、安全的C++代码至关重要。本文将从string类的基础知识入手,逐步深入探讨它的常用操作、底层实现及高级技巧,帮助你更好地理解并应用这一强大的工具。

1 string类的基础知识

1.1 什么是string类

C++的string类其实是标准库std的一部分,并且定义在了< string >头文件中,封装了字符数组并且提供了很多便捷的方法

1.2 string和STL

在C++中std::string与STL有着密切的关系(Standard Template Library,标准模板库)有着密切的联系。std::string类实际上是基于STL设计原则构建的一的特殊模板类,用于处理字符串这种常见的数据类型。

1 std::string是STL容器的特例 :
容器是组成STL的六大组件之一,它包含了 std::vector std::list 等等一些容器,而std::string本质上是专门处理字符串的一个容器,和vector< char >有很多相似的地方

自动分配内存:std::string会自动管理储存的字符串内存,在对字符串进行增删查改等内容时会自动分配内存,不需要手动管理迭代器:std::string可以使用STL标准模板库中的迭代器进行遍历整个容器,可以使用begin() end() 用来遍历字符。
例如下面的代码 :
#include<iostream>#include<string>using namespace std;int main(){string str = "hello world";for (auto it : str){cout << it;}return 0;}

这里的for循环时范围for因为后续学习STL的过程中都少不了他的存在所以接下来为大家介绍一下

2 范围for

其实范围for的本质上还是使用了STL中的六大组件之一的迭代器,通过调用begin() end()两个函数来返回string容器中的开头和结尾的迭代器。

2.1 范围for的语法

for(auto it : 容器){cout<< it ;}

这里的it是一个迭代器而不是指针,但是你可以理解为他是一个智能指针,因为它提供了像(*解引用,++递增)的一些用法,但是并不一定是指向实际内存的地址。而且不同的容器迭代器的类型也不同,例如vector的迭代器就是普通类型,但是list迭代器的类型可能是一个复杂的对象。
指针:则是指向内存的地址,是指向内存中某个位置的变量,并且只能用于数组中还有连续内存中的对象。
如果看不懂的话范围for的写法也可以是这样:

auto begin = str.begin();auto end = str.end();for(auto it = begin; it != end; it++){char currentChar = *it;cout<< currentChar;}

这里是定义了三个迭代器 分别是begin(用于记录str容器的开头位置)end(用于记录str的结尾位置) 还有it(作为循环变量),在for的循环体中我们定义了一个currentChar的变量用于记录当前字符,然后通过对it进行解引用来获取当前字符,最后输出当前字符然后it++,知道it == end的时候循环结束完整的输出整个字符串。

3 string类的主要功能和操作

在这里给大家提供一个可以作为参考的网址:
链接: C++string参考资料

3.1 string类的构造

函数名称功能说明
string() (重点)构造空字符串作为string类的对象
string(const char * s) (重点)字符串作为string类的对象
string(size_t n, char c)n个字符c来构造string类的对象
string(const string& str) (重点)用一个string类型来初始化另一个string类型的对象
string (const string& str, size_t pos, size_t len = npos)使用字符串str的pos位置向后len个长度来构建string类的对象)

代码演示:

int main()int main(){//string() string s1;//string(const char* s)string s2("hello world");//string(const string& str)string s3(s2);//string(siez_t, char c)string s4(10, 'a');//string(const string& str, size_t pos, size_t len);string s5(s3, 6, 5);  //区间是左闭右开cout << "s1 :" << s1 << "\ns2: " << s2 << "\ns3: " << s3 << endl;cout << "s4: " << s4 << endl;cout << "s5: " << s5 << endl;return 0;}

输出结果:
在这里插入图片描述
由于string的功能太多所以只对主要内容进行讲解。我们在写构造函数的时候需要注意在构造s1 的时候后面不能加()如果加了括号编译器会认为是一个函数声明并且不需要传参,不加括号编译器则会自动调用string的构造函数当我们在使用示例s5构造函数的时候要注意打印的区间是左开右闭,代码示例中是从第六个位置开始打印包括第六个位置后的五个字符

3.2 string类对象空间容量操作

函数名称功能说明
size() (重点)返回字符串有效字符长度
length()返回字符串有效字符长度
capacity()返回空间总大小
empty() (重点)检测字符串是否为空,是返回 true,否则返回 false
clear() (重点)清空有效字符串
reserve(size_t n) (重点)为字符开辟n个空间
resize(size_t n, char c) (重点)将字符串的个数改成 n 个,多出的空间用字符 c填充

代码演示:

int main(){string s1("hello world");cout << "s1.size() :" << s1.size() << endl;cout << "s1.length() :" << s1.length() << endl;cout << "s1.capacity() :" << s1.capacity() << endl;if (!s1.empty()){cout << "s1.empty() :" << "true" << endl;}s1.reserve(40);cout << "s1.reserve(40) :" << s1.capacity() << endl;s1.resize(20, 'p');cout <<"s1.resize(20, 'p'):" << s1 << endl;s1.clear();cout<< "s1.clear(): " << s1 << endl;return 0;}

输出结果:
在这里插入图片描述
在我们reserve(40)之后为什么编译器开辟的空间是47?是因为编译器的内存管理策略,目的是提高性能并减少未来重新分配,一般开辟的空间只会比我们输入的更大不会更小

3.3 string类对象的访问和遍历操作

函数名称功能说明
operator[] (pos) (重点)返回 pos 位置的字符,const string 类对象调用
begin() + end()begin() 获取第一个字符的迭代器 + end() 获取最后一个字符下一个位置的迭代器
rbegin() + rend()rbegin() 获取反向迭代的第一个字符的迭代器 + rend() 获取最后一个字符前一个位置的反向迭代器
范围 for (for (auto& item : container))C++11 支持更简洁的范围 for 的新遍历方式

代码演示:

int main(){string s1("hello world");for (int i = 0; i < s1.size(); i++){cout << s1[i];}cout << endl;auto begin = s1.begin();auto end = s1.end();for (auto it = begin; it != end; it++){cout << *it;}cout << endl;for (auto i : s1){cout << i;}cout << endl;auto rbegin = s1.rbegin();auto rend = s1.rend();for (auto it = rbegin; it != rend; it++){cout << *it;}return 0;}

输出结果:
在这里插入图片描述
需要注意一种情况就是在调用rbegin 和 rend的时候最后循环条件改变的方式依旧是++,而不是--。

3.4 string类对象的修改操作

函数名称功能说明
push_back (char c)在字符串后尾插字符 c
append (const char * ch)在字符串后追加一个字符串 ch
operator+= (const char * ch) (重点)在字符串后追加字符串 ch
c_str() (重点)返回 C 格式字符串
find (const char * s, size_t pos = 0) + npos (重点)从字符串 pos 位置开始往后查找字符串 s,返回字符串中的位置
rfind (const char * s, size_t pos = npos)从字符串 pos 位置开始往前查找字符串 s,返回字符串中的位置
substr (size_t pos = 0, size_t len = npos)在字符串中从 pos 位置开始,截取 len 个字符,然后将其返回

代码演示:

int main(){string s1;s1.push_back('a');s1.push_back('a');s1.push_back('a');s1.push_back('a');cout << s1 << endl;s1.append("bxvxcvb");cout << s1 << endl;s1 += "xzviuynq";cout << s1 << endl;size_t c = s1.find('c', 0);cout << "c第一次出现的坐标大小 :" << c << endl;size_t rc = s1.rfind('c',-1);cout << "c最后一次出现的坐标大小 :" << rc << endl;string s2;s2 = s1.substr(0, 9);  //左闭右开所以返回的是下标从0-8的字符cout << s2 << endl;if (strcmp(s1.c_str(), s2.c_str()) > 0){cout << "s1 > s2" << endl;}else if (strcmp(s1.c_str(), s2.c_str()) < 0){cout << "s1 < s2" << endl;}else{cout << "s1 == s2" << endl;}return 0;}

输出结果:
在这里插入图片描述注意这里的find 和refind 的返回值都是字符c的坐标,我们调用c_str的原因是我们没有重载< 和 >操作符所以不能对string类直接进行比较,所以我们需要使用c_str来将他们转换成字符型来进行比较。

3.5 string类对象的非成员函数

函数名称功能说明
operator+将两个字符串拼接并返回一个新字符串
relational operators (==, !=, <, >, <=, >=)用于比较两个字符串的大小或相等性
swap (string& str)交换两个字符串的内容
operator>> (istream& in, string& str)从输入流读取字符串
operator<< (ostream& out, const string& str)将字符串输出到输出流
getline (istream& in, string& str)从输入流中读取一行字符串,直到遇到换行符

代码演示:

int main(){string s1("hello ");string s2("world");string s3 = s1 + s2;cout << s3 << endl;string foo = "alpha";string bar = "beta";if (foo == bar) cout << "foo and bar are equal\n";if (foo != bar) cout << "foo and bar are not equal\n";if (foo < bar)  cout << "foo is less than bar\n";if (foo > bar)  cout << "foo is greater than bar\n";if (foo <= bar) cout << "foo is less than or equal to bar\n";if (foo >= bar) cout << "foo is greater than or equal to bar\n";string s4;cout << "s4 = ";cin >> s4;cout << s4 << endl;cin.ignore();string s5;cout << "输入一串文字 :";getline(cin, s5);cout << s5 <<endl;return 0;}

输出结果:
在这里插入图片描述
注意当我们在使用cin和getline的时候需要注意一种情况就是cin只会读取到空格而在你输出的完之后按下的空格cin不会读取而是会存到缓冲区里,当我们使用getline的时候会直接读取缓冲区的\n从而导致程序出错直接结束不会再读取你输入的内容。,

解决的办法有两种:

使用cin.ignore()用来清除缓冲区的一个字符一般是换行符‘\n’先执行getline()在用cin。

点击全文阅读


本文链接:http://zhangshiyu.com/post/174759.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1