【C++String类使用】万字详解保姆级教学,手把手教你使用string类。2

简介: 【C++String类使用】万字详解保姆级教学,手把手教你使用string类。

返回迭代器结束
返回指向字符串的结尾字符的迭代器。

理解了这两个迭代器函数。我们来运行上面代码看结果>

a299e1bbebf24346ae851f447723b4db.png


注:itertor是像指针一样的类型,有可能是指针,有可能不是指针。 具体是什么,我们以后再来探讨。

迭代器也是可以对数据进行修改的

int main()
{
  string s1("hello C++");
  cout << s1 << endl;
  string::iterator it = s1.begin();
  while (it != s1.end())
  {
    //通过迭代器对s1中的字符进行--
    (*it)--;
    ++it;
  }
  /让s1.begin()重新指向开头位置
  it = s1.begin();
  while (it != s1.end())
  {
    cout << *it << " ";
    ++it;
  }
  cout << endl;
  return 0;
}

391c7d425f0d498fae6e47a932358565.png


reverse_iterator反向迭代器

如果想要倒着打印字符串也可以通过反向迭代器来进行操作>

int main()
{
  string s1("hello C++");
  cout << s1 << endl;
  string::reverse_iterator it = s1.rbegin();
  while (it != s1.rend())
  {
    cout << *it ;
    ++it;
  }
  cout << endl;
  return 0;
}


上面代码中的s1.rbegin()返回反向迭代器到反向开始,返回指向字符串最后一个字符,s1.rend()返回反向迭代器到反向结束返回指向字符串第一个字符之前的理论元素的反向迭代。


616f511821af4c0f9954e6f02b52abc3.png

rbegin() 返回一个反向迭代器,指向 string 对象中最后一个字符。


2bffe445aad240b7a3bdf05b04a96978.png


rend()返回一个反向迭代器,指向 string 对象中第一个字符之前的位置。

了解了上面两个函数我们再来运行上面代码看结果>


4e304f66aacc441b8ab5265ee57001f3.png


范围for

C++11支持更简洁的范围for的新遍历方式

使用方法也是很简单,来看一段代码>


int main()
{
  string s1("hello C++");
  //for(char& ch : s1)
  for (auto& ch : s1)
  {
    cout << ch;
  }
  cout << endl;
  return 0;
}

1625169187d54020845d2b26d722a1d9.png



上面for (auto& ch : s1)的意思是依次取出s1中的字符传给ch,再对ch进行打印。auto是自动识别类型,当然我们也可以写成for (char& ch : s1),在我们日常中经常使用auto自动识别类型。

当然也可以通过范围for对字符串中的内容进行修改。


int main()
{
  string s1("hello C++");
  for (auto& ch : s1)
  {
    ch++;
  }
  for (auto& ch : s1)
  {
    cout << ch;
  }
  cout << endl;
  return 0;
}

63098100e0ef43e4ad0f96eb693e220d.png

范围for底层实现原理

范围for底层其实就是调用使用迭代器来完成>



79ae35496ccd4170a3bad129947bdf69.png


通过反汇编代码我们可以看到在我们使用范围for的时候调用了两个迭代器函数,分别是begin()和end()。

string类对象的修改操作

push_back()

56cbad5fe3404925adf9c15cd8d72ee3.png


将字符附加到字符串
将字符c附加到字符串的末尾,将其长度增加一。


int main()
{
  string str("hello C+");
  cout << str << endl;
  str.push_back('+');
  cout << str << endl;
  return 0;
}


2c90f2164230443ea4e177a73d8b6832.png

append()

c3493cc8e3ed48ba9c9d52e33554330c.png

附加到字符串
通过在当前值的末尾附加额外的字符来 扩展字符串:

append也重载了许多个函数。我们这里介绍几个比较常用的。


string& append (const string& str);

这个函数的功能是追加str的拷贝。

eg:

int main()
{
  string str1("hello ");
  string str2("C++");
  str1.append(str2);
  cout << str1 << endl;
  return 0;
}


91ea5b221c9e41ea9f770b4e5ee8f6c6.png


string& append (const string& str, size_t subpos, size_t sublen);

追加str的子字符串的副本。子字符串是str的一部分,它从字符位置subpos开始并跨越sublen个字符(或者直到str的结尾,如果str太短或者sublen是string::npos)。

eg:


int main()
{
  string str1("hello ");
  string str2("C++");
  str1.append(str2,0,2);
  cout << str1 << endl;
  return 0;
}

a41b740a0fe74e2f87a681a5e2b7a405.png


从str2的第0个位置开始追加追加两个字符。

string& append (const char* s);

在字符串后面追加一个字符串。

eg:


