🤖🌟 欢迎降临张有志的未来科技实验室🤖🌟
专栏:C++
👨💻👩💻 先赞后看,已成习惯👨💻👩💻
👨💻👩💻创作不易,多多支持👨💻👩💻
🚀 启动创新引擎,揭秘C++的密码🚀
引言
- 编程中字符串至关重要。无论是构建用户界面、处理数据还是网络通信,都离不开字符串操作。
- C 语言里的char数组处理字符串时,需手动管理内存,容易出现缓冲区溢出等错误,像字符串拼接、复制等常见操作,代码编写繁琐且易出错。
- C++ 的 string类则是强大的字符串处理工具。它能自动处理内存分配与释放,避免手动管理的风险。还提供大量实用成员函数,如拼接、查找、替换、比较等操作都很便捷,可有效提升开发效率,助力开发者专注核心业务逻辑,在 C++ 编程里处理字符串极为得力。
💡目录
[一、string 类基础](#一、string 类基础)
[string 类对象的创建及初始化](#string 类对象的创建及初始化)
[二、string 类基本操作](#二、string 类基本操作)
[(四) 探讨拼接时的内存管理与性能优化( reserve( ) 方法的应用)](#(四) 探讨拼接时的内存管理与性能优化( reserve( ) 方法的应用))
[1.==、>、<、!= 等运算符在 string 类中的应用](#1.==、>、<、!= 等运算符在 string 类中的应用)
[2. compare() 方法的深入讲解,包括返回值含义与多参数用法](#2. compare() 方法的深入讲解,包括返回值含义与多参数用法)
一、string 类基础
C++ 标准库(Standard Template Library, STL)是 C++ 的核心组成部分之一,提供了丰富的数据结构和算法。
<string> 是 C++ 标准库中用于处理字符串的头文件。
在 C++ 中,字符串是由字符组成的序列。**<string>**头文件提供了 std::string 类,它是对 C 风格字符串的封装,提供了更安全、更易用的字符串操作功能。
想要使用string类,需包含头文件string与iostream:
cpp
#include<iostream>
#include<string>
string 类对象的创建及初始化
1. 直接赋值初始化
cpp
#include<iostream>
#include<string>
int main(){
std::string str1 = "Hello, World!";
std::cout << str1 << std::endl;
return 0;
}
2.默认构造函数
cpp
#include <iostream>
#include <string>
int main() {
std::string str2;
std::cout << "str2的长度为: " << str2.length() << std::endl;
return 0;
}
3.指定长度初始化
cpp
#include <iostream>
#include <string>
int main() {
std::string str4(10, 'a');
std::cout << str4 << std::endl;
return 0;
}
二、string 类基本操作
(一)字符串访问
1.下标访问
cpp
#include <iostream>
#include <string>
int main() {
std::string str = "Hello";
char firstChar = str[0]; // 获取字符串的第一个字符 'H'
std::cout << "第一个字符: " << firstChar << std::endl;
// 也可以修改单个字符
str[0] = 'J';
std::cout << "修改后的字符串: " << str << std::endl;
return 0;
}
2.迭代器遍历
cpp
#include <iostream>
#include <string>
int main() {
std::string str = "World";
std::string::iterator it;
for (it = str.begin(); it!= str.end(); ++it) {
std::cout << *it;
}
std::cout << std::endl;
return 0;
}
- string类提供了 begin() 和 end() 函数分别返回指向字符串开头和结尾(不包含最后一个字符)的迭代器
- 可以使用常量迭代器const_iterator来遍历不可修改的字符串,以增强程序的安全性和规范性。
(二)字符串长度获取
1. length() 与 size() 方法的使用及区别
string类中的 length() 和 size()方法在功能上基本相同,都用于获取字符串中字符的数量,并返回 size_t 类型。
cpp
#include <iostream>
#include <string>
int main() {
std::string str = "Test String";
std::cout << "字符串长度(length): " << str.length() << std::endl;
std::cout << "字符串长度(size): " << str.size() << std::endl;
return 0;
}
2. 获取字符串长度并应用于实际逻辑
cpp
#include <iostream>
#include <string>
int main() {
std::string password;
std::cout << "请输入密码: ";
std::cin >> password;
if (password.length() < 8) {
std::cout << "密码长度不足 8 位,请重新输入。" << std::endl;
// 可以在这里进行重新输入密码等相关逻辑处理
} else {
std::cout << "密码长度符合要求。" << std::endl;
}
return 0;
}
(三)字符串拼接
1. 使用 + 运算符拼接字符串
cpp
#include <iostream>
#include <string>
int main() {
std::string firstName = "John";
std::string lastName = "Doe";
std::string fullName = firstName + " " + lastName;
std::cout << "全名: " << fullName << std::endl;
return 0;
}
**2.****append( )**函数
cpp
#include <iostream>
#include <string>
int main() {
std::string str1 = "Hello";
std::string str2 = " World";
std::string str3 = "!";
// 拼接一个字符串
str1.append(str2);
// 拼接一个字符串的一部分
str1.append(str3, 0, 1);
std::cout << str1 << std::endl;
return 0;
}
这里先将 str2 拼接到 str1 后面,然后将 str3 的从索引 0 开始长度为 1 的部分(即
'!'
)拼接到 str1 上。
**(四) 探讨拼接时的内存管理与性能优化(****reserve( )**方法的应用)
当进行多次字符串拼接时,如果不加以优化,可能会导致频繁的内存重新分配,降低程序性能
cpp
#include <iostream>
#include <string>
int main() {
std::string result;
for (int i = 0; i < 1000; ++i) {
std::string temp = std::to_string(i);
result += temp;
}
std::cout << result << std::endl;
return 0;
}
每次执行 result += temp 时,string 对象可能会重新分配内存来容纳新拼接的内容。为了避免这种情况,可以使用 reserve() 方法预先分配足够的内存空间
cpp
#include <iostream>
#include <string>
int main() {
std::string result;
int estimatedLength = 0;
for (int i = 0; i < 1000; ++i) {
std::string temp = std::to_string(i);
estimatedLength += temp.length();
}
result.reserve(estimatedLength);
for (int i = 0; i < 1000; ++i) {
std::string temp = std::to_string(i);
result += temp;
}
std::cout << result << std::endl;
return 0;
}
首先预估字符串的长度并提前开辟空间,以此来避免多次开辟空间降低效率
cpp
#include <iostream>
#include <string>
#include <ctime>
// 未优化的多次字符串拼接函数
void withoutReserve() {
std::string result;
for (int i = 0; i < 1000; ++i) {
std::string temp = std::to_string(i);
result += temp;
}
}
// 使用reserve优化后的多次字符串拼接函数
void withReserve() {
std::string result;
int estimatedLength = 0;
for (int i = 0; i < 1000; ++i) {
std::string temp = std::to_string(i);
estimatedLength += temp.length();
}
result.reserve(estimatedLength);
for (int i = 0; i < 1000; ++i) {
std::string temp = std::to_string(i);
result += temp;
}
}
int main() {
clock_t start1, end1, start2, end2;
// 测量未优化代码的执行时间
start1 = clock();
withoutReserve();
end1 = clock();
// 测量优化后代码的执行时间
start2 = clock();
withReserve();
end2 = clock();
double time1 = static_cast<double>(end1 - start1) / CLOCKS_PER_SEC;
double time2 = static_cast<double>(end2 - start2) / CLOCKS_PER_SEC;
std::cout << "未使用reserve的代码执行时间: " << time1 << " 秒" << std::endl;
std::cout << "使用reserve的代码执行时间: " << time2 << " 秒" << std::endl;
return 0;
}
使用reserve()函数后,效率明显提高(在数据较大时)
(五)空字符串的判断
**1. 使用****empty()**函数
cpp
std::string strToCheck = "";
if (strToCheck.empty()) {
std::cout << "这是一个空字符串。" << std::endl;
}
2.比较长度
cpp
std::string anotherStrToCheck;
if (anotherStrToCheck.length() == 0) {
std::cout << "这个字符串长度为0,是一个空字符串。" << std::endl;
}
三、string类对象的比较
1.==、>、<、!= 等运算符在 string 类中的应用
cpp
#include <iostream>
#include <string>
int main() {
std::string str1 = "apple";
std::string str2 = "banana";
std::string str3 = "apple";
if (str1 == str3) {
std::cout << "str1 和 str3 相等" << std::endl;
}
if (str1!= str2) {
std::cout << "str1 和 str2 不相等" << std::endl;
}
return 0;
}
2. compare() 方法的深入讲解,包括返回值含义与多参数用法
compare( ) 的基本用法是将当前字符串与另一个字符串进行比较,返回值为一个整数,其含义如下:
- 如果当前字符串小于比较的字符串,返回值小于 0
- 如果当前字符串等于比较的字符串,返回值等于 0
- 如果当前字符串大于比较的字符串,返回值大于 0
cpp
#include <iostream>
#include <string>
// 函数用于比较两个完整字符串
void compareFullStrings() {
std::string strX = "hello";
std::string strY = "world";
int result = strX.compare(strY);
if (result < 0) {
std::cout << "strX 小于 strY" << std::endl;
}
}
// 函数用于从指定位置和长度比较字符串与子串
void compareSubstring() {
std::string longStr = "This is a long string";
std::string subStr = "long";
// 从索引10开始比较,比较长度为4
int posResult = longStr.compare(10, 4, subStr);
if (posResult == 0) {
std::cout << "从索引10开始的子串与subStr相等" << std::endl;
}
}
int main() {
std::cout << "比较两个完整字符串的结果:" << std::endl;
compareFullStrings();
std::cout << "比较指定位置子串的结果:" << std::endl;
compareSubstring();
return 0;
}
区分大小写与不区分大小写比较的实现方式及应用场景
区分大小写比较
如前面所述,使用比较运算符(> == < != )和compare方法都是区分大小写的比较。这种比较方式在很多场景下是适用的,比如密码验证(包括大小写)才能通过验证
cpp
#include <iostream>
#include <string>
int main() {
std::string storedPassword = "Abc123";
std::string inputPassword;
std::cout << "请输入密码: ";
std::cin >> inputPassword;
if (inputPassword == storedPassword) {
std::cout << "密码正确" << std::endl;
} else {
std::cout << "密码错误" << std::endl;
}
return 0;
}
不区分大小写比较
在一些场景中,例如文件名比较或者文本搜索时,可能不需要区分大小写。实现不区分大小写比较可以通过将字符串转换为统一的大小写形式后再进行比较。例如,可以使用 transform
函数结合 tolower
或 toupper
函数来实现。以下是一个不区分大小写比较两个字符串的示例
cpp
#include <iostream>
#include <algorithm>
#include <string>
bool caseInsensitiveCompare(const std::string& str1, const std::string& str2) {
std::string str1Copy = str1;
std::string str2Copy = str2;
std::transform(str1Copy.begin(), str1Copy.end(), str1Copy.begin(), [](unsigned char c) { return std::tolower(c); });
std::transform(str2Copy.begin(), str2Copy.end(), str2Copy.begin(), [](unsigned char c) { return std::tolower(c); });
return str1Copy == str2Copy;
}
int main() {
std::string file1 = "TEST.TXT";
std::string file2 = "test.txt";
if (caseInsensitiveCompare(file1, file2)) {
std::cout << "文件名不区分大小写比较相等" << std::endl;
} else {
std::cout << "文件名不区分大小写比较不相等" << std::endl;
}
return 0;
}