C++ string类

目录

0.前言

1.为什么学习string类

1.1 C语言字符串的局限性

1.2 C++ string类的优势

2.标准库中的string类

2.1 字符串作为字符序列的类

2.2 接口与标准容器类似

2.3 基于模板的设计

2.4 编码和字符处理

3.string类的常用接口说明

3.1构造函数

3.1.1默认构造函数

3.1.2拷贝构造函数

3.1.3子字符串构造函数

3.1.4从C字符串构造

3.1.5从字符序列构造

3.1.6填充构造函数

3.2 容量操作函数

3.2.1 size() 和 length()

 3.2.2 max_size()

3.2.3 resize()

 3.2.4 capacity()

 3.2.5 reserve()

 3.2.6 clear()

 3.2.7 empty()

3.3访问及遍历操作

3.3.1 operator[]

3.3.2 迭代器

3.3.3 范围for

3.4类对象修改操作

3.4.1 operator+=

3.4.2 append

3.4.3 push_back

3.4.4 assign

3.4.5 insert

3.4.6 erase

3.4.7 replace 

3.4.8 swap

3.4.9 pop_back

4.小结


(图像由AI生成) 

0.前言

在现代软件开发中,文本处理是不可或缺的一部分。C++作为一种强大的编程语言,提供了多种方式来处理字符串。在本文中,我们将深入探讨C++标准库中的string类,了解其设计理念、功能以及使用方式。

1.为什么学习string类

学习C++中的string类对于任何使用C++进行软件开发的程序员来说都是至关重要的,尤其是从C语言的传统字符串处理转变而来的开发者。以下几点阐述了学习string类的重要性:

1.1 C语言字符串的局限性

C语言中的字符串处理依赖于字符数组和一系列标准库函数(如strcpy, strcat, strlen等)。这些方法虽然基本能满足需求,但存在几个显著的缺点:

  1. 安全性问题:C语言中的字符串操作常常涉及直接的内存操作,这容易造成缓冲区溢出、内存泄露等安全问题。例如,strcpy函数在复制数据时不会检查目标缓冲区的大小,这可能导致超出其容量的写操作。

  2. 效率低下:C语言的字符串操作通常需要手动管理字符串长度和内存,如需拼接字符串时,可能需要多次调用strlen来获取当前长度,然后再添加新内容,这样的操作效率较低。

  3. 使用不便:C语言的字符串需要程序员对内存非常小心地操作,容易出错且代码难以维护。

1.2 C++ string类的优势

与C语言的基本字符串处理相比,C++的string类提供了一个更安全、更高效、更易用的字符串操作方式:

  1. 自动内存管理string类自动管理内存,使用者不需要关心内存分配和释放的问题,极大地降低了内存泄漏和缓冲区溢出的风险。

  2. 丰富的成员函数string类内置了大量的成员函数,如append, find, replace, substr等,使得字符串的处理更为方便和直观。

  3. 动态大小string对象可以根据需要动态增长和缩小,无需预先声明最大容量,这一点与静态大小的C语言字符数组形成鲜明对比。

  4. 操作符重载和迭代器支持string类重载了多个操作符(如+=等),支持迭代器,使得字符串操作更符合C++的对象操作习惯,也支持现代C++中的范围for循环和算法库函数。

  5. 兼容性和灵活性:尽管string以字节为单位进行操作,对于多字节字符集的支持可能有限,但它在大多数情况下能够兼容处理UTF-8等编码,尤其是在使用支持这些编码的库时。

2.标准库中的string类

C++的string类是标准库中一个非常重要的组成部分,主要用于表示和操作字符序列。它被设计为易于使用且功能强大,以适应现代软件开发中对文本处理的复杂需求。以下是对string类详细介绍的几个关键方面。如果想要进一步地了解string的详细特性与使用方法,可以参考官方文档,详见:string - C++ Reference (cplusplus.com)。

2.1 字符串作为字符序列的类