int main()
{
  string str1("hello ");
  str1.append("C++");
  cout << str1 << endl;
  return 0;
}

7f4f5208f42546dab6ff3d06eb8552af.png


string& append (const char* s, size_t n);

在s指向的字符数组中追加前n个字符的副本。

eg:

int main()
{
  string str1("hello ");
  str1.append("C++! hello",3);
  cout << str1 << endl;
  return 0;
}


62fe0635f38044a2ac11a9b1f632e412.png


在str后面追加"C++ hello"字符串中的前三个字符。

string& append (size_t n, char c);

填充
追加字符c的n 个连续拷贝。

eg:


int main()
{
  string str1("hello C");
  str1.append(2,'+');
  cout << str1 << endl;
  return 0;
}


fb60e3f6233249c385684660f063aefc.png

operator +=

7789c4b2ec0d4f0c993ef8c3134409d1.png



这个重载也是字符串追加的功能。可以追加string对象,可以追加字符串,也可以追加单个字符。

eg:

int main()
{
  string name("John");
  string family("Smith");
  name += " K. ";         // c-string
  name += family;         // string
  name += '\n';           // character
  cout << name;
  return 0;
}

2b151e85eb6042768f326bbe3a16f3ff.png



c_str()

8e27323bc38e499fb07cb6bcb42afbc2.png


c_str()string 类的成员函数,用于返回一个指向 string 对象中第一个字符的指针。该指针指向的字符数组以空字符结尾,可以用于与 C 风格字符串进行交互。以下是 c_str() 的用法和示例:

#include <iostream>
#include <string>
int main() {
    std::string str = "hello";
    const char *cstr = str.c_str();
    std::cout << cstr << std::endl; // hello
    return 0;
}

在上面的示例中,我们首先创建了一个 string 对象 str,然后使用 c_str() 函数将其转换为 C 风格字符串,并将返回的指针存储在 const char *cstr 中。最后,我们使用 std::cout 输出了 cstr 指向的字符数组。需要注意的是,由于 c_str() 返回的指针指向的字符数组是以空字符结尾的,因此可以使用该指针与 C 风格字符串进行交互。


find + npos


5ab02309d2ef4ad5ab7a62cbd0a68c86.png


find()string 类的成员函数,用于在字符串中查找指定的子串,并返回其位置。nposstring 类的静态成员变量,表示未找到指定子串时的返回值。以下是 find()npos 的用法和示例:


#include <iostream>
#include <string>
int main() {
    std::string str = "hello world";
    std::string sub = "world";
    std::size_t pos = str.find(sub);
    if (pos != std::string::npos) {
        std::cout << "Substring found at position " << pos << std::endl;
    } else {
        std::cout << "Substring not found" << std::endl;
    }
    return 0;
}

在上面的示例中,我们首先创建了一个 string 对象 str,然后使用 find() 函数查找字符串 "world" 在 str 中的位置,并将返回值存储在 pos 中。接着,我们使用 if 语句判断 pos 是否等于 std::string::npos,如果不等于,则说明找到了子串,输出其位置;否则说明未找到子串,输出提示信息 "Substring not found"。


需要注意的是,find() 函数可以接受一个可选的参数,用于指定搜索起始位置。例如,如果我们想从 str 的第 7 个字符开始查找子串,可以将其作为 find() 函数的第二个参数传入:


std::size_t pos = str.find(sub, 7);

这样就会从第 7 个字符开始查找子串。


另外,需要注意的是,npos 的值是一个特殊值,表示未找到指定子串时的返回值。它的值是一个无符号整数,通常是一个非常大的数值,因此可以用于判断 find() 函数是否查找到了指定子串。

注意:


在string尾部追加字符时,s.push_back(c) / s.append(1, c) / s += 'c'三种的实现方式差不多,一般

情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。

对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好。


string类非成员函数

我们上面一直在使用cout<<str<<endl;在对字符串进行打印输出,string不是内置类型,为什么还可以使用输出<<打印呢?

这是因为string类外面重载了operator<<(string)和operator>>(string)。


5f26453867724e55892c1286c430d144.png

将字符串插入流
将符合str 值的字符序列插入到os中。
此函数重载operator<<使其行为如ostream::operator<<中所述,适用于 C 字符串,也适用于字符串对象。


53dc80cb2e534c9896fac12f638437d0.png

从流中提取字符串

从输入流is中提取一个字符串,将序列存储在str中,它被覆盖( str的先前值被替换)。

此函数重载operator>>使其行为如istream::operator>>中描述的用于 c 字符串,但应用于字符串对象。

每个提取的字符都附加到字符串,就好像它的成员push_back被调用一样。


getline

22156feeda044d92ada8bda42cc4d2f6.png

