【C++入门篇】保姆级教程篇【上】

news2025/2/26 23:22:58

目录

一、第一个C++程序

二、C++命名空间

        1)什么是命名空间?

        2)命名空间的使用

        3) std库与namespace展开

        4)命名空间的嵌套使用 

三、输入输出方式

四、缺省参数

        1)什么是缺省参数?

        2)多个缺省值的缺省参数

五、函数重载

        1)什么是函数重载?

        2)为什么C++可以用函数重载? 

六、C++引用与指针

        1)什么是引用?

        2)引用的规则特点:

        1、引用必须初始化才能用

        2、引用不能传空指针

​编辑  

     3、一个变量或对象可以有多个别名

​编辑

        4、没有所谓的二级引用

​编辑

        5、引用不能改变指向

        3)引用与指针的区别?

        4)引用的使用

七、内联函数

        1)什么是内联函数?

        2)内联函数的特性


前言:

        说到C++大家总会想到C语言,毕竟C++也就是C plus plus 么,没有错,C++在语法上是兼容C语言的。我们C++的祖师爷本贾尼·斯特劳斯特卢普在写C程序的时候对于C的一些语法规则感到不合适,于是祖师爷在C的基础上开发了这样一门语言。今天,我们就要开启C++世界的大门了。

一、第一个C++程序

说到学习新的语言,那就不得不写下人生中第一个C++程序了————你好,世界。

#include<iostream>

using namespace std;

int main()
{
	cout << "Hello World!\n";
	return 0;
}

        是不是有当年学C语言那味了,首先我们来分析一下是如何打印出来"Hello World!"。

        我们在C语言中是用printf函数打印字符串的,在C++中是用cout(console out:控制台输出)来向控制台输出内容的,在C语言中printf函数对不同类型的数据有对应的输出格式访问控制符像%d,%s...才会打印出对应类型的数据,而在C++中的cout会自动识别变量类型,相比之下写起来更加方便。

        而在cout 后面跟着 '<<'叫做流插入限定符,表示在‘<<’右边的数据流向左边,cout << "hello world\n"; 就是将字符串信息流 流入到控制台当中打印

        那么知道了cout和流插入限定符就可以打印了吗?很遗憾告诉你,还是不行,这就要涉及到using namespace std;这条语句了,那这是什么意思呢?那个头文件也和C语言也不一样啊,又是什么意思呢?让我来一一为你介绍。


二、C++命名空间

        1)什么是命名空间?

        话说在祖师爷那个年代C语言是主流的高级语言,当然祖师爷也不例外,写项目也是用的C语言,其中祖师也在写大型项目的时候总会遇到这样一个问题:不同的程序员负责实现不同的模块,但是在最后整合的时候总是会有两个程序员用的变量或函数的名字相同。例如:

#include<iostream>
#include<stdio.h>//C语言中printf函数所需要的头文件

int printf = 1;

int main()
{
	printf("%d", printf);
	return 0;
}

        这种命名冲突要改是很麻烦的,祖师爷经常被这个东西搞得头疼,所以祖师爷在开发C++的时候直接规定了一种关键字来避免这种情况————namespace(命名空间)

        命名空间就是使用 namespace + 空间名 在namespace内部会自动生成“一堵墙”, 这堵墙将namespace内部内容的命名与整个程序以及库里的程序隔开,互不影响,就像这个世界上不止一个人叫张三,但是他们并不是同一个人。


        2)命名空间的使用

        那么我们知道了命名空间,但是该如何使用呢?我们把可能会冲突的变量或者函数放进命名空间内,在外部想要调用命名空间内的内容就需要  ‘::’  叫做域作用限定符,是访问namespace的专用符号,使用方法是:空间名::内部变量/函数等,例如下面代码:

#include<iostream>

namespace byte{
	
	int printf = 1;
	
}

int main()
{
	std::cout << byte::printf;
	return 0; 
 } 

 这样就可以输出printf这个变量了,就不会造成命名冲突的问题。


        3) std库与namespace展开

        有些时候我们在命名空间内的函数或者变量在外部要多次调用的情况,每次调用之前都要加上空间名和域作用限定符,也是一件挺麻烦的事情,例如:

