C++ string(2)

在这里插入图片描述

文章目录

  • 1.初识迭代器和范围for
    • 1.1迭代器
    • 1.2范围for
    • 1.3 aout关键字
  • 2.字符串长度相关计算
    • 1.size 和 length
    • 2. capacity 和 reserve
  • 3.例题演示
    • 1. [917. 仅仅反转字母 - 力扣(LeetCode)](https://leetcode.cn/problems/reverse-only-letters/description/)
    • 2. [387. 字符串中的第一个唯一字符 - 力扣(LeetCode)](https://leetcode.cn/problems/first-unique-character-in-a-string/description/)
    • image-20241021201950153

1.初识迭代器和范围for

1.1迭代器

上次我们知道了可以通过operator[]重载了后,可以直接访问字符串:

Test01()
{
	string s1;
	string s2("hello world");
	s2[0] = 'x';
	cout << s1 << s2 << endl;
	//下标加[]重载
	for (size_t i = 0; i < s2.size(); i++)
	{
		cout << s2[i] << " " ;
	}
	cout << endl;
}

而我们也可以通过迭代器来实现,实现的方式与指针相仿,而且所有的容器都能使用:

string::iterator it = s2.begin();
while (it != s2.end())
{
		cout << *it << " ";
		++it;
}
cout << endl;

image-20241014184335471

也有反向的迭代器:

string::reverse_iterator rit = s2.rbegin();
while (rit != s2.rend())
{
	cout << *rit << " ";
	++rit;
}
cout << endl;

当然结果也是相反的:

image-20241016194503303

但是这样里面的内容可以被修改,如果字符串本身不能修改,那么就会将权限放大,这时就有以下这种写法了:

const string s3("hello world");
string::const_iterator lt = s3.begin();
//auto = s3.begin();
while (lt != s3.end())
{
	cout << *lt << " ";
	lt++;
}
cout << endl;

//string::const_reverse_iterator rlt = s3.rbegin();
auto rlt = s3.rbegin();
while (rlt != s3.rend())
{
	cout << * rlt << endl;
	rlt++;
}

image-20241016200615323

1.2范围for

  • 对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此 C++11中引入了基于范围的for循环。for循环后的括号由冒号“ :”分为两部分:第一部分是范围 内用于迭代的变量,第二部分则表示被迭代的范围,自动迭代,自动取数据,自动判断结束。

  • 范围for可以作用到数组和容器对象上进行遍历

  • 范围for的底层很简单,容器遍历实际就是替换为迭代器,这个从汇编层也可以看到。

for (auto ch : s2)//字符赋值,自动迭代,自动判断结束
{
	cout << ch << " ";
}
cout << endl;

auto 为自动推导为类型,这里推导char

所以我们可以通过范围for进行数组的遍历:

image-20241014194319961

如果要修改数据auto&就可以了

1.3 aout关键字

  • 在早期C/C++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量,后来这个 不重要了。C++11中,标准委员会变废为宝赋予了auto全新的含义即:auto不再是一个存储类型 指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期 推导而得。

  • 用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&

  • 当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际 只对第一个类型进行推导,然后用推导出来的类型定义其他变量。 auto不能作为函数的参数,可以做返回值,但是建议谨慎使用

  • auto不能直接用来声明数组

#include<iostream>
using namespace std;
int func1()
{
return 10;
}
// 不能做参数
void func2(auto a)
{}
// 可以做返回值,但是建议谨慎使用
auto func3()
{
return 3;
}
int main()
{
int a = 10;
auto b = a;
auto c = 'a';
auto d = func1();
// 编译报错:rror C3531: “e”: 类型包含“auto”的符号必须具有初始值设定项
auto e;
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;
cout << typeid(d).name() << endl;
int x = 10;
auto y = &x;
auto* z = &x;
auto& m = x;
cout << typeid(x).name() << endl;
cout << typeid(y).name() << endl;
cout << typeid(z).name() << endl;
auto aa = 1, bb = 2;
// 编译报错:error C3538: 在声明符列表中,“auto”必须始终推导为同一类型
auto cc = 3, dd = 4.0;
// 编译报错:error C3318: “auto []”: 数组不能具有其中包含“auto”的元素类型
auto array[] = { 4, 5, 6 };
return 0;
}

这样我们前面的代码也能优化了

string::iterator it = s2.begin();
while (it != s2.end())
{
		cout << *it << " ";
		++it;
}
cout << endl;

2.字符串长度相关计算

1.size 和 length

这里有两种方式去解决:

string s1("hello world");
cout << s1.length() << endl;     //11
cout << s1.size() << endl;       //11

两种方式的方式是一样滴,但是我们经常用size

image-20241016202800812

2. capacity 和 reserve

  1. capacity可以计算出字符串开出的空间

  2. reserve保留所对应的空间,也可以提前开空间避免扩容,提高效率

    但是reserve一般来说在Vs下就不存在缩容,但是不同平台有不同的标准

image-20241021192540182

例如:

image-20241021191912061

  1. clear用来清理数据但是一般来说不清理容量

image-20241021194714488

3.例题演示

1. 917. 仅仅反转字母 - 力扣(LeetCode)

image-20241021195455184

这里有两个问题:

  1. 要求让字符反转
  2. 但是字符不能反转

我们优先写一个判断是否时字母的函数:

bool isLetter(char ch) {
        if (ch >= 'a' && ch <= 'z')
            return true;
        if (ch >= 'A' && ch <= 'Z')
            return true;
        return false;
    }

那我们能用逆向迭代器吗?

首先正向迭代器和逆向迭代器的类型上就不一样,无法向指针一样直接比较,

但是同时用向迭代器或者同时用反向迭代器是可以的

例如:

class Solution {
public:
bool isLetter(char ch) {
        if (ch >= 'a' && ch <= 'z')
            return true;
        if (ch >= 'A' && ch <= 'Z')
            return true;
        return false;
    }
    string reverseOnlyLetters(string s) {
        auto left = s.begin();
        auto right = s.end() - 1;
        while (left < right) {
            if (!isLetter(*left)) {
                left++;
            } else if (!isLetter(*right)) {
                right--;
            } else {
                swap(*left, *right);
                left++;
                right--;
            }
        }
        return s;
    }
};

但是相比于下标就要复杂很多了
后续代码:

class Solution {
public:
    bool isLetter(char ch) {
        if (ch >= 'a' && ch <= 'z')
            return true;
        if (ch >= 'A' && ch <= 'Z')
            return true;
        return false;
    }

    string reverseOnlyLetters(string s) {
        int left = 0;
        int right = s.size() - 1;
        while (left < right) {
            while (left < right && !isLetter(s[left])) {
                ++left;
            }
            while (left < right && !isLetter(s[right])) {
                --right;
            }
            swap(s[left++], s[right--]);
        }
        return s;
    }
};

注意这里的判断,如果不加前面的在无字符的情况下直接访问越界了

while (left < right && !isLetter(s[left])) {
                ++left;
            }
while (left < right && !isLetter(s[right])) {
                --right;
            }

2. 387. 字符串中的第一个唯一字符 - 力扣(LeetCode)

image-20241021201950153

这道题可以直接进行比较,但是时间复杂度就比较高了

例如:

class Solution {
public:
    int firstUniqChar(string s) {
        int r = s.size();
        for (int i = 0; i < r; i++) {
            bool isUnique = true;
            for (int j = 0; j < r; j++) {
                if (i!= j && s[i] == s[j]) {
                    isUnique = false;
                    break;
                }
            }
            if (isUnique) {
                return i;
            }
        }
        return -1;
    }
};

后续的改进我们放到下次string(3)的前面进行讲解

后续会将C语言数据结构的排序部分更完在进入string(3)

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

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

相关文章

spring揭秘31-spring任务调度01-spring集成Quartz及JDKTimer定时器

文章目录 【README】【1】Quartz任务调度框架【1.1】Job调度任务【1.2】任务调度触发器Trigger【1.3】\*Quartz框架执行调度任务代码实践【1.3.1】硬编码执行Quartz调度任务【1.3.2】基于生产者模式执行quartz调度任务&#xff08;推荐&#xff09; 【2】spring集成Quartz【2.1…

查找与排序-选择排序

选择排序也是基于“比较”和“交换”两种操作来实现的排序方法 。 每一趟排序在待排序序列中选择关键字最小&#xff08;或最大&#xff09;的数据元素加入到排好序的序列前&#xff08;或后&#xff09;&#xff0c;直至所有元素排完为止。 一、简单选择排序 1.简单…

2024产品管理新风向:项目管理软件不懂敏捷开发?

一、产品管理与敏捷开发的紧密关联 产品管理和敏捷开发之间存在着紧密的关联&#xff0c;二者相互促进&#xff0c;共同为企业创造价值。 &#xff08;一&#xff09;敏捷开发为产品管理带来的优势 敏捷开发能够极大地加快产品上市速度。在传统的开发模式下&#xff0c;产品…

SAP 关于在交货单进行定价条件的确定简介

SAP 关于在交货单进行定价条件的确定简介 业务场景前台操作1、创建交货单2、创建交货单3、创建发票系统配置1、定义条件类型2、定义并分配定价过程3、定义交货的定价过程确定4、维护开票凭证的复制控制SAP交货单定价是针对销售交货单的价格计算过程,通常包括基本价格、折扣、附…

Java读取PDF后做知识库问答_SpringAI实现

​​​​​​​​​​​​​​ 核心思路&#xff1a; 简单来说&#xff0c;就是把PDF文件读取并向量化&#xff0c;然后放到向量存储里面&#xff0c;再通过大模型&#xff0c;来实现问答。 RAG&#xff08;检索增强生成&#xff09;介绍&#xff1a; 检索增强生成&#x…

数据结构——树、二叉树和森林间的转换

前言 介绍 &#x1f343;数据结构专区&#xff1a;数据结构 参考 该部分知识参考于《数据结构&#xff08;C语言版 第2版&#xff09;》129~130页 &#x1f308;每一个清晨&#xff0c;都是世界对你说的最温柔的早安&#xff1a;ૢ(≧▽≦)و✨ 目录 前言 1、基础知识 2…

Qml-Button的使用

Qml-Button的使用 Button属性 Button的继承关系&#xff1a; Button – AbstractButton – Control – Item; Button的属性主要继承于AbstractButton。AbstractButton属性主要如下&#xff1a; a.action:是一个Action类型属性&#xff0c;与QAction类似&#xff0c;用于提供快…

【论文解读系列】EdgeNAT: 高效边缘检测的 Transformer

代码&#xff1a; https://github.com/jhjie/edgenat 论文&#xff1a; https://arxiv.org/abs/2408.10527v1 论文 EdgeNAT: Transformer for Efficient Edge Detection 介绍了一种名为EdgeNAT的基于Transformer的边缘检测方法。 1. 背景与动机 EdgeNAT预测结果示例。(a, b)…

c语言基础程序——经典100道实例。

c语言基础程序——经典100道实例 001&#xff0c; 组无重复数字的数002&#xff0c;企业发放的奖金根据利润提成003&#xff0c;完全平方数004&#xff0c;判断当天是这一年的第几天005&#xff0c;三个数由小到大输出006&#xff0c;输出字母C图案007&#xff0c;特殊图案008&…

【Petri网导论学习笔记】Petri网导论入门学习(七) —— 1.5 并发与冲突

导航 1.5 并发与冲突1.5.1 并发定义 1.14定义 1.15 1.5.2 冲突定义 1.17 1.5.3 一般Petri网系统中的并发与冲突定义 1.18一般网系统中无冲撞概念阻塞&#xff08;有容量函数K的P/T系统&#xff0c;类似于冲撞&#xff09;一般Petri网中并发与冲突共存情况 1.5 并发与冲突 Petr…

lstm基础知识

lstm前言 LSTM(Long short-term memory)通过刻意的设计来避免长期依赖问题&#xff0c;是一种特殊的RNN。长时间记住信息实际上是 LSTM 的默认行为&#xff0c;而不是需要努力学习的东西&#xff01; 在标准的RNN中&#xff0c;这个重复模块具有非常简单的结构&#xff0c;例…

路由器原理和静态路由配置

一、路由器的工作原理 根据路由表转发数据 接收数据包→查看目的地址→与路由表进行匹配找到转发端口→转发到该端口 二、路由表的形成 它是路由器中维护的路由条目的集合&#xff0c;路由器根据路由表做路径选择&#xff0c;里面记录了网段ip地址和对应下一跳接口的接口号。…

【C语言备课课件】(下)指针pointer

目录 定义type *var_name;初始化int *p &a; // p指向变量a的地址 空指针NULL,野指针&#xff0c;指针悬挂 解引用指针的算术运算指针与数组 数组名—首指针二维数组指针 行指针列指针 多级指针&#xff08;进阶&#xff09;数组指针,指针数组&#xff08;进阶&#xff09…

如何利用 Python抓取网页数据 其他方式抓取网页数据列举

在 Python 中可以使用多种方法抓取网页数据&#xff0c;以下是一种常见的方法&#xff0c;使用requests和BeautifulSoup库。 一、安装所需库 在命令提示符或终端中执行以下命令安装requests和BeautifulSoup库&#xff1a; pip install requests pip install beautifulsoup4二…

python——类

问&#xff1a;小编为什么突然开始发python&#xff1f;难道C语言你不行了&#xff1f; 废话少说&#xff0c;让我们进入python中的类的学习&#xff01;&#xff01; &#xff08;一&#xff09;基本知识 &#xff08;1&#xff09;掌握类的概念 1、类的定义&#xff1a; 即…

python安装transformer教程

本章教程,记录在Windows中如何使用python安装transformer。 一、安装依赖 pip install transformers推荐使用国内镜像源,速度会快很多。 二、测试代码 from transformers import pipeline# 加载一个文本生成模型 text_generator = pipe

LCWLAN设备的实际使用案例

我们的LCWLAN设备在实际使用中以裸板的形式放在客户的智能总线控制器中&#xff0c;客户的 智能总线刀片灯&#xff0c;柔性灯货架&#xff0c;柔性感应钢网柜以及智能电子料架等设备都是接到总线控制 器中&#xff0c;然后总控制器通过CAN总线和我们的LCWLAN设备连接&#xff…

Linux DEADLINE调度算法详解

介绍 在实时系统中&#xff0c;调度算法的选择对于任务的及时执行至关重要。为了满足实时性需求&#xff0c;Linux内核引入了不同的调度算法&#xff0c;其中 DEADLINE 调度算法是为硬实时任务而设计的。DEADLINE 调度算法的目标是在多任务的情况下确保任务在其指定的最后期限…

Cpp::STL—容器适配器Stack和Queue的讲解和模拟实现(15)

文章目录 前言一、适配器模式概念分类 二、Stack核心作用代码实现 三、Queue核心作用代码实现 四、deque双端队列貌似兼收并蓄&#xff1f;实则也难以兼得~ 总结 前言 适配器也是STL六大组件之一&#xff0c;请跟我一起领悟它的智慧&#xff01;   正文开始&#xff01; 一、…

如何实现简单的 WinCC 项目分屏?

说明&#xff1a; 本文主要介绍了在不使用分屏器的情况下&#xff0c;通过 WinCC 项目中的设置&#xff0c;实现简单的分屏操作。两台显示器分别显示不同的 WinCC 画面&#xff0c;独自操作&#xff0c;互不影响。 试验环境 &#xff1a; 本文试验时所用硬件及软件环境…