文章目录
前言
在 C++ 编程中,string 类是处理文本数据的核心工具,凭借动态扩容机制与丰富接口,成为日常开发中高频使用的基础组件。从力扣算法题里数字字符串的逐位相加,到实际项目中文本的解析与格式化,string
类的灵活应用直接影响代码效率与可读性。无论是reserve
与resize
的扩容策略差异,还是find
系列接口的精准检索技巧,亦或是字符串与数字的双向类型转换,掌握这些实用知识能让你在文本处理场景中事半功倍。
本章节将围绕 string
类的核心接口展开详解,结合经典例题与性能优化实践,带你系统掌握从基础操作到高级应用的全流程技巧。无论你是初涉 C++ 的新手,还是希望提升字符串处理能力的开发者,这里都将成为你高效驾驭 string
类的起点,为深入 STL 编程与复杂文本场景开发奠定基础。
初步认识STL
STL的底层实现必须要会(面试时会考)
阅读STL源代码的话,最好选择SGI版本的
STL有六个组成部分:仿函数,算法,迭代器,空间配置器,容器,配接器
容器的本身是类
虽然有了这些,但是C语言里面的知识也不能忘,因为面试时会被问到
容器不一定都有反向迭代器
string
使用string类时,必须包含#include头文件(这里的头文件是string)及using namespace std(或者eg:std::string这样搞)
但是string不属于STL,但是和STL很接近
注意点:1.如果直接打印一个 char 类型的 \0,cout 会将其视为不可见字符(无输出),但不会终止打印。
和vector的区别:1.string自带\0
2.string有很多专属的接口,比如:+
常见接口
不常见的要用时到时候查就行 这下面介绍的都是成员函数
以下说的最后一个地方不是指
\0
哈
string类对象的常见构造
c++
string() -- 构造空的string类对象,也就是空字符串
string(const char*s) -- 用C语言风格的字符串(""的那种)构造string类对象
比如: string s1("hello");
string(size_t n,char c) -- 构造出的string类对象中包含n个字符c
string(const string&s) -- 也就是调用拷贝构造函数
引申注意:不加其他操作的话,字符串的类型是const char*或者char[]
单个字符的类型是char
注意:string不能隐式类型转换成字符串,字符串可以隐式类型转换成string
string类对象的容量操作
size--返回字符串有效字符长度 --像这种不可能是负数的东西,库里面一般搞成size_t类型的
c++注意点:长度为1时,s1.size()/2-1就会那啥 string不看\0,以size为终止算长度
length--返回字符串有效字符长度(和size没有区别)
c++s1.size(); s1.length(); 要注意的是,他们都不会算上'\0',但是string里面是有'\0'的 s1[s1.size()]下面正好存的是\0 要注意的是:s1.size()和sizeof(s1)区分 sizeof(s1)那个是内存对齐那个算对象一共占用的空间
capacity--返回空间总大小(没有算上
\0
)
c++用法:s1.capacity();
empty--检测字符串释放为空串,是空返回true,否则返回false
c++用法: if(s1.empty())
clear--清空有效字符,但是不会释放空间(size变为0,capacity不会变)
c++s1.clear();
reserve--为字符串预留空间(避免编译器频繁扩容浪费时间)
resize--将有效字符的个数改成n个,多出的空间用字符c填充(无c就用的0)
c++用法:void reserve (size_t n = 0); void resize (size_t n);或者void resize (size_t n, char c); 注意:reserve和reverse要区分 reserve和resize还有区别就是:resize一定会改变size()的结果,reserve不会 引申:具体扩容多少要看编译器(但是很少能原地扩容),不是reserve和resize里面写多少就多少的 缩容的话本质上是时间换空间(系统是不支持分段缩容的),一般编译器不会去缩容; 目前指知道clear之后再用reserve或resize可以缩容(capacity就会变了)
string类对象的访问及遍历操作
operator[pos] -- 返回pos位置的字符(第一个位置是[0])
begin--获取第一个字符的迭代器 end--获取最后一个字符的下一个位置的迭代器
rbegin--获取最后一个字符的迭代器 rend-获取第一个字符的上一个位置的迭代器(这里的迭代器其实是反向迭代器)
c++rbegin和rend的迭代器的方向是反着的,比如:it是迭代器,it++就向前走了一个位置 引申:迭代器的类型很长,一般都是用的auto解决(迭代器是一种类型,类似指针;也可以*) 迭代器的类型有很多种:比如: const_iterator iterator 不是const的话,可以通过迭代器修改字符
范围for
string类对象的修改操作
push_back--在字符串末尾插入字符c
append--在字符串末尾插入一个字符串
operator+=--在字符串末尾追加一个字符串(一般用的这个)
c_str--返回C风格的字符串(有时要用c语言函数,而那些函数识别不了string类型)
c++用法: s1.c_str();
find--从字符串pos位置(含这里)开始往后找字符串,返回字符串第一个字符在字符串中的位置(返回的是第一次匹配时的)
rfind--从字符串pos位置(含这里)开始往前找字符串,返回字符串第一个字符在字符串中的位置(返回的是最后一次匹配时的)
c++这俩个如果一直没能匹配到的话会返回npos(也就是size_t类型的-1) 注意:迭代器和npos前面要加上域名 比如:string::iterator和string::npos才行
find_first_of--在字符串中从左到右搜索,返回第一个出现在指定字符集合中的字符的位置
find_last_of--从右到左搜索,返回第一个出现在指定字符集合中的字符的位置
c++找不到的话都是返回npos
substr--在str中从pos位置开始,截取n个字符,然后将其返回
c++string substr (size_t pos = 0, size_t len = npos) const; 用法: string str3 = str1.substr (pos);
要注意的是:虽然string里面可以存中文,但是中文++的结果可能跟自己想的不一样,而且两个中文不一定只占string[]里面的0和1两个位置,可能会占更多位置
string类非成员函数
operator+ --尽量少用,因为传值返回,导致深拷贝效率低
operator>> --输入运算符重载
operator<< --输出运算符重载
getline --获取一行字符串(解决cin遇到空格不行的场景,getline默认是遇到换行符停止)
relational operators --大小比较(也是用字典序去比较的)
包含在string头文件下的好用函数
stoi-把数字字符串转换成int类型的
stod-把数字字符串转换成double类型的
to_string-把整数和浮点数转换成字符串
作业部分
c++
力扣 字符串相加
主要问题:就是把数字和字符串混一起搞了(没去分辨哪个是数字,哪个是字符导致的问题)
数字转字符要eg:to_string
字符转数字要eg:a-'0'
混一起搞就会出现输出是eg:\u这些
c++
代码展示:
class Solution {
public:
string addStrings(string num1, string num2) {
string num3;
//让num1是最大的那个
if(num1.size()<num2.size()||(num1.size()==num2.size()&&num2>num1))
swap(num1,num2);
int ret = 0;
int partsum = 0;
int gap = num1.size()-num2.size();
for(int i = num2.size()-1;i>=0;i--)
{
partsum = num2[i]+num1[i+gap]+ret-'0'-'0';
ret = partsum/10;
partsum%=10;
num3+=to_string(partsum);//最后要反转一下
}
//num1还有gap个数没搞
for(int i = gap-1;i>=0;i--)
{
partsum = num1[i]+ret-'0';
ret = partsum/10;
partsum%=10;
num3+=to_string(partsum);//最后要反转一下
}
if(ret==1) num3+=to_string(ret);
reverse(num3.begin(),num3.end());
return num3;
}
};

c++
HJ1 字符串最后一个单词的长度
注意点:像这种有空格的要读取时,不能用cin,要eg:getline(cin,s1);
还有eg:for(int i = 0;i<n;i++);
for(int i = 0;i<n;i++){}
//前两个是一个意思
for(int i = 0;i<n;i++)
//这个是后面紧跟for或者while的话形成嵌套循环
还有,注意是2*k不是2k!
c++
代码展示:
#include <iostream>
#include<string>
using namespace std;
int main()
{
string s1;
getline(cin,s1);
int count = 0;
auto i = s1.end()-1;
for(;*i==' ';i--);
for(;*i!=' ';i--)
{
count++;
if(i == s1.begin()) break;
}
cout<<count<<endl;
return 0;
}
