string 概念
string 字符串其实是一种更加高级的封装,string字符串中包含大量的方法,
这些方法使得字符串的操作变得更加简单。
C++中将字符串直接作为一种类型,也就是string类型,使用string类型创建的
对象就是C++的字符串。
使用C++中提供的string是,必须添加头文件string。
string 的常见操作
string 字符串的创建和初始化
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1;//空字符串
string s2 = "hello world";
string s3("hello C++");
cout << "s1:" << s1 << endl;
cout << "s2:" << s2 << endl;
cout << "s3:" << s3 << endl;
return 0;
}
string 字符串的创建共有s1、s2、s3这三种方式
string s1;表示创建空字符串,就是说这个字符串是空的,并不是随机值
s2和s3是字符串创建和初始化的两种方式
注意:s2和s3中的字符串不再以\0作为结束标志了,跟C语言的不同
上面这个图,只是s2的示意图,实际上string类型的字符串比这个要复杂的多
C++中的string字符串和char类型的数组所表示的字符串还有一个区别
string类型的字符串对象可以直接赋值
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1 = "hello world";
string s2 = "XXX";
cout << s2 << endl;
s2 = s1;
cout << s2 << endl;
return 0;
}
string 字符串的输入
cin的方式
使用cin输入一个string的字符串,只能胜任不带空格的字符串
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
//输入
cin >> s;
//输出
cout << s << endl;
return 0;
}
getline的方式
getline是C++标准库中的一个韩素华,用于从输入流中读取一行文本,并将其存储为字符串。
getline函数有两种不同的形式,分别对应着字符串的结束方式。
istream& getline(istream& is, string& str);
istream& getline(istream& is, string& str, char delim);
istream是输入流类型,cin是istream类型的标准输入流对象。
ostream是输出流类型,cout是ostream类型的标准输出流对象。
getline函数是输入流中读取一行文本信息,如果是在标准输入流(键盘)
中读取数据,就可以传cin给第一个参数
第一种getline函数以\n作为字符串的结束标志,它的一般格式是:
getline(cin, string str);
cin 表示从输入流中读取信息
str 是存放读取到的信息的字符串
这种形式的getline函数从输入流(例如cin)中读取文本,直到遇见\n为止,
然后将读取到的文本(不包括\n)存储到指定的string类型的变量str中。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
//输入
getline(cin, str);
//输出
cout << str << endl;
return 0;
}
第二种getline函数允许用户自定义结束标志,它的一般格式是:
getline(cin, string str, char delim);
cin 表示从输入流中读取信息
str 是存放读取到的信息的字符串
delim 是自定义的结束标志
这种形式的getline函数从输入流(例如cin)中读取文本,直到遇见用户指定
的结束标志(delim)为止,然后将读取到的文本(不包括结束标志字符)
存储到指定的string类型的变量str中。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
//输入
getline(cin, str, 'e');
//输出
cout << str << endl;
return 0;
}
size()
string中提供了size()函数用于获取字符串长度。
在C++中关于字符串的操作函数都是包含在syting中的,
所以需要调用这些函数时,通常用 **.**点运算符。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1;
string s2 = "hello";
string s3 = "hello world";
string s4("abc ");
cout << "s1:" << s1.size() << endl;
cout << "s2:" << s2.size() << endl;
cout << "s3:" << s3.size() << endl;
cout << "s4:" << s4.size() << endl;
return 0;
}
注意string类型的字符串是可以通过下标访问的
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "abcdef";
for(int i = 0; i < s.size(); i++)
{
cout << s[i] << " ";
}
cout << endl;
return 0;
}
迭代器(iterator)
迭代器是一种对象,它可以用来遍历容器(比如string)中的元素,
迭代器的作用类似于指针,或者数组下标
begin() 和 end()
begin(): 返回指向字符串第一个字符的迭代器,需要一个迭代器的变量来接收
end(): 返回指向字符串最后一个字符的下一个位置的迭代器(该位置不属于字符串)
string中begin()和end()返回的迭代器类型是string::iterator
迭代器可以进行大小比较,也可以+或者-整数运算。
同一个容器的两个迭代器也可以相减,相减结果的绝对值是两个迭代器中间元素的个数。
#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;
return 0;
}
迭代器通常用于遍历字符串,可以正序遍历,也可以逆序遍历。
正序遍历:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "abcdef";
for(string::iterator it = s.begin(); it < s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
return 0;
}
逆序遍历
#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 << " ";
}
cout << endl;
return 0;
}
通过迭代器找到元素后,改变迭代器指向的元素是可以直接改变字符串内容的。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "abcdef";
cout << s << endl;
for(string::iterator it = s.begin(); it < s.end(); it++)
{
*it = 'x';
}
cout << s << endl;
return 0;
}
push_back()
push_back()用于在字符串尾部插一个字符
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "hello";
cout << s << endl;
s.push_back('w');
cout << s << endl;
return 0;
}
#include <iostream>
#include <string>
using namespace std;
int main()
{
//向空字符串中插入字符
string s;
s.push_back('w');
s.push_back('o');
s.push_back('r');
s.push_back('l');
s.push_back('d');
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;
for(char i = 'a'; i <= 'z'; i++)
{
s2.push_back(i);
}
cout << s2 << endl;
return 0;
}
string 的+=和+运算
string类型的字符串支持+和+=运算,本质是string中重载了operator+=这个操作符。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1 = "world";
string s2 = "hello";
//头部拼接
cout << s2 + s1 << endl;
cout << "h" + s1 << endl;
cout << "hello" + s1 << endl;
s1 = "hello" + s1;
cout << s1 << endl;
//尾部拼接
s1 = "world";//让s1重新变为"world"
cout << s1 + s2 << endl;
cout << s1 + "h" << endl;
cout << s1 + "hello" << endl;
s1 += "hello";
cout << s1 << endl;
return 0;
}
pop_back
pop_back()用于删除字符串中最后一个字符。
这个成员函数是在C++11标准中引入的,有的编译器可能不支持。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "hello";
cout << s << endl;
s.pop_back();
cout << s << endl;
return 0;
}
注意:当字符串中没有字符时,调用pop_back()的话,程序会出现异常。
这种行为也是未定义行为,要避免使用。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
s.pop_back();
cout << s << endl;
return 0;
}
在DevC++上程序最后崩了。
为避免删除导致上述情况,可以改写代码
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "abc";
while(s.size() > 0)//通过size()函数来控制字符串长度
s.pop_back();
return 0;
}
insert()
inset()可以在字符串中间的某个位置插入一个字符串。
函数原型如下:
string& insert(size_t pos, const string& str);//pos位置前面插入一个string字符串
string& insert(size_t pos, const char* c);//pos位置前面插入一个C风格的字符串
string& insert(size_t pos, size_t n, char c);//pos位置前面插入n个字符c
#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;
return 0;
}
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "abcdefghi";
cout << s << endl;
s.insert(3, "xxx");
cout << s << endl;
return 0;
}
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "abcdefghi";
cout << s << endl;
s.insert(3, 3, 'x');
cout << s << endl;
return 0;
}
find()
find()函数用于查找字符串中指定子串/字符,并返回子串/字符在字符串中第一次出现的位置。
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就能知道是否查找到子串/字符
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "hello world hello everyone";
string str = "llo";
//查找string类型的字符串
size_t n = s.find(str);
cout << n << endl;
n = s.find(str, n + 1);//从n+1位置开始查找str
cout << n << endl;
//查找C风格的字符串
n = s.find("llo");
cout << n << endl;
n = s.find("llo", n + 1);//从n+1位置开始查找
cout << n << endl;
return 0;
}
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "hello world hello everyone";
//在s中,0位置开始,查找"world"的前3个字符
size_t n = s.find("world", 0, 3);
cout << n << endl;
//在s中,n+1位置开始,查找"everyday"的前5个字符
n = s.find("everyday", n + 1, 5);
cout << n << endl;
return 0;
}
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "hello world hello everyone";
size_t n = s.find('o');
cout << n << endl;
n = s.find('o', n + 1);
cout << n << endl;
return 0;
}
查找不到的情况
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "hello world hello everyone";
string str = "xxx";
size_t n = s.find(str);
if(n != string::npos)
cout << "找到了,位置是:" << n << endl;
else
cout << "找不到" << endl;
return 0;
}
在字符串中查找字符或者字符串时,有可能查不到,这时候find函数会返回npos这个值,
该数字并不是一个随机的数字,而是string中定义的一个静态常量npos。
我们通常会判断find函数的返回值是否等于npos来判断,查找是否成功。
static const size_t npos = -1;
#include <iostream>
#include <string>
using namespace std;
int main()
{
//注意:npos是string中定义的,使用npos需要带上string::
cout << "npos:" << string::npos << endl;
return 0;
}
npos不是-1的原因是:-1是有符号的,而npos是size_t类型的,其是无符号的
substr()
substr()函数用于截取字符串中指定位置指定长度的子串。
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的子串。
返回值类型:string,返回的是截取到的字符串,可以使用string类型的字符串接收。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "hello world hello everyone";
string s1 = s.substr(7);
cout << s1 << endl;
string s2 = s.substr(7, 6);
cout << s2 << endl;
return 0;
}
substr()和find()经常配合使用,find负责找到位置,substr从这个位置向后获得字符串。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "hello world hello everyone";
size_t n = s.find("world");
string s1 = s.substr(n, 11);
cout << s1 << endl;
return 0;
}
string 的关系运算
支持的关系运算
运算: >、<、>=、<=、==、!=
string类型 与 string类型 的运算
string类型 与 char类型 的运算
char类型 与 string类型 的运算
字符串比较
字符串的比较是基于字典序进行的,比较的是对应位置上字符的ASCII值的大小。
比如
“abc” < “aq”,'b’的ASCII值是小于’q’的
“abcdef” < “ff”,'a’的ASCII值是小于’f’的
“100” < “9”,'1’的ASCII值是小于’9’的
string 和数字的转换函数
stoi/stol
stoi是将字符串转换成int类型的值
stol是将字符串转换成long int类型的值
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是一个输出型参数,也就是该函数会通过这个参数带回一个值。
idx是一个指针,需要在外边创建一个size_t类型的值,传递它的地址
给idx,这个参数将会带回str中无法正确匹配数字的第一个字符的位置。
base表示被解析的字符串中数字的进制值,可能是2,8,10,16或者0。
默认情况下这个值是10,表示10进制数字
如果传递的是2 ,表示被解析的字符串中是2进制的数字,最终会转换成10进制。
8,16进制等同。
如果传递的是0,会根据字符串的内容的信息自动推导进制。
若字符串中有0x,就认为是10进制,0开头会被认为是8进制,最终会转换成10进制。
#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;
//ret1得到的是16进制的11,换算成10进制是17
cout << "pos:" << pos << endl;
//pos中存放的是'x'的位置,因为16进制中没有'x',
//所以无法正确匹配
string s2 = "11x34";
int ret2 = stoi(s2, &pos, 2);
cout << ret2 << endl;//2^1*1+2^0*1 == 3
cout << "pos:" << pos << endl;
string s3 = "0x11x34";
int ret3 = stoi(s3, &pos, 0);
cout << ret3 << endl;//0x说明是16进制,所以是17
cout << "pos:" << pos << endl;//第二个'x'的下标位置是4
return 0;
}
stod/stof
stod是将字符串转换成double类型的值
stof是将字符串转换成float类型的值
double stod(const string& str, size_t* idx = 0);
float stof(const string& str, size_t* idx = 0);
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "3.14x456";
double ret = stod(s, NULL);
//不需要第二个参数可以写成NULL或者0
cout << ret << endl;
return 0;
}
to_string
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);
#include <iostream>
#include <string>
using namespace std;
int main()
{
string pi = "pi is " + to_string(3.14159);
cout << pi << endl;
return 0;
}