C语言之函数设计(1)

目录

没有返回值的函数

通用性

不含形参的函数

函数返回值的初始化

作用域

 文件作用域

声明和定义

函数原型声明

头文件和文件包含指令


在上节中我们简单的学习了函数的创建方法(函数定义)与函数的使用方法(函数调用),现在我们来学习更为知识的函数创建方法等知识。


没有返回值的函数

在前面的循环结构中我们学习了用*来显示出等腰三角形的程序,下面我们把显示出*的部分作为一个单独的函数,通过调用这个函数显示出直角在左下方的三角形。

#include<stdio.h>/*连续显示出多个n*/
void put_stars(int n)
{while(n-- > 0)putchar('*');
}int main()
{int i, len;printf("生成一个直角在左下方的等腰直角三角形。\n");printf("短边:");scanf("%d", &len);for(i = 1; i <= len; i++){put_stars(i);putchar('\n');}return 0;
}

在put_stars函数中只是用来显示n个*,并没有需要返回的值。这种没有返回值的函数类型,要声明为void

 void就是“空”的意思,在C语言中无论有没有返回的值都同样称为函数,而在其他编程语言中会定义为其他非函数的概念,例如子程序(fortran)或过程(Pascal)。

 这里我们使用put_stars函数把二重循环简化为一重循环,从而提高程序的可读性。


通用性

我们这次来编写一个显示出直角在右下方的等腰三角形的程序。

#include<stdio.h>/*连续显示出多个ch*/
void put_chars(int ch, int n)
{while(n-- > 0)putchar(ch);
}int main()
{int i, len;printf("生成一个直角在左下方的等腰直角三角形。\n");printf("短边:");scanf("%d", &len);for(i = 1; i <= len; i++){put_chars(' ', len - i); //显示出len-i个空格put_chars('*', i);//紧接着显示出i个*putchar('\n');}return 0;
}

让我们来解释下:

本程序需要连续显示出多个空白字符,因此需要创建出put_chars来代替函数put_stars。

put_chars可以连续显示出n个通过形参传递来的字符。

前面我们学习过字符常量是int型的,这里还存在显示字符的char型,我们以后会学习到

 函数put_chars和只能显示*的函数put_stars相比较更具有通用的优势。

putchar(ch);
put_chars(' ', len - i); put_chars('*', i);

ch就是put_chars用来传递字符的,既可以传递空白字符又可以传递*,相信这样单独拉出来解释大家有更加明白的认识。


不含形参的函数

我们用下面一段程序来引出不含形参的参数,大家可以先看程序中的特别的代码试着分析它的作用然后再阅读解析。

#include<stdio.h>
//返回输入的正整数
//关于这个函数的名字不必纠结,学的后面我们就能熟练起适当的函数名了
int scan_pint(void)
{int tmp;do{printf("请输入一个整数:");scanf("%d", &tmp);if(tmp <= 0)puts("\a请不要输入非负正整数。");}while(tmp <= 0);return tmp;
}
/*返回正整数倒转后的值*/
int rev_int(int num)
{int tmp = 0;if(num > 0){do{tmp = tmp * 10 + num % 10;num /= 10;}while(num > 0);}return tmp;
}
int main()
{int nx = scan_pint();//不赋予实参printf("该整数倒转后的值是%d。\n", rev_int(nx));return 0;
}

其中有几段代码是不是有点特殊呢?让我们来看看吧!

int scan_pint(void)

函数scan_pint读取从键盘输入的正整数并返回。该函数不接受形参,为了加以说明在小括号中加入void。

int nx = scan_pint()

调用方也没有必要赋予实参,所以函数调用运算符()是空的,其实在到目前为止我们学习的main函数也可以写为int main(void)


函数返回值的初始化

int nx = scan_pint();

注意main函数中声明变量nx的部分,该变量得初始值是函数scan_pint()的表达式,变量逆向使用函数scan_pint()的返回值进行初始化。

但是该初始化方法只适用于拥有自动存储期的对象,不适合拥有静态存储期的对象。


作用域

函数scan_pint和函数rev_int都包含一个拥有相同的标识符(名称)的变量tmp,但它们是各自不同的变量。

就是说scan_pint中的变量tmp是函数scan_pint特有的变量,对rev_int也是一样。

赋给变量的标识符,它的名称有一个通用的范围就是作用域

在程序块中声明变量的名称,只在该程序块中通用,在其他区域无效,简单来说就是从变量声明的位置开始,到该声明的程序块中的大括号 } 为止这一区间内通用,这样的作用域称为块作用域(block scope)。


 文件作用域