#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>

namespace byte{
		
	typedef int STDataType;
	typedef struct Stack
	{
		STDataType* _a;
		int _top;		// 栈顶
		int _capacity;  // 容量 
	}Stack;
	
	// 初始化栈 
	Stack* StackInit(STDataType n)
	{
		Stack *p = (Stack *)malloc(sizeof(Stack));
		//...
		p -> _a = (STDataType *)malloc(sizeof(STDataType) * n);
		//...
		p -> _top = -1;
		p -> _capacity = n;
		return p;
	}
	
	// 入栈 
	void StackPush(Stack* ps, STDataType data)
	{
		assert(ps);
		//...
		ps -> _a[++ps -> _top] = data;
		return;
	}
	
	// 出栈 
	void StackPop(Stack* ps)
	{
		assert(ps);
		if(ps -> _top > -1)
		{
			ps -> _top -= 1;
		}
		return;
	}
	
}

void Test()
{
	byte::Stack *ps = byte::StackInit(5);
	byte::StackPush(ps, 1);
	byte::StackPush(ps, 1);
	byte::StackPush(ps, 1);
	byte::StackPush(ps, 1);
	byte::StackPop(ps);
	//... 
}

int main()
{
	Test();
	return 0; 
 } 

        我们来模拟栈的实现(没有全部写出来),把栈的操作放在namespace里面在Test()中想要访问栈每次都需要在造作前面加上这么一些东西,写起来也很麻烦,所以祖师爷就规定了一种配套的关键字——using,使用方法是:using namespace 空间名;这样就可以展开命名空间,也就是打开那堵墙,在使用时就不需要加上前面那一大坨了,但这个时候就不能保证命名冲突

我们只需在命名空间下面加上这样一条语句:using namespace byte;

这样编译的效果和上面代码效果就是相同的了。

        namespace还有一种局部展开的方式,将命名空间内的常用的变量或函数名局部展开防止命名空间内的其他变量会与程序发生冲突,使用方法是:using 空间名::变量/函数名等 这样也是比较常用的展开方式。例如:

#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>

namespace byte{
		
	typedef int STDataType;
	typedef struct Stack
	{
		STDataType* _a;
		int _top;		// 栈顶
		int _capacity;  // 容量 
	}Stack;
	
	// 初始化栈 
	Stack* StackInit(STDataType n)
	{
		Stack *p = (Stack *)malloc(sizeof(Stack));
		//...
		p -> _a = (STDataType *)malloc(sizeof(STDataType) * n);
		//...
		p -> _top = -1;
		p -> _capacity = n;
		return p;
	}
	
	// 入栈 
	void StackPush(Stack* ps, STDataType data)
	{
		assert(ps);
		//...
		ps -> _a[++ps -> _top] = data;
		return;
	}
	
	// 出栈 
	void StackPop(Stack* ps)
	{
		assert(ps);
		if(ps -> _top > -1)
		{
			ps -> _top -= 1;
		}
		return;
	}
	
}

using byte::StackPush;
using byte::StackPop;

void Test()
{
	byte::Stack *ps = byte::StackInit(5);
	StackPush(ps, 1);
	StackPush(ps, 1);
	StackPush(ps, 1);
	StackPush(ps, 1);
	StackPop(ps);
	//... 
}

int main()
{
	Test();
	return 0; 
 } 

        这样不经常使用的和命名冲突的就可以不展开使用了,常用的变量或函数就可以来展开使用,避免了不必要的麻烦。

        想必你也发现了,我们在最开始打印hello world的时候发现有这样一条语句:using namespace std;实际上std也是一种命名空间,只不过std是C++库的命名空间里面有很多用得到的函数模版等等,东西非常多,其中cout等也在std库内,所以使用的时候要展开命名空间。

        值得注意的是,我们前面也说了,如果展开命名空间就不能保证命名冲突的问题了,而且std库内的的内容很多,保不准就会发生命名冲突,所以在写大型项目时最好不要展开std,但是在日常的练习中还是展开的。


        4)命名空间的嵌套使用 

        我们在使用命名空间内容比较多的时候,也保不准命名空间内会出现命名冲突,所以C++就规定了可以允许命名空间嵌套命名空间,例如:

