前言
string是c++中常见的容器,它是用来管理字符的,它在物理上是可以动态增长的线性表,对于了解它的使用,以及常见的接口使用对于我们日常开发和使用是很有必要的,所以接下来让我们一起来了解一下string常见的接口吧!
目录
1.string类常见的构造函数
2.迭代器
2.1迭代器
2.2遍历方式
3.容量相关的接口
4.数据的增删查改
5.string类的大小比较
5.1string对象的大小比较
5.2operator+,operator<<和operator>>
1.string类常见的构造函数
| 函数名称 | 功能说明 | 
| string(); | 构造一个空的string对象 | 
| (const string& str); | 使用字符串构造一个string对象 | 
| string (size_t n, char c); | 构造n个字符c的string类 | 
| string (const char* s, size_t n); | 从字符串上取长度为n构造string对象 | 
| string (const string& str); | 拷贝构造函数 | 
例如:
void TestString1()
{
	string s1;//无参的构造
	string s2("hello");//字符串构造
	string s3("abcdefg", 3);//用字符串的前三个字符进行构造
	string s4(5, 'a');//用5个字符a构造string对象
	string s5(s2);//拷贝构造
}2.迭代器
2.1迭代器
| 迭代器 | 解释 | 
| iterator begin(); const_iterator begin() const; | begin()是返回string对象第一个字符的迭代器, const修饰的begin()是返回const string的第一个字符的迭代器 | 
| iterator end(); const_iterator end()const; | end()是返回string对象最后一个字符位置的下一个位置的迭代器 const修饰的end()是返回const string的最后一个字符所在位置的下一个位置的迭代器 | 
| reverse_iterator rbegin(); const_reverse_iterator rbegin() const; | rbegin()和rend()是为了支持string对象倒着遍历。 rbegin()返回的string对象最后一个字符的迭代器。 const修饰的rbegin()返回的const string对象最后一个字符的迭代器。 | 
| reverse_iterator rend(); const_reverse_iterator rend() const; | rend()返回的是string对象第一个字符位置的前一个位置的迭代器 const修饰的rend()返回的是const string对象第一个字符位置的前一个位置的迭代器 | 
例如:
void TestString2()
{
	string s2("hello");//字符串构造
	string s3("abcdefg", 5);//用字符串的前三个字符进行构造
	string::iterator it = s3.begin();
	while (it != s3.end())//迭代器正向遍历
	{
		cout << *it;
		it++;
	}
	cout << endl;
	string::reverse_iterator rit = s3.rbegin();
	while (rit != s3.rend())//迭代器反向遍历
	{
		cout << *rit;
		++rit;
	}
	cout << endl;
}
void PrintString(const string&s)
{
	string::const_iterator it = s.begin();
	while (it != s.end())//const string对象的正向遍历
	{
		cout << *it;
		++it;
	}
	cout << endl;
}
void ReversePrintString(const string& s)
{
	string::const_reverse_iterator it = s.rbegin();
	while (it != s.rend())//const string对象的逆向遍历
	{
		cout << *it;
		++it;
	}
	cout << endl;
}2.2遍历方式
string对象可以有多种遍历方式,如下:
1.operator[]
2.迭代器
3.范围for
void TestString3() { string s1("happy happy every day!"); string::iterator it = s1.begin(); while (it != s1.end())//const string对象的遍历 { cout << *it; ++it; } cout << endl; for (int i = 0; i < s1.size(); ++i)//operator遍历 { cout << s1[i]; } cout << endl; for (auto e : s1)//范围for遍历 { cout << e; } cout << endl; }string类重载类operator[]使得我们遍历string对象时可以像遍历数组一样遍历。
函数原型:
char& operator[] (size_t pos);const char& operator[] (size_t pos) const;范围for是c++11新增的语法,范围for是由迭代器支持的,编译的时候范围for会被编译器替换为迭代器。
3.容量相关的接口
| 函数名称 | 函数作用 | 
| size | 返回字符串中有效字符的个数 | 
| capacity | 返回字符串存储字符的最大个数 | 
| length | 返回字符串中有效字符的个数 | 
| clear | 清空字符串中的有效字符 | 
| empty | 判断字符串是不是空串 | 
| resize | 改变字符串中有效字符的个数 | 
| reserve | 改变字符串的存储字符的最大个数 | 
例如:
void TestString4()
{
	string s1("happy happy");
	for (int i = 0; i < s1.size(); ++i)//operator遍历
	{
		cout << s1[i];
	}
	cout << endl;
	cout << s1.length()<<endl;//输出字符串有效字符的个数
	cout << s1.empty() << endl;//判断字符串是不是空
	cout << s1.capacity() << endl;//输出字符串的存储最大字符的个数
	s1.resize(8, 'd');//改变s1的有效字符个数,
	cout << s1 << endl;
	cout << s1.size() << endl;
	cout << s1.capacity() << endl;
	s1.reserve(20);//改变s1的容量
	cout << s1 << endl;
	cout << s1.size() << endl;
	cout << s1.capacity() << endl;
}注意resize函数,是用来改变string对象的有效字符个数的,它的原型:
void resize (size_t n);void resize (size_t n, char c);
如果传给resize的参数的n大于原来字符串的size,就会在原来字符串的后面加上n-size个字符c,如果n大于原来字符串的capacity,原来字符串的容量也会被改变。例如:
void TestString4()
{
	string s1("happy happy");
	for (int i = 0; i < s1.size(); ++i)//operator遍历
	{
		cout << s1[i];
	}
	cout << endl;
	
	cout << s1.size() << endl;
	cout << s1.capacity() << endl;
	s1.resize(20, 'd');//改变s1的有效字符个数,
	cout << s1 << endl;
	cout << s1.size() << endl;
	cout << s1.capacity() << endl;
	
} 
 
          reserve是用来改变字符串的最大容量的,它的函数原型为:void reserve (size_t n = 0);
如果n小于字符串原来的最大容量,则字符串的容量不会改变,如下:
void TestString4()
{
	cout << "reserve前:"<<endl;
	string s1("happy happy");
	for (int i = 0; i < s1.size(); ++i)//operator遍历
	{
		cout << s1[i];
	}
	cout << endl;
	cout << s1.size() << endl;
	cout << s1.capacity() << endl;
	cout << "reserve后:" << endl;
	s1.reserve(5);//改变s1的容量
	cout << s1 << endl;
	cout << s1.size() << endl;
	cout << s1.capacity() << endl;
} 
4.数据的增删查改
| 函数名称 | 功能说明 | 
| push_back pop_back | 在字符串的尾上插入一个字符 删除字符串尾上的字符 | 
| append | 在字符串尾上插入一个字符串 | 
| opreator+= | 在字符串的末尾插入一个字符或者一个字符串 | 
| insert | 在任意合法位置插入一个字符或者字符串 | 
| erase | 删除任意合法位置的字符 | 
| find和npos | 从pos 位置开始向后在字符串str中查找另一个字符或者字符串,如果没有找到返回npos,如果找到了返回该字符或者字符串在字符串str中的位置 | 
| substr | 在str中从pos位置开始,截取n个字符,然后将其返回 | 
| c_str | 返回c格式的字符串 | 
| rfind | 从pos位置开始向前在字符串str中查找另一个字符或者字符串,如果没有找到返回npos,如果找到了返回该字符或者字符串在字符串str中的位置 | 
例如:
void TestString5()
{
	string s1;
	s1.push_back('h');//在字符串末尾插入元素
	s1.push_back('e');
	s1.push_back('l');
	s1.push_back('l');
	s1.push_back('0');
	cout << s1 << endl;
	s1.pop_back();//删除s1末尾的元素
	s1.pop_back();//删除s1末尾的元素
	s1.pop_back();//删除s1末尾的元素
	cout << s1 << endl;
	s1.append("xxxxxx");//在s1末尾插入一个字符串
	cout << s1<<endl;
	string s2;
	s2 += 'a';//在s2末尾插入一个字符
	s2 += 'a';
	s2 += 'a';
	s2 += 'a';
	s2 += 'a';
	cout << s2 << endl;
	s2 += "xxxxxxxx";//在s2的末尾插入一个字符串
	cout << s2 << endl;
	string s3("bbbbbbbbbb");
	s3.insert(s3.begin(), 'c');//在s3的开始位置插入一个字符
	s3.insert(s3.begin(), 'c');
	s3.insert(s3.begin(), 'c');
	cout << s3 << endl;
	s3.insert(s3.begin(), 'c');
	s3.insert(5,2, 'c');//在s3第五个字符之前插入2个字符
	cout << s3 << endl;
	s3.insert(3, "ffff");//在s3第三个字符之前插入一个字符串
	cout << s3 << endl;
	cout << s3.c_str() << endl;//返回c类型的字符串
}        find是在字符串str中查找字符或者字符串,函数的原型: 它可以查找字符,字符串还可以查找string对象。它返回的是 字符,字符串在对象string(字符串str)中的位置。我们可以配合substr使用,substr的函数原型:
         它可以查找字符,字符串还可以查找string对象。它返回的是 字符,字符串在对象string(字符串str)中的位置。我们可以配合substr使用,substr的函数原型:
string substr (size_t pos = 0, size_t len = npos) const;它是从pos位置开始取出长度为len的字符串的子串,如果len的长度大于从pos位置开始字符串的长度,就会从pos位置开始取到字符串的结束。npos是string类中的静态成员变量,它的值为无符号整形的最大值。如图:
rfind和find的用法相似只不过rfind是从string对象的末尾开始从后向前查找。
使用:
void TestString6()
{
	string s1("abcdefg hijklmn opqrst uvwxyz");
	size_t pos = s1.find('c');//查找字符c
	if (pos != string::npos)//确保找到要查找的字符
	{
		cout<<s1.substr(pos, 1);//从s1中取出子串
	}
	pos = s1.find("def");
	if (pos != string::npos)//确保找到要查找的字符
	{
		cout << s1.substr(pos, 1);//从s1中取出子串
	}
	pos = s1.rfind("def");//从后向前查找
	if (pos != string::npos)//确保找到要查找的字符
	{
		cout << s1.substr(pos, 1);//从s1中取出子串
	}
}void SplitStr(const string& url)//分离协议,域名和资源
{
	size_t pos = url.find(':');
	if (pos != string::npos)
	{
		cout << url.substr(0, pos) << endl;
	}
	size_t pos1 = url.find('/', pos + 3);
	if (pos != string::npos)
	{
		cout << url.substr(pos + 3, pos1 - (pos + 3)) << endl;
	}
	cout << url.substr(pos1 + 1) << endl;
}5.string类的大小比较
5.1string对象的大小比较
string是可以用来进行大小比较的,本质上还是比较字符串中字符的ASCII码值。例如:
void TestString8()
{
	string s1("abcd");
	string s2("aabc");
	cout <<( s1 > s2) << endl;//判断s1和s2的大小关系
	cout << (s1 < s2) << endl;
}5.2operator+,operator<<和operator>>
string类重载输入和输出,所以string对象可以像内置类型一样输入输出。如下:
void TestString9()
{
	string s1("abcdefghijkl");
	cout << s1 << endl;//输出s1
	string s2;
	cin >> s2;//从标准输入中接收字符
}operator+的效率较低,一般不常用,operator+ 和operator+=的区别是+不会改变对象本身,+=会改变对象本身。例如:
void TestString10()
{
	string s1("abcdefghijkl");
	cout << s1 << endl;//输出s1
	s1 + "1111";
	cout << s1 << endl;
	s1 += "1111";
	cout << s1 << endl;
}













