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.mfbz.cn/a/589444.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

前端Web开发基础知识

HTML定义 超文本标记语言&#xff08;英语&#xff1a;HyperText Markup Language&#xff0c;简称&#xff1a;HTML&#xff09;是一种用于创建网页的标准标记语言。 什么是 HTML? HTML 是用来描述网页的一种语言。 HTML 指的是超文本标记语言: HyperText Markup LanguageH…

ELK Stack 8 接入ElasticFlow

介绍 Netflow v5 / v9 / v10&#xff08;IPFIX&#xff09;&#xff0c;支持大部分网络厂商及VMware的分布式交换机。 NetFlow是一种数据交换方式。Netflow提供网络流量的会话级视图&#xff0c;记录下每个TCP/IP事务的信息。当汇集起来时&#xff0c;它更加易于管理和易读。…

EasyExcel 处理 Excel

序言 本文介绍在日常的开发中&#xff0c;如何使用 EasyExcel 高效处理 Excel。 一、EasyExcel 是什么 EasyExcel 是阿里巴巴开源的一个 Java Excel 操作类库&#xff0c;它基于 Apache POI 封装了简单易用的 API&#xff0c;使得我们能够方便地读取、写入 Excel 文件。Easy…

常用AI工具分享 + IDEA内使用通义灵码

引言 随着人工智能技术的飞速发展&#xff0c;AI工具已经渗透到我们日常生活和工作的各个领域&#xff0c;带来了前所未有的便利。现在我将分享一下常用的AI工具&#xff0c;以及介绍如何在IDEA中使用通义灵码。 常用AI工具 1. 通义灵码 (TONGYI Lingma) - 由阿里云开发的智能…

Neo4j v5 中 Cypher 的变化

How Cypher changed in Neo4j v5 Neo4j v5 中 Cypher 的变化 几周前&#xff0c;Neo4j 5 发布了。如果你像我一样&#xff0c;在 Neo4j 4 的后期版本中忽略了所有的弃用警告&#xff0c;你可能需要更新你的 Cypher 查询以适应最新版本的 Neo4j。幸运的是&#xff0c;新的 Cyp…

【翻译】REST API

自动伸缩 API 创建或更新自动伸缩策略 API 此特性设计用于 Elasticsearch Service、Elastic Cloud Enterprise 和 Kubernetes 上的 Elastic Cloud 的间接使用。不支持直接用户使用。 创建或更新一个自动伸缩策略。 请求 PUT /_autoscaling/policy/<name> {"rol…

什么是UDP反射放大攻击,有什么安全措施可以防护UDP攻击

随着互联网的飞速发展和业务复杂性的提升&#xff0c;网络安全问题日益凸显&#xff0c;其中分布式拒绝服务&#xff08;DDoS&#xff09;攻击成为危害最为严重的一类网络威胁之一。 近些年&#xff0c;网络攻击越来越频繁&#xff0c;常见的网络攻击类型包括&#xff1a;蠕虫…

AI图书推荐:用ChatGPT快速创建在线课程

您是否是您领域的专家&#xff0c;拥有丰富的知识和技能可以分享&#xff1f;您是否曾想过创建一个在线课程&#xff0c;但被这个过程吓倒了&#xff1f;那么&#xff0c;是时候把这些担忧放在一边&#xff0c;迈出这一步了&#xff01;有了这本指南和ChatGPT的帮助&#xff0c…

ssh远程访问windows系统下的jupyterlab

网上配置这一堆那一堆&#xff0c;特别乱&#xff0c;找了好久整理后发在这里 由于既想打游戏又想做深度学习&#xff0c;不舍得显卡性能白白消耗&#xff0c;这里尝试使用笔记本连接主机 OpenSSH 最初是为 Linux 系统开发的&#xff0c;现在也支持包括 Windows 和 macOS 在内…

[1673]jsp在线考试管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 在线考试管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&…

R语言学习—4—数据矩阵及R表示

1、创建向量、矩阵 在R中&#xff0c;c()函数用于创建向量或组合数据对象。它在某些情况下可能会被省略&#xff0c;因为R有一些隐式的向量创建规则。例如&#xff0c;当你使用:操作符创建一个数字序列时&#xff0c;R会自动创建一个向量&#xff0c;所以你不需要显式地调用c()…

《QT实用小工具·五十二》文本或窗口炫酷有趣的滚动条——果冻条

1、概述 源码放在文章末尾 该项目实现了文本或窗口纤细的滚动条——果冻条 一个可以像弓弦一样拉出来&#xff0c;并且来回弹动的普通滚动条。 思路为此&#xff0c;但发现实际效果更像条状果冻&#xff0c;并且略有谐音&#xff0c; 故&#xff0c;称之为——“果冻条”&am…

条件依赖性的方法示例

5个条件判断一件事情是否发生&#xff0c;每个条件可能性只有2种&#xff08;发生或者不发生&#xff09;&#xff0c;计算每个条件对这件事情发生的影响力&#xff0c;条件之间有很强的依赖关系。 例一 如果条件之间有很强的依赖关系&#xff0c;那么简单地计算每个条件独立的…

初探 Google 云原生的CICD - CloudBuild

大纲 Google Cloud Build 简介 Google Cloud Build&#xff08;谷歌云构建&#xff09;是谷歌云平台&#xff08;Google Cloud Platform&#xff0c;GCP&#xff09;提供的一项服务&#xff0c;可帮助开发人员以一致和自动化的方式构建、测试和部署应用程序或构件。它为构建和…

B树:原理、操作及应用

B树&#xff1a;原理、操作及应用 一、引言二、B树概述1. 定义与性质2. B树与磁盘I/O 三、B树的基本操作1. 搜索&#xff08;B-TREE-SEARCH&#xff09;2. 插入&#xff08;B-TREE-INSERT&#xff09;3. 删除&#xff08;B-TREE-DELETE&#xff09; 四、B树的C代码实现示例五、…

基于 Wireshark 分析 IP 协议

一、IP 协议 IP&#xff08;Internet Protocol&#xff09;协议是一种网络层协议&#xff0c;它用于在计算机网络中实现数据包的传输和路由。 IP协议的主要功能有&#xff1a; 1. 数据报格式&#xff1a;IP协议将待传输的数据分割成一个个数据包&#xff0c;每个数据包包含有…

mac电脑关于ios端的appium真机自动化测试环境搭建

一、app store 下载xcode,需要登录apple id 再开始下载 二、安装homebrew 1、终端输入命令&#xff1a; curl -fsSL <https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh>如果不能直接安装&#xff0c;而是出现了很多内容&#xff0c;那么这个时候不要着急&…

06.Git远程仓库

Git远程仓库 #仓库种类&#xff0c;举例说明 github gitlab gitee #以这个仓库为例子操作登录码云 https://gitee.com/projects/new 创建仓库 选择ssh方式 需要配置ssh公钥 在系统上获取公钥输入命令&#xff1a;ssh-keygen 查看文件&#xff0c;复制公钥信息内…

【画图】读取无人机IMU数据并打印成log用matlab分析

一、修改IMU频率 原来的imu没有加速度信息&#xff0c;查看加速度信息的指令为&#xff1a; rostopic echo /mavros/imu/data 修改imu频率&#xff0c;分别修改的是 原始IMU数据话题 /mavros/imu/data_raw。飞控计算过后的IMU数据 /mavros/imu/data rosrun mavros mavcmd l…

Uniapp好看登录注册页面

个人介绍 hello hello~ &#xff0c;这里是 code袁~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的…