【C++】继续学习 string类 吧

简介: 首先不得不说的是由于历史原因,string的接口多达130多个,简直冗杂…所以学习过程中,我们只需要选取常用的,好用的来进行使用即可(有种垃圾堆里翻美食的感觉)

开始使用 string类 吧

首先不得不说的是由于历史原因,string的接口多达130多个,简直冗杂…

所以学习过程中,我们只需要选取常用的,好用的来进行使用即可(有种垃圾堆里翻美食的感觉)

1 继续学习

上一篇文章

上一篇文章我们给出了构造函数和一些成员函数的功能:

成员函数 作用
begin() 返回字符首位置 (迭代器常用 )
end() 返回字符结尾 (迭代器常用)
size(重点) 返回字符串有效字符长度
length 返回字符串有效字符长度
capacity 返回空间总大小
empty (重点) 检测字符串释放为空串,是返回true,否则返回false
clear (重点) 清空有效字符
reserve (重点) 为字符串预留空间
resize (重点) 将有效字符的个数该成n个,多出的空间用字符c填充

1.1 扩容机制

上一篇文章,我们看到了string的容量是比较模糊的,为什么是15???,它的扩容规则是什么???

接下来我们来探索一下string的扩容机制:

首先我们来写一个简单的测试程序:


#include<string>
#include<iostream>

using namespace std;

int main(){

  string s1 = "";

  for (int i = 0; i < 200; i++) {
    s1 += "c";
    //检查是否需要扩容 然后打印出来
    if (s1.size() == s1.capacity()) 
      cout << "string 的空间 :" << s1.capacity() << endl;
  }

  return 0;
}

来看看效果:

可以看出来VS2022 基本是以1.5 倍扩容。那全部的编译器都是1.5 倍吗???

再让我们来liunx中,用g++ 来试试哈。

所以不同编译器的扩容机制也不同,这就是历史的原因了。根据我们所学过的顺序表,我们可以很容易想到内部扩容机制是什么样子:

  1. 检查 size 是否 等于 capacity
  2. 如果相等 扩容
  3. 否则直接插入尾部。

1.2 string类对象的访问及遍历操作

函数名称 功能说明
operator[] (重点) 返回pos位置的字符,const string类对象调用
begin+ end begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器
rbegin + rend rbegin获取一个字符的迭代器 + rend获取最后一个字符下一个位置的迭代器
范围for C++11支持更简洁的范围for的新遍历方式(底层是迭代器)

迭代器是C++新增的内容,功能类似指针,这里不细说,只将在string中如何使用。

首先看到迭代器(iterator)功能类似指针,那必须想到遍历的作用,对不对。接下来我们来看看迭代器的遍历好不好用。

注意不同类型的迭代器需要使用命名空间限定 这里是 string :: iterator

#include<string>
#include<iostream>

using namespace std;

int main() {

  string s1 = "I love you !";
  string::iterator it = s1.begin();
  while (it != s1.end())
  {
    cout << *it << " ";
    it++;
  }
  return 0;
}

看见这熟悉的结构,while()循环 *it it++是不是真的和指针一样。

再让我们看一下结果吧:

顺利的遍历了全部字符串。

接下来再来看一个好玩的,逆转迭代器reverse_iterator

#include<string>
#include<iostream>

using namespace std;

int main() {

  string s1 = "I love you !";

  string::reverse_iterator it = s1.rbegin();

  while (it != s1.rend())
  {
    cout << *it << " ";
    it++;
  }
  return 0;
}

仔细看,依然是 it++,而且起始位置也成为了rbegin() 结尾是rend() 是不是非常有意思。

来看效果:

成功逆转打印,very good!!!

同样也可以使用基于范围的for循环

for(auto it : s1){ } 即可完成遍历操作;

1.3 string类对象的修改操作

来给一波函数:

函数名称 功能说明
push_back 在字符串后尾插字符c
append 在字符串后追加一个字符串
operator+= (重点) 在字符串后追加字符串str
c_str(重点) 返回C格式字符串
find + npos(重点) 从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
rfind 从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
substr 在str中从pos位置开始,截取n个字符,然后将其返回

这里面其实有许多函数重载,不过常用的就那几个,有需求请自行查看:C++库

来初步使用一下插入函数:

#include<string>
#include<iostream>

using namespace std;

int main() {

  string s1 = "I love you !";

  s1.push_back('c');
  cout << "结尾插入字符 :" << s1 << endl;
  s1.append("forever");
  cout << "append 结尾插入字符串 :" << s1 << endl;
  s1 += "xxxxx";
  cout << "+= 结尾插入字符串 :" << s1 << endl;


  return 0;
}

非常顺利的插入了:

来看效果:

1.4 其他一些成员函数

函数 功能说明
operator+ 尽量少用,因为传值返回,导致深拷贝效率低
operator>> (重点) 输入运算符重载
operator<< (重点) 输出运算符重载
getline (重点) 获取一行字符串
relational operators (重点) 大小比较

这些我们以后再进行详细讲解。

2 实践解决问题:

家人们,上链接!!!!

1859 . 将句子排序

来看题目描述:

这个我们直接套用字符串操作模版即可:

这个非常好用的获取单词的办法,首先使用基于范围的for循环,然后遍历,只要不是空格,就插入到中间string类temp中,遇到空格,就把该单词存入数组中。非常好用!

然后这道题还要求我们完成排序,所以直接使用sort按要求排序即可。

最后删除结尾的数字,重新插入到s中即可。

bool compare(string a,string b){
    return a.back() < b.back();
}