string类本质上是一个用于表示字符序列的容器。它封装了字符数组的许多复杂操作,提供了一种更安全、更直观的方式来处理文本数据。用户不需要关心底层的字符数组和内存管理,所有这些都由string类自动处理。

2.2 接口与标准容器类似

string类的接口设计借鉴了标准STL容器的模式,例如vectordeque。这意味着string提供了类似于这些容器的多种成员函数,如迭代器支持、元素访问、修改操作、容量查询等。这种设计使得string类既熟悉又易于使用对于已经熟悉其他C++标准容器的开发者。

2.3 基于模板的设计

string类实际上是basic_string模板的一个特化实例,使用char类型作为字符类型。basic_string是一个模板类,可以用不同的字符类型来实例化,如wchar_tchar16_tchar32_t等,对应的实例分别可以处理宽字符或Unicode字符。

  • basic_string<char>被typedef为string
  • basic_string<wchar_t>被typedef为wstring

这种模板设计提供了极大的灵活性,允许string类以几乎相同的方式处理不同类型的字符数据。

2.4 编码和字符处理

尽管string是以单字节字符char进行操作,这使得它在默认情况下适用于ASCII编码的字符串处理,但对于多字节字符集(如UTF-8)的支持则需要更多注意。由于string按字节操作,对于包含多字节字符的字符串,如UTF-8编码的文本,长度和位置的计算可能与字符实际显示的数量不同。这意味着在处理多字节字符集时,开发者可能需要使用额外的库或函数来正确解析和处理这些字符。

3.string类的常用接口说明

3.1构造函数

default (1)
string();
copy (2)
string (const string& str);
substring (3)
string (const string& str, size_t pos, size_t len = npos);
from c-string (4)
string (const char* s);
from sequence (5)
string (const char* s, size_t n);
fill (6)
string (size_t n, char c);

string类提供了多种构造函数,允许以不同的方式创建和初始化字符串对象。下面详细介绍这些构造函数的用法和适用场景,结合示例代码进行说明。

3.1.1默认构造函数

string();

默认构造函数创建一个空的字符串。这是最简单的构造函数,用于初始化时不提供任何字符内容的情况。

std::string str1; // 创建一个空字符串

3.1.2拷贝构造函数

string(const string& str);

拷贝构造函数用于创建一个新的字符串,其内容是另一个已存在的string对象的副本。这个函数在复制字符串或函数返回字符串时经常使用。

std::string original = "Hello"; 
std::string copy(original); // 使用拷贝构造函数

3.1.3子字符串构造函数

string(const string& str, size_t pos, size_t len = npos);

这个构造函数从一个现有的string对象创建一个新字符串,开始于指定的pos位置,长度为len。如果lennpos(默认值),则复制从pos开始到原字符串结束的部分。

std::string text = "Hello world"; 
std::string sub(text, 6, 5); // 从位置6开始,长度为5,结果为"world"

3.1.4从C字符串构造

string(const char* s);

这个构造函数使用C风格的字符串(以null终止的字符数组)初始化string对象。它复制字符直到遇到null字符。

const char* cstr = "C++ string"; 
std::string str2(cstr); // 使用C字符串构造,结果为"C++ string"

3.1.5从字符序列构造

string(const char* s, size_t n);

这个构造函数从指定的字符数组创建一个字符串,复制前n个字符。这适用于从部分字符数组构建字符串的情况。

const char* data = "Example"; 
std::string part(data, 4); // 只取前4个字符,结果为"Exam"

3.1.6填充构造函数

string(size_t n, char c);

创建一个字符串,其中包含n个重复的字符c。这个构造函数在需要初始化固定长度和内容的字符串时非常有用。

std::string filled(5, 'a'); // 创建一个包含5个'a'的字符串,结果为"aaaaa"

3.2 容量操作函数

string 类提供了一组容量操作函数,允许开发者查询和修改字符串的存储特性。这些功能对于优化性能和管理内存非常重要。以下是这些函数的详细介绍和示例代码:

3.2.1 size() 和 length()

size_t size() const;
size_t length() const;

