C语言:函数

                                                 创作不易,友友们给个三连吧!! 

一、函数的概念

数学中我们见过函数的概念,例如y=kx+b,k和b都是常数,给任意一个x就可以得到y

         而C语言也引入了函数(function)这个概念,C语言中的函数就是一个完成某项特定任务一小段代码。而这段代码有自己的特殊写法和调用方法。

         因为C语言的程序是由无数个小的函数组合而成的,所以我们也把函数叫做子程序。

         也就是说:一个大的计算任务可以分解成若干个小任务(函数)来完成,而C语言作为一个面向过程的语言,每个函数的设置都是为了完成某些特定的任务,并且也可以在工程中是可以重复使用的,因此也提高了开发效率

综上,我们可以简单总结出函数的两个好处:

1、可以将一个大型的任务拆分成多个小任务,也方便程序员之间的协作。

2、函数本身是为了实现工程中的某个特定功能的,而该功能有些时候可能会使用多次,所以函数封装之后的重复使用可以有效提高开发效率。

而在C语言中存在这样两种类型的函数:

库函数:现成的,可以直接使用的函数

自定义函数:根据实际需要自己设计的函数

二、库函数

2.1 标准库和头文件

1、C语言只是规定了使用的语法规则

2、但C语言不提供库函数的

3、不过C语言的国际标准ANSI C规定了一些库函数的各种信息

比如说scanf:名字,参数,返回类型,函数的功能…………

4、而C语言的编译器厂商根据这些规定来实现这些函数

比如微软——MSVC——微软的团队就实现对应的库函数

        苹果——clang——苹果的团队就实现对应的库函数

5、库函数实现后,厂商们将这些库函数的具体实现隐藏起来,导入静态库,并将这些库函数根据功能的划分在不同的头文件中进行的声明,使得我们程序员可以通过对应的头文件去直接使用相应的库函数。

比如我们想要使用printf、scanf,就要通过头文件<stdio.h>(标准输入、标准输出有关库函数的头文件),这里面有这俩函数的声明。

6、库函数在编译器的标准库中,可以直接使用,所以不需要程序员自己去实现,大大提高了开发效率,同时库函数的实现往往是公司的一个团队一起完成的,所以基本上封装得很好,库函数的质量和执行效率都是更有保证的,所以我们能使用库函数的时候就尽量使用库函数,不能用库函数解决问题的时候才会去根据自己的需求创建自定义函数。

7、因为不同编译器的团队不同,所以不同编译器的库函数的实现细节可能略有差异,但因为都是根据国际标准去实现的,所以使用起来基本没有什么感觉,在有些编译器中可能会封装得更好,但是绝对不会低于国际标准。

比如memcpy函数在C语言标准中规定的是拷贝空间不重叠的内存,而memmove函数在C语言中规定的是拷贝空间重叠的内存。但是在vs2022中,memcpy也可以做到拷贝空间重叠的内存,但是在其他编译器可能就不一定了,所以我们使用的时候也要尽量根据标准去使用。

2.2 库函数的使用方法

库函数有非常多,要慢慢去学习,逐个击破。

库函数相关头⽂件:https://zh.cppreference.com/w/c/header

C/C++官⽅的链接:https://zh.cppreference.com/w/c/header

cplusplus.com:https://legacy.cplusplus.com/reference/clibrary/

比如sqrt

double sqrt (double x);

sqrt是函数名

x是函数的参数,表示调用函数需要传递一个double类型的值

 double是返回值类型,表示函数计算的结果是double类型的值

功能:Compute square root 计算平⽅根

            square root of x          返回平方根

头文件:<cmath>/<math.h>

2.3 库函数文档的一般格式

1. 函数原型

2. 函数功能介绍

3. 参数和返回类型说明

4. 代码举例

5. 代码输出

6. 相关知识链接

三、自定义函数

相比库函数,其实自定义函数更加重要,因为库函数远远不能满足我们的需求,而自定义函数使得我们写代码更具有创造性。

ret_type fun_name(形式参数)
{

}