getline 是 C++ 中 string 类的一个成员函数,用于从输入流中获取一行数据。它的使用方法如下:

int main() {
  string name;
  cout << "请输入你的名字>";
  getline(cin, name);
  cout << "Hello " << name << endl;
  return 0;
}


e6b22add35b64368aa7fe654ad8d4859.png

在上面的例子中,我们使用 getline 从标准输入流 std::cin 中读取一行数据,并将其存储到 line 变量中。然后,我们将这个字符串输出到标准输出流 std::cout 中。

也可以指定一个分隔符来代替默认的换行符 \n。例如,如果你想使用逗号作为分隔符,可以这样写:

int main() {
  std::string name;
  std::cout << "请输入你的名字>";
  std::getline(std::cin, name, ',');
  std::cout << "Hello " << name << std::endl;
  return 0;
}


2afd47b7dfc246f386bb1ac19b71f0be.png


在上面的例子中,我们使用逗号作为分隔符来读取输入流中的一行数据。

relational operators (string)字符串比较函数

27fd811fa6fd411f9d53936163cac9c2.png

relational operators 是 string 类的比较运算符,用于比较两个 string 类型的对象。

以下是 relational operators 的用法和示例:


== 运算符:判断两个 string 对象是否相等,如果相等则返回 true,否则返回 false。


#include <iostream>
#include <string>
int main() {
    std::string str1 = "hello";
    std::string str2 = "world";
    std::string str3 = "hello";
    std::cout << std::boolalpha << (str1 == str2) << std::endl; // false
    std::cout << std::boolalpha << (str1 == str3) << std::endl; // true
    return 0;
}
  1. != 运算符:判断两个 string 对象是否不相等,如果不相等则返回 true,否则返回 false


#include <iostream>
#include <string>
int main() {
    std::string str1 = "hello";
    std::string str2 = "world";
    std::string str3 = "hello";
    std::cout << std::boolalpha << (str1 != str2) << std::endl; // true
    std::cout << std::boolalpha << (str1 != str3) << std::endl; // false
    return 0;
}
  1. < 运算符:判断一个 string 对象是否小于另一个 string 对象,如果是则返回 true,否则返回 false
#include <iostream>
#include <string>
int main() {
    std::string str1 = "hello";
    std::string str2 = "world";
    std::string str3 = "abc";
    std::cout << std::boolalpha << (str1 < str2) << std::endl; // true
    std::cout << std::boolalpha << (str1 < str3) << std::endl; // false
    return 0;
}


  1. > 运算符:判断一个 string 对象是否大于另一个 string 对象,如果是则返回 true,否则返回 false


#include <iostream>
#include <string>
int main() {
    std::string str1 = "hello";
    std::string str2 = "world";
    std::string str3 = "abc";
    std::cout << std::boolalpha << (str1 > str2) << std::endl; // false
    std::cout << std::boolalpha << (str1 > str3) << std::endl; // true
    return 0;
}


5.<= 运算符:判断一个 string 对象是否小于或等于另一个 string 对象,如果是则返回 true,否则返回 false


#include <iostream>
#include <string>
int main() {
    std::string str1 = "hello";
    std::string str2 = "world";
    std::string str3 = "abc";
    std::cout << std::boolalpha << (str1 <= str2) << std::endl; // true
    std::cout << std::boolalpha << (str1 <= str3) << std::endl; // false
    return 0;
}
  1. >= 运算符:判断一个 string 对象是否大于或等于另一个 string 对象,如果是则返回 true,否则返回 false
#include <iostream>
#include <string>
int main() {
    std::string str1 = "hello";
    std::string str2 = "world";
    std::string str3 = "abc";
    std::cout << std::boolalpha << (str1 >= str2) << std::endl; // false
    std::cout << std::boolalpha << (str1 >= str3) << std::endl; // true
    return 0;
}


上面的几个接口大家了解一下,string类中还有一些其他的操作,这里不一一列举,大家在需要用到时不明白了查文档即可。


🍀小结🍀

今天我们认识了C++string类的用法相信大家看完有一定的收获。

种一棵树的最好时间是十年前,其次是现在! 把握好当下,合理利用时间努力奋斗,相信大家一定会实现自己的目标!加油!创作不易,辛苦各位小伙伴们动动小手,三连一波💕💕~~~,本文中也有不足之处,欢迎各位随时私信点评指正!

