【C++标准库类型】深入理解string类型:从基础到实践

news/2025/3/15 12:11:31/

目录

一、string类型的基本概念

1.1. 定义与头文件

1.2. 本质与特点

1.3. 与 C 风格字符串的区别

二、string类型的构造函数

2.1. 默认构造函数

2.2. 使用C风格字符串初始化

2.3. 拷贝构造函数

2.4. 使用字符和重复次数初始化

2.5. 使用子串初始化

三、string类型的赋值操作

3.1 使用赋值运算符=

3.2 使用assign成员函数

四、string类型的容量操作

五、string类型的元素访问

5.1 使用下标运算符[]

5.2 使用at成员函数

六、string类型的迭代遍历

七、string类型的字符串操作

八、字符串输入输出处理

九、内存管理与性能优化

9.1 容量管理

9.2 避免不必要的拷贝

十、字符串与数值的转换

十一、C++11 及后续版本的新特性

十二、string 类型在实际应用中的示例

十三、 参考资料


在C++编程中,string类型是一个非常重要的标准库类型,用于处理可变长度的字符序列。相比C语言中的字符数组(以\0结尾的字符串),std::string提供了更高效、更安全的字符串操作方法。

一、string类型的基本概念

1.1. 定义与头文件

std::string是C++标准库中的一个类,定义在<string>头文件中。要使用std::string,需要在程序开头包含该头文件:

include <string>

为了简化代码,通常使用std命名空间:

using namespace std;

1.2. 本质与特点

  • std::string本质std::string本质上是一个模板类 basic_string 的 typedef,即 typedef basic_string<char> string;内部封装了char*指针,通过容器的方式管理字符串。
  • 动态增长和缩小:支持动态增长和缩小,无需关心字符串的长度或容量。

1.3. 与 C 风格字符串的区别

  • 自动内存管理string 自动处理内存分配和释放,无需手动管理。

  • 安全性:避免缓冲区溢出(如 strcpy 的潜在风险)。

  • 功能丰富:支持拼接、查找、替换等操作,无需调用低级函数。

二、string类型的构造函数

std::string提供了多种构造函数,用于初始化字符串对象。以下是一些常用的构造函数。

2.1. 默认构造函数

创建一个空的字符串对象:

string str1;  // str1是一个空字符串

2.2. 使用C风格字符串初始化

使用C风格字符串(以\0结尾的字符数组)初始化std::string对象。

const char* cstr = "hello";
string str2(cstr);  // str2是"hello"的副本

2.3. 拷贝构造函数

使用另一个std::string对象初始化新的字符串对象。

string str3(str2);  // str3是str2的副本

2.4. 使用字符和重复次数初始化

使用指定的字符和重复次数初始化字符串。

string str4(5, 'x');  // str4是"xxxxx"

2.5. 使用子串初始化

从已有的字符串中提取子串,用于初始化新的字符串对象。

string str5(str4, 1, 3);  // str5是str4从索引1开始的3个字符,即"xxx"

三、string类型的赋值操作

std::string支持多种赋值方式,可以将一个字符串的值赋给另一个字符串对象。

3.1 使用赋值运算符=

可以将C风格字符串、std::string对象或单个字符赋值给std::string对象:

string str1;
str1 = "hello";  // 将C风格字符串赋值给str1
string str2 = str1;  // 将str1赋值给str2
string str3;
str3 = 'a';  // 将字符'a'赋值给str3,注意这里str3会变成"a"

3.2 使用assign成员函数

assign成员函数提供了更多的赋值方式,可以指定赋值的起始位置和长度:

使用assign成员函数
assign成员函数提供了更多的赋值方式,可以指定赋值的起始位置和长度:

四、string类型的容量操作

std::string提供了多个成员函数,用于获取或修改字符串的容量。

