C++中string类基本使用的详细归纳

发布时间 2023-11-03 15:19:37作者: 少玩手机

目录:

  1. string类的初始化操作

  2. 实例化得到一个string类对象之后的常用成员函数的操作

    2.1 从外部键盘获取输入的方式(注意与C风格字符串做区别)
    2.2 比较string对象
    2.3 遍历每个字符
    2.4 string类中的insert()增加成员函数
    2.5 string类中的erase()删除成员函数
    2.6 常用基本操作函数:append() replace()函数
    2.7 string类中的find查询相关的成员函数
    2.8 string类中的compare()比较成员函数
    2.9 字符串与数值之间的转换成员函数

3.力扣题目:“字符串解码” 其本身包含诸多string类基本成员函数的使用

1.string类的初始化操作

首先,在cpp中使用string类 一定需要导入其官方提供的头文件: #include <string>

其次,需要我们注意的两个概念:变量的初始化与赋值是两个不同的操作!
初始化:是在实例化对象时,应该按照初始化的内容来构造;而非先单独构造(此时对象所存储内容没有意义,属于脏数据),有了对象后,进行赋值。
如下,我们直接给出string类的几种初始化方式:
string s1; //默认s1是个空串
string s2(s1); //调用了拷贝构造函数 s2形成了s1的副本
string s2=s1; //与上边语句等价
string s3("value"); //字符串常量的内容给s3 s3形成字符串常量“value”的副本
string s3="value"; //与上边语句等价
string s4(n , 'c'); //把s4初始化形成一个由n个'c'连续组成的字符串
//另一种拷贝构造函数 将字符数组的的内容拷贝给string字符串类的对象
string s(cp,n)

`const char *cp = "hello world";//最后有一个空字符

char cp2[] = "hello world";//最后有一个空字符

char cp3[] = { 'h', 'e' };//最后没有空字符

`

//拷贝对象的其他参数是使用
string s(s1,pos)
string s(s1,pos,len)

列子:
string s1("value");

(1) string s2(s1, 1);//s2为” alue”,长度为4
(2) string s3(s1, 5);//s3为””,长度为0
(3) string s8(s1, 6);// 错误,未定义的行为,抛出异常

(4) string s4(s1, 1,3);// s4为” alu”,长度为3
(5) string s5(s1, 1,8);// 正确,s5为” alue”,长度为4
(6) string s6(s1, 5,8);// s6为””,长度为0
(7) string s7(s1, 6,1);// 错误,未定义的行为,抛出异常

2. 实例化得到一个string类对象之后的常用成员函数的操作

2.1 从外部键盘获取输入的方式(注意与C风格字符串做区别)

使用cin进行输入:
cin>>str;//即使输入一行句子,但是只会读取到第一个单词,空格被视为输入结束
注意:string对象会自动忽略开头的空白(既空格、换行符、制表符等),并从第一个真正的字符开始读入,直到遇到下一处空白

使用getline进行输入:
getline(cin , str);//正常读取一整行输入
getline(cin , str , ':'); //可以定义以什么符号结束输入
注意:getline的作用是读取一整行,直到遇到换行符才停止读取,期间能读取像空格、Tab等的空白符。

C++风格的初始化和输入就是以上内容,虽然还有一些输入方式,但是在日常项目开发,这两种输入已经完全足够!

2.2 比较string类的对象

直接通过例子来理解和记住其运用,因为这就是别人设计好的,首先学会使用即可:
可以通过比较运算符比较两个字符串 但是重要的事情是我们需要知道比较运算比较字符串的规则是什么?
case1:
string str = "Hello"; string phrase = "Hello ";
解释:尽管两者的前面对应的字符都一样,但是phrase长度长(多一个空格),所以phrase>str。

case2:
string str2 = "Hello"; string phrase2 = "Hi ";
解释:这种情况比较的是第一个相异字符,根据字符值比较大小,因为i的字符值>e的字符值,所以phrase2> str2。

总结:看上面两种情况,实际上可以都看成是一个一个字符比较。对于第一种,str最后为空,而phrase为空格,空格字符值不为负,所以phrase>str。