#include<iostream>

namespace ptr{
	
	namespace spa1{
		int ptr = 1;
	}
	
	namespace spa2{
		int ptr = 2;	
	}
	
	namespace spa3{
		int ptr = 3;
	}
}

using std::cout;

int main()
{
	cout << "spa1:  " << ptr::spa1::ptr << std::endl;
	cout << "spa2:  " << ptr::spa2::ptr << std::endl;
	cout << "spa3:  " << ptr::spa3::ptr << std::endl;
	return 0;
}

         在C++的一些库里这种方式也很常见,但是嵌套太多层也是坑的很,还是谨慎使用嵌套功能为好。


三、输入输出方式

        C++的输出方式在最开始也已经提到了,cout:控制台输出,<<:流插入运算符。那么我们输出有了,我们输入呢?

        在C语言中,我们输入的方式是调用<stdio.h>中的scanf函数来进行输入,与printf一样也需要输入格式访问控制符才能对输入数据类型进行判断。

        在C++中,我们的输入为:cin(console in控制台输入),搭配'>>'(流提取运算符)使用,使用方式为:

std::cin >> 变量;//其中cin与cout一样会自动识别变量的类型

         其中我们在使用输入输出的时候就需要包含头文件<iostream>也就是输入输出流文件,保证cout和cin的正常输入输出的使用。

        其中cin和cout都是在std库内的,所以之前在使用的时候要展开std命名空间,这里在介绍一种C++中常用的换行符,不是'\n'而是叫做:endl(end line 结束行) 通常在cout结尾处使用,例如:

#include<iostream>

int main()
{
	std::cout << "Hello World" << std::endl;
	return 0;
}

 其中endl也是内置在std库里的,这样写也是会有换行效果的。

        到这里你可能还有一些疑问,我们如果想要对浮点数进行精度控制,C++是不是也有新的语法规则来写呢?很遗憾并没有,但是C++语法是兼容C的,所以如果想要对浮点数进行精度控制的时候,我们直接用printf函数进行精度控制就行


四、缺省参数

        1)什么是缺省参数?

        祖师爷对C语言的函数部分也不是很满意,例如在栈的数据结构中,在栈的初始化期间,需要传参capacity容量来给栈开辟空间大小,在C语言中我们每次初始化时都需要给个值,祖师爷觉得有些麻烦,所以在C++里面出现了一个叫做缺省参数的语法规则在函数传参时直接对参数进行赋值

Stack *InitNewStack(int capacity = 3)
{
	//...
}

 这样在调用这个函数时,不传参数就默认capacity初始化为3, 传参就以传的参数为准。

        那么什么是缺省参数呢?实际上,缺省参数是声明和定义函数时为函数的参数指定一个缺省值,在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参

例如:

#include<iostream>

using std::cout;
using std::cin;
using std::endl;

void Func(int a = 0)
{
	cout << a << endl;
}

int main()
{
	Func();//没有参数时使用形参默认值
	Func(1);//有参数时使用指定实参
	return 0;
}

        这就是缺省参数的具体用法。


        2)多个缺省值的缺省参数

        实际上,缺省参数可以有多个缺省值,而且在多个缺省值当中有着全缺省与半缺省之分全缺省参数的函数在调用时没有传实参就会进行自动采用该参数的缺省值为参数,如果传参就以实参为参数,这点与上面的相同。

        如果我们在全缺省函数传参传不完整参数会发生什么?我们不妨看以下代码:

#include<iostream>

using std::cout;
using std::cin;
using std::endl;

void Func(int a = 0, int b = 1, int c = 2)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl;
}