ret_type是函数的返回类型:

1、函数的返回类型可以是char、int、short、double……这些内置类型,也可以是自定义类型

2、函数的返回类型也可以是void,void的意思是函数不需要返回值,也不需要返回值

注:即使我们不需要返回值,我们也要写void,不能省略,因为返回类型如果不写,默认的返回类型是int!!

test()
{
	int a = 0;
	printf("%d ", a);
}
int main()
{
	int a = test();
	printf("%d ", a);
}

运行结果:0 2  

3、函数需不需要返回值是根据实际情况来设计的

fun_name是函数名:

函数名是为了⽅便使⽤函数;就像⼈的名字⼀样,有了名字⽅便称呼,函数有了名字⽅便调⽤,所以函数名尽量要根据函数的功能起的有意义。比如说该函数的功能是实现加法,我们就起名Add

括号里放的是形式参数

1、函数的参数类型可以是char、int、short、double……这些内置类型,也可以是自定义类型

2、函数的参数如果是0个,也就是不需要参数,函数的参数类型可以写成void,void在这里表示函数没有参数,也不需要参数!!

注:如果我们不需要参数,括号里也没有写void:

void test()
{
	int a = 0;
	printf("%d ", a);
}
int main()
{
	test(1);
	test(1,2);
	test(1,2,3);
}

运行结果0 0 0  

我们发现因为test没有形参,所以没有办法接收对应的值,所以test不管传什么结果都是一样的,但是我们的test函数设计的时候就是不需要参数,这样子去使用显然不合适。

 如果我们在括号里写上void:

void test(void)
{
	int a = 0;
	printf("%d ", a);
}
int main()
{
	test(1);
	test(1,2);
	test(1,2,3);
}

 虽然最后的运行结果还是一样的,但是void会明确告诉编译器这个函数不需要传参,所以如果你在调用的传了参数,就会有警告

3、函数的参数可以有0个,也可以有多个,这个根据实际的需要来确定。

{ }括起来的就是函数体,也就是函数的定义(具体实现)

      函数的设计有点像这个工厂,参数是原材料,函数体里是材料的加工过程,而计算结果相当于产品。 

四、形参和实参

int Add(int x, int y)
{
	int z = 0;
	z = x + y;
	return z;
}
int main()
{
	int a = 0;
	int b = 0;
	//输⼊
	scanf("%d%d", &a, &b);
	//调⽤加法函数,完成a和b的相加
	//求和的结果放在r中
	int r = Add(a, b);
	//输出
	printf("%d\n", r);
	return 0;
}

调用Add函数传的参数a和b我们叫做实参,实参就是真实传递给函数的参数 

定义Add函数中的x和y就是形参,为什么叫做形参呢?实际上我们如果只是定义了Add函数而不去调用的话,Add函数的x和y只是形式上存在,并不会向内存申请空间,不会真实存在,所以叫形式参数。

形参只要在函数调用的过程中为了存放实参传递过来的值,才向内存申请空间,这个过程就是形参的实例化。

实参是传递给形参的,他们之间是有联系的的,但是形参和实参是在各自独立的空间!!

所以形参只是实参的一份临时拷贝 ,改变形参的值并不会影响实参!!

具体的过程可以参考博主的文章:C语言:底层剖析——函数栈帧的创建和销毁-CSDN博客

五、数组充当函数参数

有些时候我们需要将数组作为参数传递给函数,在函数内部进行操作。

⽐如:写⼀个函数对将⼀个整型数组的内容,全部置为-1,再写⼀个函数打印数组的内容。 简单思考⼀下,基本的形式应该是这样的:

int main()
{
 int arr[] = {1,2,3,4,5,6,7,8,9,10};
 set_arr();//设置数组内容为-1
 print_arr();//打印数组内容
 return 0;
}

      这⾥的set_arr函数要能够对数组内容进⾏设置,就得把数组作为参数传递给函数,同时函数内部在设 置数组每个元素的时候,也得遍历数组,需要知道数组的元素个数。所以我们需要给set_arr传递2个参 数,⼀个是数组,另外⼀个是数组的元素个数。仔细分析print_arr也是⼀样的,只有拿到了数组和元 素个数,才能遍历打印数组的每个元素。

