【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类的用法相信大家看完有一定的收获。

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

相关文章
|
1月前
|
编解码 Java 开发者
Java String类的关键方法总结
以上总结了Java `String` 类最常见和重要功能性方法。每种操作都对应着日常编程任务,并且理解每种操作如何影响及处理 `Strings` 对于任何使用 Java 的开发者来说都至关重要。
257 5
|
5月前
|
对象存储 C++ 容器
c++的string一键介绍
这篇文章旨在帮助读者回忆如何使用string,并提醒注意事项。它不是一篇详细的功能介绍,而是一篇润色文章。先展示重载函数,如果该函数一笔不可带过,就先展示英文原档(附带翻译),最后展示代码实现与举例可以直接去看英文文档,也可以看本篇文章,但是更建议去看英文原档。那么废话少说直接开始进行挨个介绍。
119 3
|
5月前
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
156 0
|
5月前
|
存储 编译器 C语言
关于string的‘\0‘与string,vector构造特点,反迭代器与迭代器类等的讨论
你真的了解string的'\0'么?你知道创建一个string a("abcddddddddddddddddddddddddd", 16);这样的string对象要创建多少个对象么?你知道string与vector进行扩容时进行了怎么的操作么?你知道怎么求Vector 最大 最小值 索引 位置么?
142 0
|
5月前
|
存储 编译器 程序员
c++的类(附含explicit关键字,友元,内部类)
本文介绍了C++中类的核心概念与用法,涵盖封装、继承、多态三大特性。重点讲解了类的定义(`class`与`struct`)、访问限定符(`private`、`public`、`protected`)、类的作用域及成员函数的声明与定义分离。同时深入探讨了类的大小计算、`this`指针、默认成员函数(构造函数、析构函数、拷贝构造、赋值重载)以及运算符重载等内容。 文章还详细分析了`explicit`关键字的作用、静态成员(变量与函数)、友元(友元函数与友元类)的概念及其使用场景,并简要介绍了内部类的特性。
243 0
|
7月前
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
282 12
|
8月前
|
编译器 C++
类和对象(中 )C++
本文详细讲解了C++中的默认成员函数,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载和取地址运算符重载等内容。重点分析了各函数的特点、使用场景及相互关系,如构造函数的主要任务是初始化对象,而非创建空间;析构函数用于清理资源;拷贝构造与赋值运算符的区别在于前者用于创建新对象,后者用于已存在的对象赋值。同时,文章还探讨了运算符重载的规则及其应用场景,并通过实例加深理解。最后强调,若类中存在资源管理,需显式定义拷贝构造和赋值运算符以避免浅拷贝问题。
|
8月前
|
存储 编译器 C++
类和对象(上)(C++)
本篇内容主要讲解了C++中类的相关知识,包括类的定义、实例化及this指针的作用。详细说明了类的定义格式、成员函数默认为inline、访问限定符(public、protected、private)的使用规则,以及class与struct的区别。同时分析了类实例化的概念,对象大小的计算规则和内存对齐原则。最后介绍了this指针的工作机制,解释了成员函数如何通过隐含的this指针区分不同对象的数据。这些知识点帮助我们更好地理解C++中类的封装性和对象的实现原理。
|
8月前
|
编译器 C++
类和对象(下)C++
本内容主要讲解C++中的初始化列表、类型转换、静态成员、友元、内部类、匿名对象及对象拷贝时的编译器优化。初始化列表用于成员变量定义初始化,尤其对引用、const及无默认构造函数的类类型变量至关重要。类型转换中,`explicit`可禁用隐式转换。静态成员属类而非对象,受访问限定符约束。内部类是独立类,可增强封装性。匿名对象生命周期短,常用于临时场景。编译器会优化对象拷贝以提高效率。最后,鼓励大家通过重复练习提升技能!
|
8月前
|
缓存 安全 Java
《从头开始学java,一天一个知识点》之:字符串处理:String类的核心API
🌱 **《字符串处理:String类的核心API》一分钟速通!** 本文快速介绍Java中String类的3个高频API:`substring`、`indexOf`和`split`,并通过代码示例展示其用法。重点提示:`substring`的结束索引不包含该位置,`split`支持正则表达式。进一步探讨了String不可变性的高效设计原理及企业级编码规范,如避免使用`new String()`、拼接时使用`StringBuilder`等。最后通过互动解密游戏帮助读者巩固知识。 (上一篇:《多维数组与常见操作》 | 下一篇预告:《输入与输出:Scanner与System类》)
223 11