int main()
{
	Func();//不传参数
	cout << endl;
	Func(5);//传一个参数
	cout << endl;
	Func(5, 6);//传两个参数
	cout << endl;
	Func(5, 6, 7);//传三个参数
	cout << endl;
	return 0;
}

         

        我们可以看到,全缺省参数的函数是可以传空参的,也可以传不完整的参数,同时,不知道聪明的你有没有发现,这里传参有个规律:当Func(5),Func(5, 6)的时候,Func(5)是将第一个参数初始化,后面两个参数为缺省值,Func(5, 6)是将前两个参数初始化,最后一个参数为缺省值。这其实就是祖师爷规定的默认传参顺序,对于全缺省函数传不完整参数,是从左到右进行传参的

        或许你又会有疑问,能不能前面不传参,后面传参?或者只有中间值传参?例如:

Func( , 6, 7); 或 Func( , 6 , ); 

         实际上并不存在这种传参的方式,C++中这样是会报错的,所以缺省参数只能顺序传参。

还有一种叫做半缺省参数的函数,所谓半缺省就是函数参数一部分是缺省参数,一部分是普通参数,这类函数被称为半缺省参数函数,而且半缺省参数函数的缺省值只能从右往左给,例如:

#include<iostream>

using std::cout;
using std::cin;
using std::endl;

void Func(int a, int b = 1, int c = 2)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl;
}

int main()
{
	Func(0);
	cout << endl;
	Func(5);
	cout << endl;
	Func(5, 6);
	cout << endl;
	Func(5, 6, 7);
	cout << endl;
	return 0;
}

        这个函数就是一个半缺省函数 ,a没有缺省值,只有b,c有缺省值,那么运行起来会发生什么事呢?

        我们发现在Func(5, 6)中, 传的参数是依旧是从左往右进行传参的,既然如此,我们半缺省函数能不能缺省后边的值或者中间的值呢?

#include<iostream>

using std::cout;
using std::cin;
using std::endl;

void Func(int a = 0, int b, int c = 2)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl;
}

void Func2(int a = 0, int b = 1, int c)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl;
}

int main()
{
	return 0;
}

        这种会发生什么情况?         我们发现这两种情况会报错,但是为什么会报错?报错信息显示形参缺少默认实参,也就是说,我们在传不完整参数的时候其实是不能确定你要传的是缺省参数还是普通形参,所以干脆C++把这种半缺省方式定义为错误的语法方式,最终半缺省函数传参只能从右往左进行缺省

注意缺省参数函数的生命和定义不能同时出现缺省值,通常的做法是在声明时写缺省值,定义时默认不写


五、函数重载

        1)什么是函数重载?

        祖师爷不仅对函数的参数有意见,对函数的命名也很有意见,有些功能相似的函数,或许只是参数不同,但是却要好几个不同的命名,像在函数名后面加1,2,3...用来区分不同的函数,其实也就是为了解决一词多义的问题,就例如网络段子“中国足球谁也赢不了,中国乒乓球谁也赢不了”,虽然都是赢不了,但是意义却不一样,祖师爷觉得这样很麻烦,不如干脆用同一个函数名得了,于是C++中出现了函数重载这一语法规则。

         实际上,函数重载是函数的一种特殊情况,C++允许在同一个作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的问题

        函数重载又分为:1、参数类型不同。2、参数个数不同。3、参数顺序不同。代码如下:

#include<iostream>

using namespace std;

//1、参数类型不同 
int f(int a, int b)
{
	cout << "f(int): " << a + b << endl; 
	return a + b;
}

double f(int a, double b)
{
	cout << "f(double): " << a + b << endl;
	return a + b;
}

//2、个数不同 
void f2(int index)
{
	cout << "f2(int index)" << endl;
}

void f2()
{
	cout << "f2(NULL)" << endl;
}

//3、顺序不同
void f3(int a, double b)
{
	cout << "f3(int, double)" << endl;
}

void f3(double a, int b)
{
	cout << "f3(double, int)" << endl;
}