void set_arr(int arr[], int sz)
{
 int i = 0;
 for(i=0; i<sz; i++)
 {
 arr[i] = -1;
 }
}
void print_arr(int arr[], int sz)
{
 int i = 0;
 for(i=0; i<sz; i++)
 {
 printf("%d ", arr[i]);
 }
 printf("\n");
}

数组传参的重要知识点: 

1、函数的实参是数组,形参也可以写成数组的形式

2、形参如果是一维数组,数组大小可以省略不写

3、形参如果是二维数组,行可以省略,但列不能省略

4、数组传参,形参是不会创建新的数组的,因为形参和实参操作的数组就是同一个数组!!

六、return语句

1、return后边可以是⼀个数值,也可以是⼀个表达式,如果是表达式则先执⾏表达式,再返回表达式的结果。

int Add(int x, int y)
{
	return x+y;
}
int main()
{
	int a = 0;
	int b = 0;
	//输⼊
	scanf("%d%d", &a, &b);
	//调⽤加法函数,完成a和b的相加
	//求和的结果放在r中
	int r = Add(a, b);
	//输出
	printf("%d\n", r);
	return 0;
}

2、return后边也可以什么都没有,直接写return; 这种写法适合函数返回类型是void的情况。

void print(int arr[], int n)
{
	if (n < 1)
		return;//因为n传小于1的数没有意义
	for (int i = 0; i < n; i++)
		printf("%d ", arr[i]);
}

3、return返回的值和函数返回类型不⼀致,系统会⾃动将返回的值隐式转换为函数的返回类型。

int test()
{
	return 3.5;
}
int main()
{
	int a = test();
	printf("%d", a);
}

输出结果:3 

4、return语句执⾏后,函数就彻底返回,后边的代码不再执⾏。

void print(int arr[], int n)
{
	if (n < 1)
		return;
	for (int i = 0; i < n; i++)
		printf("%d ", arr[i]);
}
int main()
{
	int a[10] = { 1,2,3,4,5,6,7,8,9,10 };
	print(a, 0);
}

什么也没输出,因为传进去的n等于0,直接返回了。 

5、如果函数中存在if等分⽀的语句,则要保证每种情况下都有return返回,否则会出现编译错误。

//如果是奇数返回1,是偶数返回0
int test()
{
	int n = 0;
	scanf("%d", &n);
	if (n % 2 == 1)
	return 1;
}

 这样写是有问题的,因为没有考虑是偶数的时候应该返回什么

int test()
{
	int n = 0;
	scanf("%d", &n);
	if (n % 2 == 1)
	return 1;
	else
	return 0;
}

七、嵌套访问

       嵌套调⽤就是函数之间的互相调⽤,每个函数就⾏⼀个乐⾼零件,正是因为多个乐⾼的零件互相⽆缝 的配合才能搭建出精美的乐⾼玩具,也正是因为函数之间有效的互相调⽤,最后写出来了相对⼤型的程序。

