C语言 —— 此去经年 应是良辰好景虚设 - 函数
目录
1. 函数的概念
1.1 库函数
1.2 自定义函数
2. 形参和实参
3. return 语句
4. 数组做函数参数
5. 嵌套调用和链式访问
5.1 嵌套调用
5.2 链式访问
6. 函数的声明和定义
6.1 单个文件
6.2 多个文件
7. static 和 extern
7.1 static 修饰局部变量
7.2 static 修饰全局变量
7.3 static 修饰函数
1. 函数的概念
C语⾔中的函数就是⼀个完成某项特定的任务的⼀⼩段代码
1.1 库函数
C语⾔标准中规定了C语⾔的各种语法规则,C语⾔并不提供库函数;C语⾔的国际标准ANSI C规定了⼀些常⽤的函数的标准,被称为标准库,那不同的编译器⼚商根据ANSI提供的C语⾔标准就给出了⼀系列函数的实现和,这些函数就被称为库函数
我们前⾯内容中学到的 printf 、 scanf 都是库函数,库函数的也是函数,不过这些函数已经是现成的,我们只要学会就能直接使⽤了
库函数相关头⽂件:
C 标准库标头 - cppreference.comhttps://zh.cppreference.com/w/c/header
库函数的学习和查看⼯具很多,⽐如:
C library - C++ Reference
https://legacy.cplusplus.com/reference/clibrary/
比如:sqrt ,这个函数的作用是用来计算一个数的平方根的,其头文件为:
#include <math.h>
sqrt - C++ Reference
https://legacy.cplusplus.com/reference/cmath/sqrt/
double sqrt(double x); //sqrt 是函数名//x 是函数的参数,表⽰调⽤sqrt函数需要传递⼀个double类型的值//double 是返回值类型 - 表⽰函数计算的结果是double类型的值
#include <stdio.h> #include <math.h>int main() {double d = 16.0;double r = sqrt(d);printf("%lf\n", r);return 0; }
1.2 自定义函数
光有库函数提供的函数远远不足以实现所有的代码功能,所以程序员自行写了许多函数以实现各种功能,这种代码就叫做自定义函数
自定义函数的语法形式和库函数相同:
ret_type fun_name(形式参数) {}
1. ret_type 是函数返回类型:有时候可以是void,表示什么都不返回,当不需要返回数值时,也可以不写返回值的类型
2. fun_name 是函数名:函数的名字与其功能相关联,所以函数起名时要根据其功能起有意义的名字,便于程序员解读
3. 括号中放的是形式参数 :参数要交代清楚类型,名字和参数个数
4. {}括起来的是函数体:也就是函数完成功能实现的过程
如:
int Add(int x, int y) {return x+y; }
2. 形参和实参
在函数使⽤的过程中,把函数的参数分为,实参和形参
举个例子:
#include <stdio.h>
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;
}
在上面这段代码中:
1. a 和 b 为函数的实参,实参就是真实传递给函数的参数
2. x 和 y 为函数的形参,形参只在形式上存在,并不会一直存在,只有在调用函数时向内存申请空间,使用完函数后形参又被销毁
形式参数只有在函数被调用的过程中为了存放实参传递过来的值,才向内存申请空间,这个过程就是形式的实例化
实参和形参的关系
形参和实参各自是独立的内存空间,我们调试下面的代码来观察
#include <stdio.h>
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;
}
我们在调试的可以观察到,x和y确实得到了a和b的值,但是x和y的地址和a和b的地址是不⼀样的,所以我们可以理解为形参是实参的⼀份临时拷贝
3. return 语句
在函数的设计中,函数中经常会出现return语句,这⾥讲⼀下return语句使⽤的注意事项
1. return后边可以是⼀个数值,也可以是⼀个表达式,如果是表达式则先执⾏表达式,再返回表达式的结果
2. return后边也可以什么都没有,直接写 return; 这种写法适合函数返回类型是void的情况
3. return返回的值和函数返回类型不⼀致,系统会⾃动将返回的值隐式转换为函数的返回类型
4. return语句执⾏后,函数就彻底返回,后边的代码不再执⾏
5. 如果函数中存在if等分⽀的语句,则要保证每种情况下都有return返回,否则会出现编译错误
4. 数组做函数参数
在使⽤函数解决问题的时候,难免会将数组作为参数传递给函数,在函数内部对数组进⾏操作
⽐如:举个例子:写⼀个函数将⼀个整型数组的内容,全部置为9,再写⼀个函数打印数组的内容
#include <stdio.h>void set_arr(int arr[], int sz)
{int i = 0;for (i = 0; i < sz; i++){arr[i] = 9;}
}void print_arr(int arr[], int sz)
{int i = 0;for (i = 0; i < sz; i++){printf("%d ", arr[i]);}printf("\n");
}int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9,10 };int sz = sizeof(arr) / sizeof(arr[0]);set_arr(arr, sz);//设置数组内容为-1print_arr(arr, sz);//打印数组内容return 0;
}
这⾥的set_arr函数要能够对数组内容进⾏设置,就得把数组作为参数传递给函数,同时函数内部在设置数组每个元素的时候,也得遍历数组,需要知道数组的元素个数。所以我们需要给set_arr传递2个参数,⼀个是数组,另外⼀个是数组的元素个数
仔细分析print_arr也是⼀样的,只有拿到了数组和元素个数,才能遍历打印数组的每个元素
1. 函数的形式参数要和函数的实参个数匹配
2. 函数的实参是数组,形参也是可以写成数组形式的
3. 形参如果是⼀维数组,数组⼤⼩可以省略不写
4. 形参如果是⼆维数组,⾏可以省略,但是列不能省略
5. 数组传参,形参是不会创建新的数组的
6. 形参操作的数组和实参的数组是同⼀个数组
5. 嵌套调用和链式访问
5.1 嵌套调用
嵌套调⽤就是函数之间的互相调⽤,每个函数就⾏⼀个乐⾼零件,正是因为多个乐⾼的零件互相⽆缝的配合才能搭建出精美的乐⾼玩具,也正是因为函数之间有效的互相调⽤,最后写出来了相对⼤型的程序
假设我们计算某年某⽉有多少天?如果要函数实现,可以设计2个函数:
1. is_leap_year():根据年份确定是否是闰年
2. get_days_of_month():调⽤is_leap_year确定是否是闰年后,再根据⽉计算这个⽉的天数
int is_leap_year(int y)
{if (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))return 1;elsereturn 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;
}
这⼀段代码,完成了⼀个独立的功能,代码中反应了不少的函数调用:
1. main 函数调用 scanf 、 printf 、 get_days_of_month
2. get_days_of_month 函数调用 is_leap_year
未来的稍微大⼀些代码都是函数之间的嵌套调用,但是函数是不能嵌套定义的
5.2 链式访问
链式访问就是将一个函数的返回值作为另外一个函数的参数,像链条一样函数串起来就是函数的链式访问
比如:
#include <stdio.h> int main() {int len = strlen("abcdef");//1.strlen求⼀个字符串的⻓度printf("%d\n", len);//2.打印⻓度return 0; }
前面的代码完成动作写了2条语句,当我们把strlen的返回值直接作为printf函数的参数,那么就是⼀个链式访问的例子了
#include <stdio.h> int main() {printf("%d\n", strlen("abcdef"));//链式访问return 0; }
再看一个有趣的代码:
#include <stdio.h>int main() {printf("%d", printf("%d", printf("%d", 43)));return 0; }
这个代码的关键是明⽩ printf 函数的返回是什么
printf - C++ Reference
https://legacy.cplusplus.com/reference/cstdio/printf/?kw=printf
int printf ( const char * format, ... );
printf函数返回的是打印在屏幕上的字符的个数上⾯的例⼦中,我们就第⼀个printf打印的是第⼆个printf的返回值,第⼆个printf打印的是第三个printf的返回值
第三个printf打印43,在屏幕上打印2个字符,再返回2
第⼆个printf打印2,在屏幕上打印1个字符,再放回1
第⼀个printf打印1
所以屏幕上最终打印:4321
6. 函数的声明和定义
6.1 单个文件
⼀般我们在使用函数的时候,直接将函数写出来就使用了
比如:我们要写⼀个函数判断⼀年是否是闰年
#include <stido.h>//函数的定义
int is_leap_year(int y)
{if (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))return 1;elsereturn 0;
}int main()
{int y = 0;scanf("%d", &y);int r = is_leap_year(y);//函数的调用if (r == 1)printf("闰年\n");elseprintf("⾮闰年\n");return 0;
}
上面的代码是函数的定义,下面的int r = is_leap_year(y);是函数的调用
那如果我们将函数的定义放在函数的调用后边会怎么样呢?如下:
#include <stido.h>int main()
{int y = 0;scanf("%d", &y);int r = is_leap_year(y);//函数的调用if (r == 1)printf("闰年\n");elseprintf("⾮闰年\n");return 0;
}//函数的定义
int is_leap_year(int y)
{if (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))return 1;elsereturn 0;
}
这个代码在VS2022上编译,会出现下⾯的警告信息:
这是因为C语⾔编译器对源代码进⾏编译的时候,从第⼀⾏往下扫描的,当遇到第7⾏的is_leap_year函数调⽤的时候,并没有发现前⾯有is_leap_year的定义,就报出了上述的警告
怎么解决这个问题呢?就是函数调⽤之前先声明⼀下is_leap_year这个函数,声明函数只要交代清楚:函数名,函数的返回类型和函数的参数
如:int is_leap_year(int y);这就是函数声明,函数声明中参数只保留类型,省略掉名字也是可以的,代码变成这样就能正常编译了
#include <stido.h>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");elseprintf("⾮闰年\n");return 0;
}//函数的定义
int is_leap_year(int y)
{if (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))return 1;elsereturn 0;
}
函数的调用⼀定要先声明后使用;
函数的定义也是⼀种特殊的声明,所以如果函数定义放在调⽤之前也是可以的
6.2 多个文件
⼀般在企业中我们写代码时候,代码可能⽐较多,不会将所有的代码都放在⼀个⽂件中;我们往往会根据程序的功能,将代码拆分放在多个⽂件中
⼀般情况下,函数的声明、类型的声明放在头⽂件(.h)中,函数的实现是放在源⽂件(.c)⽂件中
比如:
add.c
//函数的定义
int Add(int x, int y)
{return x + y;
}
add.h
//函数的声明
int Add(int x, int y);
test.c
#include <stdio.h>
#include "add.h"int main()
{int a = 10;int b = 20;//函数调⽤int c = Add(a, b);printf("%d\n", c);return 0;
}
7. static 和 extern
static 和 extern 都是C语言中的关键字
static 是 静态的 的意思,可以⽤来:
1.修饰局部变量 2. 修饰全局变量 3. 修饰函数
extern 是用来声明外部符号的
作用域:⼀段程序代码中所用到的名字并不总是有效可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域
生命周期:变量的创建(申请内存)到变量的销毁(收回内存)之间的⼀个时间段局部变量的生命周期是:进入作用域变量创建,生命周期开始,出作用域生命周期结束
全局变量的生命周期是:整个程序的生命周期
7.1 static 修饰局部变量
//代码1
#include <stdio.h>
void test()
{int i = 0;i++;printf("%d ", i);
}int main()
{int i = 0;for (i = 0; i < 5; i++){test();}return 0;
}
代码1的test函数中的局部变量i是每次进⼊test函数先创建变量(⽣命周期开始)并赋值为0,然后++,再打印,出函数的时候变量⽣命周期将要结束(释放内存)
//代码2
#include <stdio.h>
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;
}
代码2中,我们从输出结果来看,i的值有累加的效果,其实 test函数中的i创建好后,出函数的时候是不会销毁的,重新进⼊函数也就不会重新创建变量,直接上次累积的数值继续计算
结论:static修饰局部变量改变了变量的⽣命周期,⽣命周期改变的本质是改变了变量的存储类型,本来⼀个局部变量是存储在内存的栈区的,但是被 static 修饰后存储到了静态区。存储在静态区的变量和全局变量是⼀样的,⽣命周期就和程序的⽣命周期⼀样了,只有程序结束,变量才销毁,内存才回收,但是作⽤域不变的
未来⼀个变量出了函数后,我们还想保留值,等下次进⼊函数继续使⽤,就可以使⽤static
修饰
7.2 static 修饰全局变量
//代码1
int g_val = 2018;#include <stdio.h>
extern int g_val;
int main()
{printf("%d\n", g_val);return 0;
}//代码2
static int g_val = 2018;#include <stdio.h>
extern int g_val;
int main()
{printf("%d\n", g_val);return 0;
}
extern 是⽤来声明外部符号的,如果⼀个全局的符号在A⽂件中定义的,在B⽂件中想使⽤,就可以使⽤ extern 进⾏声明,然后使用
代码1正常,代码2在编译的时候会出现链接性错误
结论:
⼀个全局变量被static修饰,使得这个全局变量只能在本源⽂件内使⽤,不能在其他源⽂件内使⽤
本质原因是全局变量默认是具有外部链接属性的,在外部的⽂件中想使⽤,只要适当的声明就可以使用
但是全局变量被 static 修饰之后,外部链接属性就变成了内部链接属性,只能在⾃⼰所在的源⽂件内部使⽤了,其他源⽂件,即使声明了,也是⽆法正常使⽤的
所以:如果⼀个全局变量,只想在所在的源⽂件内部使⽤,不想被其他⽂件发现,就可以使⽤static修饰
7.3 static 修饰函数
//代码1
int Add(int x, int y)
{return x + y;
}#include <stdio.h>
extern int Add(int x, int y);
int main()
{printf("%d\n", Add(2, 3));return 0;
}
//代码2
static int Add(int x, int y)
{return x + y;
}#include <stdio.h>
extern int Add(int x, int y);
int main()
{printf("%d\n", Add(2, 3));return 0;
}
我们运行之后可以发现:代码1是能够正常运⾏的,但是代码2就出现了链接错误
其实 static 修饰函数和 static 修饰全局变量是⼀模⼀样的,⼀个函数在整个⼯程都可以使用,被static修饰后,只能在本⽂件内部使用,其他⽂件⽆法正常的链接使用了
本质是因为函数默认是具有外部链接属性,具有外部链接属性,使得函数在整个⼯程中只要适当的声明就可以被使⽤。但是被 static 修饰后变成了内部链接属性,使得函数只能在⾃⼰所在源⽂件内部使用
使用建议:⼀个函数只想在所在的源⽂件内部使⽤,不想被其他源⽂件使⽤,就可以使⽤ static 修饰
完结撒花~
相关文章:
C语言 —— 此去经年 应是良辰好景虚设 - 函数
目录 1. 函数的概念 1.1 库函数 1.2 自定义函数 2. 形参和实参 3. return 语句 4. 数组做函数参数 5. 嵌套调用和链式访问 5.1 嵌套调用 5.2 链式访问 6. 函数的声明和定义 6.1 单个文件 6.2 多个文件 7. static 和 extern 7.1 static 修饰局部变量 7.2 static 修…...
最新前端框架选型对比与建议(React/Vue/Svelte/Angular)
前端框架选型对比与建议(React/Vue/Svelte/Angular) 一、核心框架技术特性对比(基于最新版本) 维度React 19 25Vue 3.5 12Svelte 5 25Angular 19 5核心理念函数式编程、JSX语法、虚拟DOM渐进式框架、组合式API、模板语法编译时框…...
AOP基础-01.快速入门
一.AOP 对于统计每一个业务方法的耗时这一操作,如果再业务层的每一个方法前获取方法运行的开始时间,方法结束获取结束时间,然后计算执行耗时,那这样就太繁琐了。能不能定义一个模板方法,使得该方法能够在业务层的方法执…...
为什么MySQL选择使用B+树作为索引结构
B树是MySQL最常见的索引结构,大部分存储引擎都支持 B 树索引。 相对于其他竞争力强的数据结构,B树都有战胜它们成为大多时候MySQL选择使用索引结构的理由: 第一个强有力的竞争对手是B树: 1. B树每个节点都存储了完整的数据&…...
基于SSA-KELM-Adaboost(麻雀搜索优化的极限学习机自适应提升算法)的多输入单输出回归预测【MATLAB】
SSA-KELM-Adaboost 是一种结合了麻雀搜索算法(SSA)、核极限学习机(KELM)和Adaboost集成学习的复合回归预测模型。该模型通过参数优化与集成策略提升预测精度和鲁棒性,适用于复杂非线性回归问题。以下是其核心理论与…...
分享些常用的工具类
一、照片 1、Unsplash:https://unsplash.com/ 2、pixabay:https://pixabay.com/zh/ 二、壁纸 1、Wallpaper Engine 2、wallhaven:https://wallhaven.cc/ 3、极简壁纸:https://bz.zzzmh.cn/ 三、AI语音 1、微软Azure项目&…...
Apache SeaTunnel 构建实时数据同步管道(最新版)
文章作者 王海林 白鲸开源 数据集成引擎研发 Apache SeaTunnel Committer & PMC Member,Apache SkyWalking Committer,多年平台研发经验,目前专注于数据集成领域。 导读 在当今数字化快速发展的时代,数据已然成为企业决策…...
96.【C语言】解析预处理(4)
目录 5.条件编译 #ifdef 其他条件编译指令 #if 多个分支的条件编译 判断是否被定义 嵌套指令 6.头文件的包含方式 本地文件包含 库文件包含 嵌套文件包含 问题:头文件的重复包含 解决问题:避免头文件的重复包含 方法1:#pragma once 方法2:#ifndef、#define和#en…...
linux用户操作与权限
Linux的root用户 root用户(超级管理员) root用户拥有最大的系统操作权限。 普通用户的权限一般在其home目录内是不受限的,但是出来自己的home目录,仅有只读和执行权限。 su su命令切换到root账号 语法:su [-] [用户…...
Proof Beyond Boundaries: Hong Kong zkNight 活动精彩回顾
2 月 19 日,随着夜幕的降临,一场汇聚行业智慧与前瞻视野的高端主题活动 ——Proof Beyond Boundaries: Hong Kong zkNight,在香港铜锣湾 Vpoint 的 6/F 盛大启幕。本次活动由 ZEROBASE 主办,Techub News 承办,吸引了众…...
QT零基础学习之路(五)--自定义信号和槽
源码地址(优先更新):点击此处...
Pytorch实现之GIEGAN(生成器信息增强GAN)训练自己的数据集
简介 简介:在训练数据样本之前首先利用VAE来推断潜在空间中不同类的分布,用于后续的训练,并使用它来初始化GAN。与ACGAN和BAGAN不同的是,提出的GIEGAN有一个分类器结构,这个分类器主要判断生成的图像或者样本图像属于哪个类,而鉴别器仅判断图像是来自于生成器还是真实样…...
HTTP 动态报错码的原因和解决方法
目录 1xx(信息性状态码) 2xx(成功状态码) 3xx(重定向状态码) 4xx(客户端错误状态码) 5xx(服务器错误状态码) 参考文章 以下是 HTTP 动态报错码的常见原…...
单核处理器编程会简单很多的原因
乱序执行的本质:单核处理器的乱序执行(Out-of-Order Execution)允许指令动态调度以提升效率,但其核心原则是保持程序语义的单线程正确性。所有指令的最终提交(Retirement)必须严格按照程序顺序完成,以确保异常处理、中断和外部观察结果的正确性。 提交阶段的顺序性:尽管…...
C++之vector和list辨析
std::vector 和 std::list 是 C 标准库中两种常用的容器,它们都用于存储和管理元素集合,但在底层实现和性能特性上有显著的区别。 1. 底层实现 std::vector: 基于动态数组实现。元素在内存中是连续存储的。支持随机访问(通过下标访问元素&a…...
C++ 八股(整理记录)
1. 指针和引用的区别 定义与初始化: 指针:可以声明时不初始化,并且可以在之后指向任何同类型的变量。指针是一个变量,它存储的是另一个变量的地址。 int a 10; int* p; // 声明一个指向int的指针 p &a; // 将p指向变量a的…...
docker部署GPU环境
使用 Docker 部署 GPU 环境涉及到几个关键步骤,以下是详细步骤: 1. 安装 NVIDIA 驱动程序 确保你的系统已经安装了 NVIDIA GPU 驱动。这是使用 GPU 的前提条件。 2. 安装 Docker 和 nvidia-container-toolkit 首先,确保你已经安装了 Docker。然后,安装 NVIDIA Containe…...
单片机裸机编程-时机管理
对于 RTOS 实时操作系统,我们是通过 TASK(任务)进行底层操作的,这与裸机编程中的函数(fun)类似。不同的任务或函数实现不同的功能,在RTOS中,单片机有信号量、队列等不同任务之间的通…...
使用VScode开发STM32:基于CMake(包含标准库和HAL库工程)
使用VScode开发STM32:基于CMake(包含标准库和HAL库工程) 本教程使用VScode作为代码编辑工具、Cmake作为构建系统生成器、Make进行构建系统、使用arm-none-eabi-gcc进行交叉编译、使用OpenOCD作为代码下载与调试工具,最终搭建出适…...
Linux操作与权限2
查看权限控制信息 序号1,表示文件,文件夹权限控制信息 序号2,表示文件,文件夹所属用户 序号3,表示文件,文件夹所属用户组 12345678910d/l/-r/-w/-x/-r/-w/-x/-r/-w/-x/- 权限细节总共分为10个槽位 表格1&…...
解析第十一页
多选707、如图所示组网,SWA、SWB、SWC、SWD运行RSTP,则以下说法正确的是? A、可以在SWB的GE0/0/2端口开启边缘端口,让连接终端的接口快速进入转发状态 B、边缘端口收到BPDU之后会重新参与生成树的计算 C、可以在SWC的GEO/0/2端口开启边缘端口,让连接终端的接口快速进入转…...
SQL之order by盲注
目录 一.order by盲注的原理 二.注入方式 a.布尔盲注 b.时间盲注 三.防御 一.order by盲注的原理 order by子句是用于按指定列排序查询结果,列名或列序号皆可。 order by 后面接的字段或者数字不一样,那么这个数据表的排序就会不同。 order by 盲…...
阻止浏览器的默认缩放机制
在移动端浏览器中,当用户点击输入框(如密码输入框)时,页面可能会自动放大以提高可读性。这种行为通常是由于浏览器的默认缩放机制引起的。要阻止这种自动放大行为,可以采取以下几种方法: 使用 viewport 元…...
python 引用父目录:层级的模块
from pathlib import Path import sys 获取 project 目录 project_dir Path(file).resolve().parent.parent 将 project 目录添加到 sys.path 中 sys.path.append(str(project_dir)) 导入 support 模块 import support support.print_func(“Runoob”)...
实用:查找Linux进程调度统计信息的三个方法
实用:查找Linux进程调度统计信息的三个方法 在现代操作系统中,理解进程调度行为对于优化性能和解决瓶颈问题至关重要。本文将详细介绍如何在Linux系统中获取进程从调度队列中调入(enqueue)和调出(dequeue)…...
以下是自定义针对 Vite + TypeScript 项目的完整路径别名配置流程:
以下是针对 Vite TypeScript 项目的完整路径别名配置流程: 1. 安装必要依赖 bash npm install -D types/node 2. 配置 vite.config.ts typescript // vite.config.ts import { defineConfig } from vite import vue from vitejs/plugin-vue import path from pat…...
基于Matlab实现汽车远近光灯识别的详细步骤及代码示例
以下是一个基于Matlab实现汽车远近光灯识别的详细步骤及代码示例,主要通过图像处理技术来区分远光灯和近光灯。 整体思路 图像预处理:包括读取图像、灰度化、去噪等操作,以提高后续处理的准确性。边缘检测:找出图像中的边缘信息…...
Solidity 开发环境
Solidity 开发环境 Solidity编辑器:Solidity编辑器是⼀种专⻔⽤于编写和编辑Solidity代码的编辑器。常⽤的Solidity编辑器包括 Visual Studio Code、Atom和Sublime Text。以太坊开发环境:以太坊开发环境(Ethereum Development Environment&a…...
Ollama+Cherrystudio+beg-m3+Deepseek R1 32b部署本地私人知识库(2025年2月win11版)
之前综合网络各方面信息得到的配置表: 在信息爆炸的时代,数据安全和个性化需求愈发凸显。搭建本地私人知识库,不仅能确保数据的安全性,还能根据个人需求进行个性化定制,实现知识的高效管理和利用。随着技术的不断发展…...
vue3.0将后端返回的word文件流转换为pdf并导出+html2pdf.js将页面导出为pdf
实现思路 1.将Word文档转换为HTML:mammoth.js,它可以将.docx文件转换为HTML 2.将HTML转换为PDF:使用html2pdf.js将HTML转换为PDF 如果想要相同的效果,也可以把前端页面直接导出转换为pdf: 运用的插件:html2pdf.js 后端…...
【心得】缓存穿透与缓存击穿总是记混,一文从英语单词含义角度分析带你区分清楚!
一句话省流版:缓存穿透的英语为cache penetration,可以翻译为缓存渗透,“渗透”联想到网安的攻击渗透,故缓存穿透是绕过防护进行攻击; 缓存击穿的英语为"cache breakdown",可以翻译为缓存故障,“…...
day02
作业2 为 Activity 设置2种不同的启动模式并通过 adb 命令进行查看任务栈信息,并且打印生命周期方法执行日志 step1:生成第二个Activity和相应配置、 一个是singleTask模式,还一个是mainActivity的默认格式 step2:打印生命周期…...
JavaScript 简单类型与复杂类型-堆和栈
深入理解JavaScript中的简单类型(基本数据类型)与复杂类型(引用数据类型)如何在内存中存储对于编写高效、无误的代码至关重要。本文将探讨这两种类型的差异,以及它们在内存中的存储机制——栈(Stack&#x…...
五、AIGC大模型_04LLaMA-Factory基础知识与SFT实战
1、LLaMA-Factory 基本介绍 1.1 定义 LLaMA-Factory 是一个开源的大型语言模型(LLM)微调框架,旨在帮助开发者和研究人员轻松地对预训练语言模型进行定制化训练和优化 1.2 功能特点 支持多种预训练模型 LLaMA Factory 支持超过 100 种主流的…...
数字IC后端设计实现OCC(On-chip Clock Controller)电路介绍及时钟树综合案例
数字IC后端时钟树综合专题(OCC电路案例分享) 复杂时钟设计时钟树综合(clock tree synthesis)常见20个典型案例 1、什么是OCC? 片上时钟控制器(On-chip Clock Controllers ,OCC),也称为扫描时钟控制器(Scan Clock Con…...
LeetCodehot 力扣热题100 全排列
这段代码的目的是计算给定整数数组的所有全排列(permutations),并返回一个包含所有排列的二维数组。 思路解析 在这段代码中,采用了 深度优先搜索(DFS) 和 回溯 的方法来生成所有的排列。 关键步骤…...
深度学习c++资源库:vector容器,蓝桥杯常用算法sort,unique(排序+去重)
vector容器 1.基本概念 <vector> 是 STL 中的一个容器类,不同于普通数组的静态空间,vector可以动态扩展。 动态扩展:并不是在原空间连接新空间,而是找到更大的内存空间,将原数据拷贝到新空间,释放…...
Postgresql-重置统计信息(reset statistics)
文章目录 理解 PostgreSQL 中的 pg_stat_resetpg_stat_reset 的作用与使用时机pg_stat_reset 所需权限PostgreSQL 重置统计信息的方法重置整个database重置特定表的统计重置特定function的统计重置Statistics Collector:重置 WAL(Write-Ahead Logging)统…...
【Uniapp-Vue3】导入uni-id用户体系
在uniapp官网的uniCloud中下载uni-id用户体系 或者直接进入加载,下载地址:uni-id-pages - DCloud 插件市场 进入以后下载插件,打开HbuilderX 选中项目,点击确定 点击跳过 点击合并 右键uniCloud文件夹下的database文件夹&#x…...
【前沿探索篇七】【DeepSeek自动驾驶:端到端决策网络】
第一章 自动驾驶的"感官革命":多模态神经交响乐团 1.1 传感器矩阵的量子纠缠 我们把8路摄像头+4D毫米波雷达+128线激光雷达的融合称为"传感器交响乐",其数据融合公式可以简化为: def sensor_fusion(cam, radar, lidar):# 像素级特征提取 (ResNet-152…...
Staruml软件的介绍安装uml类图的绘制流程
文章目录 1.uml和staruml之间的关系2.软件的安装3.配置脚本语言4.Staruml创建类图4.反向工程 1.uml和staruml之间的关系 这篇文章主要是介绍这个staruml软件的安装和相关的背景介绍: 我和uml初识于IDEA软件,学习java的你一定用过这个软件,当…...
神经网络发展简史:从感知机到通用智能的进化之路
引言 神经网络作为人工智能的核心技术,其发展历程堪称一场人类对生物大脑的致敬与超越。本文将用"模型进化"的视角,梳理神经网络发展的五大关键阶段,结合具象化比喻和经典案例,为读者呈现一幅清晰的AI算法发展图谱。 一…...
快节奏生活
在当今快节奏的商务环境中,效率成为了决定企业竞争力的关键因素之一。亿可达软件连接平台,以其独特的功能和优势,为职场人士带来了前所未有的便捷与高效,成为了众多用户心中的“宝藏”工具。 1、亿可达:自动化流程的搭…...
Windows 11【1001问】通过Rufus制作Win 11系统安装U盘
随着科技的发展,Windows 11 已经成为许多用户的首选操作系统。在之前的几篇文章中,我们详细探讨了 Windows 11 的概念、安装配置要求以及如何下载 Windows 11 镜像文件,并介绍了六种不同的安装方法。本篇博客将聚焦于使用 ISO 文件安装 Windo…...
spring中手写注解开发(创建对象篇)
说明: 在spring底层中并不是我写的如此,这篇只是我用我自己的方式实现了使用注解组件扫描并且 创建对象,方法并不是很难,可以看一看,欢迎大佬评论 第一步: 我们需要自己写一个注解,我用的是idea…...
DeepSeek进入开源周,分享几点关于开源的思考
最近DeepSeek进入开源周,又把差点被大众遗忘在角落的开源话题拉了出来。 作为一个开源作者,也分享几点关于开源的思考。 AI对开源的影响 开源项目遇到的最大困难 开源项目不应该商业化 你的开源项目是垃圾...
大模型训练中的数据不平衡问题及其解决策略
目录 大模型训练中的数据不平衡问题及其解决策略 一、数据不平衡问题的影响 二、处理数据不平衡问题的方法 1. 过采样(Oversampling) 2. 欠采样(Undersampling) 3. 代价敏感学习(Cost-Sensitive Learning…...
本地部署DeepSeek R1满血版大模型
一、前言 老周上一篇分享了《本地部署DeepSeek R1大模型》,本地受硬件条件限制,只跑了80亿参数量的模型。 1.5b模型基本可以在大部分个人电脑甚至手机中运行,如果你有 6G 显存以上,那么可以部署7b模型,如果有16G显存&…...
外发抄板SCH与PCB检查系列
外发抄板SCH与PCB检查系列 一、检查到手的文件二、PCB与原理图的对应检查1.为什么要查SCH与Pcbdoc的对应?2.查询方法 三、PCB与实物的信号对应检查 一、检查到手的文件 外发出去两块板子:控制板与功率板。 抄板机构返回的文件: 1.互相独立的…...
EX_25/2/25
编写一个如下场景: 有一个英雄Hero类,私有成员,攻击,防御,速度,生命值,以及所有的set get 方法 编写一个 武器 Weapon 类,拥有私有成员攻击力,以及set get 方法 编写一个…...