int main()
{
	f(5, 5);
	f(3, 3.5);
	
	f2(0);
	f2();
	
	f3(4, 4.4);
	f3(4.4, 4);
	return 0; 
}

         以上都是函数重载的方式的具体用法。

        值得注意的是这里并没有说返回值不同而造成函数的重载,实际上仔细想想,如果两个函数都是相同的,只有返回值不一样,那么究竟是调用哪个函数呢?这就是造成重载的二义性的原因。


        2)为什么C++可以用函数重载? 

        在学习完函数重载的过程中,有没有思考这样一个问题:为什么这么好用的东西C语言不支持呢?其实这里涉及到程序的编译与链接,实际上程序在从写下来到打印到控制台上需要经历预处理、编译、汇编、链接的几个过程,如果对于这几个过程没有一点概念的同学可以看看我的这篇文章:C语言预编译详解,可以稍微了解一些。

        实际上,重载函数在编译生成汇编的过程中,C语言对于函数名并没有什么特殊的变化,但是C++在编译生成汇编的过程中函数名会生成某种符号规则来确定这个函数是否为重载。        


六、C++引用与指针

        我们在日常生活中身边的朋友不免有些外号,比如我的好朋友玩的好的都叫他‘小李子’,只听过小李在校园传奇故事的同学都叫他‘李哥’,那么这个李哥,和前面的小李,指的就是同一个人,而引用在语法层面上的理解就是,引用就是取别名

        1)什么是引用?

        其实上面那个例子就已经能够说明什么是引用了,实际上,引用就是给变量取一个别名,编译器不会给它专门开一个空间,它与引用的变量共用同一块内存空间

        引用的格式如下:

类型& 引用变量名(对象名) = 引用实体;//左值引用

        这里&符号左右可以带空格可以不带空格,没什么实际影响, 我们来看一下如何给一个引用:

#include<iostream>
#include<stdio.h>

using namespace std;

int main()
{
    int a = 0;
    int &b = a;//b是a的别名
    cout << "a:" << a << endl << "b:" << b << endl;
    printf("%p\n",a);
    printf("%p\n",b);
    return 0;
}

         我们可以看到对于变量a,引用b是变量a的引用,变量b输出的内容是变量a的值,变量a与引用b都是指向同一片地址的。


        2)引用的规则特点:
        1、引用必须初始化才能用
#include<iostream>
#include<stdio.h>

using namespace std;

int main()
{
    int a = 1;
    int &b;
    return 0;
}

C++规定引用使用必须初始化。

        2、引用不能传空指针
#include<iostream>
#include<stdio.h>

using namespace std;

int main()
{
    int a = 1;
    int& b = nullptr;
    return 0;
}
  
     3、一个变量或对象可以有多个别名
#include<iostream>
#include<stdio.h>

using namespace std;

int main()
{
    int a = 1;
    int &b = a;
    int &c = a;
    int &d = a;
    cout << a << endl;
    cout << b << endl;
    cout << c << endl;
    cout << d << endl;
    return 0;
}
        4、没有所谓的二级引用
#include<iostream>
#include<stdio.h>

using namespace std;

int main()
{
    int a = 1;
  	int &b = a;
  	int &&pb = b;
    return 0;
}
        5、引用不能改变指向
#include<iostream>
#include<stdio.h>

using namespace std;

int main()
{
    int a = 1;
    int c = 2;
  	int &b = a;
  	int &b = c;
    return 0;
}

 以上便是引用的一些规则的特点。


        3)引用与指针的区别?

        汇编层面上来说,引用就是一个指针,但是不同的是,引用相当于常量指针,改变不了它所引用对象的地址

         在语法层面上来说:

1、引用是别名,指针存的是地址。

2、指针解引用要加上*,而引用是自动解引用的

3、引用不会分配空间,但是指针会分配空间

4、指针有空指针,但是引用没有空引用

5、指针运用自增运算符是指向下一位,而引用使用自增运算符是对内容+1

6、指针有多级指针,但是引用只有一级引用

7、对指针用sizeof是指针变量的大小,对引用sizeof是引用变量的大小

