C++入门1

news2025/2/27 8:42:06

C++入门1

  • 1.前言
  • 2.命名空间
    • 1.C语言对于命名空间方面的缺陷
    • 2.命名空间的语法特性
      • 1.域作用限定符
      • 2.命名空间的可嵌套性
    • 3.声明与定义分离的命名空间
    • 4.命名空间的展开
    • 5.多个命名空间中命名冲突
    • 6.对于命名空间的推荐写法
  • 3.iostream
    • 1.cout和endl
    • 2.cin
  • 3.缺省参数
    • 1.缺省参数的形式
    • 2.缺省参数举例
    • 3.缺省参数"坑点"
  • 4.函数重载
    • 1.函数重载的形式
    • 2.函数重载和缺省参数的联系
    • 3.函数重载的底层原理:函数名修饰规则
      • 为什么C语言不支持函数重载,而C++支持函数重载呢?

1.前言

C++是在C语言的基础之上,容纳进去了面向对象的编程思想和泛型编程,并增加了许多有用的库,以及一些关键字

本节主要介绍C++对于C语言语法不足的补充,以及C++是如何对C语言设计不合理的地方进行优化的,为后续学习类和对象打下基础

首先我们先看一下C++如何打印"hello world"
在这里插入图片描述
下面我们会介绍一下

#include <iostream>
using namespace std;

这两行代码的作用

2.命名空间

1.C语言对于命名空间方面的缺陷

首先因为C++是兼容C语言的,所以在C++程序里面是可以运行C语言代码的,如图是在C++文件中运行C语言代码
在这里插入图片描述
可是.如果我们定义了一个变量或者函数,跟库中的某一个变量或者函数重命名了(即发生了命名冲突问题)会发生什么状况呢?

下面我们来看一下
我们定义了一个变量rand(注意:在stdlib.h头文件中有一个函数叫做rand)

在还没有包括stdlib.h头文件时,程序是可以正常运行的
在这里插入图片描述
因为此时还没有发生命名冲突
那么当我们包括了这个头文件时呢?
在这里插入图片描述
报错:rand重定义,以前的定义是函数

所以,对于项目开发而言,我们要定义的变量和函数肯定会特别多
我们就算不跟库中的命名发生冲突,也难免会发生与我们一起开发某个项目的同事的命名冲突的问题

如果发生了命名冲突问题,那么修改名字会非常麻烦,会影响项目开发的进度,这是C语言的一个非常大的缺陷

所以C++引入了命名空间这一语法

2.命名空间的语法特性

1.域作用限定符

namespace 命名空间的名称
{
	可以放入int,double,char.......
	函数,结构体,类等等所有我们可以定义的类型
}

如图,现在我们把我们定义的rand这个整形变量放入了命名空间wzs中,那么此时就不会跟stdlib.h头文件中的rand函数发生命名冲突了
在这里插入图片描述
命名空间就像是一个围墙,把rand这个整型变量"封"起来
防止非法访问
默认情况下编译器并不会去命名空间中进行查找,只有指定时才会到该命名空间里面去找

那么如果我们想要访问命名空间wzs中的rand呢?
想要访问呢?wzs::rand来访问
这个::叫做域作用限定符
在这里插入图片描述
同理,wzs命名空间中也可以定义函数,结构体等等…
下面我们来看一下
这里请注意,当我们想要访问wzs命名空间下的结构体SListNode时
需要把命名空间的名称放到struct的后面

struct wzs::SListNode* plist=NULL;

在这里插入图片描述

2.命名空间的可嵌套性

如果我们想要定义的数据太多了,出现了一个命名空间中的命名冲突问题呢?
此时我们可以嵌套命名空间
在这里插入图片描述
还可以在wzs1或者wzs2中继续嵌套,就像是套娃一样…但是最好不要嵌套太深,否则麻烦的还是自己

那么对于那种在头文件中声明,在源文件中定义的情况呢?

3.声明与定义分离的命名空间

我们定义了一个栈,放到了wzs命名空间中
这里就先不去全部写完了,毕竟我们这节课介绍的不是栈的代码实现
而是命名空间

请注意,我们将这里的命名空间也命名为wzs会报错吗?
答案是:并不会,因为不同文件下的命名空间会被编译器合并到一起,所以并不会报错

