当前位置:网站首页>C语言学习-Day_05
C语言学习-Day_05
2022-06-27 09:49:00 【坏坏-5】
- 学习参考B站郝斌老师的视频,文章内的源码如有需要可以私信联系。
函数
- 是一个工具,不针对某一问题设计,是针对大量同类型的问题设计的
- 函数对处理的数是不一样的,但是对于数据的操作是相同的
- 什么是函数
- 逻辑上:能够完成特定功能的独立的代码块
- 物理上:能够对接受的数据进行处理,并且返回值
- 也可以不接受数据,不返回值
例:
/*函数举例*/
# include <stdio.h>
int f(void) //int表示函数返回值类型,void表示该函数不能接收数据
{
return 5; //向主调函数返回5
}
void g(void) //函数名前的void表示该函数没有返回值
{
return 3; //error,没有返回值,使用此语句会报错
}
int main(void)
{
int j = 10;
j = f(); //括号内不写值
printf("%d\n", j); //输出f函数的返回值5
j = g(); //error,因为g函数没有返回值,所以不能赋值
return 0;
}
为什么需要函数
- 对数据的操作相同,需要对多个数据进行操作,则需要使用函数来减少代码量
- 可以避免写大量重复的代码
- 有利于程序的模块化
例:现有a-f共6个变量,每个变量都有一个值,要求比较a、b,c、d,e、f之间的大小,并且输出较大的数。
/*现有a-f共6个变量,每个变量都有一个值,要求比较a、b,c、d,e、f之间的大小,并且输出较大的数*/
# include <stdio.h>
int main(void)
{
int a, b, c, d, e, f;
a = 1, b = 2, c = 4, d = -3, e = 5, f = 10; //逗号表达式
/*因为整体没有赋给变量,所以没有影响,也可以使用分号隔开 a = 1; b = 2; ... */
if (a > b)
printf("max = %d\n", a);
else
printf("max = %d\n", b);
if (c > d)
printf("max = %d\n", c);
else
printf("max = %d\n", d);
if (e > f)
printf("max = %d\n", e);
else
printf("max = %d\n", f);
return 0;
}
/*运行结果*/
max = 2
max = 4
max = 10
Press any key to continue
- 同样功能的语句,写了多次,可以使用函数,进行调用,节省代码
方法一:
/*现有a-f共6个变量,每个变量都有一个值,要求比较a、b,c、d,e、f之间的大小,并且输出较大的数*/
# include <stdio.h>
void max(int i, int j) //定义函数
{
if (i > j)
printf("max = %d\n", i);
else
printf("max = %d\n", j);
}
int main(void)
{
int a, b, c, d, e, f;
a = 1, b = 2, c = 4, d = -3, e = 5, f = 10;
max(a, b); //调用函数
max(c, d);
max(e, f);
return 0;
}
void表示函数没有返回值,max是函数的名字,i、j是形式参数,即形参- 程序执行,从
main开始执行,执行到max(a, b);后,认为这是调用了函数,开始检测是否定义了max的函数
- 调用前面定义的
max函数,然后将 a 赋值给 i,b 赋值给 j,执行函数- 函数执行完后,分配给形参的地址空间将会被释放
/*运行结果*/
max = 2
max = 4
max = 10
Press any key to continue
方法二:
/*现有a-f共6个变量,每个变量都有一个值,要求比较a、b,c、d,e、f之间的大小,并且输出较大的数*/
# include <stdio.h>
int max(int i, int j) //定义函数
{
if (i > j)
return i; //将i返回给主调函数
else
return j;
}
int main(void)
{
int a, b, c, d, e, f;
a = 1, b = 2, c = 4, d = -3, e = 5, f = 10;
printf("max = %d\n", max(a, b)); //主函数将i输出
printf("max = %d\n", max(c, d));
printf("max = %d\n", max(e, f));
return 0;
}
- 输出结果同上
- 不同点在于第一个程序中被调函数是直接将结果输出,而第二个程序中,被调函数将值返回主调函数,由主调函数进行处理
如何定义函数
- 函数定义的本质是详细描述函数之所以能够实现某个特定功能的具体方法
return 表达式;的含义- 终止被调函数,向主调函数返回表达式的值
- 如果表达式为空,则只终止函数,不返回任何值
break用来终止循环和switch
例:return和break的区别
/*return和break的区别*/
# include <stdio.h>
void f(void)
{
int i;
for (i = 0; i < 5; ++i)
{
printf("Bad!\n");
break; //终止的是for循环
}
return; //终止的是f函数
printf("Boy!\n"); //不会输出
}
int main(void)
{
f();
return 0;
}
/*运行结果*/
Bad!
Press any key to continue
- 函数返回值的类型也是函数的类型
- 如果函数名前的返回值类型和函数执行体中的
return 表达式类型不同,则最终函数返回值的类型是函数名前的返回值类型
- 如果函数名前的返回值类型和函数执行体中的
- 格式
函数返回值的类型 函数的名字(函数的形参要求)
{
函数的执行体
}
例:函数返回值的类型
/*函数返回值的类型*/
# include <stdio.h>
int f()
{
return 3.5; //因为函数的返回类型是int,所以最终返回的值为3
}
int main(void)
{
double x = 5.5;
x = f(); //调用函数,数值类型以函数名前的类型为准
printf("%lf\n", x);
return 0;
}
- 函数f中的返回值是浮点型,函数名前的类型是整形
- 如果函数值类型是以
return返回的类型为准,则返回的是3.5。如果函数值类型是以函数名前的类型为准,则函数值为3
/*运行结果*/
3.000000
Press any key to continue
函数的分类
- 有参函数和无参函数
- 有返回值和无返回值
- 库函数和自定义函数
- 值传递函数和地址传递函数
- 普通函数和主函数(main函数)
- 一个程序必须有且只有一个主函数
- 主函数可以调用普通函数,普通函数不能调用主函数
- 普通函数之间可以互相调用
- 主函数是程序的入口和出口
程序举例
例:判断一个数是否是素数
/*判断一个数是否是素数*/
# include <stdio.h>
int main(void)
{
int val;
int i;
printf("请输入需要判断的数:");
scanf("%d", &val);
for (i = 2; i < val; ++i)
{
if (val % i == 0)
break; //终止for循环
}
if (i == val)
printf("%d是素数!\n", val);
else
printf("%d不是素数!\n", val);
return 0;
}
/*运行结果*/
请输入需要判断的数:13
13是素数!
---------------------
请输入需要判断的数:9
9不是素数!
Press any key to continue
定义函数
/*判断一个数是否是素数【定义函数】*/
# include <stdio.h>
bool IsPrime(int val) //bool类型数据返回真或假
{
int i;
for (i = 2; i < val; ++i)
{
if (val % i == 0)
break;
}
if (i == val)
return true; //return会终止函数
else
return false;
}
int main(void)
{
int m;
printf("请输入需要判断的数:");
scanf("%d", &m);
if (IsPrime(m)) //判断被调函数返回值是否为真
printf("%d是素数!\n", m);
else
printf("%d不是素数!\n", m);
return 0;
}
- 输出结果同上
函数声明
- 定义函数要写在调用函数前,如果写在调用函数后,则需要写函数声明
- 函数前置声明
- 告诉编译器,即将出现的若干个字母代表的是一个函数
- 告诉编译器,若干个字母代表的函数的形参和返回值的具体情况
- 函数声明是一个语句,必须使用分号
- 对库函数的声明是通过`# inculde <库函数所在文件的文件名.h>来实现的
例:
/*函数声明*/
# include <stdio.h>
void f(void); //函数声明
int main(void)
{
f();
return 0;
}
void f(void)
{
printf("Bad Boy!\n");
}
/*运行结果*/
Bad Boy!
Press any key to continue
形参和实参
- 形参和实参的位置和个数必须一一对应,类型也必须兼容
例:
/*形参和实参*/
# include <stdio.h>
void f(int i, int j) //形参
{
printf("%d %d\n", i, j);
}
int main(void)
{
f(3, 5); //实参
return 0;
}
/*运行结果*/
3 5
Press any key to continue
合理设计函数解决实际问题
例:用户输入一个数,输出0到这个数之间的所有素数
/*用户输入一个数,输出0到这个数之间的所有素数*/
# include <stdio.h>
int main(void)
{
int i, j;
int val;
printf("请输入一个数:");
scanf("%d", &val);
printf("素数有:");
for (i = 2; i <= val; ++i)
{
for (j = 2; j < i; ++j)
{
if (0 == i % j)
break;
}
if (i == j)
printf("%d ", i);
}
printf("\n");
return 0;
}
/*运行结果*/
请输入一个数:50
素数有:2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
Press any key to continue
- 以上代码重用性不高,不容易理解,有局限性
方法二:定义函数
/*定义函数,输出指定数之间的素数*/
# include <stdio.h>
bool IsPrime(int m) //定义函数只判断数是否是素数
{
int i;
for (i = 2; i < m; ++i)
{
if (0 == m % i)
break;
}
if (i == m)
return true;
else
return false;
}
int main(void)
{
int i, val;
printf("请输入一个数:");
scanf("%d", &val);
printf("素数有:");
for (i = 2; i <= val; ++i)
{
if (IsPrime(i))
printf("%d ", i);
}
printf("\n");
return 0;
}
优化:
/*定义函数,输出指定数之间的素数*/
# include <stdio.h>
bool IsPrime(int m) //定义函数只判断数是否是素数,是则返回true,否则返回false
{
int i;
for (i = 2; i < m; ++i)
{
if (0 == m % i)
break;
}
if (i == m)
return true;
else
return false;
}
void TraverseVal(int n) //定义函数把1-n之间的所有素数输出
{
int i;
printf("素数有:");
for (i = 2; i <= n; ++i)
{
if (IsPrime(i))
printf("%d ", i);
}
printf("\n");
}
int main(void)
{
int val;
printf("请输入一个数:");
scanf("%d", &val);
TraverseVal(val); //调用函数
return 0;
}
- 函数是C语言的基本单位,类是Java,C#,C++的基本单位
常用的系统函数
double sqrt(double x); //求x的平方根
int abs(int x); //求整形x的绝对值
double fabs(double x); //求浮点数x的绝对值
变量的作用域和存储方式
- 作用域
- 全局变量
- 局部变量
- 在一个函数内部定义的变量或函数的形参
- 只能在本函数内使用
- 变量的存储方式
- 静态变量
- 自动变量
- 寄存器变量
例:
/*变量的作用域*/
# include <stdio.h>
void g()
{
printf("k = %d\n", k); //error,因为k变量被定义在了函数的后面
}
k = 3; //全局变量,之后所有的函数都可以调用
void f(int i) //局部变量,只有本函数可以调用
{
int j = 5; //局部变量
int i = 3; //error,因为形参中的变量名和函数中的变量名冲突
}
- 在一个函数内部,如果定义的局部变量名字和全局变量的名字一样,局部变量会屏蔽掉全局变量
以上内容均属原创,如有不详或错误,敬请指出。
边栏推荐
- SVN版本控制器的安装及使用方法
- [200 opencv routines] 211 Draw vertical rectangle
- 产品力对标海豹/Model 3,长安深蓝SL03预售17.98万起
- Privacy computing fat offline prediction
- 通俗易懂理解樸素貝葉斯分類的拉普拉斯平滑
- Principle and application of the most complete H-bridge motor drive module L298N
- 我大抵是卷上瘾了,横竖睡不着!竟让一个Bug,搞我两次!
- 基于STM32设计的蓝牙健康管理设备
- torchvision.models._utils.IntermediateLayerGetter使用教程
- R语言plotly可视化:plotly可视化二维直方图等高线图、在等高线上添加数值标签、自定义标签字体色彩、设置鼠标悬浮显示效果(Styled 2D Histogram Contour)
猜你喜欢

CPU设计(单周期和流水线)

通俗易懂理解朴素贝叶斯分类的拉普拉斯平滑
![文件名设置导致writelines写入报错:OSError: [Errno 22] Invalid argument](/img/08/2d4f425e6941af35616911672b6fed.png)
文件名设置导致writelines写入报错:OSError: [Errno 22] Invalid argument

最全H桥电机驱动模块L298N原理及应用

【生动理解】深度学习中常用的各项评价指标含义TP、FP、TN、FN、IoU、Accuracy

E+h secondary meter repair pH transmitter secondary display repair cpm253-mr0005

E+H二次表维修PH变送器二次显示仪修理CPM253-MR0005

别再用 System.currentTimeMillis() 统计耗时了,太 Low,StopWatch 好用到爆!

产品力对标海豹/Model 3,长安深蓝SL03预售17.98万起

基于STM32设计的蓝牙健康管理设备
随机推荐
Freemarker
Semi-supervised Learning入门学习——Π-Model、Temporal Ensembling、Mean Teacher简介
如何获取GC(垃圾回收器)的STW(暂停)时间?
[system design] proximity service
借助原子变量,使用CAS完成并发操作
12 necessary tools for network engineers
Vector:: data() pointer usage details
Advantages and disadvantages of distributed file storage system
js 所有的网络请求方式
Markem Imaje Marken IMAS printer maintenance 9450e printer maintenance
es 根据索引名称和索引字段更新值
Decompile the jar package and recompile it into a jar package after modification
2-4Kali下安装nessus
std::memory_order_seq_cst内存序
多個類的設計
运维一线工作常用shell脚本再整理
Conception de plusieurs classes
.NET 中的引用程序集
测试同学怎么参与codereview
通俗易懂理解樸素貝葉斯分類的拉普拉斯平滑