8、引用比指针更加安全


        4)引用的使用

        既然说到引用对象的地址不可改变,值可以变,对于指针来说,值和地都可以随意改变,他俩相比较下,引用对象的地址不可变,值可变,指针指向对象的地址可变,值也可变。当值不可变时又是什么情况呢?

#include<iostream>
#include<stdio.h>

using namespace std;

int main()
{
   	const int a = 1;
   	int &b = a;
    return 0;
}

          其实这个时候虽然a被加上了const变成了常量, 但是依然可以通过b对a的值进行修改,这种我们可以称之为权限放大,就是b的权限要高于a了,那么有权限放大就有权限缩小与平等权限,没错,实际上权限缩小就是对a不加任何修饰,对引用b加上const修饰,这样b不可修改,a却可以,平等权限就是两个变量前都加上const,这样就都不能改变了

//权限缩小
int a = 0;
const int &b = a;
//权限平等
const int c = 0;
const int &d = c;

        引用还有什么作用?我们不妨以指针的视角看一下,指针除了可以作为指针变量,指针还可以传参,还可以作为返回值。那么我们引用是否也可以传参,作为返回值呢? 

        答案是可以的,而且引用做返回值在一定程度上会提高程序的运行效率。这是因为我们在传参数时实际上是拷贝一份实参传给形参的,而加上了引用就不需要在进行拷贝了,便可以直接访问内容。

        而引用作为返回值也是比较奇怪的:

#include<iostream>
#include<stdio.h>

using namespace std;

int& Add(int a, int b)
{
    int c = a + b;
    return c;
}

int main()
{
    int a = 1, b = 2;
    int ind = Add(a, b);
    cout << ind << endl;
    return 0;
}

         首先,以引用作为返回值表示返回的ind是c的别名,这个就相当对在函数里返回一个局部指针,出了作用域就会销毁,但是现在的编译器都比较高级,可能会保留下来这个值,所以就能看到这个值是3,我们再看下面这段代码:

#include<iostream>
#include<stdio.h>

using namespace std;

int &Add(int a, int b)
{
	int c = a + b;
	return c;
}

int main()
{
   	int ind = Add(5,5);
   	cout << ind << endl;
   	
   	Add(3,4);
   	cout << ind << endl;
    return 0;
}

         这里我们两次调用了Add这个函数,可是两次的值都是第一次调用的结果(语法规定除了作用域为随机值,这里是进行了优化),第一次调用后将调用的c拷贝了一份给了ind,这时他俩并不指向同一块空间,所以第二次调用时并不会影响ind的值。

        但是我们想要正常运行且能多次调用呢?看看下面这段代码:

#include<iostream>
#include<stdio.h>

using namespace std;

int &Add(int a, int b)
{
	int c = a + b;
	return c;
}

int main()
{
   	int &ind = Add(5,5);
   	cout << ind << endl;
   	
   	Add(3,4);
   	cout << ind << endl;
    return 0;
}

        这里我们将ind为引用来接收引用的返回值,他们指向了同一块空间,多次调用时就不会是同一个结果了。


七、内联函数

        1)什么是内联函数?

        我们在C语言中其实有个很好用的东西————宏,但是学过C的都知道,宏很难用,虽然它写的程序运行很快,但是不能进行调试,特别容易出错,我们的祖师爷还是比较喜欢宏的,于是祖师爷去劣留优,也增加了一些新的规则,创建了一种新的关键字——inline关键字。

        内联函数也就是普通函数前面加上inline关键字就变成了内联函数,内联函数本质上和宏一样,都是对文本进行替换,而且可以对函数进行调试,这样可以节省很多函数调用销毁的开销,但同时会让目标文件变大。


        2)内联函数的特性

        这个时候你可能就会说了,那以后每个函数都用inline关键字不香吗?实际上内联函数的适用场景是短小、多次重复调用的函数,因为内联本质上还是文本替换,全都进行展开的话编译器会吃不消,所以编译器默认最多你的函数在10行左右及以下,inline才会有效,否则就是个普通的函数。

        内联函数的声明和定义不能分离,在预处理过程会进行文本替换,替换后函数的地址就找不到了,那么就会在运行时报错。


       创作不易,还望各位佬能多多三连【可怜】【可怜】~~

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

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