①获取字符串的长度:使用sizelength成员函数获取字符串中字符的个数(不包括结束符\0

string str = "hello";
size_t len = str.size();  // len是5

②判断字符串是否为空:使用empty成员函数判断字符串是否为空。

if (str.empty()) {cout << "字符串为空" << endl;
} else {cout << "字符串不为空" << endl;
}

③修改字符串的容量

  • 使用reserve成员函数为字符串预留空间,不改变当前内容:

str.reserve(100);  // 为str预留至少100个字符的空间
  • 使用resize成员函数改变字符串的大小,可以指定填充字符:
str.resize(10, '*');  // 将str的大小改为10,不足部分用'*'填充
  • 使用clear成员函数清空字符串的内容,但不改变容量:
str.clear();  // str变为空字符串,但容量不变

五、string类型的元素访问

可以通过多种方式访问std::string中的字符。

5.1 使用下标运算符[]

通过下标运算符访问字符串中的单个字符,下标从0开始:

string str = "hello";
char ch = str[1];  // ch是'e'

注意:使用下标运算符访问字符时,不会进行越界检查,需要确保下标在有效范围内。

5.2 使用at成员函数

at成员函数提供了安全的字符访问方式,会进行越界检查:

char ch = str.at(1);  // ch是'e',如果索引超出范围,会抛出std::out_of_range异常

六、string类型的迭代遍历

可以使用迭代器或范围for循环遍历std::string中的字符。

①使用迭代器:std::string提供了beginend成员函数,返回指向字符串开头和结尾的迭代器

string str = "hello";
for (string::iterator it = str.begin(); it != str.end(); ++it) {cout << *it << " ";
}
// 输出:h e l l o

②使用范围for循环:范围for循环提供了一种更简洁的遍历方式

for (char ch : str) {cout << ch << " ";
}
// 输出:h e l l o

七、string类型的字符串操作

std::string提供了丰富的成员函数,用于执行各种字符串操作。

①字符串连接:使用+运算符或append成员函数连接字符串

string str1 = "hello";
string str2 = "world";
string result = str1 + " " + str2;  // 使用+运算符连接
cout << result << endl;  // 输出:hello worldstring str3 = "hello";
str3.append(" ");
str3.append(str2);  // 使用append成员函数连接
cout << str3 << endl;  // 输出:hello world

②字符串比较:可以使用关系运算符(==!=<<=>>=)或compare成员函数比较字符串

if (str1 == str2) {cout << "str1等于str2" << endl;
} else {cout << "str1不等于str2" << endl;
}int cmp = str1.compare(str2);
if (cmp == 0) {cout << "str1等于str2" << endl;
} else if (cmp < 0) {cout << "str1小于str2" << endl;
} else {cout << "str1大于str2" << endl;
}

③查找子串:使用findrfind成员函数查找子串的位置

size_t pos = str.find("world");
if (pos != string::npos) {cout << "找到子串,位置为:" << pos << endl;
} else {cout << "未找到子串" << endl;
}size_t rpos = str.rfind("o");
cout << "最后一个'o'的位置为:" << rpos << endl;

④替换子串:使用replace成员函数替换字符串中的子串

string str =

八、字符串输入输出处理

①读取整行输入:使用 getline() 代替 cin >> 以避免空格截断

string line;
getline(cin, line);  // 读取一行输入(包括空格)

②格式化处理:结合 stringstream 进行字符串分割或转换

string data = "10 3.14 hello";
stringstream ss(data);
int num; double d; string s;
ss >> num >> d >> s;  // 解析为 num=10, d=3.14, s="hello"

九、内存管理与性能优化

9.1 容量管理

  • capacity():返回当前分配的存储容量。

  • reserve(n):预分配至少 n 个字符的内存,减少动态分配次数。

  • shrink_to_fit():请求减少容量以匹配实际大小(C++11)。

9.2 避免不必要的拷贝

  • 使用移动语义(C++11)提升性能:

string s1 = "Hello";
string s2 = std::move(s1);  // s1 变为空,s2 接管资源
  • 传递 const string& 避免拷贝。

十、字符串与数值的转换

字符串 → 数值

string s = "123";
int num = stoi(s);         // 转换为 int
double d = stod("3.14");  // 转换为 double

数值 → 字符串

string s1 = to_string(42);      // "42"
string s2 = to_string(3.1415); // "3.1415"

十一、C++11 及后续版本的新特性

字面量后缀

using namespace std::string_literals;
auto s = "Hello"s;  // 直接生成 string 类型(而非 const char*)

范围 for 循环

for (char c : s) {cout << c << " ";
}

十二、string 类型在实际应用中的示例

文件读取与处理:在处理文本文件时,string 类型非常有用。例如,从文件中逐行读取内容并进行处理:

#include <iostream>
#include <fstream>
#include <string>
int main() {std::ifstream file("test.txt");if (file.is_open()) {std::string line;while (std::getline(file, line)) {// 对每一行进行处理std::cout << line << std::endl;}file.close();} else {std::cerr << "Unable to open file" << std::endl;}return 0;
}

字符串查找与替换:在处理字符串时,经常需要查找特定的子字符串并进行替换。string 类型提供了 find() 成员函数来查找子字符串的位置,以及 replace() 成员函数来进行替换:

std::string str = "hello world";
size_t pos = str.find("world");
if (pos != std::string::npos) {str.replace(pos, 5, "C++");std::cout << str << std::endl;  // 输出: hello C++
}

希望这篇文章能够帮助你对 string 类型有更深入的理解和掌握。如果还有其他关于 C++ 的问题,欢迎继续探索和学习。


十三、 参考资料

  • 《C++ Primer》

  • cppreference.com


http://www.ppmy.cn/news/1579308.html

相关文章

基于图神经网络(GNN)的节点分类实战:从GCN到GraphSAGE

图神经网络(GNN)是一种专门用于处理图结构数据的深度学习模型,广泛应用于社交网络分析、推荐系统和生物信息学等领域。图卷积网络(GCN)是GNN的经典方法,而GraphSAGE则通过引入采样机制进一步提升了其性能。本文将通过一个完整的实战案例,展示如何使用GCN和GraphSAGE对图…

计算机网络基础:网络安全基础

计算机网络基础&#xff1a;网络安全基础 一、前言二、网络安全的重要性2.1 保护个人隐私2.2 保障企业运营2.3 维护国家主权与安全 三、常见的网络安全威胁3.1 恶意软件3.2 网络钓鱼3.3 拒绝服务攻击&#xff08;DoS/DDoS&#xff09;3.4 漏洞攻击 四、常见的安全防护措施4.1 安…

wx131基于ssm+vue+uniapp的智能停车场管理系统小程序

开发语言&#xff1a;Java框架&#xff1a;ssmuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;M…

一文解读python的高阶功能:从闭包到装饰器的理解

文章目录 一、闭包1.1 举个栗子输出结果&#xff1a; 1.2 可以用来干啥&#xff1f;1.3 用闭包来创建函数工厂示例&#xff1a;创建函数工厂解释闭包的关键点另一个示例&#xff1a;创建计数器解释总结 1.4 用闭包来实现回调函数示例&#xff1a;使用闭包实现回调函数输出结果&…

uni-app打包h5并部署到nginx,路由模式history

uni-app打包有些坑&#xff0c;当时运行的基础路径填写了./&#xff0c;导致在二级页面刷新之后&#xff0c;页面直接空白。就只能换一个路径了&#xff0c;nginx也要跟着改&#xff0c;下面是具体步骤。 manifest.json配置web 运行路径写/h5/&#xff0c;或者写你们网站的目…

系统可观测性(5)OpenTelemetry基础使用

系统可观测性(5)OpenTelemetry基础概念 Author: Once Day Date: 2025年3月12日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 本文档翻译整理自《OpenTelemetry Docs》&a…

K8S学习之基础二十八:k8s中的configMap

k8s中的configMap ​ configMap是k8s的资源对象&#xff0c;简称cm&#xff0c;用于保存非机密性的配置&#xff0c;数据可以用key/value键值对形式保存&#xff0c;也可以通过文件形式保存 ​ 在部署服务的时候&#xff0c;每个服务都有自己的配置文件&#xff0c;如果一台服…

ELK(Elasticsearch、Logstash、Kbana)安装及Spring应用

Elasticsearch安装及Spring应用 一、引言二、基本概念1.索引&#xff08;Index&#xff09;2.类型&#xff08;Type&#xff09;3.文档&#xff08;Document&#xff09;4.分片&#xff08;Shard&#xff09;5.副本&#xff08;Replica&#xff09; 二、ELK搭建1.创建挂载的文件…