目录
string
C++中的string类是字符串类
string类本质上就是一个可以管理动态增长的字符数组的类,并且这个字符数组以 ‘\0’ 结尾;
string类底层已经将增、删、查、改以及扩容这些机制封装好了,我们只需要直接使用即可;
头文件: #include<string>
1.string与char* 的区别
char*是一个指针;
string是一个类,类内部封装了char*,管理这个字符串,是一个char*型的容器。
2.string的使用
string的构造函数7个
注:第三个构造函数中,npos 为 size_t (无符号整形)类型的-1,这个数是极大的数(根据不同编译器可能有所差异);
这个构造函数的意思是:从字符串str的pos位置开始,拷贝len个字符,如果str太短或len= npos(缺省),则从pos位置拷贝构造到str的末尾
int main()
{
string s0;
string s1("hello world");
string s2(s1);
string s3(s1, 5, 3); //拷贝s1的第五个位置往后的三个
string s4(s1, 5, 10);
string s5(s1, 5);
cout << s0 << endl; //无
cout << s1 << endl; //hello world
cout << s2 << endl; //hello world
cout << s3 << endl; // wo
cout << s4 << endl; // world
cout << s5 << endl; // world
string s6(10,'#');
cout << s6 << endl;
return 0;
}
字符串遍历
[]+下标遍历;
注:这里的调用,实际上是用了运算符重载 operator[]。不是数组的形式
a[i] = *(a+i)
void test_string1()
{
string s("hello world");
for (size_t i = 0; i < s.size(); i++)
{
cout << s[i]; //注意这里 实际是 s.operator[](i) 并非数组 a[i] = *(a+i)
}
cout << endl;
}
利用迭代器遍历
迭代器基本上每个容器都有,string::iterator 表明是string域的;
begin():函数返回的是string字符串的首位置
end:会在字符串最后一个有效位置的下一个位置;
begin~end = 左闭右开
//迭代器遍历
string s("hello world");
string::iterator it = s.begin();
while (it != s.end()) //end 和在字符串的最后一个有效符号的下一个位置
{
cout << *it;
++it;
}
cout << endl;
范围for遍历
范围for:是c++提供的一个非常方便的访问方式。
可以自动取对象的内容并且自动向后访问自动停止
范围for的底层实现其实是迭代器,我们还可以利用auto关键字来配合使用范围for
//范围for
string s("hello world");
for (auto ch : s)
{
cout << ch;
}
cout << endl;
反向迭代器
使用begin()函数和end()函数的迭代器遍历是正向迭代器
反向迭代器顾名思义,就是顺序反过来了,它的用法与正向迭代器非常类似。
使用前先介绍: rbegin()和rend()这两个函数,这两个函数是用来配合反向迭代器使用的,rbegin() : 函数返回的是string字符串的最后一个有效字符
rend() :函数返回的是string字符串的第一个字符的前一个位置。
//反向迭代器
string s("hello world");
string::reverse_iterator rit = s.rbegin();
while (rit != s.rend())
{
cout << *rit;
rit++;// 反向迭代器也是++
}
cout << endl;
字符串capacity
string - C++ Reference (cplusplus.com)
void test_string_capacity()
{
//支持cout cin进行输入输出
string s("hello world");
cout << s.size() << endl;
cout << s.length() << endl;
cout << s.capacity() << endl;
cout << s << endl;
cout << endl;
//将s的字符串清空,只是size清0,不会改变容量大小
s.clear();
cout << s.size() << endl;
cout << s.capacity() << endl;
cout << endl;
//将s中有效字符个数增加到15,多出的位置用a填充
s.resize(15,'a');
cout << s.size() << endl;
cout << s.capacity() << endl;
cout << s << endl;
cout << endl;
//将s中有效字符缩小到5个,
s.resize(5);
cout << s.size() << endl;
cout << s.capacity() << endl;
cout << s << endl;
}
字符串插入操作
push_back函数
push_back函数可以实现string对象的插入操作,但是需要注意的是push_back函数只能够尾插入一个字符,不能插入字符串。
append函数
可以插入字符串,可以插入另一个string对象,而且可以指定n个字符插入
//append
string s("hello");
s.append("-world");// 插入常量字符串
cout << s << endl;
string str("world");
s.append(str);// 插入另一个string对象
cout << s << endl;
+=运算符
不仅可以插入新的string对象,还可以插入常量字符串,也可以插入单个字符
//+=
string s("hello ");
s += "-world"; // 插入常量字符串
cout << s << endl;
string str("world");
s += str; // 插入新的string对象
cout << s << endl;
s += 'A';// 插入单个字符
cout << s << endl;
insert函数
insert 函数可以在任意的指定位置进行插入。insert 函数它可以在任意的指定位置插入一个新的string对象、一个常量字符串、一个常量字符串的n个字符、一个字符等等。
//insert
string s("hello");
// 在下标为0的位置插入一个新的string对象
string str("C++");
s.insert(0, str);
cout << s << endl; //C++hello
// 在下标为0的位置插入一个常量字符串
s.insert(0, "hello world");
cout << s << endl;
// 在下标为0的位置插入一个常量字符串的前3个字符
s.insert(0, "he-lo world", 3);
cout << s << endl; //he-hello worldC++hello
// 在下标为0的位置插入一个字符x
s.insert(0, 1, 'x');
s.insert(s.begin(), 'x');
cout << s << endl; //xxhe-hello worldC++hello
// 在下标为0的位置插入三个字符x
s.insert(0, 3, 'x');
cout << s << endl; //xxxxxhe-hello worldC++hello
substr函数
substr函数是用来返回string字符串的一个任意子串,我们可以通过设定起始位置pos和子串长度len来获取子串;
//substr
string s1("hello world");
// 012345678910 '\0'
// 取出子串"world"
string s2 = s1.substr(6, 5); //第6个位置往后的五个字符
cout << s2 << endl; //world
字符串查找函数
find函数
find函数:可以查找string对象、常量字符串或者是一个字符,并且可以设定pos值来规定查找的起始位置,默认从0下标开始查找。
例题:
URL化。编写一种方法,将字符串中的空格全部替换为
%20
。假定该字符串尾部有足够的空间存放新增字符
class Solution {
public:
string replaceSpaces(string S, int length) {
size_t pos = S.find(' '); //find找空格,记录位置pos值
while(pos != string::npos) //一直找到字符串结束
{
S.replace(pos,1,"%20"); //找到了就替换
pos = S.find(' '); //找下一个空格
}
return S;
}
};
rfind函数
find函数是顺着查找,而rfind是倒着查找。
find函数和rfind函数的区别就是查找方向不同。
查找函数的使用
对URL进行分割。
URL = 协议、域名和uri
void test_string_find()
{
string url("https://legacy.cplusplus.com/reference/string/string/rfind/");
cout << url << endl;
// 提取协议
string protocol;
size_t pos1 = url.find("://");
// 查找成功
if (pos1 != string::npos)
{
protocol = url.substr(0, pos1);
cout << "协议:" << protocol << endl;
}
else
{
cout << "非法url" << endl;
}
// 提取域名
string domainName;
size_t pos2 = url.find('/', pos1 + 3);
// 查找成功
if (pos2 != string::npos)
{
domainName = url.substr(pos1 + 3, pos2 - (pos1 + 3));
cout << "域名:" << domainName << endl;
}
else
{
cout << "非法url" << endl;
}
// 提取uri
string uri = url.substr(pos2);
cout << "uri:" << uri << endl;
}
getline函数
用cin对string进行流提取时,由于cin遇到空格和换行会停止读取.
所以我们如果想要读取带有空格的字符串就会出现读取不完整的现象。
此时就需要用到getline函数,getline函数可以获取一行字符串,遇到换行符才会停止读取,遇到空格不会停止。
getline(cin, s);
cout << s << endl;