这两个函数都返回字符串当前的长度,即字符串中字符的数量。在 std::string 中,size()length() 是等价的,提供了相同的功能。

std::string str = "Hello, world!";
std::cout << "Length of string: " << str.length() << std::endl; // 输出 13
std::cout << "Size of string: " << str.size() << std::endl;     // 同样输出 13

 3.2.2 max_size()

size_t max_size() const;

max_size() 函数返回字符串可能的最大长度,这是由于系统或库实现的限制决定的。这不是一个固定值,而是表示字符串可以达到的最大理论长度。

std::string str; 
std::cout << "Maximum size of string: " << str.max_size() << std::endl; // 输出可能的最大长度

3.2.3 resize()

void resize(size_t n);
void resize(size_t n, char c);

resize() 函数更改字符串的长度。如果新的长度大于当前长度,新位置将用字符 c 填充(如果提供了 c 的话)。如果新的长度小于当前长度,多余的字符将被截断。

std::string str = "Hello";
str.resize(10, 'x'); // "Helloxxxxx"
str.resize(3);       // "Hel"

 3.2.4 capacity()

size_t capacity() const;

capacity() 函数返回为字符串分配的存储空间的大小,通常这个值大于或等于 size()。这可以给出底层数组可能的空间大小,有助于了解内存使用情况。

std::string str = "Test";
std::cout << "Capacity of string: " << str.capacity() << std::endl; // 输出分配的内存大小

 3.2.5 reserve()

void reserve(size_t n = 0);

reserve() 函数试图改变字符串的容量,即预先分配足够的内存来存储至少 n 个字符,避免多次增加字符串大小时的重复分配。

std::string str;
str.reserve(100); // 为存储至少100个字符预分配内存
std::cout << "New capacity after reserve: " << str.capacity() << std::endl;

 3.2.6 clear()

void clear() noexcept;

clear() 函数删除字符串中的所有字符,使其长度变为0。这个函数不改变容量。

std::string str = "Something";
str.clear(); // 清空字符串
std::cout << "String after clear: '" << str << "'" << std::endl; // 输出 ''

 3.2.7 empty()

bool empty() const;

empty() 函数检查字符串是否为空(即长度为0)。如果字符串为空,返回 true,否则返回 false

std::string str;
std::cout << "Is the string empty? " << (str.empty() ? "Yes" : "No") << std::endl; // 输出 'Yes'

3.3访问及遍历操作

std::string 类中,访问和遍历字符串的方法包括使用下标操作符、迭代器和范围 for 循环。这些方法提供了灵活的方式来访问和遍历字符串中的字符。

3.3.1 operator[]

下标操作符 operator[] 允许你访问字符串中的特定位置的字符。这种访问方式是随机访问,时间复杂度为 O(1)。

std::string str = "Hello, world!";
char ch1 = str[0];  // 访问第一个字符,ch1 = 'H'
char ch2 = str[7];  // 访问第八个字符,ch2 = 'w'std::cout << "First character: " << ch1 << std::endl;
std::cout << "Eighth character: " << ch2 << std::endl;// 修改字符串中的字符
str[5] = '!';
std::cout << "Modified string: " << str << std::endl;  // 输出 "Hello! world!"

3.3.2 迭代器

std::string str = "Hello";
std::cout << "Characters in string: ";// 使用正向迭代器遍历字符串
for (auto it = str.begin(); it != str.end(); ++it) {std::cout << *it << ' ';
}
std::cout << std::endl;// 使用反向迭代器遍历字符串
std::cout << "Characters in reverse: ";
for (auto rit = str.rbegin(); rit != str.rend(); ++rit) {std::cout << *rit << ' ';
}
std::cout << std::endl;

 

迭代器提供了一种方式来顺序访问容器中的每个元素。std::string 支持正向和反向迭代器(begin/endrbegin/rend)。

3.3.3 范围for

范围 for 循环是 C++11 引入的一个特性,它允许简洁地遍历容器中的所有元素。在使用范围 for 循环遍历 std::string 时,可以直接访问每个字符。