Stack.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
//这里的命名空间也命名为wzs会报错吗?并不会
//不同文件下的同名命名空间会被编译器合并到一起,所以并不会报错
namespace wzs
{
	struct Stack
	{
		int* a;
		int top;
		int capacity;
	};
	void StackInit(struct Stack* ps);
	void StackPush(struct Stack* ps, int num);
}
Stack.cpp
#include "Stack.h"
namespace wzs
{
	void StackInit(struct Stack* ps)
	{
		ps->a = NULL;
		ps->capacity = ps->top = 0;
	}
	void StackPush(struct Stack* ps, int num)
	{
		if (ps->capacity == ps->top)
		{
			int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
			int* tmp = (int*)realloc(ps->a,sizeof(int) * newcapacity);
			if (tmp == NULL)
			{
				perror("realloc fail");
				exit(-1);
			}
			ps->a = tmp;
			ps->capacity = newcapacity;
		}
		ps->a[ps->top++] = num;
	}
}
TestStack.cpp
#include "Stack.h"
int main()
{
	struct wzs::Stack st;
	wzs::StackInit(&st);
	wzs::StackPush(&st, 1);
	wzs::StackPush(&st, 2);
	wzs::StackPush(&st, 3);
	wzs::StackPush(&st, 4);
	wzs::StackPush(&st, 5);
	return 0;
}

我们调试一下,程序运行正确
在这里插入图片描述

4.命名空间的展开

但是总是写命名空间真的好麻烦
所以能不能有一些情况下不用每次都指定命名空间呢?

using namespace wzs;//展开命名空间:默认指定在wzs这个命名空间下使用(把wzs这个墙拆掉)
//请注意:这跟展开头文件完全不同,尽管都叫做展开

那么什么情况下我们可以展开呢?
一般情况下不要展开,除非自己写好做测试,没有给别人用,不存在冲突

所以一开始写的using namespace std;(这里的std是C++官方库定义的命名空间)
的意思是
展开C++官方库定义的命名空间

但是在工程项目中不要展开std,容易发生命名冲突
但是在我们自己日常练习的时候为了方便可以展开

5.多个命名空间中命名冲突

如果我们展开的两个命名空间之间本来就有命名冲突呢?
在这里插入图片描述
此时会报错
在加上域作用限定符之后就不会报错了
在这里插入图片描述

6.对于命名空间的推荐写法

在工程项目中,我们推荐这样使用

比方说我们现在想要很方便的使用使用C++中的cout这个对象,就可以这样去做
(因为cout,cin,<<(流插入运算符),>>(流提取运算符)
涉及到类和对象的知识,我们目前无法展开详细介绍原理)
(endl(end line)相当于C语言中的换行符"\n")

//在工程当中推荐这种写法
using std::cout;
using std::endl;
using std::cin;

我们不建议直接展开std命名空间
但是每次指定cout和endl,cin的命名空间很不方便,而直接展开就会把std全部暴露出来出现冲突风险
所以我们推荐这种指定展开的写法

所以我们就可以在使用cout,cin,endl的时候不用去指定命名空间了
注意:使用cout,cin,endl必须包含头文件iostream
在这里插入图片描述

3.iostream

C++中的iostream头文件类似于C语言中的stdio.h头文件
也就是标准IO头文件

C语言中的printf被cout取代,scanf被cin取代,“\n"被endl取代
一般情况下cout,cin,endl比printf,scanf,”\n"更加方便
不过请注意,有一些情况下它们三个也并不方便,(比方说cout对于浮点数精度的控制方法就不如printf方便)
因为C++是兼容C语言的,所以在这个时候可以使用C语言中的printf,scanf,“\n”

1.cout和endl

cout这里的c的意思:console(控制台/终端)
在这里我们没有展开cout,endl
发现使用cout和endl必须加上std::,太麻烦了,所以在工程中展开我们推荐那种写法
在这里插入图片描述
在这里插入图片描述

2.cin

在这里插入图片描述

3.缺省参数

缺省参数的好处是:可以让函数传参更加灵活,这也是C++设计者设计缺省参数的一个原因

1.缺省参数的形式

诸如这样的函数,它的所有形参都被赋予了默认值,这种情况情况下叫做全缺省参数
void f(int a=1,int b=2,int c=3);

诸如这样的函数,它的形参有一部分被赋予了默认值,这种情况下叫做半缺省参数
void f(int a,int b=2,int c=3);

