C++ string 类详解:概念、常用操作与实践(算法竞赛类)

C++ string 类详解:概念、常用操作与实践(算法竞赛类)
🔥个人主页:星轨初途
❄专栏传送门:C语言数据结构C++学习(竞赛类)算法及编程题分享

文章目录

前言

嗨,大家好呀!我已经很久没有更新了,今天是元旦,祝大家元旦快乐呀。◕ᴗ◕。!
我们上一篇讲解了C++的条件判断与循环及数组(算法竞赛类),了解了数组的相关知识,我们感觉其中字符串数组还是没那么好用,为了更加简单⽅便,在C++中,⼜增加了 string 来处理字符串。今天我们来一起了解string的神奇之处吧!

一、string概念

string字符串其实是一种更加高级的封装,string字符串中包含大量的方法,这些方法使得字符串的操作变得更加简单。string使用的好,慢慢你就不想使用字符数组来存放字符串了。
而C++中将字符串直接作为一种类型,也就是string类型,使用string类型创建的对象就是C++的字符串。

string也就是存储字符串的另一种方式,就是和字符数组差不多,只不过封装了一些好用的功能而已,十分简单易懂

二、string的常见操作和功能

常见操作文档:常见操作

1、头文件

#include<string>

2、创建字符串

#include<iostream>#include<string>usingnamespace std;intmain(){ string s1;//空字符串 string s2 ="hello world"; cout <<"s1:"<< s1 << endl;//s1: cout <<"s2:"<< s2 << endl;//s2: hello worldreturn0;}

这里就不用多说了,和字符串的初始化一样

在这里插入图片描述


string也可以下标进行访问

除了以上创建字符串的写法外,C++中还有一些其他的创建字符串方式。如:
当然C++中的string创建的字符串和char类型的数组所表示的字符串还有一个区别,string类型的字符串对象可以直接赋值,比如:

方式1:其他字符串创建写法

string s("hello world");//等同于string s1 = "hello world"; string s1 = s;//用一个现成的字符串s,初始化另外一个字符串s1

方式2:string对象直接赋值示例

#include<iostream>#include<string>usingnamespace std;intmain(){ string s1("hello world"); string s2("hehe"); s2 = s1; cout << s2 << endl;return0;}

3、string字符串的输入

(1)正常输入(cin)

和scanf功能一样,string可以用cin输入,但是只能输入不带空格的字符串

#include<iostream>#include<string>usingnamespace std;intmain(){ string s;//输入 cin >> s;//输出 cout << s << endl;return0;}

(2)getline(带空格输入)

  1. getline是C++标准库中的一个函数,用于从输入流中读取一行文本,并将其存储为字符串。
  2. getline函数有两种不同的形式,分别对应着字符串的结束方式。
istream&getline(istream& is, string& str); istream&getline(istream& is, string& str,char delim);
✅提示:istream是输入流类型,cin是istream类型的标准输入流对象。ostream是输出流类型,cout是ostream类型的标准输出流对象。getline函数是从输入流中读取一行文本信息,所以如果是在标准输入流(键盘)中读取数据,就可以传cin给第一个参数。
第一种(默认以‘\n’为结束标志)

第一种 getline 函数以换行符(‘\n’)作为字符串的结束标志,它的一般格式是:

getline(cin, string str)//cin -- 表示从输入流中读取信息//str 是存放读取到的信息的字符串

这种形式的 getline 函数从输入流(例如cin)中读取文本,直到遇到换行符(‘\n’)为止,然后将读取到的文本(不包括换行符)存储到指定的string类型的变量str中。
实例:

#include<iostream>#include<string>usingnamespace std;intmain(){ string name;getline(cin, name); cout << name << endl;return0;}

效果:

在这里插入图片描述
第二种(自定义结束标志)

第二种 getline 函数允许用户自定义结束标志,它的一般格式是:

getline(cin, string str,char delim)//cin -- 表示从输入流中读取信息//str 是存放读取到的信息的字符串//delim 是自定义的结束标志

这种形式的 getline 函数从输入流中读取文本,直到遇到用户指定的结束标志字符(delim)为止,然后将读取到的文本(不包括结束标志字符)存储到指定的string类型的变量str中。
实例:

#include<iostream>#include<string>usingnamespace std;intmain(){ string name;getline(cin, name,'q'); cout << name << endl;return0;}

效果

在这里插入图片描述

