1,string定义:
Strings are objects that represent sequences of characters(string是表示字符序列的对象)string是一个类。string属于标准库,头文件<string>.
(注:string的有些方法比较冗杂,我这里会陈列所有方法,但只阐述常用的!!!)
2,npos:
string有一个静态成员变量:npos
3,string的构造函数:
string s1;
string s2("hello world");
string s3(s2, 6, 5);//从下标为6开始,取五个字符
string s4(s2, 6);//从下标为6开始,缺省值为size_t npos=-1;最大的整型,越界,到字符串完为止
string s5 (10, 'a');
cout << s5 << endl;//aaaaaaaaaa
string s6(s5.begin(), s5.end());
cout << s6 << endl;//aaaaaaaaaa
4,operator=
string s8 = s7;
s8 = "xxx";
s8 = 'x';
5,非成员函数
(1)operator<<
此函数非成员函数,原因:这个运算符是用来直接打印字符串的,(cout<<s1)运算符左右两边分别是ostream类型和string类型,所以这两个参量将作为这个运算符重载的第一第二参数,如果这个作为成员函数,那么第一个参数默认是*this(也就是string),那么与我们想要达到的参数顺组颠倒,所以它不能作为成员函数。
用法:cout << s1 << endl;
(2)operator>>
此函数非成员函数。
用法:string s1("wwwwww");
cin >> s1;
cout << s1 << endl;
(1)留提取后,原先的的内容会被覆盖。
(2)提取的时候以空格和换行符截止,如果想要得到一整行的内容,应该使用getline();
(3)getline (string)
此函数非成员函数。
(1)这个方法,字符串原先的的内容会被覆盖。
(2)第一个是遇到字符(delim)这个参数,才停止。第二个是遇到'\0'截止
用法:
(1)string s1;
getline(cin, s1,'#');
(2)string s1;
getline(cin, s1);
(4)swap (string)
非成员函数:
成员函数:
两者原理大致相同,
用法:string s1("xxx");
string s2("yyy");
swap(s1, s2);
(5)operator+ (string)
非成员函数:
用法:
string s1("hello");
string s2("world");
cout << s1 + s2 << endl;
cout << s1 + '#' << endl;
(6)relational operators (string)
非成员函数:
这里有各种各样的字符串的比较方法,这里是根据首元素字母的ascll码值进行比较的
用法:
string s1("hello");
string s2("world");
cout << (s1 < s2) << endl;//1
cout << (s1 == s2) << endl;//0
6,Element access
**(1)**operator[]
(1)[ ]可以直接通过下标访问字符数组中的值。
(2)这里提供了两种,一种是既可以读又可以改变内容的,第二种是只可以读取,不可以更改的
const string s1("hello world");
for (size_t i = 0;i < s1.size();i++) {
//读
cout << s1[i] << " ";
}(这里调用的第二个用函数)
以上情况就是因为,这是一个用const就是的引用,不可以修改,但是这里修改了,所以报错。
string s1("hello world");
for (size_t i = 0;i < s1.size();i++) {
cout << s1[i]++ << " ";
}(这里调用的第一个用函数)所以这里的值可以修改
(2)at()
at和[]相似,但失败后会抛异常
(3)back()
返回字符串最后一个字符的引用
(4)front()
返回字符串第一个字符的引用
7,迭代器相关的函数
(1)begin()
返回一个指向字符串第一个字符的迭代器。
(2)end()
返回一个指向字符串末尾后的字符的迭代器。
(3)rbegin()
返回指向字符串最后一个字符的反向迭代器
(4)rend()
返回一个反向迭代器,该迭代器指向字符串第一个字符前面的理论元素。
(5)cbegin()
返回一个指向字符串第一个字符的const_iterator迭代器,该迭代器是指向const内容的迭代器,这个迭代器本身可以改变指向的对象(除非它本身也是const修饰的),但是指向的的内容,即用const修饰的字符串,不能随意修改。
(6)cend()
返回一个指向字符串末尾后的字符的const_iterator迭代器。
(7)crbegin()
返回一个const_reverse_iterator,指向字符串的最后一个字符
(8)crend()
返回一个const_reverse_iterator,该迭代器指向字符串第一个字符前面的理论元素
(9)用法:
(1)string::iterator it = s1.begin();
while (it != s1.end()) {
cout << *it << " ";
++it;
}
cout << endl;//用来读
(2) it = s1.begin();
while (it != s1.end()) {
//写
*it = 'a';
++it;
}
cout <<s1<< endl;//用来写
(3)auto rit= s1.rbegin();
while (rit!=s1.rend())
{
cout << *rit << " ";
rit++;
}
cout << endl;//倒着遍历
(4)void func(const string& s) {
//引用传参
string::const_iterator it = s.begin();
while (it != s.end()) {
//读
cout << *it << " ";
++it;
}
cout << endl;
迭代器的优势:定义在类域,运用方式相似,屏蔽了底层细节
第三种遍历方式:
上述已经提供了两种遍历的方法了,第一种是【】遍历,第二种是迭代器。一下讲第三种范围for,它的底层也是迭代器。
for (auto ch : s1) {
//读
cout << ch << " ";
}
cout << endl;
for (auto& ch : s1) {
//写
cout << ch << " ";
}
cout << endl;
8,Capacity:
(1)size()和length()
string s1 = "hello world";
cout << s1.size() << endl;//从容器来看,具有通用性
cout << s1.length() << endl;
(2)clear()
s1.clear();//清除数据,但是没有释放空间
(3)max_size()
返回字符串可以达到的最大长度。这是字符串可以达到的最大潜在长度,但不能保证对象能够达到该长度,它无法分配内存在达到该长度之前。
(4)resize()
将字符串大小调整为n个字符的长度。如果n小于当前字符串长度,则将当前值缩短到前n个字符,删除第n个字符以外的字符。如果大于当前字符串长度,将字符串大小调整为n个字符的长度,并用'\0',或者字符char c补齐补齐。
用法:
string s1 = "hello world";
s1.resize(20,'$');
cout <<s1 << endl;
(5)capacity()
返回分配内存的大小。
string s;
size_t old = s.capacity();
cout << "初始" << s.capacity() << endl;//可以存的有效字符
for (size_t i = 0; i <100; i++)
{
s.push_back('x');
if (s.capacity() != old) {
cout << "扩容" << s.capacity() << endl;
old = s.capacity();
}
}
vs中:
(6)reserve()
该方法和resize相似,但是也有区别。reserve只是预留空间,不创建元素对象。resize既分配了空间,也创建了对象,可以通过下标访问。reserve会修改capacity大小,但不修改size大小;resize既修改capacity大小,也修改size大小。
价值:确定大概要多少空间,提前开好,减少扩容,提高效率
9,Modifiers:
(1)operator+=
用法:
string s;
string s1("world");
s += '#';
s += "hello";
s += s1;
cout << s << endl;
(2)push_back()
尾插法
用法:string s;
s.push_back('#');
(3)append()
在当前字符串的基础上进行拼接,
string s;
s.append("hello");
s.append("world",0,3);
string s2("ld");
s.append(s2);
string s3("xxxxxx");
s.append(s3,1);
s.append(4,'#');
cout << s << endl;
(4)assign()
为字符串赋一个新值,替换其当前内容
用法:
string ss;
string ss1("hello world");
ss.assign(ss1);
cout << ss << endl;//hello world
string ss2("xxxxx");
ss2.assign(ss1);
cout << ss2 << endl;//hello world,覆盖
string ss3("xxxxx");
ss3.assign(ss1,5,10);
cout << ss3 << endl;// world
(5)insert()
string s("hello world");
s.insert(0, 1, 'x');
s.insert(s.begin(), 'x');
s.insert(0, "aaa", 1, 2);在下标为0的位置插入,字符串"aaa"中的一部分,这一部分从下标1开始,长度为两个字符。
cout << s << endl;
(6)erase()
s.erase(7, 2);//从小标7,开始删,删2个字符
s.erase(7);//从小标7,开始删,删完
(8)replace()
s.replace(5, 1, "%%%%%%");//将下标为5的一个字符改为这个字符串
注:insert / erase / replace 尽量不要用,都涉及移动数据,效率不高
10,String operations
(1)c_str()
返回指向数组的指针
(2)find()
用法:
string s1("test.c.ter.zip");
size_t i = s1.find('.',5);//4
size_t i = s1.find('.');//6
string s2("est");
string& s3 = s2;
int i=s1.find(s3);//1
cout << i << endl;
(3)substr()
string s1("test.c.ter.zip");
size_t i = s1.find('.');
string s2 = s1.substr(i);
cout << s2 << endl;//.c.ter.zip
(4)rfind()
从后往前找
string s1("test.c.ter.zip");
size_t j = s1.rfind('.');
s2 = s1.substr(j);//.zip
练习一:
分离协议,域名,资源名:
string s3("https://cplusplus.com/reference/string/string/swap-free/");
//协议
//域名
//资源名
size_t i1 = s3.find(':');
string sub1, sub2, sub3;
if (i1 != string::npos) {
sub1 = s3.substr(0, i1);
}
else {
cout << "没有找到i1的位置" << endl;
}
size_t i2 = s3.find('/',i1+3);
if (i1 != string::npos) {
sub2 = s3.substr(i1+3,i2-(i1+3));
}
else {
cout << "没有找到i2的位置" << endl;
}
sub3 = s3.substr(i2 + 1);
cout << sub1 << endl;
cout << sub2 << endl;
cout << sub3 << endl;
练习二:
大数相加:
string addstrings(string num1, string num2) {
int end1 = num1.size() - 1,
end2 = num2.size() - 1;
int next = 0;
string str;
while (end1 >= 0 || end2 >= 0)
{
int x1 = end1 >= 0 ? num1[end1] - '0' : 0;
int x2 = end2 >= 0 ? num2[end2] - '0' : 0;
int ret = x1 + x2 + next;
next = ret / 10;
ret = ret % 10;
str += ('0' + ret);
--end1;
--end2;
}if (next == 1) {
str +=' 1';
}
reverse(str.begin(), str.end());
return str;
}