还是老样子,我们用程序来引出,大家可以先观察程序中某一语句的特别之处猜想它们的用法:

/*计算最高分*/
#include<stdio.h>#define NUMBER 5//学生人数int tensu[NUMBER];//数组定义:创建数组实体的声明(定义)int top(void);//函数top的函数原型声明int main()
{extern int tensu[];//数组的声明(可以省略)int i;printf("请输入%d名学生的分数。\n", NUMBER);for(i = 0; i < NUMBER; i++){printf("%d:", i+1);scanf("%d", &tensu[i]);}printf("最高分=%d\n", top());return 0;
}
/*返回数组tensu的最大值(函数top的函数定义)*/
int top(void)
{extern int tensu[];//数组的声明(可以省略)int i;int max = tensu[0];for(i = 1; i < NUMBER; i++){if(tensu[i] > max)max = tensu[i];}return max;
}

在函数程序块中声明的变量等标识符是该程序块中特有的部分,而像数组tensu[ ]这样,在函数外声明的变量标识符,其位置从声明的位置开始到程序的结束都是通用的。

int tensu[NUMBER];//数组定义:创建数组实体的声明(定义)

这样的作用域称为文件作用域


声明和定义

像上面的一个语句,创建了一个元素为5、元素类型为int的数组tensu。这样创建变量实体的声明称为定义(definition)声明

extern int tensu[];//数组的声明(可以省略)

像这样使用了extern的声明表示“使用的是在某处创建的tensu”,这里并没有真正创建出变量的实体,因此称为非定义声明

由于数组tensu是在函数外定义的,所以只需要在main函数或top函数中明确声明要使用它就可以放心使用了。

由于数组tensu被赋予了文件作用域,因此在main函数和top函数中无需特意声明,就可以使用它。


函数原型声明

和人一样,编译器在读取数据时也是从头到尾按照顺序进行读取的,因为top函数的函数定义在main函数之后,所以在想要调用top函数,就需要让编译器知道你的想法。

int top(void);//函数top的函数原型声明

像这样明确记述了函数的返回类型,形参类型和个数的声明称为函数原型声明

该语句要以“;”结尾

 函数原型声明只声明了函数的返回值和形参等相关类型,并没有定义函数的实体。

函数定义和函数原型声明的不同之处如下所示:

函数top的函数定义——定义声明(有实体)

函数top的函数原型声明——非定义声明(没有实体)

 如果top函数的需求(返回值类型,形参等)发生了改变那么函数定义和函数原型声明两部分都必须进行修改,不能只改动其中一个!

如果把函数top的函数定义写在main函数之前,就不用特意使用函数原型声明了,我们推荐把main函数放在程序最后的位置。


头文件和文件包含指令

通过函数原型声明,可以指定函数的参数以及返回值的类型等信息,这样就可以放心的使用函数了。

库函数printf或putchar等的函数原型声明都包含在<stdio.h>中,因此必须要使用以下固定的指令:

#include<stdio.h>

通过#include指令,就可以把<stdio.h>中的全部内容都读取到程序中。

包含库函数的函数原型声明的<stdio.h>称为头文件,而取得头文件的#include称为文件包含指令

例如,putchar的函数原型声明在头文件<stdio.h>中的声明格式如下:

	int putchar(int _ _ c);

编译器不同,形参的名称也可能不同。

在函数原型声明的时可以不指定形参的名称,也可以这样进行声明:

	int putchar(int);

我们先学习到这里,之后我们会学习函数的通用性——可以处理任意数组、处理不同元素个数的数组等更加精细的内容。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

道路基础设施三维数字化及GIS平台建设方案

目录 1.应用背景2.三维移动测量系统2.1 车载三维移动测量系统2.2 无人机倾斜摄影系统2.3 地面激光采集系统 3.多源数据三维融合处理4.道路设施专题信息提取与分析4.1 路产三维地理信息4.2 高精度导航地图4.3 路面病害检测4.4 隧道形变分析 5. 三维全要素模型建模5.1 道路5.2 桥…

安卓拍照扫描APP解决方案——基于深度学习与NDK实现文档图像版面检测与分析