相关文章

html web前端 登录,短信验证码登录

html web前端 登录&#xff0c;短信验证码登录 1&#xff0c;手机号码格式校验 2&#xff0c;按钮点击60秒倒计时&#xff0c;按钮限制点击 3&#xff0c;验证码/或密码长度校验&#xff08;被注释&#xff0c;公司发的验证码长度不一致&#xff0c;不一定是6位&#xff09; 4…

LabVIEW应用开发——控件的使用(三)

接上文&#xff0c;这篇介绍簇Cluster控件。 LabVIEW应用开发——控件的使用&#xff08;二&#xff09; 1、簇Cluster 1&#xff09;创建 蔟控件又称为组合、集群控件&#xff0c;顾名思义它是一个类似于C语言的结构体的一个数据结构控件。在描述一个对象的时候&#xff0c;…

SAP POorPI RFC接口字段调整后需要的操作-针对SP24及以后的PO系统

文章目录 问题描述解决办法 问题描述 在SAP系统的RFC接口结构中添加了字段&#xff0c;RFC也重新引用到了PO系统&#xff0c;Cache和CommunicationChannel都刷新或启停了&#xff0c;但是新增的字段在调用接口的时候数据进不到SAP系统&#xff0c;SAP系统内的值也出不来。经过…

图像处理之《基于多MSB预测和Huffman编码的加密图像可逆数据隐藏》论文精读

一、文章摘要 随着云存储和隐私保护的发展&#xff0c;可逆数据隐藏在加密图像中(RDHEI)作为一种技术越来越受到人们的关注&#xff0c;它可以&#xff1a;在图像加密领域嵌入额外的数据&#xff0c;确保嵌入的数据可以无差错地提取&#xff0c;原始图像可以无损地恢复。本文提…

安卓 实现60s倒计时的CountDownTimer(小坑)

安卓 实现60s倒计时的CountDownTimer&#xff08;小坑&#xff09; 前言一、CountDownTimer 是什么&#xff1f;二、代码示例1.使用2.小坑的点误差及时取消 总结 前言 前段时间写倒计时没有用线程&#xff0c;想换一种实现方式结果踩了个小坑&#xff0c;特此记录。 一、Count…

no main manifest attribute, in xxx.jar

使用Docker运行一个SpringBoot应用时&#xff0c;出现如下图所示的错误信息 解决方案&#xff1a; SpringBoot应用的pom.xml文件中添加以下配置;重新打包即可 <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifac…

计算机网络——理论知识总结(上)

开新番&#xff0c;因为博主备考的学校计网只考察1/6的分值&#xff0c;而且定位偏向于送分题&#xff0c;因此在备考时并没有很高强度的复习。本帖基于王道考研的教辅总结归纳&#xff0c;虽然是408的教材&#xff0c;但忽略其中有难度的部分&#xff0c;如计算题、画图题等&a…

18.Raising and Lower Indexs

提高和降低张量索引 同样&#xff0c;使用的是非标准的符号。 我们对V和熟悉&#xff0c;一个是向量所在的空间&#xff0c;一个是协向量所在的 对偶空间 &#xff0c; 有一个问题&#xff1a; 有何办法能在V的向量与 的协向量之间 建立对应的关系&#xff1f; 换句话说&…

Git中 fork, clone,branch有什么区别?

一、是什么 fork fork&#xff0c;英语翻译过来就是叉子&#xff0c;动词形式则是分叉&#xff0c;如下图&#xff0c;从左到右&#xff0c;一条直线变成多条直线 转到git仓库中&#xff0c;fork则可以代表分叉、克隆 出一个&#xff08;仓库的&#xff09;新拷贝 包含了原来…

如何安装ubuntu22.04以及ubuntu各个版本配置国内源和ssh远程登录