std::string str = "world";std::cout << "Characters in string using range-for: ";
for (char c : str) {std::cout << c << ' ';
}
std::cout << std::endl;// 修改字符串中的字符(需要使用引用)
for (char &c : str) {c = toupper(c);  // 将字符转换为大写
}
std::cout << "Modified string: " << str << std::endl;  // 输出 "WORLD"

3.4类对象修改操作

std::string 类提供了多种方法来修改字符串的内容,这些方法包括添加、删除、插入和替换字符等操作。下面是这些方法的详细介绍和使用示例:

3.4.1 operator+=

void operator+=(const string& str);
void operator+=(char c);
void operator+=(const char* s);

operator+= 用于将字符串、字符或C字符串附加到现有的 std::string 对象上。

std::string str = "Hello";
str += ", world!";
std::cout << str << std::endl;  // 输出 "Hello, world!"

3.4.2 append

string& append(const string& str);
string& append(const string& str, size_t subpos, size_t sublen);
string& append(const char* s);
string& append(const char* s, size_t n);
string& append(size_t n, char c);

append 方法添加字符串、字符数组或多个相同字符到现有字符串的末尾。

std::string str = "Hello";
str.append(" world", 6);  // 附加了 " world" 中的前6个字符
std::cout << str << std::endl;  // 输出 "Hello world"

3.4.3 push_back

void push_back(char c);

push_back 将一个字符追加到字符串的末尾。

std::string str = "Hello"; 
str.push_back('!'); 
std::cout << str << std::endl; // 输出 "Hello!"

3.4.4 assign

string& assign(const string& str);
string& assign(const string& str, size_t subpos, size_t sublen);
string& assign(const char* s);
string& assign(const char* s, size_t n);
string& assign(size_t n, char c);

assign 方法用于将一个新的字符串内容赋给 std::string 对象,替换原有的内容。

std::string str;
str.assign("Hello world");
std::cout << str << std::endl;  // 输出 "Hello world"

3.4.5 insert

string& insert(size_t pos, const string& str);
string& insert(size_t pos, const char* s);

insert 方法在指定位置插入字符串或字符。

std::string str = "Hello world";
str.insert(6, "beautiful ");
std::cout << str << std::endl;  // 输出 "Hello beautiful world"

3.4.6 erase

string& erase(size_t pos = 0, size_t len = npos);

erase 方法从字符串中删除指定位置和长度的字符。

std::string str = "Hello beautiful world";
str.erase(5, 10);  // 删除从位置5开始的10个字符
std::cout << str << std::endl;  // 输出 "Hello world"

3.4.7 replace 

string& replace(size_t pos, size_t len, const string& str);
string& replace(size_t pos, size_t len, const char* s);

replace 方法替换字符串中指定位置和长度的部分为新的内容。

std::string str = "Hello beautiful world";
str.replace(6, 9, "awesome");  // 替换从位置6开始的9个字符
std::cout << str << std::endl;  // 输出 "Hello awesome world"

3.4.8 swap

void swap(string& str);

swap 方法交换两个字符串的内容。

std::string str1 = "Hello";
std::string str2 = "World";
str1.swap(str2);
std::cout << "str1: " << str1 << " str2: " << str2 << std::endl;  // 输出 "str1: World str2: Hello"

3.4.9 pop_back

void pop_back();

pop_back 删除字符串的最后一个字符。

std::string str = "Hello!";
str.pop_back();
std::cout << str << std::endl;  // 输出 "Hello"

4.小结

在本篇博客中,我们深入探讨了C++标准库中的string类,从其构造函数、容量操作函数,到访问及遍历操作,以及类对象的修改操作。string类作为C++中处理字符串的核心工具,提供了丰富的接口来高效、安全地管理和操作字符串。掌握这些功能不仅可以提高编程效率,还能帮助开发者编写更加健壮和可维护的代码,有效地处理现代软件开发中的文本数据挑战。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/830887.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GPU 架构与 CUDA 关系 并行计算平台和编程模型 CUDA 线程层次结构 GPU 的算力是如何计算的 算力峰值

