一. 为什么学习string类?
C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列 的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户 自己管理,稍不留神可能还会越界访问。
二. 标准库中的string类
1. string类对象的常见构造
#include<iostream>
#include<string>
using namespace std;
int main()
{//直接创造一个对象string a; cout << a << endl;//直接构造string b("hello world");cout << b << endl;//首地址来构造char arr[] = {"abcd"};string c(arr);cout << c << endl;//拷贝构造string d(b);string e = b;cout << d << endl;//将前n个初始化string f(5, 'x');cout << f << endl;
}
2. string类对象的容量操作
#include<iostream>
#include<string>
using namespace std;
int main()
{string a("hello world");cout <<"a:" << a << endl;cout << endl;//输出a占了多少个字节cout <<"size:" << a.size() << endl;cout <<"length:" << a.length() << endl;cout << endl;//输出系统给a一共开了多少空间cout <<"capacity:" << a.capacity() << endl;cout << endl;//将字符串的空间进行调整a.resize(5);cout << "resize之后:" << endl;cout << "a:" << a << endl;cout << "size:" << a.size() << endl;cout << "capacity:" << a.capacity() <<endl;cout << endl;//判断是否为空 1为空,0是不空cout << "empty:" << a.empty() << endl;cout << endl;//清除所有字符a.clear();cout <<"clear:" << a << endl;cout << endl;//判断是否为空 1为空,0是不空cout << "empty:" << a.empty() << endl;cout << endl;//为字符串预留空间cout <<"reserve前的capacity:" << a.capacity() << endl;a.reserve(100);cout <<"reserve后的capacity:" <<a.capacity() << endl;cout << endl;
}
注意:
1 resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。
2.resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。
3. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserver不会改变容量大小。
3. string类对象的访问及遍历操作
扩充:auto关键字
1.用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&
2.当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。
3.auto不能作为函数的参数,可以做返回值,但是建议谨慎使用 auto不能直接用来声明数组
auto会自动推导数据的类型,我们也可以看到auto与auto*没有区别。
#include<iostream>
using namespace std;
#include<string>
int main()
{string a("hello world");//访问方法:下标访问法cout << a[0] << endl;cout << a[6] << endl;a[0] = 'w';cout << a << endl;//1、下标遍历法cout << "下标遍历法:" << endl;for (int i = 0; i < a.size(); i++){cout << a[i] << " ";}cout << endl;//2、迭代器法(正向)cout << "迭代器法(正向):" << endl;string::iterator it = a.begin();//auto it = a.begin(); 与上面的效果一样for (; it != a.end(); it++){cout << *it << " ";}cout << endl;//3、迭代器(反向)cout << "迭代器(反向):" << endl;string::reverse_iterator rit = a.rbegin();//auto it = a.rbegin(); 与上面的效果一样while (rit != a.rend()){cout << *rit << " ";rit++;}cout << endl;//范围for法 底层还是迭代器的原理,速度与迭代器相似cout << "范围for法:" << endl;for (auto e : a){cout << e << " ";}cout << endl;return 0;
}
4. string类对象的修改操作
#include<iostream>
using namespace std;
#include<string>
int main()
{string a("hello world");cout << a << endl;cout << endl;//在末尾加入字符a.push_back('g');cout << "push_back后:" << a << endl;cout << endl;//在末端加入字符串a.append(" world");cout << "append后:" <<a << endl;cout << endl;//在末端随意添加a += "!!!!!";cout << "+=后:" <<a << endl;cout << endl;//返回C格式字符串const char* b= a.c_str();cout << "c_str:" <<b << endl;cout << endl;//从pos位置开始查找字符并返回其位置int npos1 = a.find('o');cout << "find:" <<npos1 << endl;cout << endl;//从pos位置开始从后往前查找字符并返回其位置int npos2 = a.rfind('o');cout << "rfind:" <<npos2 << endl;cout << endl;//从pos位置开始截取n个字符并返回string tmp1 = a.substr(npos1, npos2 - npos1);cout << "substr后tmp1:"<<tmp1 << endl;string tmp2 = a.substr(npos1);cout << "substr后tmp2:" << tmp2 << endl;cout << endl;//从指定的pos位置开始往后找int npos3 = a.find('o',npos1+1);cout << "从指定位置开始从前往后找:" << npos3 << endl;string tmp3 = a.substr(npos3);cout << "substr后tmp3:" << tmp3 << endl;return 0;
}
5. string类非成员函数
#include<iostream>
using namespace std;
#include<string>
int main()
{string a("hello ");string b("world");//涉及深层拷贝,不建议多用cout <<"operator+" << operator+(a, b) << endl;cout << "a+b:" << a + b << endl;cout << endl;//输入运算符重载string c;operator>>(cin, c); //cin>>c;效果相似 录入空格之前的,并在遇到换行时,停止输入cout << "operator>>:" <<c << endl;cout << endl;//输出运算符重载cout << "operator<<:";operator<<(cout, a) << endl; //cout<<a;效果相似cout << endl;//获取一行字符串cout << "getline:"; //即使是空格之后的也是可以录入的,遇到换行时停止输入string d;getline(cin, d); //这个在这个程序中测不出来,需要单独测试cout << d << endl;cout << endl;return 0;
}