文章目录
前言
C语言中,字符串是以’\0’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合面向对象的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。
一、string是什么?
string是表示字符串的类,该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
二、string类常用接口说明
1.string类的常见构造
代码演示
int main()
{
string str1;//string()
string str2("abcdef");//string(const char* s)
string str3(3,'x');//string(size_t n,char c)
string str4(str2);//string(const string& s)
}
2.string类对象的容量操作
代码演示
//测试size / length / capacity /empty / clear
void Test01()
{
string str("hello,word!!");
cout << "size=" << str.size() << endl;//返回有效字符长度
cout << "length=" << str.length() << endl;//返回有效字符长度
cout << "capacity=" << str.capacity() << endl;
cout << "empty=" << str.empty() << endl;
str.clear();//不会改变底层的空间大小,只是清除有效字符
cout << "size=" << str.size() << endl;
cout << "capacity=" << str.capacity() << endl;
cout << "empty=" << str.empty() << endl;
//VS2019测试数据如下:
/*
size=12
length=12
capacity=15
empty=0
size=0
capacity=15 //可以看到clear()不改变底层空间的大小
empty=1
*/
}
//测试 resize
void Test02()
{
string str("hello,word!!");
cout << "\"" << str << "\"" << endl;
cout << "size=" << str.size() << endl;
cout << "capacity=" << str.capacity() << endl;
//"hello"
str.resize(5);//将str有效字符个数改为5个,若需增添字符用'\0'填充
cout << "\"" << str << "\"" << endl;
cout << "size=" << str.size() << endl;
cout << "capacity=" << str.capacity() << endl;//大小不变
//"hello\0\0\0\0\0"
str.resize(10);//将str有效字符个数改为10个,若需增添字符用'\0'填充
cout << "\"" << str << "\"" << endl;
cout << "size=" << str.size() << endl;
cout << "capacity=" << str.capacity() << endl;//大小可能会变
//"hello\0\0\0\0\0xxxxxx"
str.resize(16, 'x');//将str有效字符个数改为16个,若需增添字符用'x'填充
cout << "\"" << str << "\"" << endl;
cout << "size=" << str.size() << endl;
cout << "capacity=" << str.capacity() << endl;//大小可能会变
//VS2019测试数据如下:
/*
"hello,word!!"
size=12
capacity=15
"hello"
size=5
capacity=15
"hello"
size=10
capacity=15
"helloxxxxxx"
size=16
capacity=31
*/
}
//测试 reserve
void Test03()
{
string str("hello");
cout << "\"" << str << "\"" << endl;
cout << "size=" << str.size() << endl;
cout << "capacity=" << str.capacity() << endl;
//为字符串预留空间,不改变字符串的有效字符
str.reserve(100);//需预留空间大于字符串底层空间,增大底层空间
cout << "\"" << str << "\"" << endl;
cout << "size=" << str.size() << endl;
cout << "capacity=" << str.capacity() << endl;
str.reserve(50);//需预留空间小于字符串底层空间,不改变底层空间
cout << "\"" << str << "\"" << endl;
cout << "size=" << str.size() << endl;
cout << "capacity=" << str.capacity() << endl;
//VS2019测试结果如下:
/*
"hello"
size=5
capacity=15
"hello"
size=5
capacity=111
"hello"
size=5
capacity=111
*/
}
小结
1.size() 和 length() 接口底层原理实现相同,引入size() 的原理是为了与其他容器的接口保持一致
2.clear()只是将有效字符清空,不会改变底层空间的大小
3.resize(size_t n) 和 resize(size_t n, char c)都是改变有效字符的个数,不同的是后者确定了需要填充的字符,而前者默认填充’\0’,如果是需要填充字符,可能会改变底层空间的大小,不需要填充或者需要删减有效字符,是不会改变底层空间的大小的。
4.reserve(size_t n)是为字符串预留空间,不会影响字符串的有效字符,当reserve()参数小于字符串的底层空间时,不会改变底层空间大小,反之则增大底层空间。
3.string类对象的访问及遍历
代码演示
//测试char operator[](int pos)
void Test04()
{
string str1("hello,word!");
const string str2("Hello,word!");
cout << str1 << " " << str2 <<endl;
cout << str1[0] << " " << str2[0]<< endl;//访问pos位置字符
str1[0] = 'H';//修改pos位置字符
//str2[0] = 'h' ; //编译错误,const对象不允许修改属性
cout << str1 << endl;
//Vs2019测试数据如下:
/*
hello,word! Hello,word!
h H
Hello,word!
*/
}
//测试 begin + end
void Test05()
{
string s("hello,word!");
//定义一个正向迭代器it
string::iterator it = s.begin();//c++11可以使用auto推导出该类型 auto it = s.begin
while(it != s.end() )
{
cout << *it ;
++it;
}
cout << endl;
//VS2019运行结果
/*
hello,word!
*/
}
//测试 rbegin + rend
void Test06()
{
string s("hello,word!");
//定义一个逆序迭代器r_it,与begin + end 的区别是迭代的顺序相反
auto r_it = s.rbegin(); //string::reverse_iterator r_it = s.rbegin();
while(r_it != s.rend() )
{
cout << *r_it++ ;
}
cout << endl;
//VS2019测试结果如下:
/*
!drow,olleh
*/
}
//范围for
void Test07()
{
string s("hello,word!");
for(auto c : s )
cout << c;
//VS2019运行结果
/*
hello,word!
*/
}
4.string类对象的追加及查找
![在这里插入图片描述](https://img-blog.csdnimg.cn/789cac41127542b7ad24e1212d8a046b.png
代码演示
// push_back/ append/ +=/ c_str
void Test08()
{
string s;// s = ""
s.push_back('h'); //在字符串尾追加一个字符 s = "h"
s.append("ello"); // s = "hello"
cout << s << endl;
s += ','; // 追加字符 s = "hello,"
s += "word!"; //追加字符串 s = "hello,word!"
cout << s << endl;
cout << s.c_str() << endl; //以c语言方式打印字符串
//VS2019测试如下:
/*
hello
hello,word!
hello,word!
*/
}
// find/ rfind/ substr
void Test09()
{
//查找file后缀
string file("Test.cpp");
size_t pos = file.find('.',0);//从0位置开始往后查找
string suffix = file.substr(pos, file.size()-pos );
cout << suffix <<endl;
//取出url的域名
string url("https://editor.csdn.net/md?not_checkout=1&articleId=13058");
size_t pos1 = url.find("://",0);//从头开始往后查找
size_t pos2 = url.rfind('/',url.size() );//从末尾开始往前查找
pos1+=3;
pos2-=1;
string address = url.substr(pos1,pos2-pos1+1);//获取pos1~pos2间的字符串
cout << address <<endl;
/*
.cpp
editor.csdn.net
*/
}
小结
push_back:在字符串末尾追加一个字符(只能追加字符)。
append:在字符串末尾追加一个字符串(只能追加字符串)。
operator+=:既能追加字符又能追加字符串。
find(c , pos) :从pos位置开始往后查找字符或字符串c,如果没找到返回npos (npos是string类的一个静态成员 static const size_t npos = -1;)。
rfind() : 与find不同的是从pos位置往前查找,这跟正反迭代器类似。
substr(size_t pos, size_t n):从pos位置开始截取n个字符,以字符串形式返回。
总结
string类中还有一些其他的操作,这里不一一列举,大家在需要用到时不明白了查文档即可。