前言
今天我们来学习string类,读完本文不仅可以掌握string类的用法,还可以很轻松的解决下面问题:
为什么学习String类?
C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问.
在OJ中有关字符串的题目基本以string类的形式出现,而且在常规工作中,为了简单、方便、快捷,基本都使用string类,很少有人去使用C库中的字符串操作函数。
标准库中的String类
String类(简要了解)
string::string - C++ Reference
总结:
1. string是表示字符串的字符串类
2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作
3. string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator>string;
4. 不能操作多字节或者变长字符的序列
在使用string类时,必须包含#include头文件以及using namespace std;
String类的常用接口说明
String类对象的常见构造
这里不需要全部掌握,我挑几个重要的来说:
1.String():构造空的String类对象,即空字符;
2.String(const string& str);拷贝构造函数\
3.string(const char* s); 用c_str来S构造函数
4.string(size_t n,char c);string类对象中包含n个字符c
示例:
#include<iostream> using namespace std; int main() { string s1;//空字符 string s2 = "hello world"; string s3(s2);//拷贝构造 string s4("hello world"); //用c_str来构造函数 string s5(5, 'a');//5个字符'a' cout << s1 << endl; cout << s2 << endl; cout << s3 << endl; cout << s4 << endl; cout << s5 << endl; return 0; }
String类对象的容量操作
1.size:返回字符串的有效长度;
2.length:返回字符串的有效长度;
注:size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size().
3.capacity:返回空间总大小
4.empty:检测字符串是否释放为空串,是返回true,否则返回false
5.clear:清除有效字符
注:clear()只是将string中有效字符清空,不改变底层空间大小。 6.reserve:为字符串预留**空间注:reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserver不会改变容量大小. 7.resize:将有效字符串个数改为n,多出的地方用字符串c填充
注:resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字
符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的
元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大
小,如果是将元素个数减少,底层空间总大小不变。
示例:
void test(){ string s("hello world"); cout << s.size() << endl;//11 cout << s.length() << endl;//11 cout << s.capacity() << endl;//15 s.clear();//将s中的字符串清空, //注意清空时只是将size清0,不改变底层空间的大小 cout << s.size() << endl;//0 cout << s.capacity() << endl;//15 //将s中有效字符个数增加到16,不够的地方用"a"填充 s.resize(16, 'a');//resize(16);不够地方默认补0 cout << s << endl;//helloworldaaaaa cout << s.size() << endl;//16 cout << s.capacity() << endl;//31 //将s中有效字符缩小到5个字符,capacity保持不变 s.resize(5); cout << s << endl;//hello cout << s.size() << endl;//5 cout << s.capacity() << endl;//15 // 测试reserve是否会改变string中有效元素个数 s.reserve(100); cout << s.size() << endl;//0 cout << s.capacity() << endl;//111 // 测试reserve参数小于string的底层空间大小时,是否会将空间缩小 s.reserve(50); cout << s.size() << endl;//0 cout << s.capacity() << endl;//111 }
String类对象三种遍历操作
1.for+oprtator[]访问
2.迭代器遍历
3.范围
示例:
string s = "helllo world"; //1.for+operator[]可以遍历也可以修改字符串,s[i]+=1; for (int i = 0; i < s.size(); i++) { //cout << s.operator[](i) << " "; cout << s[i] << " "; } cout << endl; //2.迭代器iterator 也可以修改字符串 *it+=1; string::iterator it = s.begin(); //auto it = s.begin(); while (it != s.end()) { cout << *it << " "; ++it; } cout << endl; //3.范围for 如果要是想修改字符串需要加上引用 //for(auto& e:s) for (auto e : s) { cout << e << " "; } cout << endl;
String类的四种迭代器
按方向分: 有正向迭代器和反向迭代器(iterator和reverse_iterator)分别配合being()、end()和rbegin()、rend()使用
按属性分: 有普通迭代器和const迭代器 (iterator const_iterator | reverse_iterator const_reverse_iterator)
示例:
string s = "hello world"; //正向迭代器 string::iterator it = s.begin(); while (it != s.end()) { cout << *it << " "; ++it; } cout << endl; //反向迭代器 string::reverse_iterator it1 = s.rbegin(); while (it1 != s.rend()) { cout << *it1 << " "; ++it1; } cout << endl;
String类对象的修改操作
1.operator+=:在字符串后追加一个字符串
2.append:在字符串后追加一个字符串
3.push_back:在字符串后尾插字符c
4.c_str:返回c格式字符串
5.find+npos:从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
6.rfind:从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
7.substr:在str中从pos位置开始,截取n个字符,然后将其返回
operator+=/append/push_back/insert
示例:
//operator+= string s = "hello"; s += "world"; cout << s << endl; //append s.append("I"); cout << s << endl; string s1("I"); string s2(" am qk"); //append(string)完成两个string对象拼接 s1.append(s2); //append(str)完成两个string对象和字符串str的拼接 s1.append(" like"); //append(n,char)将n个字符char拼接到string对象后面 s1.append(3,'!'); //push_back s.push_back('a'); s.push_back('m'); cout << s << endl; //insert s.insert(s.size() , "qk"); string s("C"); //insert(pos,string)插入string对象 string t("SD"); s.insert(1, t); //insert(pos,str)插入字符串str s.insert(3, "N"); cout << s << endl;//CSDN cout << s << endl;
我们比较常用operator+=,append.insert的插入效率比较低,不建议大家使用
pop_back/erase
string s("c++"); s.pop_back(); s.pop_back(); cout << s << endl;//c //erase string s("I like c++"); //erase(pos,n)删除pos位置开始的n个字符 s.erase(8, 2);//i like c //erase(pos)删除pos位置的字符 s.erase(s.end() - 1);//I like //erase(pos1,pos2) s.erase(s.begin() + 1, s.end());//I
c_str/find/rfind/substr
string file("test.txt.zip"); FILE* fout = fopen(file.c_str(), "w");//c_str将string类型转换成const char* //要求取出.zip size_t pos = file.rfind('.');//从后往前找第一个出现的“.”的位置 if (pos != string::npos) { cout << file.substr(pos, file.size() - pos) << endl; } //要求取出.txt size_t pos1 = file.find('.');//从前往后找到第一个人出现"."的位置 if (pos1 != string::npos) { cout << file.substr(pos1, pos - pos1); }
swap
#include <iostream> #include <string> using namespace std; int main() { string s1("hello"); string s2("CSDN"); //使用string类的成员函数swap交换s1和s2 s1.swap(s2); cout << s1 << endl; //CSDN cout << s2 << endl; //hello //使用非成员函数swap交换s1和s2 swap(s1, s2); cout << s1 << endl; //hello cout << s2 << endl; //CSDN return 0; }
replace
#include <iostream> #include <string> using namespace std; int main() { string s("hello world"); //replace(pos, len, str)将pos位置开始的len个字符替换为字符串str s.replace(6, 4, "CSDN"); //hello CSDNd //replace(pos, len, n, char)将pos位置开始的len个字符替换为n个字符char s.replace(10, 1, 3, '!'); //hello CSDN!!! cout << s << endl; return 0; }
String类非成员函数
1.operator+:不改变原来字符串的值,尽量少用因为传值返回,导致深拷贝效率低
2.operator>>:输入运算符重载
3.operator<<:输出运算符重载
4.getline:获取一行字符串;
5.relational operators:大小对比
我们知道,使用>>进行输入操作时,当>>读取到空格便会停止读取,基于此,我们将不能用>>将一串含有空格的字符串读入到string对象中。
这时,我们就需要用getline函数完成一串含有空格的字符串的读取操作了。
用法一:
istream& getline (istream& is, string& str);
std::string name; std::cout << "Please, enter your full name: "; std::getline(std::cin, name); std::cout << "Hello, " << name << "!\n";
用法二:
istream& getline (istream& is, string& str, char delim);
getline函数将从is中提取到的字符存储到str中,直到读取到分隔符delim或换行符’\n’为止。
#include <iostream> #include <string> using namespace std; int main() { string s; getline(cin, s, 'D'); //输入:hello CSDN cout << s << endl; //输出:hello CS return 0; }
String与数字之间的转换
数字和字符串之间的转换在竞赛中还是屡见不鲜的,希望大家多练习练习.
1.数字转换成字符串
//1.数字转换成字符串;stringstream int num = 123; stringstream ss; ss << num; string s = ss.str(); cout << s << endl; //2.to_string string p = "pi is" + to_string(3.1415926); string perfect = to_string(1 + 2 + 3 + 4 + 5) + "is a perfect number"; cout << p << endl; cout << perfect << endl;
2.字符串转化成数字
//字符串转换成数字 stoi string s = "1234"; int num = stoi(s); cout << num << endl; //atoi string s2 = "456"; int num1 = atoi(s2.c_str()); cout << num1 << endl; //stringstream string s3 = "789"; stringstream ss2; ss2 << s3; int num2; ss2 >> num2; cout << num2 << endl;