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 stringchar* 的转换

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 内部结构)。

  1. 指针有效期:仅在 string 对象未被修改(如 append / erase )且未被销毁时有效。若 string 被修改,指针可能失效(内存重新分配)。

1.6.4 string 的输⼊与输出

string⽀持C++标准IO流( cin/cout ),但需要注意输⼊的分隔符特性。

#include <iostream>

#include <cstdio>

string str3("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 >> stringgetline

cin >> string :默认分隔符输⼊

规则:以(空格、制表符、换⾏符)为分隔符,仅读取第⼀个分隔符前的内容。

⽰例:

getline(cin,string) :整⾏输⼊

场景:需要读取包含空格的整⾏字符串

⽰例:

注意:若 getline 前使⽤过 cin >> , cin 会将换⾏符留在输⼊缓冲区,导致 getline 读取空串,需⽤ cin.ignore() 清除缓冲区。

string str("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 vs capacity:

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 不同)。

string str("123456");

str.clear(); // size=0, capacity=6

str.shrink_to_fit(); // capacity 变为 0(释放内存)

string str4("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 (静态常量,表⽰⽆效位置)。

// 替换

string str5("0123456789abcdef");

cout << "替换前:" << str5 << endl; // 替换前:0123456789abcdef

str5.replace(3,8,"HELLOWORLD"); // 替换后:012HELLOWORLDbcdef

cout << "替换后:" << str5 << endl;

string s1("郭德纲");

string s2("于谦");

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 未指定或超过剩余字符数,截取

到字符串末尾。

代码⽰例:

// 正向查找,返回第一次出现的位置

string s3("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;

}

string str("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

// + 字符串拼接

string ss1("西安");

string ss2("粤嵌科技");

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追加

string s11("0123456789abcdef");

string s12("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; // 容器超出后,采用二倍扩容

// 关系运算符比较

string s21("abc");

string s22("abc");

cout << (s21 == s22) << endl; // 0-不相等,1-相等

cout << (s21 < s22) << endl; // 0-不成立,1-成立

cout << (s21 >= "abd") << endl; // 0-不成立,1-成立

// compare()比较

string s31("abcdef");

string s32("abc123");

// 1. 完整比较

cout << s31.compare(s32) << endl; // 0-相等,大于0-大于,小于0-小于

// 2. 比较子串:s31的前3个字符 vs s32的前三个字符

cout << s31.compare(0,3,s32,0,3) << endl;

相关推荐
乐悠小码3 小时前
Java设计模式精讲---02抽象工厂模式
java·设计模式·抽象工厂模式
数据的世界013 小时前
技术变革:为何C#与.NET是未来的开发方向
java·c#·.net
想搞艺术的程序员3 小时前
Go Error 全方位解析:原理、实践、扩展与封装
开发语言·后端·golang
向上的车轮3 小时前
Actix Web适合什么类型的Web应用?可以部署 Java 或 .NET 的应用程序?
java·前端·rust·.net
脸大是真的好~3 小时前
黑马JAVAWeb-03 SpringBootWeb-分层解耦-三层架构-@SpringBootApplication注解-IOC控制反转-DI依赖注入
java
微露清风3 小时前
系统性学习C++-第十讲-stack 和 quene
java·c++·学习
闲人编程3 小时前
Python游戏开发入门:Pygame实战
开发语言·python·游戏·pygame·毕设·codecapsule
一蓑烟雨任平生√3 小时前
两种上传图片的方式——91张先生
java·ossinsight
是苏浙3 小时前
零基础入门C语言之枚举和联合体
c语言·开发语言