class Solution {
public:
    string sortSentence(string s) {
        string temp = "";
        vector<string> res;
        s += " ";

        for(auto ch : s){
            if(ch == ' '){
                res.push_back(temp);
                temp.clear();
            }
            else{
                temp.push_back(ch);
            }
        }

        sort(res.begin(),res.end(),compare);
        s.clear();

        for(auto& it : res){
            it.pop_back();
            s += it + ' ';
        }   
        s.pop_back();
        return s;
    }
};

运行效果非常好:

Thanks♪(・ω・)ノ谢谢阅读!!!

下一篇文章见!!!

相关文章
|
1月前
|
存储 安全 C语言
C++ String揭秘:写高效代码的关键
在C++编程中,字符串操作是不可避免的一部分。从简单的字符串拼接到复杂的文本处理,C++的string类为开发者提供了一种更高效、灵活且安全的方式来管理和操作字符串。本文将从基础操作入手,逐步揭开C++ string类的奥秘,帮助你深入理解其内部机制,并学会如何在实际开发中充分发挥其性能和优势。
|
15天前
|
设计模式 安全 C++
【C++进阶】特殊类设计 && 单例模式
通过对特殊类设计和单例模式的深入探讨,我们可以更好地设计和实现复杂的C++程序。特殊类设计提高了代码的安全性和可维护性,而单例模式则确保类的唯一实例性和全局访问性。理解并掌握这些高级设计技巧,对于提升C++编程水平至关重要。
39 16
|
15天前
|
缓存 安全 Java
《从头开始学java,一天一个知识点》之:字符串处理:String类的核心API
🌱 **《字符串处理:String类的核心API》一分钟速通!** 本文快速介绍Java中String类的3个高频API:`substring`、`indexOf`和`split`,并通过代码示例展示其用法。重点提示:`substring`的结束索引不包含该位置,`split`支持正则表达式。进一步探讨了String不可变性的高效设计原理及企业级编码规范,如避免使用`new String()`、拼接时使用`StringBuilder`等。最后通过互动解密游戏帮助读者巩固知识。 (上一篇:《多维数组与常见操作》 | 下一篇预告:《输入与输出:Scanner与System类》)
44 11
|
8天前
|
编译器 C++
类和对象(中 )C++
本文详细讲解了C++中的默认成员函数,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载和取地址运算符重载等内容。重点分析了各函数的特点、使用场景及相互关系,如构造函数的主要任务是初始化对象,而非创建空间;析构函数用于清理资源;拷贝构造与赋值运算符的区别在于前者用于创建新对象,后者用于已存在的对象赋值。同时,文章还探讨了运算符重载的规则及其应用场景,并通过实例加深理解。最后强调,若类中存在资源管理,需显式定义拷贝构造和赋值运算符以避免浅拷贝问题。
|
8天前
|
存储 编译器 C++
类和对象(上)(C++)
本篇内容主要讲解了C++中类的相关知识,包括类的定义、实例化及this指针的作用。详细说明了类的定义格式、成员函数默认为inline、访问限定符(public、protected、private)的使用规则,以及class与struct的区别。同时分析了类实例化的概念,对象大小的计算规则和内存对齐原则。最后介绍了this指针的工作机制,解释了成员函数如何通过隐含的this指针区分不同对象的数据。这些知识点帮助我们更好地理解C++中类的封装性和对象的实现原理。
|
21天前
|
Java
课时14:Java数据类型划分(初见String类)
课时14介绍Java数据类型,重点初见String类。通过三个范例讲解:观察String型变量、&quot;+&quot;操作符的使用问题及转义字符的应用。String不是基本数据类型而是引用类型,但使用方式类似基本类型。课程涵盖字符串连接、数学运算与字符串混合使用时的注意事项以及常用转义字符的用法。
|
19天前
|
安全 C++
【c++】继承(继承的定义格式、赋值兼容转换、多继承、派生类默认成员函数规则、继承与友元、继承与静态成员)
本文深入探讨了C++中的继承机制,作为面向对象编程(OOP)的核心特性之一。继承通过允许派生类扩展基类的属性和方法,极大促进了代码复用,增强了代码的可维护性和可扩展性。文章详细介绍了继承的基本概念、定义格式、继承方式(public、protected、private)、赋值兼容转换、作用域问题、默认成员函数规则、继承与友元、静态成员、多继承及菱形继承问题,并对比了继承与组合的优缺点。最后总结指出,虽然继承提高了代码灵活性和复用率,但也带来了耦合度高的问题,建议在“has-a”和“is-a”关系同时存在时优先使用组合。
64 6
|
21天前
|
存储 JavaScript Java
课时44:String类对象两种实例化方式比较
本次课程的主要讨论了两种处理模式在Java程序中的应用,直接赋值和构造方法实例化。此外,还讨论了字符串池的概念,指出在Java程序的底层,DOM提供了专门的字符串池,用于存储和查找字符串。 1.直接赋值的对象化模式 2.字符串池的概念 3.构造方法实例化
|
8天前
|
编译器 C++
类和对象(下)C++
本内容主要讲解C++中的初始化列表、类型转换、静态成员、友元、内部类、匿名对象及对象拷贝时的编译器优化。初始化列表用于成员变量定义初始化,尤其对引用、const及无默认构造函数的类类型变量至关重要。类型转换中,`explicit`可禁用隐式转换。静态成员属类而非对象,受访问限定符约束。内部类是独立类,可增强封装性。匿名对象生命周期短,常用于临时场景。编译器会优化对象拷贝以提高效率。最后,鼓励大家通过重复练习提升技能!
|
1月前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。