注意:缺省值必须从右向左给,不能这样给:
void f(int a=1,int b=2,int c);
因为如果我有这么一个函数调用
f(4,5);
就算是5对应的是c,但是4对应的到底是a还是b呢?
这样会产生歧义,因此C++语法规定缺省值必须从右向左给

缺省参数不能跳着给:
void f(int a=1,int b,int c=3);
f(4,5);
不知道给b的是4还是5

2.缺省参数举例

//全缺省参数
void f(int a = 10, int b = 1, int c = 3)
{
	cout << a << " " << b << " " << c << endl;
}
//半缺省参数
void g(int a, int b = 1, int c = 3)
{
	cout << a << " " << b << " " << c << endl;
}
int main()
{
	f();
	f(1);
	f(1, 2);
	f(1, 2, 3);
	//不过请注意:缺省参数不能跳着给,例如这样
	//f(, 2, );//err
	//g();//err:函数中调用的参数太少
	g(1);
	g(1, 2);
	g(1, 2, 3);
	return 0;
}

可见:缺省参数的好处是:可以让函数传参更加灵活,这也是C++设计者设计缺省参数的一个原因

3.缺省参数"坑点"

注意:缺省参数不能在声明和定义中同时存在

为什么?
因为要防止出现这种情况:
Stack.h:
在这里插入图片描述

Stack.cpp:
在这里插入图片描述
在这里插入图片描述
哪怕我不用这个缺省参数,自己传了一个实参,都会报错

也就是怕出现定义和声明中的缺省参数值不同的情况
那么这时缺省参数到底听.h的还是.cpp的呢?会产生歧义,因此C++语法不允许缺省参数在定义和声明中同时出现

那么如果我今天就是想要在一个声明和定义分离的一个程序中设计一个含缺省参数的函数
怎么办?

只能在声明中加上缺省参数,定义中不允许加上缺省参数

因为当调用该函数的源文件包含了头文件之后

1.如果缺省参数是设置在定义中,而不是声明中,那么我在这个调用该函数的源文件中是看不到实际的缺省参数的
2.如果缺省参数是设置在声明中的话,那么是可以看到实际的缺省参数的

下面给大家展示一下:
这是将缺省参数设置在定义中的情况
在这里插入图片描述
这是将缺省参数设置在声明中的情况
在这里插入图片描述

4.函数重载

C++是支持函数重载的,
所谓函数重载就是指:两个函数名称相同,但是参数的个数或者类型或者类型顺序不同,即构成函数重载
注意:如果两个函数只有返回值不同的话,并不会构成函数重载

1.函数重载的形式

这里以Add函数为例

int Add(int num1, int num2)
{
	return num1 + num2;
}

double Add(double num1, double num2)
{
	return num1 + num2;
}

int main()
{
	cout << Add(1, 2) << endl;
	cout << Add(1.1, 1.2) << endl;
	//cout << Add(1, 1.2) << endl;//err
	return 0;
}

大家注意到了这一行了吧

cout << Add(1, 1.2) << endl;//err

为什么会报错呢?
首先,在C语言的学习中,我们知道int和double类型是可以发生隐式类型转换的
也就是说在Add(1,1.2)这个函数调用中,有可能会发生两种情况:

(1)(int类型的1)被隐式转换为double类型,去匹配double Add(double num1, double num2)
(2)(double 类型的1.2)被隐式转换为int类型,去匹配int Add(int num1, int num2);

也就是说这个函数调用存在歧义,所以编译器会报错
也就是说哪怕我们去掉其中的一个Add函数,这个函数调用就不会报错了

下面是函数重载的几种错误形式
1.两个函数仅有返回值不同
在这里插入图片描述
2.参数仅有名称不同或者仅有参数名称顺序不同
在这里插入图片描述
在这里插入图片描述
注意:并不是说两个函数构成重载之后对它们的调用就不会产生歧义

2.函数重载和缺省参数的联系

下面请大家看一下下面两个函数能不能构成函数重载

void f(int num)
{
	cout << "f(int num)" << endl;
}
void f(int num = 1)
{
	cout << "f(int num = 1)" << endl;
}

在这里插入图片描述
答案是:不构成重载,因为参数的个数,类型,类型顺序均相同

那么在请大家看一下这两个函数会不会构成重载呢?

void f()
{
	cout << "f()" << endl;
}

void f(int num = 1)
{
	cout << "f(int num = 1)" << endl;
}