一、概述 文档版面分析是针对图片或页面扫描图像上感兴趣的区域进行定位和分类的过程。其主要目标在于让机器能够理解文档结构&#xff0c;即将文档图像划分为不同类型内容的区域&#xff0c;并分析这些区域之间的关系。这是进行内容识别之前的关键步骤&#xff0c;它通常可以…

12.9_黑马数据结构与算法笔记Java

目录 057 多路递归 e03 杨辉三角2 thinking&#xff1a;二维数组的动态初始化&#xff1f; 057 多路递归 e03 杨辉三角3 058 链表 e01 反转单向链表1 058 链表 e01 反转单向链表2 058 链表 e01 反转单向链表3 递归 058 链表 e01 反转单向链表4 为什么是returnn1呢&…

Go开发运维:Go服务发布到K8S集群

目录 一、实验 1.Go服务发布到k8s集群 二、问题 1.如何从Harbor拉取镜像 一、实验 1.Go服务发布到k8s集群 &#xff08;1&#xff09;linux机器安装go(基于CentOS 7系统) yum install go -y &#xff08;2&#xff09;查看版本 go version &#xff08;3&#xff09;创…

【数电笔记】54-或非门构成的基本RS触发器

目录 说明&#xff1a; 1. 电路组成 2. 逻辑功能 3. 特性表 4. 特性方程 5. 例题 6. 两种基本RS触发器的形式比 说明&#xff1a; 笔记配套视频来源&#xff1a;B站&#xff1b;本系列笔记并未记录所有章节&#xff0c;只对个人认为重要章节做了笔记&#xff1b;标题前…

万户 ezOFFICE 文件上传漏洞复现

0x01 产品简介 万户OA ezoffice是万户网络协同办公产品多年来一直将主要精力致力于中高端市场的一款OA协同办公软件产品,统一的基础管理平台,实现用户数据统一管理、权限统一分配、身份统一认证。统一规划门户网站群和协同办公平台,将外网信息维护、客户服务、互动交流和日…

(三潮来袭)探寻2023年科技变革潮流与2024年前瞻展望

2023年对于IT行业来说是一个动荡而又充满变革的一年。随着世界逐渐走出前几年的挑战&#xff0c;企业逐渐复苏&#xff0c;但这个行业仍然在经历着激烈的变革。在这个时候&#xff0c;我们看到了一些引人注目的技术变化和未来的趋势。 一、2023年回顾 关键词&#xff1a;Chat…

计算机基础知识66

Auth的补充 #概念&#xff1a;是django 的一个app&#xff0c;关于用户的登录&#xff0c;退出&#xff0c;注册... # 配置文件中配置&#xff1a;表会被迁移 INSTALLED_APPS [django.contrib.auth,] # auth有哪些表---权限控制&#xff1a; Permission&#xff1a;auth_permi…

linux Ubuntu下,第一个C++程序访问数据库,遇到的问题,及解决办法

在ubuntu下安装了mysql&#xff0c;mysql以后&#xff0c;编写了第一个访问数据库的程序&#xff1a; #include <iostream> #include <string> #include <cstdlib> //for system #include <mysql.h>using namespace std;int main() {mysqlpp::Connect…

所有行业的最终归宿-我有才打造知识付费平台

随着科技的不断进步和全球化的加速发展&#xff0c;我们生活在一个信息爆炸的时代。各行各业都在努力适应这一变化&#xff0c;寻找新的商业模式和增长机会。在这个过程中&#xff0c;一个趋势逐渐凸显出来&#xff0c;那就是知识付费。可以说&#xff0c;知识付费正在成为所有…

代码随想录第二十八天(一刷C语言)|买卖股票的最佳时机II跳跃游戏跳跃游戏II

创作目的&#xff1a;为了方便自己后续复习重点&#xff0c;以及养成写博客的习惯。 一、买卖股票的最佳时机II 思路&#xff1a;参考carl文档 把利润分解为每天为单位的维度&#xff0c;而不是从 0 天到第 3 天整体去考虑。局部最优&#xff1a;收集每天的正利润&#xff0c…

淘宝权益玩法平台的Serverless化实践

通过对权益玩法平台现有业务应用的Serverless化改造&#xff0c;权益团队在双十一期间完美地支撑了业务需求&#xff0c;在研发效率、运维保障等方面都体现出了很高的价值和收益。 项目背景 淘宝权益平台是负责淘宝权益营销的核心团队&#xff0c;团队除了负责拉菲权益平台外&a…