GPU 架构与 CUDA 关系 本文主要包含 NVIDIA GPU 硬件的基础概念、CUDA(Compute Unified Device Architecture)并行计算平台和编程模型,详细讲解 CUDA 线程层次结构,最后将讲解 GPU 的算力是如何计算的,这将有助于计算大模型的算力峰值和算力利用率。 GPU 硬件基础概念GP…

Django后台项目开发实战二

我们的需求是开发职位管理系统 三个功能&#xff1a; 管理员发布职位候选人能浏览职位用户能投递职位 第二阶段 创建应用 jobs&#xff0c;实现职位数据的建模 python manage.py startapp jobs 然后再 setting .py 注册应用&#xff0c;只需添加应用名称到最后一行 INST…

实验报告5-Spring MVC实现页面

实验报告5-SpringMVC实现页面 一、需求分析 使用Spring MVC框架&#xff0c;从视图、控制器和模型三方面实验动态页面。模拟实现用户登录&#xff0c;模拟的用户名密码以模型属性方式存放在Spring容器中&#xff0c;控制器相应用户请求并映射参数&#xff0c;页面收集用户数据或…

Vue入门到关门之Vue介绍与使用

一、vue框架介绍 1、什么是Vue&#xff1f; Vue (读音 /vjuː/&#xff0c;类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是&#xff0c;Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层&#xff0c;不仅易于上手&#xff0c;还便于与…

【图论】图论基础

图论不同地方讲的不太一样&#xff0c;本文仅限作者的理解 定义 图一般由点集 V V V 和边集 E E E 组成。 对于 v ∈ V v\in V v∈V&#xff0c;称 v v v 为该图的一个节点。 对于 e ∈ E e\in E e∈E&#xff0c;一般用二元组 ( u , v ) (u,v) (u,v) 表示 e e e&…

短视频素材有哪些方法获得?推荐8个短视频素材免费资源

在这个视觉内容至关重要的时代&#xff0c;拥有高质量视频素材对于任何视频创作者来说都是必不可少的。视频素材不仅可以增强叙事的深度&#xff0c;还能显著提升观众的参与度。为了帮助你找到理想的视频素材&#xff0c;以下是全球范围内提供顶级视频素材的网站列表&#xff0…

基于FPGA的数字信号处理(5)--Signed的本质和作用

前言 Verilog中的signed是一个很多人用不好&#xff0c;或者说不太愿意用的一个语法。因为不熟悉它的机制&#xff0c;所以经常会导致运算结果莫名奇妙地出错。其实了解了signed以后&#xff0c;很多时候用起来还是挺方便的。 signed的使用方法主要有两种&#xff0c;其中一种…

笔记-用Python脚本启停JAR程序

用Python脚本启停JAR程序&#xff0c;需要用到python中的以下内置模块 subprocess 是 Python 的一个标准库模块&#xff0c;用于在新进程中执行子命令&#xff0c;获取子进程的输入/输出/错误以及返回码等os 是 Python 的一个标准库模块&#xff0c;它提供了与操作系统交互的功…

金融案例:统一查询方案助力数据治理与分析应用更高效、更安全

随着企业数据规模的增长和业务多元化发展&#xff0c;海量数据实时、多维地灵活查询变成业务常见诉求。同时多套数据库系统成为常态&#xff0c;这既带来了数据管理的复杂性&#xff0c;又加大了数据使用的难度&#xff0c;面对日益复杂的数据环境和严格的数据安全要求&#xf…

flexpaper 远程命令执行

flexpaper 远程命令执行 这个是有POC的&#xff0c;先简单复现一下 GET /ipg/static/appr/lib/flexpaper/php/view.php?doc1.docx"%26echoshell>shel233l.txt%23&pageexp&formatswf&callbackcallback&isSplittrue HTTP/1.1 Host: 192.168.50.22 Use…

Python 机器学习 基础 之 学习 基础环境搭建