在这里插入图片描述
答案是:构成重载
但是这意味着这两个函数在调用时就真的没有歧义了吗?
这种情况下是可以的
在这里插入图片描述
但是这种情况下就不行了:
在这里插入图片描述
因为在调用的时候产生了歧义
这就像是一个经典的问题:
你妈妈和你老婆掉水里,你只能救一个,你救谁?
C++懒得跟你折腾,直接在语法上不允许这样做,直接报错

3.函数重载的底层原理:函数名修饰规则

还有一个问题:函数的参数不同就能构成函数重载,那我返回值不同凭什么就无法构成函数重载呢?
这就要谈一下函数名修饰规则了
在谈这个之前,我们先建立一个Func.h,一个Func.cpp,一个Test.cpp文件
并且复习一下C语言阶段的编译链接的知识
在这里插入图片描述

现在我们有Func.h,Func.cpp,Test.cpp这三个文件
其中在Func.cpp文件中定义了两个重载的func函数
我们知道编译分为4个阶段:

1.预处理:
头文件展开
宏替换
去注释
条件编译

Fun.h在Func.cpp和Test.cpp中展开
Func.cpp中同时拥有func函数的声明和定义,Test.cpp中拥有func函数的声明和具体调用

Fun.cpp ->  Fun.i
Test.cpp -> Test.i

2.编译:.i文件进行语法检查(语法分析,词法分析,语义分析)生成汇编代码(.s文件)
Fun.i  ->  Fun.s
Test.i ->  Test.s

3.汇编阶段:
把汇编代码转换为二进制机器码,生成目标文件(.o文件)
Fun.s -> Fun.o
Test.s -> Test.o

4.链接阶段:
合并.o目标文件,链接一些没有确定的函数的地址,合并段表,符号表的重定位等等
生成可执行程序:
Windows: .exe,
Linux:   a.out
而这个函数名修饰规则就是在链接阶段进行的
在预处理阶段结束后
Func.cpp中同时拥有func函数的声明和定义,Test.cpp中拥有func函数的声明和具体调用
所谓声明就是一种承诺,是承诺,就要兑现
而链接阶段就是这个承诺兑现的时候
怎么兑现呢?让我的Test.cpp能够找到func函数的定义,就是兑现

怎么找到呢?
(通过函数声明去找地址)
.o文件中有一个东西叫做符号表,符号表中存储了函数名跟函数地址的一种映射关系
在链接阶段,通过符号表跟一种映射关系找到函数的地址,就能进行函数的调用了

而对于这个符号表来说
在C语言中,符号表中只会建立函数名跟函数地址的映射关系,
也就决定了在C语言中不允许存在同名函数,否则在链接阶段会找到多个函数地址,产生歧义

而对于C++来说
有函数名修饰规则:把函数的参数代入进去对符号表中的映射进行修饰
在Linux下可以尝试看到这个名字
Linux下函数名修饰规则:
_Z4func(_Z是前缀+函数名的字符个数+函数名+参数首字母)

_Z4funcdi(第一个参数类型:double,第二个:int)
_Z4funcid(第一个参数类型:int,第二个:double)

int* :Pi
有兴趣,可以自己在Linux下去试试

下面我们在Linux下给大家看一看
我们在Linux下建立了两个文件:
test.c
test.cpp
先看.c:
在这里插入图片描述
cpp:
在这里插入图片描述
然后我们用gcc把test.c编译出来,编译成testc
在这里插入图片描述
然后用这个命令查看testc的内容
在这里插入图片描述
这个 < func>前面的就是它的地址,也就是第一个指令的地址,
而且我们发现这个函数名根本就没有被修饰
在这里插入图片描述
下面我们来看一下.cpp文件
先用g++把test.cpp编译成了testcpp
在这里插入图片描述
还是用这个命令进行查看
在这里插入图片描述
然后我们发现C++编译后的函数名的确被修饰了
修饰成了

_Z4funcid

在这里插入图片描述
大家也可以试一下其他的类型,指针的话:
例如int* 类型的是:会被修饰为Pi

下面我们就可以回答这个问题了:

为什么C语言不支持函数重载,而C++支持函数重载呢?

因为在链接阶段

C语言文件的函数地址是完全只通过函数名去进行查找的,如果存在同名函数,会导致找到多个函数地址,让函数调用产生歧义

