前⾯介绍了通过字符数组保存字符串,然后对字符数组中的字符串做各种操作;
为了更加简单⽅便,在C++中,⼜增加了 string 来处理字符串string 使⽤的好,慢慢你就不想使⽤字符数组来存放字符串了。
一. string 概念
string 字符串其实是⼀种更加⾼级的封装,string 字符串中包含⼤量的⽅法,这些⽅法使得字符串的操作变得更加简单。那到底什么是string呢? ⽽C++中将字符串直接作为⼀种类型,也就是 string 类型,使⽤ C++的字符串。
string就是一种更加高级的分装
cpp
string s1;
string s2 = "abc";
使⽤C++中提供的 string 时,必须添加头⽂件
二. string 的常⻅操作
string ⽂档:https://legacy.cplusplus.com/reference/string/string
1. string字符串的创建和初始化
string s1---创建空字符串
string s2 = "hello world"--创建字符串(常⽤)
1.1.string s1 表⽰创建空字符串,相当于创建整型 int a ,但未给 a ⼀个初始值。
1.2.string s2 = "hello world" 表⽰创建⼀个字符串s2,它的内容是" hello world ",要 注意 s2 中的字符串不再以 \0 作为结束标志了。(C语⾔中的字符串是以 \0 作为结束标志 的)。
除了以上创建字符串的写法外,C++中还有⼀些其他的创建字符串⽅式。如
cpp
string s("hello world"); //等同于
string s1 = "hello world";
string s1 = s;
//用个现成的字符串s,初始化另外?个字符串s1
当然C++中的string 创建的字符串和char类型的数组所表⽰的字符串还有⼀个区别,string类型的字符串对象可以直接赋值,⽐如:
cpp
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1("hello world");
string s2("hehe");
s2 = s1;
cout << s2 << endl;
return 0;
}
2. string字符串的输⼊
2.1.cin的输入
可以直接使⽤cin给string类型的字符串中输⼊⼀个字符串的数据。
cpp
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
cin >> s;
cout << s << endl;
return 0
}
输⼊不带空格的字符串:abcdef---输出abcdef
输入带空格的: abc def ---输出abc
这⾥我们可以发现,其实 cin 的⽅式给 string 类型的字符串中输⼊数据的时候,可以输⼊不带空 格的字符串。但是如果带有空格,遇到空格也就读取结束了,没有办法正常读取,那怎么办呢?解决 办法就是使⽤ getline
2.2.getine
getline 是C++标准库中的⼀个函数,⽤于从输⼊流中读取⼀⾏⽂本,并将其存储为字符串。 getline 函数有两种不同的形式,分别对应着字符串的结束⽅式。
cpp
istream& getline (istream& is, string& str);
istream& getline (istream& is, string& str, char delim);
小提示
istream 是输⼊流类型, cin 是 istream 类型的标准输⼊流对象。 ostream 是输出流类型, cout 是 ostream 类型的标准输出流对象。 getline 函数是输⼊流中读取⼀⾏⽂本信息,所有如果是在标准输⼊流(键盘)中读取数 据,就可以传 cin 给第⼀个参数。
第⼀种 getline 函数以换⾏符('\n')作为字符串的结束标志,它的⼀般格式是
cpp
getline(cin, string str)
//cin -- 表示从输?流中读取信息
//str -- 是存放读取到的信息的字符串
这种形式的getlinee 函数从输⼊流(例如cin)中读取⽂本,直到遇到换⾏符('\n'))为⽌,然后将读取到的⽂本(不包括换⾏符)存储到指定的string 类型的变量str 中.
cpp
#include<iostream>
#include <string>
using namespace std;
int main ()
{
string name;
getline (cin, name);
cout << name << endl;
//输入 abc defghi
//输出 abc defghi
return 0;
}
第⼆种 getline 函数允许⽤⼾⾃定义结束标志,它的⼀般格式是:
cpp
getline(cin, string str, char delim)
//cin -- 表示从输入流中读取信息
//str 是存放读取到的信息的字符串
//delim 是自定义的结束标志
这种形式的getline函数从输⼊流中读取⽂本,直到遇到⽤⼾指定的结束标志字符(delim)为⽌,然后将读取到的⽂本(不包括结束标志字符)存储到指定的string 类型的变量str 中。
cpp
#include<iostream>
#include <string>
using namespace std;
int main ()
{
string name;
getline (cin, name, 'q');
cout << name << endl;
//输入 abc defqwer
//输出 abc def
}
在使⽤C++中的 string 字符串时,想要输⼊的字符串中包含空格,那么 是必须的。 候 ge 在竞赛中为了⽅便处理字符串,通常会使⽤ getline 函数就 string 类型的字符串,所以在字符串输⼊的时 tline 就很常⻅,建议认真学习。
3. size()
string 中提供了 size() 函数⽤于获取字符串⻓度。
在C++中关于字符串的操作函数都是包含在 string 中的,所以需要调⽤这些函数时,通常⽤ . 点运 算符。
比如
cpp
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
string s1 = "hello";
string s2 = "hello world";
string s3 = "12ab!~ ";
cout << s.size() << endl;
cout << s1.size() << endl;
cout << s2.size() << endl;
cout << s3.size() << endl;
//输出0 5 11 14
return 0;
}
cpp
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
string s;
cin >> s;
//输入 abc
cout << s << endl;
cout << s.size() << endl;
//输出 abc
// 3
return 0;
}
前⾯我们学到的像 ⽤ . 操作符的。 char 、 int 、 double 等内置类型的数据在操作的时候,不会使用 . 操作符来使⽤这些函数
string 是C++提供的⼀种更加复杂的封装类型,在 string 类型的变量中加⼊了操作这 个字符串的各种⽅法(函数),⽐如求字符串⻓度、字符串末尾插⼊⼀个字符等操作。所以要 对 st ring 类型的变量进⾏各种操作,就可以使⽤ . 操作符来使⽤这些函数。
我们可以看下⾯的例⼦,⼤家可以仔细体会。
通过 s ize() 能获得字符串的⻓度,顺便就可以使⽤这个⻓度遍历字符串的,注意string类型的字符串是可以通过下标访问的,⽐如:
cpp
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
string s = "abcdef";
int i = 0;
for(i = 0; i < s.size(); i++)
{
cout << s[i] << " ";
}
//输出a b c d e f
return 0;
}
4. 迭代器
迭代器是⼀种对象,它可以⽤来遍历容器(⽐如我们现在学习的 类似于指针,或者数组下标。
❗不过访问迭代器指向的值,需要解引⽤(*)。
C++中的 string 提供了多种迭代器,⽤于遍历和操作字符串中的内容。这⾥给⼤家介绍⼀种最常 ⽤的迭代器。
4.1begin() 和 end()
be gin() :返回指向字符串第⼀个字符的迭代器,需要⼀个迭代器的变量来接收。
end() :返回指向字符串最后⼀个字符的下⼀个位置的迭代器(该位置不属于字符串)。
st ring 中 begin()和end() 返回的迭代器的类型是 string::iterator
cpp
string s = "abcdef";
• 迭代器是可以进⾏⼤⼩⽐较,也可以进⾏ + 或者 整数运算的。 ⽐如: i t++ ,就是让迭代器前进⼀步, 就是让迭代器退后⼀步。
cpp
#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 << "<" << endl;
else
cout << ">=" << endl;
//输出<
return 0;
}
• 同⼀个容器的两个迭代器也可以相减,相减结果的绝对值,是两个迭代器中间元素的个数
cpp
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "abcdef";
string::iterator it1 = s.begin();
string::iterator it2 = s.end();
cout << (it1 < it2) << endl;
cout << it1 - it2 << endl;
//输出 -1
// 6
return 0;
}
使用迭代器可以便历字符串,可以正序便历或者逆序便历
正序
cpp
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "abcdef";
for(string::iterator it = s.begin(); it < s.end();it++)
//it 类型不知道时可以写为auto
{
cout << *it;
}
//输出abcdef
return 0;
}
倒序
cpp
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "abcdef";
for(string::iterator it = s.end()-1; it >= s.begin();--it)
{
cout << *it;
}
//输出fedcba
return 0;
}
❗通过迭代器找到元素后,改变迭代器指向的元素,是可以直接改变字符串内容的。
cpp
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "abcdef";
cout << s << endl;
for(string::iterator it = s.end()-1; it >= s.begin();--it)
{
*it = 'x';
}
cout << s << endl;
//输出abcdef
// xxxxxx
return 0;
}
5. push_back()
push_back() ⽤于在字符串尾部插⼀个字符。
即,最后一个字符的下一个位置插入一个新的字符
比如
cpp
#include <iostream>
#include<string>
using namespace std;
//添加string头文件
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;
//向非空字符串中尾插字符
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;
//批量插入字符
string s2;//a~z
char c = 0;
for (char c = 'a'; c <= 'z'; c++)
{
s2.push_back(c);
}
cout << s2 << endl;
return 0;
}
6. string的+=和+运算
push_back() 是⽤于在字符串后添加⼀个字符,然⽽部分情况下我们需要向原有的字符串后继续添 加字符串。 其实 s tring 类型的字符串是⽀持 + 和 += 运算的。这⾥的本质是 operator+= 这个操作符。
具体使⽤请看下⾯的⽰例:
+=运算
cpp
#include <iostream>
#include<string>
using namespace std;
int main()
{
string s = "hello";
s += "world";
cout << s << endl;
//输出 hello world
return 0;
}
+运算
cpp
#include <iostream>
#include<string>
using namespace std;
int main()
{
string s1 = "hello ";
cout << s1 + "world" << endl;
cout << s1 << endl;
s1 += "world";
cout << s1 <<endl;
//输出 hello world
// hello
// hello world
return 0;
}
前后都可以加字符
cpp
#include <iostream>
#include<string>
using namespace std;
int main()
{
string s2 = "hello ";
s2 = "world" + s2;
cout << s2 <<endl;
//输出 worldhello
return 0;
}
7. pop_back()
pop_back() ⽤于删除字符串中尾部的⼀个字符。这个成员函数是在 C++11 标准中引⼊的,有的编 译器可能不⽀持。
cpp
#include <iostream>
#include<string>
using namespace std;
int main()
{
string s = "hello";
s.pop_back();
//devc++不支持s.pop_back()
//需要在工具-编译选项添加(-std=c++11)代码令
cout << s << endl;
cout << s.size() << endl;
//输出 hello
// 4
return 0;
}
s.pop_back(); 函数可以连用
注意:
当字符串中没有字符的时候,再调⽤ pop_back() 时,程序会出现异常。这种⾏为也是未定义 ⾏为,要避免这么使⽤。
为避免循环删除导致对空字符串进⾏尾删,可以将代码改写成
cpp
#include <iostream>
#include<string>
using namespace std;
int main()
{
string s = "hello";
while(s.size() >= 1)
s.pop_back() ;
cout <<s.size() << endl;
//输出 0
return 0;
}
不可对空字符串继续进⾏pop_back()操作,否则程序出现异常
8. insert()
如果我们需要在字符串中间的某个位置插⼊⼀个字符串,怎么办呢?这时候我们得掌握⼀个函数就是 insert
函数原型如下:
cpp
string& insert (size_t pos, const string& str);
//pos位置前面插入一个string字符串
string& insert (size_t pos, const char* s);
//pos位置前面插入一个C风格的字符串
string& insert (size_t pos, size_t n, char c);
//pos位置前面插入n个字符c
eg
cpp
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "abcdefghi";
string str = "xxx";
cout << s << endl;
s.insert(3,str);
cout << s << endl;
//输出
// abcdefghi
// abcxxxdefghi
return 0;
}
cpp
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "abcdefghi";
cout << s << endl;
s.insert(3,"xxx");
cout << s << endl;
//输出
// abcdefghi
// abcxxxdefghi
return 0;
}
9. find()
find() 函数⽤于查找字符串中指定⼦串/字符,并返回⼦串/字符在字符串中第⼀次出现的位置
cpp
size_t find (const string& str, size_t pos = 0) const;
//查找string类型的字符串str,默认是从头开始查找,
//pos可以指定位置开始
size_t find (const char* s, size_t pos = 0) const;
//查找C风格的字符串s,默认是从头开始查找,
//pos可以指定位置开始
size_t find (const char* s, size_t pos, size_t n) const;
//在字符串的pos这个位置开始查找C?格的字符串
//s中的前n个字符,
size_t find (char c, size_t pos = 0) const;
//查找字符c,默认是从头开始,
//pos可以指定位置开始
返回值:
若找到。返回⼦串/字符在字符串中第⼀次出现的起始下标位置。
• 若未找到。返回⼀个整数值 的返回值是否等于 npos (针对 比特就业课 npos 的介绍会在下⾯给出)。通常判断 find() 函数 npos 就能知道是否查找到⼦串或者字符。
cpp
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "hello world hellp everyone";
string str = "llo";
size_t n = s.find(str);
cout << n << endl;
//输出2
n = s.find(str,n+1);
cout << n << endl;
return 0;
}
在字符串中查找字符或者字符串时,有可能查找不到,这时候 字并不是⼀个随机的数字,⽽是 find 函数会返回 string 中定义的⼀个静态常量 数的返回值是否等于 npos 这个值,该数 npos 。我们通常会判断 find 函 npos 来判断,查找是否成功。
cpp
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "hello world hellp everyone";
size_t n = s.find("one");
if(n == string::npos)
cout << "找不到" <<endl;
else
cout <<"找到了,位置是:" << n << endl;
//输出 找到了,位置是:23
return 0;
}
10.substr()
substr() 函数⽤于截取字符串中指定位置指定⻓度的⼦串。函数原型如下:
cpp
string substr (size_t pos = 0, size_t len = npos) const;
//pos 的默认值是0,也就是从下标为0的位置开始截取
//len 的默认值是npos,意思是一直截取到字符串的末尾
substr() :如果函数不传参数,就是从下标为0的位置开始截取,直到结尾,得到的是整个字符串;
substr(pos) :从指定下标 pos 位置开始截取⼦串,直到结尾;
substr(pos, len) :从指定下标 pos 位置开始截取⻓度为 len 的⼦串。
cpp
#include <iostream>
#include<string>
using namespace std;
int main()
{
string s = "hello world hello everyone";
string s1 = s.substr();
cout << s1 << endl;
//输出 hello world hello everyone
string s2 = s.substr(7);
cout << s2 <<endl;
//输出 orld hello everyone
string s3 = s.substr(7,6);
cout << s3 << endl;
//输出 orld h
return 0;
}
substr() 和 find() 经常是配合使⽤的,find 负责找到位置, substr 从这个位置向后获得字符串。
cpp
#include <iostream>
#include<string>
using namespace std;
int main()
{
string s = "hello world hello everyone";
// 0123456
size_t n = s.find("world");
string s1 = s.substr(n, 10);
cout << s1 << endl;
//输出 world hell
return 0;
}
11. string的关系运算
在实际写代码的过程中经常会涉及到两个字符串⽐较⼤⼩,⽐如:判断你输⼊的密码是否正确,就得 将输⼊的密码和数据库中正确的密码⽐较。 那么两个 string 类型字符串是否可以⽐较⼤⼩呢?其实是可以的,C++中为string提供了⼀系列的 关系运算。
支持的关系运算
cpp
string s1 = "abc";
string s2 = "abcd";
char s3[] = "abcdef";
//C风格的字符串
(1) s1 == s2
bool operator== (const string& lhs, const string& rhs);
//使用方式:s1 == s2
bool operator== (const char* lhs, const string& rhs);
//使用方式:s3 == s1
bool operator== (const string& lhs, const char* rhs);
//使用方式:s1 == s3
(2) s1 != s2
bool operator!= (const string& lhs, const string& rhs);
//使用方式:s1 != s2
bool operator!= (const char* lhs, const string& rhs);
//使用方式:s3 != s1
bool operator!= (const string& lhs, const char* rhs);
//使用方式:s1 != s3
(3) s1 < s2
(4) s1 <= s2
(5) s1 > s2
(6) s1 >= s2
bool operator< (const string& lhs, const string& rhs);
//使用方式:s1 < s2
bool operator< (const char* lhs, const string& rhs);
//使用方式:s3 < s1
bool operator< (const string& lhs, const char* rhs);
//使用方式:s1 < s3
bool operator<= (const string& lhs, const string& rhs);
//使用方式:s1 <= s2
bool operator<= (const char* lhs, const string& rhs);
//使用方式:s3 <= s1
bool operator<= (const string& lhs, const char* rhs);
//使用方式:s1 <= s3
bool operator> (const string& lhs, const string& rhs);
//使用方式:s1 > s2
bool operator> (const char* lhs, const string& rhs);
//使用方式:s3 > s1
bool operator> (const string& lhs, const char* rhs);
//使用方式:s1 > s3
bool operator>= (const string& lhs, const string& rhs);
//使用方式:s1 >= s2
bool operator>= (const char* lhs, const string& rhs);
//使用方式:s3 >= s1
bool operator>= (const string& lhs, const char* rhs);
//使用方式:s1 >= s3
上述的关系运算符的重载看着复杂,但是使⽤起来是⾮常简单的。
注: 关于操作符的重载,只有深⼊学习C++的类和对象,才能深⼊理解和掌握,在竞赛的课程中不需 要深⼊挖掘,会使⽤就⾏,但是要使⽤C++进⾏⼯程性开发的时候这部分知识⼀定要补上。
字符串的⽐较是基于字典序进⾏的,⽐较是对应位置上字符的ASCII值的⼤⼩;⽐较的不是字符串的⻓ 度。
比如
cpp
"abc" < "aq"
//'b'的ascii码值是?于'q'的
"abcdef" < "ff"
//'a'的ASCII码值是?于'f'的
"100" < "9"
cpp
#include <iostream>
#include<string>
using namespace std;
int main()
{
string s1 = "hello world";
string s2 = "hello";
if (s1 == (s2 + " world"))
{
cout << "s1 == s2" << endl;
}
else
{
cout << "s1 != s2" << endl;
}
//输出 s1 =s2
return 0;
}
cpp
#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 == s2)
cout << "s1 == s2" << endl;
else
cout << "s1 != s2" << endl;
if (s1 <= s3)
cout << "s1 <= s3" << endl;
else
cout << "s1 > s3" << endl;
//输出s1 > s2
//s1 != s2
//s1 <= s3
return 0;
}
12. string和数字的转换函数
2.12.1 stoi/stol
• stoi 是将字符串转换成 int 类型的值
• stol 是将字符串转换成 long int 类型的值 这两个函数⾮常类型,这⾥以 stoi 为例讲解⼀下这⾥函数的使⽤⽅式。
stoi 函数其实可以将⼀个 string 类型的字符串,转化为整型,函数原型如下:
cpp
int stoi (const string& str, size_t* idx = 0, int base = 10);
long stol (const string& str, size_t* idx = 0, int base = 10);
参数解读:
• str 表⽰被转换的 string 类型的字符串
• idx 是⼀个输出型参数,也就是这个通过这个参数会带回⼀个值。 边创建⼀个 size_t 类型的值,传递它的地址给 idx 是⼀个指针,需要在外 idx ,这个参数将会带回 数字的第⼀个字符的位置。
• base 表⽰被解析的字符串中数字的进制值,可能是 2 , 8 , str 中⽆法正确匹配 10 , 16 或者 0 . ◦ 默认情况下这个值是 10 ,表⽰ 10 进制数字
◦ 如果传递的是 2 ,表⽰被解析的字符串中是 2 进制的数字,最终会转换成 10 进制
◦ 如果传递的是 8 ,表⽰被解析的字符串中是 8 进制的数字,最终会转换成 10 进制
◦ 如果传递的是 16 ,表⽰被解析的字符串中是 16 进制的数字,最终会转换成 10 进制
◦ 如果传递的是 0 ,会根据字符串的内容的信息⾃动推导进制,⽐如:字符串中有0x,就认为 是 16 进制, 0 开头会被认为是 8 进制,最终会转换成 10 进制。
cpp
#include <iostream>
#include<string>
using namespace std;
int main()
{
size_t pos = 0;
string s1 = "11x34";
int ret1 = stoi(s1, &pos, 16);
cout << ret1 << endl;
cout << "pos:" << pos << endl;
string s2 = "11x34";
int ret2 = stoi(s2, &pos, 2);
cout << ret2 << endl;
cout << "pos:" << pos << endl;
string s3 = "0x11x34";
int ret3 = stoi(s3, &pos, 0);
cout << ret3 << endl;
cout << "pos:" << pos << endl;
//输出
//17
//pos:2
//3
//pos:2
//17
//pos:4
return 0;
}
2.12.2 stod/stof
stod 是将字符串转换成 double 类型的值,函数原型如下,和 字符串中数字进制的参数,其他参数⼀致。 stoi 函数的⽐较的话,少了描述 stof 是将字符串转换成 flaot 类型的值。
cpp
double stod (const string& str, size_t* idx = 0);
float stof (const string& str, size_t* idx = 0);
cpp
#include <iostream>
#include<string>
using namespace std;
int main()
{
string s = "3.14x456";
double ret = stod(s, NULL);
cout << ret << endl;
//输出 3.14
return 0;
}
to_string
函数原型如下:
cpp
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);
tostring 函数可以将数字转换成字符串,从上述函数原型的⻆度看的话,可以将整型、浮点型的数 字转换成字符串的,使⽤起来也⾮常简单。
cpp
#include <iostream>
#include <string>
using namespace std;
int main()
{
string pi = "pi is " + to_string(3.14159);
cout << pi << endl;
//输出 pi is 3.141590
return 0;
}
小提示
好咯,各位uu,这一篇就到这里完美结束啦~