Python 机器学习 基础 之 学习 基础环境搭建 目录 Python 机器学习 基础 之 学习 基础环境搭建 一、简单介绍 二、什么是机器学习 三、python 环境的搭建 1、Python 安装包下载 2、这里以 下载 Python 3.10.9 为例 3、安装 Python 3.10.9 4、检验 python 是否安装成功&…

Systemback Ubuntu14.04 制作自定义系统ISO镜像

工作需要&#xff0c;要基于ubuntu自定义一些编译环境并将自己配置好的ubuntu做成镜像。 硬件准备 ​ 为保证能够顺利完成系统iso镜像的制作与系统还原&#xff0c;推荐准备一个较大容量的U盘或者移动固态硬盘&#xff0c;同时确保自己的Ubuntu系统还有比较大的可用空间。 1 S…

jenkins教程

jenkins 一、简介二、下载安装三、配置jdk、maven和SSH四、部署微服务 一、简介 Jenkins是一个流行的开源自动化服务器&#xff0c;用于自动化软件开发过程中的构建、测试和部署任务。它提供了一个可扩展的插件生态系统&#xff0c;支持各种编程语言和工具。 Jenkins是一款开…

美团代付系统源码搭建ZHU16728

2024美团外卖点单代付系统源码基于php 基础开发&#xff0c;这套系统搭载了外卖系统属性&#xff0c;可添加物流信息。 1.完美对接微信支付&#xff0c;支付宝支付。 2.这套系统全新UI界面&#xff0c;完美搭建可以用作商用系统服务。 3.前端UI界面内容丰富&#xff0c;功能齐全…

有关CSS中排版常见问题(清除默认样式问题 + 元素居中问题 + 元素之间的空白问题 + 行内块的幽灵空白问题)

前言&#xff1a;在练习CSS排版的时候&#xff0c;我们经常会遇到一些排版上的问题&#xff0c;那么我们如何去解决这些问题呢&#xff1f;本篇文章给出了一些新手在练习排版时候可能会遇到的问题的解决方案。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我…

【消息队列】RabbitMQ五种消息模式

RabbitMQ RabbitMQRabbitMQ安装 常见的消息模型基本消息队列SpringAMQPWorkQueue消息预取发布订阅模式Fanout ExchangeDirectExchangeTopicExchange 消息转换器 RabbitMQ RabbitMQ是基于Erlang语言开发的开源消息通信中间件 官网地址&#xff1a;https://www.rabbitmq.com/ R…

【VUE】Vue中实现树状表格结构编辑与版本对比的详细技术实现

Vue中实现树状表格结构编辑与版本对比的详细技术实现 在Vue中&#xff0c;创建一个可编辑的树状表格并实施版本对比功能是一种需求较为常见的场景。在本教程中&#xff0c;我们将使用Vue结合Element UI的el-table组件&#xff0c;来构建一个树状表格&#xff0c;其中包含添加、…

深入探究C++四大关键特性:初始化列表、友元函数、内部类与static成员

目录 1. 构造函数不为人知的那些事 1.1 构造函数体赋值与初始化列表对比 1.2 explicit关键字与构造函数隐式转换 2. static成员 2.1 static成员的概念 2.2 static成员的特性与应用 2.3 小结 3. C11 成员变量初始化新用法 4. 友元 4.1 友元函数 4.2 友元类 5. 内部类…

Python 中的花卉矩阵组合

使用场景描述 (rib) 协议编写脚本的基础知识。通过创建在 3D 空间中转换的基本几何图形,解决了 xyz 坐标系的基础知识。初步渲染是使用基本着色完成的,因此可以更容易地看到几何体。RenderMan 图1 图 1 是我作为作业参考的示例图片,并尝试匹配 中的图片。为了完成这项任务…

Python | Leetcode Python题解之第61题旋转链表

题目&#xff1a; 题解&#xff1a; class Solution:def rotateRight(self, head: ListNode, k: int) -> ListNode:if k 0 or not head or not head.next:return headn 1cur headwhile cur.next:cur cur.nextn 1if (add : n - k % n) n:return headcur.next headwhi…