{ C++ } —— string类的使用
一、auto关键字
在介绍string之前,我们先来介绍一下auto,auto是一个自动推导类型的关键字
auto x = 3;//推导为int
auto x = 'a';//推导为char
在早期C/C++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量,后来这个不重要了。C++11中,标准委员会变废为宝赋予了auto全新的含义即:auto不再是一个存储类型 指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期 推导而得。 用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加& 当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际 只对第一个类型进行推导,然后用推导出来的类型定义其他变量。 auto不能作为函数的参数,可以做返回值,但是建议谨慎使用 auto不能直接用来声明数组
由此引出了
范围for
范围for 对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此 C++11中引入了基于范围的for循环。for循环后的括号由冒号“ :”分为两部分:第一部分是范围 内用于迭代的变量,第二部分则表示被迭代的范围,自动迭代,自动取数据,自动判断结束。 范围for可以作用到数组和容器对象上进行遍历 范围for的底层很简单,容器遍历实际就是替换为迭代器,这个从汇编层也可以看到。
二、string类常用接口
(一)string类对象的构造
string类对象可以空构造,也可以传一个字符串又或是另一个string类对象来进行构造和拷贝构造,也可以传n个字符构造。
#include<iostream>
#include<string>
using namespace std;int main()
{string s1;//空构造string s2("hello world");//C-string构造string s3(10,'a');//n个字符构造return 0;
}
(二)string类对象的容量操作
有时我们想要直到我们目前对象中有多少个有效数据,有时候我们又想知道当前对象底层申请了多大的空间我们就可以做如下操作++++++
int main()
{//string s1;//空构造//string s2("hello world");//C-string构造//string s3(10,'a');//n个字符构造string s1("hello world");s1.size();//返回字符串有效数据的个数(不包括\0)s1.capacity();//s1底层开辟容量的大小(不包括\0,实际开的多加1)
有时我们想要改变size的个数,提前初始化好一块空间,或者是将size缩小到某个数,则可以
s1.resize(5);//将有效数据个数变为n个,如果比当前有效数据个数少,则删除多的数据,多则有可能扩容,默认填充\0,也可以自己给想要填的字符)
s1.resize(20, 'x');//将有效数据个数变为n个,如果比当前有效数据个数少,则删除多的数据,多则有可能扩容,默认填充\0,也可以自己给想要填的字符)
有时我们想要清空所有有效数据,并判断是否空没空则可以
s1.empty();//检测字符串是否为空串,是返回true,不是返回false
s1.clear();//清空有效数据
有时我们想要提前开好一块空间,避免频繁扩容效率低下则可以
s1.reserve(100);//提前开多大空间
有时我们再完成字符串的输入后,想要让多余的空间释放,则可以
s1.shrink_to_fit();//将空间大小缩到size个(一定会缩,但不一定缩到正好size个,不具有强制约束力)
(三、string类对象的访问及遍历操作)
我们想要访问一个字符串类对象里面的任意一个位置只需要用方括号的形式即可访问到,他会返回第pos位置字符的引用
迭代器方式遍历string对象
string::iterator it = s1.begin();//[s1.begin(),s1.end());while (it != s1.end()){cout << (*it) << ' ';it++;}cout << endl;string::reverse_iterator it1 = s1.rbegin();//反着遍历while (it1 != s1.rend()){cout << (*it1) << ' ';it1++;}cout << endl;return 0;
}
(四、string类对象的修改操作)
我们想要尾插一个字符可以用push_back接口,尾插字符串或者另一个string类对象可以用operator+= 和append
///*s1.push_back('x');*/s1.append("hello world", 3);//从0开始追加三个s1.append("hello world", 3, 5);//从第三个下标开始追加5个s1.append(10, 'x');//追加10个xs1.append(s2, 3, 5);//s1.append(s2);s1 += 'x';
我们想要查找某个字符或者字符串可以用find接口
size_t pos = s1.find('e');
std::string::find
string (1) | size_t find (const string& str, size_t pos = 0) const; |
---|---|
c-string (2) | size_t find (const char* s, size_t pos = 0) const; |
buffer (3) | size_t find (const char* s, size_t pos, size_t n) const; |
character (4) | size_t find (char c, size_t pos = 0) const; |
rfind则是从后往前寻找字符或者是字符串或者是类对象。(默认从最后一个有效数据开始找)
substr是从一个串中指定范围返回一个字串
replace则是将某个位置开始长度为n的字符替换成别的字符
string s1("hello world");
size_t pos = s1.rfind('w',s1.size() - 3);
s1.replace(pos, 1, "**");//从pos位置替换1个字符变成**
cout << pos << endl;
cout << s1 << endl;
erase是从第pos个位置删除len个字符
sequence (1) | string& erase (size_t pos = 0, size_t len = npos); |
---|---|
character (2) | iterator erase (iterator p); |
range (3) | iterator erase (iterator first, iterator last); |
string s1("hello world");
size_t pos = s1.rfind('w',s1.size() - 3);
s1.replace(pos, 1, "**");//从pos位置替换1个字符变成**
s1.erase(0, 1);//从下标为0删除一个字符,删除h
assign是一个赋值接口
、
由于assign返回的是string& 当然也可以这么玩连续赋值。
string s3 = s2.assign(s1, 2, 3);//相当于s2 = s1;// string s3 = s2;
find_first_of是一个查找是否含有给出字符串的字符,当遇到给的字符串中的任意一个字符时返回该字符下标,find_last_of是从后往前进行查找。
find_first_not_of是查找给出字符串以外的字符,并返回遇到给出字符串以外的字符的下标当遇到的时候,find_last_not_of是反向查找。
hello的e下标为1,在我们给出的字符串“aeiou”当中。
还有一个非成员函数operator+,可以用两个字符串相加,他们的字符串会拼接起来构造一个新string对象。不会影响他们自身。
string s1("hello world");
string s2;
s2.assign(s1, 2, 3);
cout << s2 << endl;
string s3 = s2.assign(s1, 2, 3);
size_t pos = s1.find_first_of("aeiou");
cout << pos << endl;
string s4 = s1 + s2;
对于我们输入字符串如果不想让空格作为分隔符,想让空格也作为string对象的一部分读进去那就可以用getline。
这里的delim就是分隔符,默认以\n作为分隔符,遇到这个\n就会读完一个string对象。也可以自己设置分隔符。