而C++文件的函数名经过了修饰,那么如果两个函数名相同,但是参数不同就可以进行区分了
所以对于构成重载的函数,只会找到那唯一一个,不会产生歧义

Linux下函数名修饰规则:
_Z4func(_Z是前缀+函数名的字符个数+函数名+参数首字母)

注意:不同编译器下的函数名修饰规则是不同的

那么为什么我刚才不在windows下演示呢?
因为windows下的函数名修饰太过复杂
我们把Func.cpp中的代码注释掉,让它发生链接错误
在这里插入图片描述
看到蓝色标注的地方,windows下也是一个类型对应一个符号,不过不像Linux下那么直观

以上就是C++入门1的全部内容,希望能对大家有所帮助

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从零开始学习调用百度地图网页API:二、初始化地图,鼠标交互创建信息窗口

目录 代码结构headbodyscript 调试 代码 <!DOCTYPE html> <html> <head><meta http-equiv"Content-Type" content"text/html; charsetutf-8" /><meta name"viewport" content"initial-scale1.0, user-scalable…

进阶JAVA篇- Math 类和 System 类和 Runtime 类的常用API(三)

目录 API 1.0 Math 类的说明 1.1 Math 类中的 abs() 方法 1.2 Math 类中的 ceil () 方法 1.3 Math 类中的 floor () 方法 1.4 Math 类中的 round () 方法 1.5 Math 类中的 max() 和 min() 方法 1.6 Math 类中的 pow(double a , double b) 方法 1.7 Math 类中的 random&a…

案例|美创科技守护健康“一盘棋”,医共体整体数据安全建设实践

以医共体之“通”&#xff0c;破解看病之“痛”。在县域组建医疗共同体&#xff0c;逐步实现区域内医疗资源共享&#xff0c;推动形成基层首诊、双向转诊、急慢分治、上下联动的分级诊疗模式&#xff0c;是实现“首诊在基层、大病不出县”&#xff0c;更好地为全县人民群众服务…

生产环境中常用Linux命令

太简单的我就不讲解啦,浪费时间,直接将生产中常用的 文章目录 1.总纲2.整机 top3.CPU vmstat3. 内存 free4. 硬盘: df5. 磁盘IO iostat6. 网络IO ifstat7: 内存过高的情景排查 1.总纲 整机:topcpu:vmstat内存:free硬盘:df磁盘io: iostat网络io:ifstat 2.整机 top 首先们要查…

阿里云服务器10M带宽收费价格表

阿里云服务器10M公网带宽收费价格表&#xff0c;地域不同带宽价格不同&#xff0c;阿里云百科以华东2&#xff08;杭州&#xff09;地域为例&#xff0c;阿里云10M带宽一年85折优惠价格5355元&#xff0c;10M带一个月525元&#xff0c;阿里云百科aliyunbaike.com分享阿里云服务…

第二证券:全涨停,上市以来首次!

10月12日&#xff0c;国内产品商场大面积飘红&#xff0c;其间有色、化工板块上涨明显&#xff0c;碳酸锂期货自本年7月份上市以来初次呈现合约悉数触及涨停&#xff0c;到收盘时&#xff0c;主力合约LC2401上涨10750元/吨&#xff0c;涨幅6.97%&#xff0c;报164950元/吨。 碳…

pytorch学习第三篇:梯度

下面介绍了在pytorch中如何进行梯度运算,并介绍了在运行梯度计算时遇到的问题,通过解决一个个问题,来深入理解梯度计算。 梯度计算 import torch x = torch.rand(3,4,requires_grad=True) b = torch.rand(4,3,requires_grad=True) print(x,b)y = x@bt = y.sum()求导数 t.…

CrossOver2024下载安装详细图文教程

本文将集中为各位小伙伴们介绍一下类虚拟机软件CrossOver Mac是如何进行下载、安装教程。 1、双击下载好的文件&#xff08;若为压缩文件&#xff0c;请先解压&#xff09;&#xff0c;随后弹出“是否要把程序移动到应用程序文件夹中&#xff1f;”&#xff0c;一般我们选择移…

快排超详细,Leetcode排序数组题目带你升华掌握

大家好&#xff0c;这里是Dark FalmeMater。 这篇文章我将超级仔细地讲解快速排序&#xff0c;快排之所以叫快排&#xff0c;到底有多快&#xff0c;为什么这么快&#xff0c;还有快速排序的优化和改进&#xff0c;通过这篇文章你一定会对快排有进一步的掌握。 文章目录 Hoare版…

