详细介绍:C++ 中string的用法
1.6.1 string类概述
string是 C++ 标准库(STL)提供的字符串处理类,封装了字符串的存储、修改、查找等功
能,相⽐传统的char[](C ⻛格字符串),具有⾃动内存管理、丰富的成员函数、类型安全等优
⽇常开发中处理字符串的⾸选⼯具。就是势,
今天围绕string核⼼⽤法展开,结合代码⽰例解析关键功能,覆盖初始化、转换、输⼊输出、容量、控制、修改、查找、⽐较等场景。
1.6.2 string的初始化与赋值
string给予多种初始化⽅式,赋值运行也⽀持不同类型的右值,灵活性⾼。
1.6.2.1初始化⽅式(4 种核⼼场景)
void func(int a, int b = 20){...}
void func(int a){...}
void main()
{
// func(10); //错误:编译器无法确定调用哪个(产生歧义)
}
字⾯量初始化
string
str1("hello");
⽤ C ⻛格字符串(const char*)初始化
拷⻉初始化(构 造)
string str2(str1);⽤另⼀个string对象拷⻉创建(调⽤拷⻉构造函数)赋值初始化
string str3 = str1;等价于拷⻉初始化,语法糖形式直接赋值字⾯量
string str4 = "world";⽤ C ⻛格字符串直接赋值初始化
1.6.2.2赋值操作
初始化后可利用= 重新赋值,⽀持两种赋值源:
注意:赋值会覆盖原字符串内容,且string会⾃动管理内存(⽆需⼿动释放旧内容)
1.6.3 string与char*的转换
C++中部分场景需要char* 类型(如 printf、C语⾔接⼝),string提供 c_str()实现转换。
// string初始化
string str;
string str2= "world"; // world
// 用另一个string对象赋值
str = str2; // world
// 用c风格字符串复制
str = "123123";
1.6.3.1核⼼⽅法:c_str()
机制:返回⼀个指向string内部字符数组的const char*指针,该数组以\0 结尾(兼容C⻛格字符串)
代码⽰例:
关键注意事项:
1. 返回值是 const char*,禁⽌强制转换为char* 后修改内容,否则会触发[未定义⾏ 为](如内存错误)。
❌ 错误⽰例:
(破坏string内部结构)。
2. 指针有效期:仅在string对象未被修改(如append/ erase )且未被销毁时有效。若string被修改,指针可能失效(内存重新分配)。
1.6.4 string的输⼊与输出
string⽀持C++标准IO流( cin/cout),但需要注意输⼊的分隔符特性。
#include <iostream>
#include <cstdio>
stringstr3("yueqian");
const char* ptr = str3.c_str();
printf("%s\n",ptr);
char* ptr = (char*)str.c_str(); ptr[0] = 'a';
1.6.4.1输出:cout << string
直接通过 cout 输出,⽆需处理\0 ,简洁直观:
1.6.4.2输⼊:cin >> string于getline
①cin >> string:默认分隔符输⼊
规则:以(空格、制表符、换⾏符)为分隔符,仅读取第⼀个分隔符前的内容。
⽰例:
②getline(cin,string):整⾏输⼊
场景:需要读取包含空格的整⾏字符串
⽰例:
注意:若 getline前使⽤过 cin >>, cin 会将换⾏符留在输⼊缓冲区,导致getline读取空串,需⽤cin.ignore()清除缓冲区。
stringstr("hello string");
cout <<str <<endl; // 输出:hello string
string str;
cin >>str; // 若输入:“hello world”, str仅存储 hello
cout <<str <<endl; // 输出:hello
string str;
cin.ignore(); // 若之前用了cin >>需清除缓冲区残留的换行符。类似于c语言中的
while(getchar() != '\n')
getline(cin, str); // 若输入:“hello world”, str存储 hello world
返回值
size()返回字符串实用字符个数(不 含'\0')str.size()
length ()与 size()完全等价(历史兼 容接⼝)
str.length()
capacity()返回当前内存可容纳的最⼤字 符数(不扩容)
str.capacity()
max_size()返回理论最⼤可容纳字符数(系统 / 编译器限制)
str.max_size()
约2^31-1(32位系统)
empty()判断是否为空(size() == 0),返回 bool
str.empty()
false
clear( )
清空有效字符(size()置0,不释放内存)
str.clear();
str.size()
1.6.5 string的容量与状态查询
string提供多个成员函数查询和控制容量,核⼼包括size()/ length()、 capacity()、 max_
size()、 empty()、 clear()。
1.6.5.1核⼼容量函数对⽐
1.6.5.2关键概念辨析【扩展】
Size vscapacity:
size :实际使⽤的字符数(⽤⼾关⼼的 “⻓度”)。
capacity:当前内存已分配的空间(避免频繁扩容),当size 超过 capacity时,
string会⾃动扩容(通常扩容为原容量的 1.5 倍或 2 倍)。
clear ()不释放内存:clear()仅将 size()设为 0, capacity()不变,若需释放内存,可结合shrink_to_fit()(C++11+):
1.6.6 string的修改操作
string提供 erase()、 replace()、 swap()等成员函数修改内容,覆盖删除、替换、交换场 景。
1.6.6.1删除字符:erase(pos, count)
能力:从索引pos (0开始)处,删除count 个字符。
代码⽰例:
重载版本:还⽀持凭借迭代器删除单个字符(如str.erase(str.begin() + 2)删除索引2的字符)
1.6.6.2替换字符:replace(pos, count, new_str)
功能:从索引pos 处,删除 count 个字符,再插⼊new_str( new_str⻓度可与 count 不同)。
stringstr("123456");
str.clear(); // size=0, capacity=6
str.shrink_to_fit(); // capacity变为 0(释放内存)
stringstr4("0123456789abcdef");
cout <<str4 <<endl;
cout <<"size = "<<str4.size() <<",capacity = "<<str4.capacity() <<
endl; // size = 16,capacity = 16
str4.erase(4,8); // 从索引4开始连续删除8个字符
cout <<str4 <<endl;
cout <<"size = "<<str4.size() <<",capacity = "<<str4.capacity() <<
endl; // size = 8,capacity = 16
1.6.6.3交换字符串:swap(s1,s2)
机制:交换两个string对象的内容,效率极⾼(仅交换内部指针和容量,不拷⻉资料)。
代码⽰例:
1.6.7 string的查找与截取
string提供 find()、 find_last_of()等查找函数,以及substr()截取⼦串,满⾜字符串检索需求。
1.6.7.1查找函数:find() 与 find_last_of()
(1)find(sub_str, pos = 0):正向查找
功能:从索引pos (默认 0)开始,查找sub_str(完整匹配)第⼀次出现的位置,返回索引;未找到返回string::npos(静态常量,表⽰⽆效位置)。
// 替换
stringstr5("0123456789abcdef");
cout <<"替换前:" <<str5 <<endl; // 替换前:0123456789abcdef
str5.replace(3,8,"HELLOWORLD"); // 替换后:012HELLOWORLDbcdef
cout <<"替换后:" <<str5 <<endl;
strings1("郭德纲");
strings2("于谦");
cout <<"交换前:" <<s1 <<"," <<s2 <<endl;
swap(s1,s2); // 第1种写法
cout <<"交换后:" <<s1 <<"," <<s2 <<endl;
s1.swap(s2); // 第2种写法
cout <<"交换后:" <<s1 <<"," <<s2 <<endl;
(2)find_last_of(sub_str):反向查找字符集
功能:查找 sub_str中任意⼀个字符最后⼀次出现的位置(⾮完整匹配,⽽是字符集匹配)。
1.6.7.2截取⼦串:substr(pos, count = string::npos)
功能:从索引pos 开始,截取 count 个字符;若 count 未指定或超过剩余字符数,截取
到字符串末尾。
代码⽰例:
// 正向查找,返回第一次出现的位置
strings3("invaid conversion from 'const char*' to 'char*'");
// 1. 从头开始开始查找from
cout <<s3.find("from") <<endl; // 找到返回第一次出现的索引,找不到返回-1
// 2. 从指定索引位置开始查找from
cout <<s3.find("from", 18) <<endl;
// 3. 判断是否找到
if (s3.find("test") != string::npos)
{
cout <<"找到 test" <<endl;
}
else
{
cout <<"未找到 test" <<endl;
}
stringstr("from 123 from 456");
cout <<str.find_last_of("from"); // 找 'f'/'r'/'o'/'m'最后出现的位置,输
出 12(第二个 "from"的 'm')
注意:若 pos 超过 size(),会抛出 out_of_range异常,需确保pos 合法。
1.6.8 string的连接与⽐较
字符串的连接和⽐较是⾼频操作,string⽀持运算符重载与成员函数两种⽅式。
1.6.8.1字符串连接
① +运算符:创建新字符串
特性:连接两个字符串,返回新的string对象(原对象不变)
代码⽰例:
缺点:会创建临时对象,频繁连接时效率较低。
②append()成员函数:原地追加
// 字符串截取
string s4= "0123456789abcdef";
// 从索引10开始,截取5个字符
string sub= s4.substr(s4.find("a"),5);
cout <<sub <<endl; // 输出:abcde
// 从索引12开始,截取到末尾
string sub2= s4.substr(12);
cout <<sub2 <<endl; // 输出:cdef
// + 字符串拼接
stringss1("西安");
stringss2("粤嵌科技");
string ss3= ss1 + ss2;
string sa= "a", sb = "b", sc = "c";
cout <<ss3 <<" " <<(ss1 + ss2) <<endl; // 输出:西安粤嵌科技 西安粤嵌科技
cout <<(sa + sb + sc) <<endl;
功能:在当前字符串末尾追加内容,直接修改原对象(⽆临时对象,效率⾼)
代码⽰例:
1.6.8.2字符串⽐较
① 运算符重载:直观简洁
⽀持 == 、 != 、 < 、 > 、 <= 、 >= ,按字典序(ASCII 码) ⽐较:
②compare()成员函数:灵活精细
功能:返回整数,0 表⽰相等, 正数 表⽰当前字符串⼤,负数 表⽰当前字符串⼩。
代码⽰例:
// append追加
strings11("0123456789abcdef");
strings12("1234");
cout <<"追加前:" <<s11 <<"的大小是:" <<s11.size() <<"," <<s12 <<"的
大小是:" <<s12.size() <<endl;
cout <<"追加前容量:" <<s11.capacity() <<endl;
s11.append(s12);
cout <<"追加后:" <<s11 <<"的大小是:" <<s11.size() <<"," <<s12 <<"的
大小是:" <<s12.size() <<endl;
cout <<"追加后容量:" <<s11.capacity() <<endl; // 容器超出后,采用二倍扩容
法
// 关系运算符比较
strings21("abc");
strings22("abc");
cout <<(s21 == s22) <<endl; // 0-不相等,1-相等
cout <<(s21 < s22) <<endl; // 0-不成立,1-成立
cout <<(s21 >= "abd") <<endl; // 0-不成立,1-成立
// compare()比较
strings31("abcdef");
strings32("abc123");
// 1. 完整比较
cout <<s31.compare(s32) <<endl; // 0-相等,大于0-大于,小于0-小于
// 2. 比较子串:s31的前3个字符 vs s32的前三个字符
cout <<s31.compare(0,3,s32,0,3) <<endl;
浙公网安备 33010602011771号