目录 一.简介 二.配置root账号 三、配置IP地址 四、更换阿里云源 五、配置ssh&#xff0c;root可以远程登录安装ssh服务 VMware17.0安装教程(2023最新最详细)-CSDN博客 VMware虚拟机安装Ubuntu22.04教程&#xff08;2023最新最详细&#xff09;-CSDN博客 Ubuntu22.04&am…

JSX 中使用 js 表达式

学习目标&#xff1a; 能够在 JSX 中使用表达式 语法&#xff1a; {JS 表达式} function App() {// 1.识别常规变量const name 跟着老惠学前端// 2.原生js方法调用const age () > {return 25}//3.三元运算符const flag truereturn (<div className"App">…

webpack前端性能优化的操作有哪些?

一、背景 随着前端的项目逐渐扩大&#xff0c;必然会带来的一个问题就是性能 尤其在大型复杂的项目中&#xff0c;前端业务可能因为一个小小的数据依赖&#xff0c;导致整个页面卡顿甚至奔溃 一般项目在完成后&#xff0c;会通过webpack进行打包&#xff0c;利用webpack对前…

【算法|滑动窗口No.2】leetcode904. 水果成篮

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希望…

信号继电器驱动芯片(led驱动芯片)

驱动继电器需要配合BAV99&#xff08;防止反向脉冲&#xff09;使用 具体应用参考开源项目 电阻箱 sbstnh/programmable_precision_resistor: A SCPI programmable precision resistor (github.com) 这个是芯片的输出电流设置 对应到上面的实际开源项目其设置电阻为1.5K&…

【SA8295P 源码分析】111 - 使用 Infineon 工具升级DHU 的MCU 固件过程指导

【SA8295P 源码分析】111 - 使用 Infineon 工具升级DHU 的MCU 固件过程指导 系列文章汇总见:《【SA8295P 源码分析】00 - 系列文章链接汇总》 本文链接:《【SA8295P 源码分析】111 - 使用 Infineon 工具升级DHU 的MCU 固件过程指导》 打开 Infineon 工具 默认是没有工程的,需…

Unity之ShaderGraph如何实现全息投影效果

前言 今天我们来实现一个全息投影的效果&#xff0c;如下所示&#xff1a; 主要节点 Position&#xff1a;提供对网格顶点或片段的Position 的访问&#xff0c;具体取决于节点所属图形部分的有效着色器阶段。使用Space下拉参数选择输出值的坐标空间。 Time&#xff1a;提…

Cocos 系列教程 - 01 认识项目结构

(一)项目文件夹结构 初次创建并打开一个 Cocos Creator 项目后,开发者项目文件夹的结构如下: assets:资源目录 build:构建目录(在构建某平台后会生成该目录) library:导入的资源目录 local:日志文件目录 profiles:编辑器配置 temp:临时文件目录 package.js…

Java面向对象(基础)-- 类的成员之三:构造器(Constructor)

文章目录 一、介绍&#xff08;1&#xff09;理解和作用&#xff08;2&#xff09; 构造器的语法格式 二、举例剖析&#xff08;1&#xff09;构造器在哪&#xff08;2&#xff09;权限问题&#xff08;3&#xff09;声明构造器&#xff08;4&#xff09;声明多个构造器&#x…

shell-mysql备份通用脚本

代码&#xff1a; #!/bin/bash#这是一个mysql备份的通用脚本 #颜色设置 RED\E[1;31m GREEN\E[1;32m RES\E[0m#mysql备份参数 DB_USER"root" DB_PASSWORD"123456" DB_HOST"127.0.0.1" DB_NAME"docker" BACKUP_DIR"/mysql/backup/…

多线程与高并发

1.线程创建的3种方式 2.线程的状态切换步骤 3.线程的5中状态 Java中的线程的生命周期大体可分为5种状态。 1. 新建(NEW)&#xff1a;新创建了一个线程对象。 2. 可运行(RUNNABLE)&#xff1a;线程对象创建后&#xff0c;其他线程(比如main线程&#xff09;调用了该对象的sta…