当前位置: 首页 > article >正文

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

目录

一、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 world

string 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.kler.cn/a/585124.html

相关文章:

  • 【VSCODE 插件 可视化】:SVG 编辑插件 SVG Editor
  • 如何通过折扣话费接口来吸引用户?
  • CTF--Web安全--SQL注入之报错注入
  • 事件总线EventBus原理剖析
  • TCP/IP 协议精讲-精华总结版本
  • 内网穿透的应用-全流程解析如何通过VNC实现Windows与MacOS远程桌面的无缝连接
  • Windows11使用CMD命令行从零开始创建一个Flask项目并使用虚拟环境
  • 工作效率提升的原因
  • 发票实现批量真伪查验的快速途径-发票真伪查验接口-发票识别
  • 视觉定位项目中可以任意修改拍照点位吗?
  • b站视频下载工具软件怎么下载
  • 网络安全防护总体架构 网络安全防护工作机制
  • 使用Fluent-bit将容器标准输入和输出的日志发送到Kafka
  • 大型语言模型与强化学习的融合:迈向通用人工智能的新范式
  • php-fpm.log文件过大导致磁盘空间跑满及php-fpm无法重启问题处理
  • Spark;scp命令,rsync命令,ssh命令
  • Nginx + Keepalived 高可用集群
  • 奇墨科技FinOps云成本优化:精细化IT成本分摊重塑企业云财务管理
  • 前端UI编程基础知识:Flex弹性布局
  • 全面的 .NET 操作 SQLite 入门实战(包含选型、开发、发布、部署)!