消息队列缓存,以蓝牙消息服务为例

前言 消息队列缓存&#xff0c;支持阻塞、非阻塞模式&#xff1b;支持协议、非协议模式 可自定义消息结构体数据内容 使用者只需设置一些宏定义、调用相应接口即可 这里我用蓝牙消息服务举例 有纰漏请指出&#xff0c;转载请说明。 学习交流请发邮件 1280253714qq.com 原…

4D视频数据集

RealGraph: A Multiview Dataset for 4D Real-world Context Graph Generation RealGraph是一个全新的4D视频数据集&#xff0c;旨在支持“Context Graph Generation (CGG)”任务。CGG任务的目标是从动态场景的校准多视图视频中恢复出物体的语义信息&#xff0c;包括坐标、轨迹…

Idea报错 java: 程序包org.springframework.boot不存在 解决方法

发现我的是因为更改了maven的主路径和本地仓库路径&#xff0c;但是新建了一个工程后&#xff0c;设置就恢复默认了。需要重新设置正确路径。 应用后会重新下载依赖项 之后虽然还会报错&#xff0c;但是已经不影响项目运行&#xff0c;配置成功

高速数字化仪和AWG在车辆总线(CAN/LIN/PSI5)测试中的应用(一)

引言 模块化仪器比传统仪器的尺寸大大减小&#xff0c;适合安装在电路卡上&#xff0c;同时也可以将多个卡插入具有通用计算机接口、电源和互连的框架中。模块化仪器框架包括使用标准PCIe接口的计算机、PXI测试框架或基于LXI的盒子&#xff0c;工程师通常会使用多个卡并将其配…

基于Docker-compose搭建LNMP

1、配置nginx 创建nginx目录上传所需压缩包将wordress解压到指定路径下 配置Dockerfile文本文件 vim DockerfileFROM centos:7 MAINTAINER this is nginx image <zgc> RUN yum -y install pcre-devel zlib-devel gcc gcc-c make RUN useradd -M -s /sbin/nologin nginx…

【RcoketMQ】RcoketMQ 5.0新特性(二)- Pop消费模式

Pop模式消费和消息粒度负载均衡 在RocketMQ 5.0之前&#xff0c;消费有两种方式可以从Broker获取消息&#xff0c;分别为Pull模式和Push模式。 Pull模式&#xff1a;消费需要不断的从阻塞队列中获取数据&#xff0c;如果没有数据就等待&#xff0c;这个阻塞队列中的数据由消息…

springBoot 自动配置机制

springBoot 自动配置机制 自动配置的tomcat、springmvc等默认包扫描规则自定义扫描路径配置默认值按需加载自动配置总结 自动配置的tomcat、springmvc等 导入场景&#xff0c;容器中就会自动配置好这个场景的核心组件 以前&#xff1a;dispatcherservlet、viewresolver、chara…

MyCat分片规则

MyCat是一个开源的数据库中间件&#xff0c;它可以实现对MySQL数据库进行分片和负载均衡。在分片规则方面&#xff0c;MyCat支持以下几种常见的分片方式&#xff1a; 范围分片 根据指定的字段及其配置的范围与数据节点的对应情况&#xff0c; 来决定该数据属于哪一个分片。 …

LeetCode【438】找到字符串中所有字母异位词

题目&#xff1a; 注意&#xff1a;下面代码勉强通过&#xff0c;每次都对窗口内字符排序。然后比较字符串。 代码&#xff1a; public List<Integer> findAnagrams(String s, String p) {int start 0, end p.length() - 1;List<Integer> result new ArrayL…

Leetcode——统计数组中的元素练习

错误的集合 此题没做出来 class Solution { public:vector<int> findErrorNums(vector<int>& nums) {vector<int> errorNums(2);int n nums.size();sort(nums.begin(), nums.end());// 记录上一个元素int prev 0;for (int i 0; i < n; i) {int cu…

什么是指标体系,怎么搭建一套完整的指标体系?(附PDF素材)

什么是指标体系&#xff0c;怎么搭建一套完整的指标体系&#xff1f;数字化转型过程中&#xff0c;这个问题一直困扰着数据分析师。主要体现在&#xff1a; 各部门根据业务需求&#xff0c;都有一部分量化指标&#xff0c;但不够全面&#xff0c;对企业整体数据分析应用能力提…