第 5 章 string学习笔记
string
是C++中提供的数据类型,所以本章将从0开始学习
string 概念
string
字符串是一种更加高级的封装,其中包含大量的方法,让字符串的操作变得简单。
string
字符串是一种单独的类型,即string
类型,使用string
类型创建的对象就是C++字符串。
string s1;
string s2 = "abc"
string
类型需要头文件:string
string 常见操作
创建字符串
写法 | 含义 |
---|---|
string s1 | 创建空白字符串 |
string s2 = "hello world" | 创建字符串 |
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1;
string s2 = "hello world";
cout << "s1:" << s1 << endl;
cout << "s2:" << s2 << endl;
return 0;
}
/*输出结果:
s1:
s2:hello world*/
创建字符串的方式与前面学习的内置数据类型(int,float等)相同。
string s2 = "hello world"
表示创建一个字符串s2,它的内容是"hello world"
,区别于C语言中的字符串,这里的字符串不以\0
作为结束标志。
除了以上常规写法,C++中还有一些其他的创建字符串的方式:
string s("hello world");
string s1 = s;
区别于C语言中使用char类型数组创建的字符串,string
创建的字符串对象可以直接赋值:
#include <iostream>
#include <string>
using namespace std;
int main(){
string s1("hello world");
string s2("hehe");
s2 = s1;
cout << s2 << endl;
return 0;
}
/*输出结果:hello world*/
string 字符串的输入
与char类型数组类似,string
类型字符串也可以使用cin进行输入:
#include <iostream>
#include <string>
using namespace std;
int main(){
string s1;
cin >> s1;
cout << s1 << endl;
return 0;
}
/*输入:hello world
输出:hello*/
与char类型数组相同,string
类型字符串输入时,遇到空格等空白字符就会停止输入,所以输入的字符串中不能包含空格。这里就需要使用其他的方法来输入字符串了。
getline 输入
istream& getline (istream& is, string& str);
istream& getline (istream& is, string& str, char delim);
-
作用:从输入流中读取字符串,遇到换行符(写法1)或者
delim
(写法2)字符就停止读取,换行符或者delim
字符不会被读取。 -
参数:
is
:输入流对象,一般是cin
。str
:字符串对象,用于存储输入的字符串。-
- 写法1中以换行符为结束字符,无需第三个参数。
- 写法2中以
delim
,即分隔符,来指定读取字符串的结束字符。
-
返回值:输入流对象。
-
头文件:
<string>
基本用法
写法1:
#include <iostream>
#include <string>
using namespace std;
int main(){
string s1;
getline(cin, s1);
cout << s1 << endl;
return 0;
}
/* 输入:hello world
输出:hello world*/
写法2:
#include <iostream>
#include <string>
using namespace std;
int main(){
string s1;
getline(cin, s1, 'l');
cout << s1 << endl;
return 0;
}
/* 输入:hello world
输出:hello wor*/
size()
string
中的size()
函数用于获取字符串的长度,即字符串中字符的个数。
在C++中关于字符串的操作函数都是包含在string
中的,所以调用时需要使用.
运算符。
基本用法:
#include <iostream>
#include <string>
using namespace std;
int main(){
string s1 = "hello world";
cout << s1.size() << endl;
return 0;
}
/*输出结果:11*/
string
是C++中的一种更为复杂的封装类型,在string
类型的变量中包含了这个字符串的操作方法(函数),因此在使用string
类型变量时,需要使用.
运算符来调用这些方法。
通过size()
方法可以获取字符串的长度,即字符串中字符的个数,可以遍历字符串中的每个字符,string
类型同样可以使用下标来访问字符串中的每个字符:
#include <iostream>
#include <string>
using namespace std;
int main(){
string s1 = "hello world";
for(int i = 0; i < s1.size(); i++){
cout << s1[i] << " ";
}
return 0;
}
/*输出结果:h e l l o w o r l d*/
迭代器(iterator)
迭代器是一种对象,它能够用来遍历容器(比如现在学习的string
)中的元素,即可以通过迭代器来访问容器中的每个元素。区别与指针或者数组下标,访问迭代器指向的值,需要使用*
运算符进行解引用。
C++中的string
提供了多种迭代器,用于遍历和操作字符串中的内容。以下是常用的一种迭代器。
begin()
和end()
begin()
:返回指向字符串第一个字符的迭代器,需要一个迭代器的变量来接收。end()
:返回指向字符串最后一个字符的下一个位置的迭代器(该位置不属于字符串)。string
中begin()
和end()
返回的迭代器的类型是string::iterator
。
- 迭代器可以进行大小比较,也可以进行±运算。例如it++表示迭代器前进一位,it–表示迭代器后退一位。
- 同一容器中的两个迭代器可以相减,相减结果的绝对值是两个迭代器中间元素的个数。
例如:
#include <iostream>
#include <string>
using namespace std;
int main(){
string s = "abcdef";
string::iterator it1 = s.begin();
string::iterator it2 = s.end();
if(it1 < it2){
cout << "it1 < it2" << endl;
}
else{
cout << "it1 >= it2" << endl;
}
cout << it2 - it1 << endl;
return 0;
}
/*输出结果:
it1 < it2
6
*/
遍历
迭代器通常用于遍历字符串,可以正向遍历,也可以逆向遍历。
正序遍历
#include <iostream>
#include <string>
using namespace std;
int main(){
string s = "abcdef";
string::iterator it = s.begin();
for(auto it = s.begin(); it != s.end(); it++){
cout << *it << " ";
}
return 0;
}
/*输出结果:a b c d e f*/
逆序遍历
#include <iostream>
#include <string>
using namespace std;
int main(){
string s = "abcdef";
string::iterator it = s.end();
for(auto it = s.end() - 1; it!= s.begin(); it--){ /*注意这里应从s.end() - 1开始,因为end()指向的是最后一个字符的下一个位置*/
cout << *it << " ";
}
return 0;
}
/*输出结果:f e d c b a*/
push_back()
push_back()
是string
类型中的一个方法,用于在字符串的末尾添加一个字符。
基本用法:
#include <iostream>
#include <string>
using namespace std;
int main(){
string s;
s.push_back('h');
s.push_back('e');
s.push_back('l');
s.push_back('l');
s.push_back('o');
cout << s << endl;
/*输出结果:hello*/
//向非空字符串末尾添加字符
string s1 = "hello ";
s1.push_back('w');
s1.push_back('o');
s1.push_back('r');
s1.push_back('l');
s1.push_back('d');
cout << s1 << endl;
/*输出结果:hello world*/
//批量插入字符
string s2;
for(char c = 'a'; c <= 'z'; c++){
s2.push_back(c);
}
cout << s2 << endl;
/*输出结果:abcdefghijklmnopqrstuvwxyz*/
return 0;
}
字符串的+=和+运算符
push_back()
方法只能在字符串的末尾添加一个字符,如果想要在字符串的末尾添加多个字符,可以使用+=
运算符或者+
运算符。
基本用法:
#include <iostream>
#include <string>
using namespace std;
int main(){
string s1 = "hello";
string s2 = "world";
string s3 = s1 + " " + s2;
cout << s3 << endl;
/*输出结果:hello world*/
string s4 = "hello";
s4 += " ";
s4 += "world";
cout << s4 << endl;
/*输出结果:hello world*/
string s5 = "hello";
cout << s5 + " " + "world" << endl; /*此时s5仍为hello*/
/*输出结果:hello world*/
string s6 = "hello";
s6 = "world " + s6;
cout << s6 << endl;
/*输出结果:world hello*/
return 0;
}
pop_back()
pop_back()
是string
类型中的一个方法,用于删除字符串的最后一个字符(在C++11
标准中引入)。
基本用法:
#include <iostream>
#include <string>
using namespace std;
int main(){
string s = "abc";
cout << s << endl;
/*输出结果:abc*/
s.pop_back();
cout << s << endl;
/*输出结果:ab*/
s.pop_back();
cout << s << endl;
/*输出结果:a*/
s.pop_back();
cout << s << endl;
/*无输出*/
return 0;
}
- 当字符串中没有字符时,再次调用
pop_back()
方法,不会有任何输出,并且会导致程序出现异常。这种行为是未定义的行为。
为避免这种情况,可以改写代码:
#include <iostream>
#include <string>
using namespace std;
int main(){
string s = "abc";
while(s.size() > 0){
cout << s << endl;
s.pop_back();
}
return 0;
}
insert函数
string& insert (size_t pos, const string& str);
string& insert (size_t pos, const char* s);
string& insert (size_t pos, size_t n,const char* s);
- 作用:在字符串中插入字符。
- 参数:
pos
:插入位置的下标。- 写法1可以在
pos
位置前面插入一个string字符串,其中str
是要插入的字符串。 - 写法2可以在
pos
位置前面插入一个C语言风格的字符串,其中s
是要插入的字符串。 - 写法3可以在
pos
位置前面插入n
个字符c
。
基本用法:
#include <iostream>
#include <string>
using namespace std;
int main(){
string s = "abc";
string str = "xxx";
s.insert(1, str);
cout << s << endl;
/*输出结果:axxxbc*/
string s1 = "abc";
s1.insert(1, "xxx");
cout << s1 << endl;
/*输出结果:axxxbc*/
string s2 = "abc";
s2.insert(1, 3, 'x');
cout << s2 << endl;
/*输出结果:axxxbc*/
return 0;
}
find函数
size_t find (const string& str, size_t pos = 0) const;
size_t find (const char* s, size_t pos = 0) const;
size_t find (const char* s, size_t pos, size_t n) const;
size_t find (char c, size_t pos = 0) const;
- 作用:查找字符串中是否包含某个子串。
- 参数:
str
:要查找的子串。pos
:查找的起始位置,默认为0,即从头开始查找。- 写法2、3中的
s
是需要查找的C语言风格的子串。 - 写法3中的
n
可以指定需要查找子串s
中的前n
个字符。 - 写法4中的
c
是需要查找的字符。
- 返回值:
- 如果找到了子串,返回子串的起始位置。
- 如果没有找到子串,返回一个整数值
string::npos
,即-1。
- 头文件:
<string>
基本用法:
#include <iostream>
#include <string>
using namespace std;
int main(){
string s = "hello world hello everyone";
string str = "llo";
/*查找string类型的字符串*/
size_t pos = s.find(str);
cout << pos << endl;
/*输出结果:2*/
pos = s.find(str,pos + 1); /*从pos + 1位置开始查找*/
cout << pos << endl;
/*输出结果:14*/
/*查找C语言风格的字符串*/
pos = s.find("llo");
cout << pos << endl;
/*输出结果:2*/
pos = s.find("llo",pos + 1);/*从pos + 1位置开始查找*/
cout << pos << endl;
/*输出结果:14*/
return 0;
}
#include <iostream>
#include <string>
using namespace std;
int main(){
string s = "hello world hello everyone";
/*在s中,从0开始查找"word"中前3个字符*/
size_t pos = s.find("word", 0, 3);
cout << pos << endl;
/*输出结果:5*/
pos = s.find("everyday",pos + 1, 5);
cout << pos << endl;
/*输出结果:18*/
return 0;
}
#include <iostream>
#include <string>
using namespace std;
int main(){
string s = "hello world hello everyone";
/*查找字符'o'*/
size_t pos = s.find('o');
cout << pos << endl;
/*输出结果:4*/
pos = s.find('o',pos + 1);
cout << pos << endl;
/*输出结果:7*/
return 0;
}
#include <iostream>
#include <string>
using namespace std;
int main(){
string s = "hello world hello everyone";
/*查找失败时*/
size_t pos = s.find('z');
cout << pos << endl;
/*输出结果:-1*/
if(pos == string::npos){
cout << "404" << endl;
}
else{
cout << "the position is in" << pos << endl;
}
/*输出结果:404*/
return 0;
}
当find
函数查找失败时,会返回string::npos
,该数字不是一个随机的数字,而是string
中定义的一个静态常量npos
,被定义为-1,而size_t通常是无符号整型,所以当返回值为-1时,会被转换为最大值(因编译器而异)。
所以我们通常通过判断返回值是否等于string::npos
来判断查找是否成功。
打印出npos的值:
#include <iostream>
#include <string>
using namespace std;
int main(){
cout << string::npos << endl;
return 0;
}
/*输出结果:18446744073709551615(因编译器而异)*/
substr()
string substr (size_t pos = 0, size_t len = npos) const;
- 作用:从字符串中截取子串。
- 参数:
pos
:截取的起始位置,默认为0,即从头开始。len
:截取的长度,默认为npos
,即从pos
位置开始截取到字符串末尾。
- 返回值:截取到的子串。
- 头文件:
<string>
基本用法:
#include <iostream>
#include <string>
using namespace std;
int main(){
string s = "hello world";
string s1 = s.substr(6);
cout << s1 << endl;
/*输出结果:world*/
string s2 = s.substr(0,5);
cout << s2 << endl;
/*输出结果:hello*/
return 0;
}
substr()
常与find()
函数结合使用。find()
负责查找子串,substr()
负责截取子串。
例如:
#include <iostream>
#include <string>
using namespace std;
int main(){
string s = "hello world hello everyone";
string s1 = "world";
size_t pos = s.find(s1);
if(pos!= string::npos){
string s2 = s.substr(pos,10);
cout << s2 << endl;
}
else{
cout << "404" << endl;
}
return 0;
/*输出结果:world hell*/
}
string 关系运算
在实际应用过程中常涉及到两个字符串的比较,例如验证密码是否正确就需要比较输入的密码和数据库中的是否一致。
C++中为string提供了一系列的关系运算符。
运算符 | 含义 |
---|---|
== | 判断两个字符串是否相等 |
!= | 判断两个字符串是否不相等 |
< | 判断两个字符串的大小关系 |
> | 判断两个字符串的大小关系 |
<= | 判断两个字符串的大小关系 |
>= | 判断两个字符串的大小关系 |
以上的关系运算符可以对string
与string
、string
与C风格字符串
进行比较,但是无法进行C风格字符串
与C语言风格字符串
之间的比较。
同时,在比较时,是基于字典序进行比较,即对应位置上的ASCLL值的大小比较,而不是长度比较。
例如:
"abc" < "aq" /*'b' < 'q'*/
"abcdef" < "ff" /*'d' < 'f'*/
"100" < "9" /*'1' < '9'*/
代码举例:
#include <iostream>
#include <string>
using namespace std;
int main(){
string s1 = "hello world";
string s2 = "hello";
if(s1 == (s2 + " world")){
cout << "s1 == s2 + \" world\"" << endl;
}
else{
cout << "s1 != s2 + \" world\"" << endl;
}
return 0;
}
/*输出结果:s1 == s2 + " world"*/
#include <iostream>
#include <string>
using namespace std;
int main(){
string s1 = "abcd";
string s2 = "abbcdef";
char s3 = "bbc";
if(s1 < s2){
cout << "s1 < s2" << endl;
}
else{
cout << "s1 >= s2" << endl;
}
if(s1 < s3){
cout << "s1 < s3" << endl;
}
else{
cout << "s1 >= s3" << endl;
}
if(s1 == s2){
cout << "s1 == s2" << endl;
}
else{
cout << "s1 != s2" << endl;
}
return 0;
}
/*输出结果:
s1 < s2
s1 >= s3
s1 != s2
*/
其他和string相关的函数
stoi/stol
int stoi (const string& str, size_t* idx = 0, int base = 10);
long stol (const string& str, size_t* idx = 0, int base = 10);
-
作用:将字符串转换为整数,stoi将字符串转换成
int
类型,stol将字符串转换成long int
类型。 -
参数:
str
:要转换的string
字符串。idx
:指向一个size_t
类型的指针,用于存储转换过程中第一个无法转换的字符的下标,该参数需要额外创建。base
:转换的进制,默认为10进制,可能是2
,8
,10
,16
或者0
。- 默认未填写时为十进制。
- 当
base
为0时,会根据字符串的前缀自动判断进制,例如0x
表示十六进制,0
表示八进制,最终转换成十进制。 - 当
base
为2,8,10,16时,会以2,8,10,16进制数对字符串进行解析,并最终转换成十进制数。
-
返回值:转换后的整数。
-
头文件:
<string>
另外,这里的idx需要一个指针,需要创建指针类型变量或者创建size_t类型变量在使用时进行取地址操作如&idx
。
代码举例:
#include <iostream>
#include <string>
using namespace std;
int main(){
string s = "11x34";
size_t idx;
int n = stoi(s,&idx,16);
cout << n << endl;
/*输出结果:17*/
cout << idx << endl;
/*输出结果:2*/
int n1 = stoi(s,&idx,2);
cout << n1 << endl;
/*输出结果:3*/
cout << idx << endl;
/*输出结果:2*/
string s1 = "0x11x34"; /*0x表示16进制*/
int n1 = stoi(s1,&idx,0);
cout << n1 << endl;
/*输出结果:17*/
cout << idx << endl;
/*输出结果:4*/
return 0;
}
stod/stof
double stod (const string& str, size_t* idx = 0);
float stof (const string& str, size_t* idx = 0);
与stoi和stol类似,只是将字符串转换为浮点数,并且没有base
参数,也就是无需进制参数,其他参数一致。
- 作用:将字符串转换为浮点数。
- 参数:
str
:要转换的string
字符串。idx
:指向一个size_t
类型的指针,用于存储转换过程中第一个无法转换的字符的下标,该参数需要额外创建。
- 返回值:转换后的浮点数。
- 头文件:
<string>
代码举例:
#include <iostream>
#include <string>
using namespace std;
int main(){
string s = "11.34";
size_t idx;
double n = stod(s,&idx);
cout << n << endl;
/*输出结果:11.34*/
cout << idx << endl;
/*输出结果:5*/
return 0;
}
to_string
string to_string (int val);
string to_string (long val);
string to_string (long long val);
string to_string (unsigned val);
string to_string (unsigned long val);
string to_string (unsigned long long val);
string to_string (float val);
string to_string (double val);
string to_string (long double val);
- 作用:将数字转换为字符串。
- 参数:
val
:要转换的数字。
- 返回值:转换后的字符串。
- 头文件:
<string>
基本用法:
#include <iostream>
#include <string>
using namespace std;
int main(){
string pi = "pi is " + to_string(3.14159);
cout << pi << endl;
/*输出结果:pi is 3.14159*/
return 0;
}