4、size()——字符串长度

string中提供了size()函数用于获取字符串长度。
在C++中关于字符串的操作函数都是包含在string中的,所以需要调用这些函数时,通常用.点运算符。

使用示例:

#include<iostream>#include<string>//添加string头文件usingnamespace std;intmain(){ string s; string s1 ="hello"; string s2 ="hello world"; string s3 ="12ab!~ "; cout <<"s:"<< s.size()<< endl; cout <<"s1:"<< s1.size()<< endl; cout <<"s2:"<< s2.size()<< endl; cout <<"s3:"<< s3.size()<< endl;return0;}

效果

在这里插入图片描述

5、迭代器(iterator)

迭代器是⼀种对象,它可以用来遍历容器(比如我们现在学习的 string )中的元素,迭代器的作用类似于指针,或者数组下标。

❗ 不过访问迭代器指向的值,需要解引用(*)。

C++ 中的 string 提供了多种迭代器,用于遍历和操作字符串中的内容。这里给大家介绍⼀种最常用的迭代器。

begin()和end()

  • begin():返回指向字符串第一个字符的迭代器,需要一个迭代器的变量来接收。
  • end():返回指向字符串最后一个字符的下一个位置的迭代器(该位置不属于字符串)。
  • string中begin()和end()返回的迭代器的类型是string::iterator(也可以用auto来接收)。
在这里插入图片描述
(1)比较
✅注意迭代器是可以进行大小比较,也可以进行+或者-整数运算的。
比如:i++,就是让迭代器前进一步,i-- 就是让迭代器退后一步。同一个容器的两个迭代器也可以相减,相减结果的绝对值,是两个迭代器中间元素的个数。

代码:

#include<iostream>#include<string>usingnamespace std;intmain(){ string s ="abcdef"; string::iterator it1 = s.begin(); string::iterator it2 = s.end(); cout <<(it1 < it2)<< endl; cout << it1 - it2 << endl;return0;}

结果

在这里插入图片描述
(2)遍历

迭代器通常用于遍历字符串的,可以正序遍历,也可以逆序遍历
正序遍历如下

#include<iostream>#include<string>usingnamespace std;intmain(){ string s ="abcdef";//auto it 是让编译器自动推到it的类型for(auto it = s.begin(); it != s.end();++it){ cout <<*it <<' ';}//string::iterator 是正向迭代器类型//string::iterator it, 是直接创建迭代器,it是针对字符串的迭代器for(string::iterator it = s.begin(); it != s.end();++it){ cout <<*it <<' ';}return0;}
改变指定字符

通过迭代器找到元素后,改变迭代器指向的元素,是可以直接改变字符串内容的。

#include<iostream>#include<string>usingnamespace std;intmain(){ string str ="abcdef"; cout << str << endl;for(string::iterator it = str.begin(); it != str.end();++it){*it ='x';} cout << str << endl;return0;}

效果如下

在这里插入图片描述

6、字符串的插入和删除

(1)插入

push_back()——尾插

push_back()用于在字符串尾部插一个字符。

在这里插入图片描述


具体实现如下

#include<iostream>#include<string>//添加string头文件usingnamespace std;intmain(){//向空字符串中尾插字符 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;for(char c ='a'; c <='f'; c++){ s2.push_back(c);} cout << s2 << endl;return0;}

效果

在这里插入图片描述
字符串的+=和+运算

push_back()用于在字符串后添加单个字符,若需向字符串后追加字符串,string类型支持++=运算,本质是string中重载了operator+=操作符。
效果图片展示

在这里插入图片描述


代码举例

#include<iostream>#include<string>//添加string头文件usingnamespace std;intmain(){ string s ="hello"; s +=" world";//字符串用双引号,等价于 s = s + " world" cout << s << endl;//除了+=操作,也可以使用'+'灵活进行字符串拼接//头部拼接 string s2 ="hello"; s2 ="world "+ s2 ; cout << s2 << endl;//s2为: "world hello"return0;}

效果如下

在这里插入图片描述
insert——指定位置进行插入

如果我们需要在字符串中间的某个位置插入一个字符串,怎么办呢?这时候我们得掌握一个函数就是insert

string&insert(size_t pos,const string& str);//pos位置前面插入一个string字符串 string&insert(size_t pos,constchar* s);//pos位置前面插入一个C风格的字符串 string&insert(size_t pos, size_t n,char c);//pos位置前面插入n个字符c