相关文章
|
30天前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
138 77
|
30天前
|
存储 C++
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
【数据结构——树】哈夫曼树(头歌实践教学平台习题)【合集】目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:任务描述 本关任务:编写一个程序构建哈夫曼树和生成哈夫曼编码。 相关知识 为了完成本关任务,你需要掌握: 1.如何构建哈夫曼树, 2.如何生成哈夫曼编码。 测试说明 平台会对你编写的代码进行测试: 测试输入: 1192677541518462450242195190181174157138124123 (用户分别输入所列单词的频度) 预
58 14
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
|
30天前
|
C++ 芯片
【C++面向对象——类与对象】Computer类(头歌实践教学平台习题)【合集】
声明一个简单的Computer类,含有数据成员芯片(cpu)、内存(ram)、光驱(cdrom)等等,以及两个公有成员函数run、stop。只能在类的内部访问。这是一种数据隐藏的机制,用于保护类的数据不被外部随意修改。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。成员可以在派生类(继承该类的子类)中访问。成员,在类的外部不能直接访问。可以在类的外部直接访问。为了完成本关任务,你需要掌握。
67 19
|
30天前
|
存储 人工智能 算法
【C++数据结构——图】最短路径(头歌教学实验平台习题) 【合集】
任务描述 本关任务:编写一个程序,利用Dijkstra算法,实现带权有向图的最短路径。 相关知识 为了完成本关任务,你需要掌握:Dijkst本关任务:编写一个程序,利用Dijkstra算法,实现带权有向图的最短路径。为了完成本关任务,你需要掌握:Dijkstra算法。带权有向图:该图对应的二维数组如下所示:Dijkstra算法:Dijkstra算法是指给定一个带权有向图G与源点v,求从v到G中其他顶点的最短路径。Dijkstra算法的具体步骤如下:(1)初始时,S只包含源点,即S={v},v的距离为0。
53 15
|
30天前
|
存储 编译器 数据安全/隐私保护
【C++面向对象——类与对象】CPU类(头歌实践教学平台习题)【合集】
声明一个CPU类,包含等级(rank)、频率(frequency)、电压(voltage)等属性,以及两个公有成员函数run、stop。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。​ 相关知识 类的声明和使用。 类的声明和对象的声明。 构造函数和析构函数的执行。 一、类的声明和使用 1.类的声明基础 在C++中,类是创建对象的蓝图。类的声明定义了类的成员,包括数据成员(变量)和成员函数(方法)。一个简单的类声明示例如下: classMyClass{ public: int
46 13
|
30天前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
46 12
|
30天前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
42 10
|
30天前
|
编译器 数据安全/隐私保护 C++
【C++面向对象——继承与派生】派生类的应用(头歌实践教学平台习题)【合集】
本实验旨在学习类的继承关系、不同继承方式下的访问控制及利用虚基类解决二义性问题。主要内容包括: 1. **类的继承关系基础概念**:介绍继承的定义及声明派生类的语法。 2. **不同继承方式下对基类成员的访问控制**:详细说明`public`、`private`和`protected`继承方式对基类成员的访问权限影响。 3. **利用虚基类解决二义性问题**:解释多继承中可能出现的二义性及其解决方案——虚基类。 实验任务要求从`people`类派生出`student`、`teacher`、`graduate`和`TA`类,添加特定属性并测试这些类的功能。最终通过创建教师和助教实例,验证代码
48 5
|
30天前
|
存储 算法 搜索推荐
【C++面向对象——群体类和群体数据的组织】实现含排序功能的数组类(头歌实践教学平台习题)【合集】
1. **相关排序和查找算法的原理**:介绍直接插入排序、直接选择排序、冒泡排序和顺序查找的基本原理及其实现代码。 2. **C++ 类与成员函数的定义**:讲解如何定义`Array`类,包括类的声明和实现,以及成员函数的定义与调用。 3. **数组作为类的成员变量的处理**:探讨内存管理和正确访问数组元素的方法,确保在类中正确使用动态分配的数组。 4. **函数参数传递与返回值处理**:解释排序和查找函数的参数传递方式及返回值处理,确保函数功能正确实现。 通过掌握这些知识,可以顺利地将排序和查找算法封装到`Array`类中,并进行测试验证。编程要求是在右侧编辑器补充代码以实现三种排序算法
38 5
|
30天前
|
Serverless 编译器 C++
【C++面向对象——类的多态性与虚函数】计算图像面积(头歌实践教学平台习题)【合集】
本任务要求设计一个矩形类、圆形类和图形基类,计算并输出相应图形面积。相关知识点包括纯虚函数和抽象类的使用。 **目录:** - 任务描述 - 相关知识 - 纯虚函数 - 特点 - 使用场景 - 作用 - 注意事项 - 相关概念对比 - 抽象类的使用 - 定义与概念 - 使用场景 - 编程要求 - 测试说明 - 通关代码 - 测试结果 **任务概述:** 1. **图形基类(Shape)**:包含纯虚函数 `void PrintArea()`。 2. **矩形类(Rectangle)**:继承 Shape 类,重写 `Print
46 4