int is_leap_year(int y)
{
 if(((y%4==0)&&(y%100!=0))||(y%400==0))
 return 1;
 else
 return 0;
}
int get_days_of_month(int y, int m)
{
 int days[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 int day = days[m];
 if (is_leap_year(y) && m == 2)
 day += 1;
 
 return day;
}
int main()
{
 int y = 0;
 int m = 0;
 scanf("%d %d", &y, &m);
 int d = get_days_of_month(y, m);
 printf("%d\n", d);
 return 0;
}

这⼀段代码,完成了⼀个独⽴的功能。代码中反应了不少的函数调⽤:

• main 函数调⽤ scanf 、 printf 、 get_days_of_month

• get_days_of_month 函数调⽤ is_leap_year

未来的稍微大⼀些代码都是函数之间的嵌套调用,但是函数是不能嵌套定义的。 

八、链式访问

       所谓链式访问就是将⼀个函数的返回值作为另外⼀个函数的参数,像链条⼀样将函数串起来就是函数的链式访问。

#include <stdio.h>
int main()
{
 printf("%d\n", strlen("abcdef"));//链式访问
 return 0;
}

 strlen的返回值作为printf的参数

下面有一段有趣的代码,我们来探究一下他的执行结果

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

 printf函数返回的是打印在屏幕上的字符的个数。

上⾯的例⼦中,我们就第⼀个printf打印的是第⼆个printf的返回值,第⼆个printf打印的是第三个 printf的返回值。

第三个printf打印43,在屏幕上打印2个字符,再返回2

第⼆个printf打印2,  在屏幕上打印1个字符,再放回1

第⼀个printf打印1      所以屏幕上最终打印:4321

九、函数的声明和定义

9.1 单个文件

       一般我们习惯将main函数需要调用的函数写在main函数的前面,但是在以后有些大型工程的情况下避免不了函数的相互之间调用,这个时候就不得不把有些函数写在下面了!!而定义写在下面然后去调用的话编译器是会报错的

         因为编译器在对代码进行编译的时候是从第一行开始扫描的,如果我们在main函数中要调用的函数的定义写在main函数的下面,那么当编译时扫到这里的时候并不认识该调用函数,就会直接报错,为了避免这种情况,我们就需要进行函数声明

函数声明的作用就是告诉编译器,这个函数是被定义过的,虽然编译器看不到他的实现,但是至少让编译器认识这个函数,在扫描到他被调用的时候就不会报错!!

int is_leap_year(int y);//函数声明
int main()
{
 int y = 0;
 scanf("%d", &y);
 int r = is_leap_year(y);
 if(r == 1)
 printf("闰年\n");
 else
 printf("⾮闰年\n");
 return 0;
}
//判断⼀年是不是闰年
int is_leap_year(int y)
{
 if(((y%4==0)&&(y%100!=0)) || (y%400==0))
 return 1;
 else
 return 0;
}

函数声明:

int is_leap_year(int y);

函数定义:

int is_leap_year(int y)
{
 if(((y%4==0)&&(y%100!=0)) || (y%400==0))
 return 1;
 else
 return 0;
}

函数调用:

int r = is_leap_year(y);

所以

1、函数的调用一定要先声明后使用! 

2、函数的定义本身也是一种特殊的声明,所以如果函数定义放在调用之前也是可以的。

9.2 多个文件

       一般来说,以后面对大项目的时候,代码可能会比较多,我们不会把代码放在一个文件里,往往会根据程序的功能,将代码拆分到多个文件中。

好处:

1、逻辑清晰

2、方便协作

3、方便代码的隐藏(想让别人使用,但是不想让别人看到里面的源码实现)

一般情况下,函数的声明、类型的声明放在头文件(.h)中,函数的实现是放在源文件(.c)中的,当我们需要去使用这些函数的时候,包含我们自定义的头文件即可!!

add.c(add函数的实现)

//函数的定义
int Add(int x, int y)
{
 return x+y;
}

add.h(add函数的声明)

//函数的声明
int Add(int x, int y);

 test.c(测试)

int main()
{
 int a = 10;
 int b = 20;
//函数调⽤
 int c = Add(a, b);
 printf("%d\n", c);
 return 0;
}

十、static和extern(重点)

static 和 extern 都是C语⾔中的关键字。

static是静态的意思,可以⽤来:

• 修饰局部变量

• 修饰全局变量

• 修饰函数

而extern是⽤来声明外部符号的。

10.1 extern

在一个文件中定义了变量和函数, 在其他文件中要使用它们, 可以有两种方式:

1、使用头文件,然后声明它们,然后其他文件去包含头文件

2、在其他文件中直接extern。

extern 是⽤来声明外部符号的,如果⼀个全局的符号在A文件中定义的,在B文件中想使用,就可以使 ⽤ extern 进⾏声明,然后使⽤。

10.2 作用域和生命周期

作⽤域(scope)是程序设计概念,通常来说,⼀段程序代码中所⽤到的名字并不总是有效(可⽤) 的,⽽限定这个名字的可⽤性的代码范围就是这个名字的作⽤域。

1. 局部变量的作⽤域是变量所在的局部范围。(在{  }内部)

int main()
{
	int i = 0;
	int b = 20;

	for (i = 0; i < 10; i++)
	{
		int a = 10;
		printf("b = %d\n", b);
	}
	printf("a = %d\n", a);//err
	printf("b = %d\n", b);
	return 0;
}

     作用域可以直接看{ },对于a来说,他的作用域就在for循环的{ }中,出了作用域就会被销毁,所以打印不了a,但是b的作用域在main函数的{ }中,所以可以打印b! 

2. 全局变量的作⽤域是整个⼯程(项⽬)。(相当于共享单车,谁都可以用)

int c = 100;//全局变量

void test()
{
	printf("c = %d\n", c);
}

int main()
{
	int i = 0;
	int b = 20;

	for (i = 0; i < 10; i++)
	{
		int a = 10;
		printf("c = %d\n", c);
	}
	printf("c = %d\n", c);
	return 0;
}

 c作为全局变量,在任何地方都可以被使用

⽣命周期指的是变量的创建(申请内存)到变量的销毁(收回内存)之间的⼀个时间段。

1. 局部变量的⽣命周期是:进⼊作⽤域变量创建,⽣命周期开始,出作⽤域⽣命周期结束。     (出{  },相关的变量就会被销毁)

2. 全局变量的⽣命周期是:整个程序的⽣命周期。(相当于main函数的生命周期)

10.3 static修饰局部变量

我们来分析下面2段代码

//代码1
void test()
{
 int i = 0;
 i++;
 printf("%d ", i);
}
int main()
{
 int i = 0;
 for(i=0; i<5; i++)
 {
 test();
 }
 return 0;
}

输出结果:1 1 1 1 1 

void test ()
{
//static修饰局部变量
 static int i = 0;
 i++;
 printf("%d ", i);
}
int main()
{
 int i = 0;
 for(i=0; i<5; i++)
 {
 test();
 }
 return 0;
}

 输出结果:1 2 3 4 5 

 代码1的test函数中的局部变量i是每次进⼊test函数先创建变量(⽣命周期开始)并赋值为0,然后 ++,再打印,出函数的时候变量⽣命周期将要结束(释放内存)。

代码2中,我们从输出结果来看,i的值有累加的效果,其实 test函数中的i创建好后,出函数的时候是 不会销毁的,重新进⼊函数也就不会重新创建变量,直接上次累积的数值继续计算。

总结:static修饰局部变量,本质上影响了变量的存储类型,一个局部变量本来是存放在栈区的,但是被static修饰后就存放在静态区的,因为存储类型的变化,生命周期变长了,但是作用域不变。

使用建议:未来一个局部变量出了函数后,我们还想保留他的值等到下次函数继续使用,就可以使用static修饰。

10.4 static修饰全局变量

我们来分析下面2段代码:

代码1:

add.c

int g_val = 2018;

 test.c

#include <stdio.h>
extern int g_val;
int main()
{
 printf("%d\n", g_val);
 return 0;
}

代码2: 

add.c

static int g_val = 2018;

 test.c

#include <stdio.h>
extern int g_val;
int main()
{
 printf("%d\n", g_val);
 return 0;
}

代码1正常,代码2在编译的时候会出现链接性错误。 

总结:

1、全局变量是具有外部链接属性的

2、全局变量被static修饰后,外部链接属性变成了内部链接属性,使得这个全局变量只能在自己所在的.c文件中使用了,其他文件即使声明了也用不了。相当于作用域变小了

使用建议:如果我们只想让一个全局变量在所在的源文件内部使用,而不想被其他文件发现,就而已使用static修饰

10.5 static修饰函数

我们来分析下面2段代码:

代码1:

add.c

int Add(int x, int y)
{
 return x+y;
}

test.c

extern int Add(int x, int y);
int main()
{
 printf("%d\n", Add(2, 3));
 return 0;
}

代码2: 

add.c

static int Add(int x, int y)
{
 return x+y;
}

 test.c

extern int Add(int x, int y);
int main()
{
 printf("%d\n", Add(2, 3));
 return 0;
}

       其实 static 修饰函数和 static 修饰全局变量是⼀模⼀样的,⼀个函数在整个⼯程都可以使⽤, 被static修饰后,只能在本⽂件内部使⽤,其他⽂件⽆法正常的链接使⽤了。

总结:

1、函数也是具有外部链接属性的

2、函数被static修饰后,外部链接属性变成了内部链接属性,使得这个函数只能在自己所在的.c文件中使用了,其他文件即使声明了也不能用。

使用建议:如果我们只想让一个函数在所在的源文件内部使用,而不想被其他文件使用,就而已使用static修饰

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

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

相关文章

代码随想录算法训练营Day21|二叉搜索树的最小绝对差、二叉搜索树中的众数、二叉树的最近公共祖先

二叉搜索树的最小绝对差 思路1&#xff1a;将二叉搜索树转化成一个有序数组&#xff0c;在有序数组上求两个数的最小值差。 只需要遍历有序数组&#xff0c;统计出最小值差 class Solution{ private:vector<int>vec;void traversal(TreeNode* root){if(root NULL)ret…

H5 简约四色新科技风引导页源码

H5 简约四色新科技风引导页源码 源码介绍&#xff1a;一款四色切换自适应现代科技风动态背景的引导页源码&#xff0c;源码有主站按钮&#xff0c;分站按钮2个&#xff0c;QQ联系站长按钮一个。 下载地址&#xff1a; https://www.changyouzuhao.cn/11990.html

Windows 启动项无法打开 Aanconda 问题。pyqt noBinding

windows中点击Anaconda navigator 没有反应: ## 解决 (右键运行Anaconda prompt) 以管理员身份运行&#xff1a; 分别运行以下命令&#xff1a; conda update conda conda update anaconda-navigatorpip uninstall PyQt5 pip install PyQt5 pip install pyqtwebengine

5年前端仔的2023年终总结

突然发现已经有好几个月没有写过博客总结过什么&#xff0c;小小辩解一下&#xff0c;其实并不是笔者停止的学习和总结&#xff0c;随着在前端这个行业的逐年深入&#xff0c;渐渐的很多收获不再是像之前简单的技术点的确定性描述讲解了&#xff0c;而是某个领域的知识体系的串…

『运维备忘录』之 TAR 命令详解

运维人员不仅要熟悉操作系统、服务器、网络等只是&#xff0c;甚至对于开发相关的也要有所了解。很多运维工作者可能一时半会记不住那么多命令、代码、方法、原理或者用法等等。这里我将结合自身工作&#xff0c;持续给大家更新运维工作所需要接触到的知识点&#xff0c;希望大…

机器学习-线性回归法

线性回归算法 解决回归问题思想简单&#xff0c;实现容易许多强大的非线性模型的基础结果具有很好的可解释性蕴含机器学习中的很多重要思想 样本特征只有一个&#xff0c;称为&#xff1a;简单线性回归 通过分析问题&#xff0c;确定问题的损失函数或者效用函数 通过最优化…

jsp课程管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 课程管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&…

Termux配置安卓编译环境

前言 Termux安装后&#xff0c;就相当于把手机变成了一台Linux服务器&#xff0c;而且现在手机卡通常是能拿到ipv6公网地址的&#xff0c;所以&#xff0c;这个服务器能干啥&#xff1f; 编程搭建网站跑脚本 本文讲述的就是怎么在Termux搭建安卓编译环境&#xff0c;实现手机…

CV | Medical-SAM-Adapter论文详解及项目实现

******************************* &#x1f469;‍⚕️ 医学影像相关直达&#x1f468;‍⚕️******************************* CV | SAM在医学影像上的模型调研【20240207更新版】-CSDN博客 CV | Segment Anything论文详解及代码实现 本文主要讲解Medical-SAM-Adapter论文及项…

HTML 样式学习手记

HTML 样式学习手记 在探索网页设计的世界时&#xff0c;我发现HTML元素的样式调整真的是个很酷的环节。通过简单的属性设置&#xff0c;就能让文字换上五彩斑斓的颜色、变换各异的字体和大小。特别是那个style属性&#xff0c;感觉就像是一扇通往CSS魔法世界的大门。 代码小试…

【Python】虚拟环境miniconda安装(python3.7, python3.x)

背景 使用Python开发项目时&#xff0c;我们一般都需要安装环境&#xff0c;可能是在物理机上直接安装&#xff0c;也可能是在虚拟环境上安装&#xff0c;当前是怎么按照conda环境的示例&#xff0c;可以指定安装Python3.x的所有版本。 安装 首先&#xff0c;需要登录当前的…

零基础学Python之网络编程

1.什么是socket 官方定义&#xff1a; 套接字&#xff08;socket&#xff09;是一个抽象层&#xff0c;应用程序可以通过它发送或接收数据&#xff0c;可对其进行像对文件一样的打开、读写和关闭等操作。套接字允许应用程序将I/O插入到网络中&#xff0c;并与网络中的其他应用…

国产信创领跑者:暴雨信息的创新与实践

随着数字化转型的加速推进&#xff0c;信创产业作为数字经济发展的重要支柱&#xff0c;正日益受到社会各界的广泛关注。在这个大背景下&#xff0c;暴雨信息积极响应国家号召&#xff0c;全面适配国产化&#xff0c;推动信创产业的技术创新和应用拓展&#xff0c;成为了行业的…

AWS创建快照定期备份

备注&#xff1a;aws有快照定期备份工具&#xff0c;名字叫【生命周期管理器】 选择实例点击创建 点击下一步后设置备份频率等 然后点击创建即可

(Python)字典列表数据本地存储工具

前言 一个简单的实现简便 "列表字典" 数据存储本地。 适合不会SQL但又想实现数据存储本地的同学。 操作使用都非常简单。 文件只做了简单的加密处理&#xff0c;如果需要复杂加密的同学可以修改加密函数。 温馨提示&#xff1a; 1.使用前&#xff0c;在项目目录…

人工智能福利站,初识人工智能,图神经网络学习,第三课

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

九思OA user-list-3g sql注入

【产品&&漏洞简述】 九思OA办公软件全面实现协同工作、公文、流程审批、知识管理、项目管理、综合办公、信息共享、移动办公 等应用功能&#xff0c;并能够与其他异构系统整合&#xff0c;打破信息孤岛&#xff0c;建立完整的有效的企业工作平台和移动办公软件。 九思…

(2)(2.14) SPL Satellite Telemetry

文章目录 前言 1 本地 Wi-Fi&#xff08;费用&#xff1a;30 美元以上&#xff0c;范围&#xff1a;室内&#xff09; 2 蜂窝电话&#xff08;费用&#xff1a;100 美元以上&#xff0c;范围&#xff1a;蜂窝电话覆盖区域&#xff09; 3 手机卫星&#xff08;费用&#xff…

ChatGPT学习第一周

&#x1f4d6; 学习目标 掌握ChatGPT基础知识 理解ChatGPT的基本功能和工作原理。认识到ChatGPT在日常生活和业务中的潜在应用。 了解AI和机器学习的基本概念 获取人工智能&#xff08;AI&#xff09;和机器学习&#xff08;ML&#xff09;的初步了解。理解这些技术是如何支撑…

介绍一个关于 JSON 可视化的网站

最近在看到一个比较好玩的网站&#xff0c;可以将 JSON以可视化的方式展现出现&#xff0c;比如存在一下JSON数据&#xff1a; {"id": "f3bbc3bc-9f34-4bf7-8a0f-7e6f6e6fbb9a","isActive": false,"age": 25,"name": "…
最新文章