pos就是字符串下标
流程如下

在这里插入图片描述


代码功能实现:

#include<iostream>#include<string>usingnamespace std;intmain(){ string s ="abcdefghi"; string base = s;// 保存原始字符串,用于还原// 方式1:插入string类型字符串 cout <<"原始字符串:"<< s << endl; string str ="xxx"; s.insert(3, str); cout <<"方式1-插入string字符串:"<< s << endl; s = base;// 还原原始字符串// 方式2:插入C风格字符串 s.insert(3,"xxx"); cout <<"方式2-插入C风格字符串:"<< s << endl; s = base;// 还原原始字符串// 方式3:插入n个指定字符 s.insert(3,3,'x'); cout <<"方式3-插入3个字符x:"<< s << endl;return0;}

(2)删除——pop_back()

pop_back() 用于删除字符串中尾部的一个字符。

在这里插入图片描述


实现

#include<iostream>#include<string>usingnamespace std;intmain(){ string s ="hello"; cout <<"s:"<< s << endl;//尾删 s.pop_back(); cout <<"s:"<< s << endl;//尾删 s.pop_back(); cout <<"s:"<< s << endl;return0;}

效果

在这里插入图片描述
注意:不可对空字符串继续进⾏pop_back()操作,否则程序出现异常

7、字符串的查找和截取

(1)查找——find()

find()函数用于查找字符串中指定子串/字符,并返回子串/字符在字符串中第一次出现的位置。

在这里插入图片描述
find类型
// 查找string类型的字符串str,默认是从头开始查找,pos可以指定位置开始 size_t find(const string& str, size_t pos =0)const;// 查找C风格的字符串s,默认是从头开始查找,pos可以指定位置开始 size_t find(constchar* s, size_t pos =0)const;// 在字符串的pos这个位置开始查找C风格的字符串s中的前n个字符 size_t find(constchar* s, size_t pos, size_t n)const;// 查找字符c,默认是从头开始,pos可以指定位置开始 size_t find(char c, size_t pos =0)const;
返回值
  • 若找到,返回子串/字符在字符串中第一次出现的起始下标位置。
  • 若未找到,返回一个整数值npos(针对npos的介绍会在下面给出)。通常判断find()函数的返回值是否等于npos就能知道是否查找到子串或者字符。
不同类型find例子

代码例子
代码1——查找【字符串 / 子串】

//代码1#include<iostream>#include<string>//添加string头文件usingnamespace std;intmain(){ 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这个指定位置开始查找 cout << n << endl;//查找C风格的字符串 n = s.find("llo"); cout << n << endl; n = s.find("llo", n +1);//从n+1这个指定位置开始查找 cout << n << endl;return0;}

代码2——精准查找【C 风格字符串的前 N 个字符】

//代码2#include<iostream>#include<string>//添加string头文件usingnamespace std;intmain(){ string s ="hello world hello everyone";//在s中,0这个指定位置开始查找"word"中的前3个字符 size_t n = s.find("word",0,3); cout << n << endl; n = s.find("everyday", n+1,5); cout << n << endl;return0;}

代码3——查找【单个字符】

//代码3#include<iostream>#include<string>//添加string头文件usingnamespace std;intmain(){ string s ="hello world hello everyone"; size_t n = s.find('o'); cout << n << endl; n = s.find('o', n +1); cout << n << endl;return0;}

查找不到的情况
在字符串中查找字符或者字符串时,若查找不到,find函数会返回npos这个值;该值并非随机数字,而是string中定义的一个静态常量。我们通常会通过判断find函数的返回值是否等于npos,来确定查找是否成功。

//查找不到的情况#include<iostream>#include<string>//添加string头文件usingnamespace std;intmain(){ string s ="hello world hello everyone"; string str ="bit"; size_t n = s.find(str); cout << n << endl;if(n != string::npos) cout <<"找到了,位置是:"<< n << endl;else cout <<"没有找到"<< endl;return0;}

(2)截取——substr()

函数参数

substr()函数用于截取字符串中指定位置指定长度的子串。函数原型如下:

string substr(size_t pos =0, size_t len = npos)const;//pos 的默认值是0,也就是从下标为0的位置开始截取//len 的默认值是npos,意思是一直截取到字符串的末尾