** 两个string类对象相加**
幸运的是,c++中的string将+运算符进行了运算符重载,这极大地方便了开发人员完成字符串拼接的工作。
string str = "Hello,";
string phrase = "world ";

  string s = str + phrase;
  str += phrase;//相当于str = str + phrase

  cout << s << endl;
  cout << str << endl;`

注意:当string对象和字符或字符串字面值相加时,必须确保+号的两侧的运算对象至少有一个string。
下边列子:
(1)string s2 = str + "," + "world"; (2)string s3 = "Hello" + "," + str;
(2)错误的原因:如上注意!其次字符串常量其实是一个地址!

2.3 遍历每个字符

1.简单的循环操作,把字符串理解成一个字符数组 像数组一样使用 通过索引下标

string s = "Hello world!";
for (decltype(s.size()) index = 0;index != s.size(); index++){
cout << s[index] << ",";
}
cout<<endl;

这里使用的decltype关键字是C11的新特性 在我博客中的专题有其与auto专门的区别介绍

2. 使用迭代器
关于迭代器,如果还没有深入理解其本质,不妨就暂时理解成广义指针。

string s = "Hello world!";

点击查看代码
string s = "Hello world!";
for (auto i = s.begin(); i != s.end(); i++){
cout << *i  << ",";
}
cout << endl;

for (auto i = s.begin(); i != s.end(); i++){
cout << *i << ",";
}
cout << endl;

使用基于范围的for循环语句(C++11新特性提供的一种for语法格式):
image
declaration:定义一个变量,它每次的值都是expression中的基础元素
expression:一个已经定义的对象(变量)
statement:具体的语句

直接通过一个具体使用例子来理解:
string str("some string");

点击查看代码
string str("some string");
for (auto c : str)
	cout << c << ",";
cout << endl;

关于for循环的C++11新特性 我会在我的博客专题中提到!

3.string对象的substr()成员函数的使用
取指定区间上的子串
例子:
格式:s.substr(pos,n)
解释:返回一个string对象,返回的对象包含s从pos下标开始的n个字符。pos和n均为可选参数。pos默认为下标0;n默认为s.size()-pos。

string s ("value");
(1)string s2 = s.substr();//s2为”value”,大小为5

(2)string s3 = s.substr(2);//s3为”lue”,大小为3
(3)string s4 = s.substr(5);//s3为””,大小为0
(4)string s5 = s.substr(6);//错误,s5的大小为pos = 5,小于s.size()

(5)string s6 = s.substr(1,2);// s6为”al”,大小为2
(6)string s7 = s.substr(1,7);// s7为”alue”,大小为4
(7)string s8 = s.substr(5,7);// s8为””,大小为0
(8)string s9 = s.substr(6,7);// 错误,s9的大小为pos = 5,小于s.size()

2.4 string类中的insert()增加成员函数

虽然string类不属于我们的容器类 但是其结构 及其STL标准还是遵循的 因此可以使用迭代器也能使用下标
迭代器版本的insert()
例子:
string s1("value");
s1.insert(s1.begin(), 's');//执行后,s1为"svalue"
s1.insert(s1.begin(), 1, 's');//执行后,s1为"ssvalue"
s1.insert(s1.begin(), s1.begin(), ++s1.begin());//执行后,s1为"sssvalue"
s1.insert(s1.end(), {'1','2'});//执行后,s1为"sssvalue12"

下标版本的insert()
解释:在下标index前插入count个字符ch。
列子:
string s1("value");
s1.insert(0,2,’s’); //执行后,s1为” ssvalue”
s1.insert(5,2,’s’); //执行后,s1为” valuess”

在下标index前插入一个常量字符串或者string对象:
string s1("value");
string s3 = "value";
const char* cp = "value";

s1.insert(0,s3);//执行完后,s1为" valuevalue"
s1.insert(0,cp); //执行完后,s1为" valuevalue"

2.5 string类中的erase()删除成员函数

几种删除形式:有下标版本 也有迭代器版本 一共三种形式:

basic_string & erase(size_type pos=0, size_type n=npos)
解释:如果string对象s调用,它删除s从pos下标开始的n个字符,并返回删除后的s。当pos > s.size()时,报错

iterator erase(const_iterator position)
解释:如果string对象s调用,它删除s迭代器position位置的字符,并返回下一个字符的迭代器。

iterator erase(const_iterator first, const_iterator last)
解释:如果string对象s调用,它删除s迭代器[first,last)区间的字符,并返回last字符的迭代器。

点击查看代码
string s1("value");
string s2("value");
string s3("value");
string s4("value");

s1.erase();//执行后,s1为空
s2.erase(0,2); //执行后,s2为”lue”
s3.erase(s3.begin());//执行后,s3为”alue”
s4.erase(s4.begin(),++s4.begin());//执行后,s4为”alue”

2.6 常用的基本操作函数 append() 和 replace()

1.append()函数
append()是string类对象的成员函数 能够在string类对象的末尾处进行插入操作 。这一点运算符重载后的+也能做到
string s("i love China!");
s.append("forever");//执行完后,s=” i love China! forever”

2.replace()函数
replace可看作是erase和insert的结合体,它删除指定的字符,删除后再插入指定的字符。
和insert一样,可以通过下标或者是迭代器指定位置。
case1:小标指定更新位置
string s("i very love China!");

点击查看代码
string s("i very love China!");

const char* cp1 = "truly";
const char* cp2 = "truly!!!";

string str1 = "really";
string str2 = "really!!!";

//1.将s从下标2开始删除4个字符,删除后在下标2处插入cp1
s.replace(2,4,cp1);//s=” i truly love China!”
//2.将s从下标2开始删除5个字符,删除后在下标2插入cp2的前5个字符
s.replace(2, 5, cp2,5); //s=” i truly love China!”
//3.将s从下标2开始删除5个字符,删除后在下标2插入str1
s.replace(2, 5, str1);//s=”i really love China!”
//4.将s从下标2开始删除6个字符,删除后在下标2插入str2从下标0开始的6个字符
s.replace(2, 6, str2,0,6);//s=”i really love China!”
//5.将s从下标2开始删除6个字符,删除后在下标2插入4个’*’字符
s.replace(2, 6, 4, '*');//s=”i **** love China!”

case2:迭代器指定更新位置
string s1("bad phrase");

点击查看代码
string s1("bad phrase");

const char* cp3 = "sample";
const char* cp4 = "sample!!!";

string str3 = "useful";
string str4 = "useful!!!";

//1.删除[s1.begin(),s1. begin()+3)区间字符,删除后插入cp3
s1.replace(s1.begin(),s1.begin()+3,cp3);//s1="sample phrase"
//2.删除[s1.begin(),s1. begin()+6)区间字符,删除后插入cp4的前6个字符
s1.replace(s1.begin(),s1.begin()+6,cp4,6);//s1="sample phrase"
//3.删除[s1.begin(),s1. begin()+6)区间字符,删除后插入str3
s1.replace(s1.begin(),s1.begin()+6, str3);//s1="useful phrase"
//4.删除[s1.begin(),s1. begin()+6)区间字符,删除后插入str4[str4.begin(),str4. begin()+6)区间字符
s1.replace(s1.begin(),s1.begin()+6, str4.begin(),str4.begin() + 6);//s1="useful phrase"
//5. 删除[s1.begin(),s1. begin()+6)区间字符,删除后插入4个’*’字符
s1.replace(s1.begin(),s1.begin()+6, 4, '*');//s1="**** phrase"
//6. 删除[s1.begin(),s1. begin()+4)区间字符,删除后插入初始化列表
s1.replace(s1.begin(), s1.begin() + 4, {'3','4','5'});//s1="345 phrase"

2.7 string类中的find()查询相关成员函数

string提供6个不同的搜索函数,每个函数都有4个重载版本,如下表:

string搜索函数 描述
s.find(args) 在s中查找第一次出现args的下标
s.rfind(args) 在s中查找最后一次出现args的下标
s.find_first_of(args) 在s中查找第一个在args中出现的字符,返回其下标
s.find_first_not_of(args) 在s中查找第一个不在args中出现的字符,返回其下标
s.find_last_of(args) 在s中查找最后一个在args中出现的字符,返回其下标
s.find_last_not_of(args) 在s中查找最后一个不在args中出现的字符,返回其下标

c,pos 搜索单个字符。从s中位置pos开始查找字符c。pos可省略,默认值为0
s2,pos 搜索字符串。从s中位置pos开始查找字符串string对象s2。pos可省略,默认值为0
cp,pos 搜索字符串。从s中位置pos开始查找指针cp指向的以空字符结尾的C风格字符串。pos可省略,默认值为0
cp,pos,n 从s中位置pos开始查找指针cp指向的数组的前n个字符。

常用的find()函数的例子:

点击查看代码
std::string str("There are two needles in this haystack with needles.");
std::string str2("needle");
//1.对应参数args为s2,pos
std::size_t found = str.find(str2);//返回第一个"needles"n的下标
if (found != std::string::npos)
			std::cout << "first 'needle' found at: " << found << '\n';
//2.对应参数args为cp,pos, n
found = str.find("needles are small", found + 1, 6);
if (found != std::string::npos)
	std::cout << "second 'needle' found at: " << found << '\n';
//3.对应参数args为cp,pos
found = str.find("haystack");
if (found != std::string::npos)
	std::cout << "'haystack' also found at: " << found << '\n';
//4.对应参数args为c,pos
found = str.find('.');
if (found != std::string::npos)
			std::cout << "Period found at: " << found << '\n';

// 替换第一个needle:
str.replace(str.find(str2), str2.length(), "preposition");
std::cout << str << '\n';

常用的rfind()函数的例子:

点击查看代码
cout << " rfind()函数:" << endl;
std::string str("The sixth sick sheik's sixth sheep's sick.");
std::string key("sixth");

std::size_t found = str.rfind(key);//找到最后一个sixth的下标
if (found != std::string::npos)
	str.replace(found, key.length(), "seventh");//替换找到的sixth

std::cout << str << '\n';

2.8 string类中的compare()比较成员函数

compare的实现原理和之前的string类运算符重载后的> < ==一样 挨个单个字符单个字符比较 ! 遇到不同的就不比较了!
在前面,我们介绍了用比较运算符比较两个字符串的方法,同时string对象中有一个成员函数compare,它也可以比较字符串,并且有6种不同的参数形式,比较字符串时更加灵活。compare的参数形式如下:

参数形式s.compare() 说明
s2 比较s和s2
pos1, n1, s2 将s中从pos1开始的n1个字符与s2比较
pos1, n1, s2, pos2, n2 将s中从pos1开始的n1个字符与s2中从pos2开始的n2个字符比较
cp 比较s与cp指向的以空字符结尾的数组
pos1, n1, cp 将s中从pos1开始的n1个字符与cp指向的以空字符结尾的数组比较
pos1, n1, cp,n2 将s中从pos1开始的n1个字符与cp指向的以空字符结尾的数组前n个字符比较

注意compare()的返回值:
若s=指定的字符串,s.compare()返回0
若s>指定的字符串,s.compare()返回正数
若s<指定的字符串,s.compare()返回负数

compare()函数的使用例子:

点击查看代码
std::string str1("green apple");
std::string str2("red apple");

//1.str1和str2比较:参数形式1
if (str1.compare(str2) != 0)
	std::cout << str1 << " is not " << str2 << '\n';
//2.str1的下标6开始的5个字符和"apple"比较:参数形式5
if (str1.compare(6, 5, "apple") == 0)
	std::cout << "still, " << str1 << " is an apple\n";
//3.str2的下标str2.size() - 5(就是下标6)开始的5个字符和"apple"比较:参数形式5
if (str2.compare(str2.size() - 5, 5, "apple") == 0)
	std::cout << "and " << str2 << " is also an apple\n";
//4.str1的下标6开始的5个字符和str2的下标4开始的5个字符比较:参数形式3
if (str1.compare(6, 5, str2, 4, 5) == 0)
	std::cout << "therefore, both are apples\n";
//5.str1的下标6开始的5个字符和"apple pie"的前5个字符比较:参数形式6
if (str1.compare(6, 5, "apple pie",5) == 0)
	std::cout << "apple pie is maked by apple\n";

//6.str1和"poisonous apple"比较:参数形式4
if (str1.compare("poisonous apple") < 0)
	std::cout << "poisonous apple is not a apple\n";

2.9 字符串与数值之间的转换成员函数

字符串与数值间的转换的函数名与格式说明
image

常用的to_string(val)实例:
std::string pi = "pi is " + std::to_string(3.1415926);

点击查看代码
std::string pi = "pi is " + std::to_string(3.1415926);
std::string perfect = std::to_string(1 + 2 + 4 + 7 + 14) + " is a perfect number";
std::cout << pi << '\n';
std::cout << perfect << '\n';

运行结果:
image

stoi(s,p,b) 例子(stol stoll stoul stoull类似,不再举例):

点击查看代码
std::string str_dec = "2001, A Space Odyssey";
std::string str_hex = "40c3";
std::string str_bin = "-10010110001";
std::string str_auto = "0x7f";

std::string::size_type sz;   // alias of size_t

//1.转换基数为10进制,sz保存','下标,i_dec = 2001
int i_dec = std::stoi(str_dec, &sz);
//2.转换基数为16进制。所以i_hex = 0x40c3,十进制为16579
int i_hex = std::stoi(str_hex, nullptr, 16);
//3.转换基数为2进制。所以i_bin = -10010110001B,十进制为-1201
int i_bin = std::stoi(str_bin, nullptr, 2);
//4.自动确定 转换基数
int i_auto = std::stoi(str_auto, nullptr, 0);

std::cout << str_dec << ": " << i_dec << " and [" << str_dec.substr(sz) << "]\n";
std::cout << str_hex << ": " << i_hex << '\n';
std::cout << str_bin << ": " << i_bin << '\n';
std::cout << str_auto << ": " << i_auto << '\n';

关于字符串与数值之间的转换方式的介绍 请关注下一篇博客!