substr()的用法:

  • substr():如果函数不传参数,就是从下标为0的位置开始截取,直到结尾,得到的是整个字符串;
  • substr(pos):从指定下标pos位置开始截取子串,直到结尾;
  • substr(pos, len):从指定下标pos位置开始截取长度为len的子串。
两种方式效果
在这里插入图片描述
在这里插入图片描述
返回值

返回值类型:string,返回的是截取到的字符串,可以使用string类型的字符串接收。

代码举例
#include<iostream>#include<string>//添加string头文件usingnamespace std;intmain(){ string s ="hello world hello everyone"; string s1 = s.substr(7); cout << s1 << endl; string s2 = s.substr(7,6); cout << s2 << endl;return0;}

效果

在这里插入图片描述

(3)find()和substr()结合

substr()和find()经常是配合使用的,find负责找到位置,substr从这个位置向后获得字符串。

代码举例

#include<iostream>#include<string>//添加string头文件usingnamespace std;intmain(){ string s ="hello world hello everyone"; size_t n = s.find("world"); string s2 = s.substr(n,10); cout << s2 << endl;return0;}

效果

8、string的关系运算

string支持字符串比较,和strcmp比较规则一致,可以直接进行字符串比较,比如>,=,<等等,只不过返回类型为bool类型
这里仅简单展示

#include<iostream>#include<string>usingnamespace std;intmain(){ 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;return0;}

效果

在这里插入图片描述

9、string中字符串与基本数值类型的转换工具函数

(1)stoi/stol

  • stoi:将字符串转换为int类型的值
  • stol:将字符串转换为long int类型的值
    两者用法类似,以stoi为例讲解:stoi可将string类型的字符串转化为整型,函数原型如下:
函数参数
intstoi(const string& str, size_t* idx =0,int base =10);longstol(const string& str, size_t* idx =0,int base =10);
  • str:被转换的string类型字符串
  • idx:输出型参数(指针类型)。需在外创建size_t类型变量,传递其地址给idx;该参数会带回str无法匹配数字的第一个字符的位置
  • base:被解析字符串的进制值(支持2、8、10、16、0):
    • 默认值为10,表示解析10进制数字;
    • 传2:解析2进制数字,最终转为10进制;
    • 传8:解析8进制数字,最终转为10进制;
    • 传16:解析16进制数字,最终转为10进制;
    • 传0:自动推导进制(含0x则为16进制,0开头则为8进制),最终转为10进制。
代码举例
#include<iostream>#include<string>usingnamespace std;intmain(){ 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;return0;}

效果如下:

在这里插入图片描述

(2)stod/stof

stod是将字符串转换成double类型的值,就是参数少了进制的描述
参数

doublestod(const string& str, size_t* idx =0);floatstof(const string& str, size_t* idx =0);

代码示例

#include<iostream>#include<string>usingnamespace std;intmain(){ string s ="3.14x456";double ret =stod(s,NULL); cout << ret << endl;return0;}

(3)to_string

就是将数字转换为字符串

string to_string(数字类型 val);

代码举例

#include<iostream>#include<string>usingnamespace std;intmain(){ string pi ="pi is "+to_string(3.14159); cout << pi << endl;return0;}

结束语

嗨!本篇到这里就结束啦!今天我们了解了string的使用,在日常字符串处理中string十分常用,比如gline,字符串的+=和+运算,关系运算等等都是十分1常用且重要的,而今天还是2026的第一天,祝大家新年快乐!元旦快乐!٩(๑❛ᴗ❛๑)۶
我们下一篇讲解C++的输入输出(下),感谢大家的支持啦!让我们下篇再见!

在这里插入图片描述

Read more

从2025看2026前端发展趋势

🎨 从2025看2026前端发展趋势 一、📌 核心前言(2025铺垫→2026展望) 2025年前端行业已完成“基础成熟化”:Vue3、React18成为主流,TypeScript全面普及,工程化流程趋于完善,AI工具开始渗透开发环节,但也暴露了痛点——开发效率不均衡、跨端体验不一致、AI与业务结合浅显、性能优化门槛高。 ✨ 核心趋势:2026年前端将从「基础成熟」走向「深度融合」,重点围绕「AI原生开发」「跨端统一」「性能极致」「工程化提效」四大方向突破,同时Node.js等底层工具的升级(如2026年Node.js新特性)将进一步推动前端向全栈化、平台化转型。 二、✍️ 五大核心趋势(手绘重点·结合2025现状) 1. AI原生开发:从“辅助工具”到“核心生产力” 🤖(最重磅) (1)2025现状 2025年,前端AI工具多为“辅助层面”

By Ne0inhk

Xilinx用户必看!复旦微FMQL45T900与ZYNQ7045对比测评:性能差异与迁移指南

复旦微FMQL45T900深度实战:从Xilinx ZYNQ迁移的硬核指南与性能真相 如果你正在使用Xilinx ZYNQ系列,尤其是ZYNQ7045这个级别的器件,最近可能被供应链、成本或者某些不可控的外部因素搞得有点头疼。我身边不少做工业控制、通信处理和边缘计算的朋友,都在私下里讨论同一个话题:有没有一条靠谱的“备胎”路线?国产化的FMQL45T900频繁被提及,但它到底行不行?直接替换ZYNQ7045会不会掉进坑里?这篇文章,我想从一个实际项目迁移者的角度,抛开那些官方的参数对比,聊聊我们团队在真实项目中踩过的雷、趟过的河,以及最终拿到的性能数据。这不是一篇简单的参数罗列,而是一份聚焦于“如何安全落地”的实战迁移指南。 1. 架构透视:不仅仅是“ARM+FPGA”的简单对标 第一次拿到FMQL45T900的芯片手册时,我的第一反应是:这看起来和ZYNQ的PS+PL架构太像了。但深入下去,你会发现“形似而神不同”,这些差异恰恰是迁移成败的关键。 1.1 PS端:四核Cortex-A7的实战能力剖析 FMQL45T900的PS(处理系统)搭载了四核ARM Cortex-A

By Ne0inhk
圣塔克拉拉大学打造“算法育种师“:AI自动发现信息检索新方法

圣塔克拉拉大学打造“算法育种师“:AI自动发现信息检索新方法

圣塔克拉拉大学、沃尔玛全球技术公司等机构的研究团队于2026年2月18日发表了一项突破性研究,论文编号为arXiv:2602.16932v1,展示了如何让大语言模型像生物育种师一样,自动培育出更强大的信息检索算法。有兴趣深入了解的读者可以通过该编号查询完整论文。 当你在搜索引擎中输入关键词寻找信息时,背后有一套复杂的算法在决定哪些网页最适合你。这些算法就像图书管理员,需要从海量信息中挑选出最相关的内容。几十年来,这些"管理员"的工作方式主要依靠人类专家的经验和直觉来改进,就好比一代代图书管理员根据经验传授整理图书的技巧。 然而,这种依赖人工经验的方式存在明显局限。正如一个图书管理员再聪明,也很难同时掌握所有可能的图书分类方法一样,人类专家很难探索所有可能的算法改进方向。研究团队因此提出了一个大胆的想法:能否让AI像生物学家培育新品种一样,自动培育出更优秀的检索算法? 这项研究的核心成果是一个名为RankEvolve的系统。这个系统基于进化算法的原理,让候选算法像生物体一样进行"繁殖"和"进化"。研究团队从两个经典的检索算法开始,就像从两个优良品种开始育种一样,然后让大语言模型充

By Ne0inhk
算法笔记-【回溯】

算法笔记-【回溯】

十 回溯 1 回溯方法 回溯法也可以叫做回溯搜索法,它是一种搜索的方式。回溯是递归的副产品,只要有递归就会有回溯。 1.1 应对问题 回溯法,一般可以解决如下几种问题: * 组合问题:N个数里面按一定规则找出k个数的集合 * 切割问题:一个字符串按一定规则有几种切割方式 * 子集问题:一个N个数的集合里有多少符合条件的子集 * 排列问题:N个数按一定规则全排列,有几种排列方式 * 棋盘问题:N皇后,解数独等等 记住组合无序,排列有序,就可以了。 1.2 理解回溯 回溯法解决的问题都可以抽象为树形结构,是的,我指的是所有回溯法的问题都可以抽象为树形结构! 因为回溯法解决的都是在集合中递归查找子集,集合的大小就构成了树的宽度,递归的深度就构成了树的深度。 递归就要有终止条件,所以必然是一棵高度有限的树(N叉树)。 1.3 模板 在上面我们提到了,回溯法一般是在集合中递归搜索,集合的大小构成了树的宽度,递归的深度构成的树的深度。 如图: 注意图中,我特意举例集合大小和孩子的数量是相等的!

By Ne0inhk