工欲善其事,必先利其器。

方程是一种数学工具,列方程解方程能够有效解决数学问题。

函数是一种编程技巧,设计函数实现函数能够提高程序设计的效率。

函数之所以难学,是因为它太多变了,有多种形态。

课本不写全吧,作者会被骂。

课堂不讲全吧,老师会被骂。

于是乎,老师满堂灌,学生糊涂蛋。

学生要想不当糊涂蛋,必须拼命地训练。

师傅领进门,修行在个人,绝不是推诿责任,而是事物发展的规律。

客官,如果您有时间,请慢慢听我胡扯。

一、建议初学者,把变量定义全部写在函数外,成为全局变量

#include<stdio.h>
int a,b,c;
void main(void)
{scanf("%d%d",&a,&b);c=a+b;printf("%d\n",c);
}

这样理解:

1、把这个程序整体看做一个学校,a、b、c相当于书记、校长、副校长的名字;

2、main函数相当于学校的一个系;这个程序简单,所以暂时只有一个系;

3、main函数内部相当于系的内部,系内部当然都知道校领导们的名字

怎么样,通俗易懂吧。

注:对于各种程序设计竞赛,主要考察算法,因此总体上程序代码不会太长,而且对效率的要求比较高,采取这种全局变量是经常性的手段。

二、代码闹独立,要称王

我们可以像main函数一样,再设计几个其他函数,把程序代码封装起来。

例如:

#include<stdio.h>
int a,b,c;
void input(void)
{scanf("%d%d",&a,&b);
}
void calculate(void)
{c=a+b;
}
void output(void)
{printf("%d\n",c);
}
void main(void)
{input();//输入 calculate();//计算 output();//输出}

(函数调用示意图,来自百度图片搜索)

分析:

1、main函数的代码都不安分,一气化三清,代码独立啦,分解为新的三个函数,input、calculate、output

2、好处是,分而治之好管理了,等大家遇到比较复杂的程序,超过100行那种,就理解得深刻了。

3、如果到此为止,大家一定会说,函数真得太好了,使得程序逻辑更清楚了,也根本没什么难度嘛。

注意:到此为止,你已经能够用函数参加竞赛了,而且如果你算法好的话,拿个冠军都可以。

下面的部分,都是要考虑到大型程序,多人协作时容易产生函数名冲突、变量名冲突,而采取的措施,是越来越复杂。


函数理论复杂就复杂在,他不提倡使用全局变量(即在函数外定义变量),因为多个函数共享变量容易出矛盾,程序结果出现问题不太容易追责。他们的理想是,每一个函数是一个独立王国,只有一个入口和一个出口,来我国的人,必须从入口进,从出口出。也可以把每一个函数比作一个机器,比如榨汁机,苹果塞进去,苹果汁出来;葡萄塞进去,葡萄汁出来。内部怎样实现的,使用的人不必知道。

好了,这样以来,事情变复杂了。就好比两个男女青年谈恋爱,本来是以爱情为主,一见钟情,电光石火,水到渠成。现在非要加上一些其他条件,什么高富帅、白富美,结果剩男剩女一大堆,问题不好优化啊。

我们先改造代码。

三、改造我们的代码

#include<stdio.h>void input(int *a,int *b)
{scanf("%d%d",a,b);
}
int calculate(int a,int b)
{int c;c=a+b;return c;
}
void output(int c)
{printf("%d\n",c);
}
void main(void)
{int a,b,c;input(&a,&b);//输入 c=calculate(a,b);//计算 output(c);//输出}

分析:

1、为了达到每个函数独立的目的,还需要有理论的支撑。函数外定义的变量叫“全局变量”,函数内定义的变量叫“局部变量”。全局变量、局部变量各在内存的什么地方分配才能高效?

2、mai函数的a、b和input中的a、b只是重名而已,但是他们不在同一个系,不会冲突。什么样的机制才能保障他们不冲突?

3、以上,说出来轻松,编译程序却要精心设计,才能应对变化。

4、最主要的,这些设计的原理,却会成为找工作时面试官的题目。所以在各种课本,函数不仅单独一章,还和其后各章相关联。

因此,同志们,同学们,在大一的阶段,40个课时,只能学基本语法,就像幼儿园学个拼音、儿歌、数个数,哪能讲什么语法,讲了也没什么效果。

C 语言背后原理,或者其他语言背后的原理,有一门课叫做编译原理的,会慢慢到来。

你想,一门课的东西,你非要你的C语言老师给你讲清楚,臣妾估计也是打死都做不到啊。

编译原理三大经典书籍(龙书 虎书 鲸书):

https://blog.csdn.net/shenwansangz/article/details/44217233

编译原理三大圣书——龙书、虎书、鲸…

https://blog.csdn.net/xiaolanmyself/article/details/16944135

同学,你骨骼不太惊奇,不建议你看,知道这三本书的名字,会吹吹牛bi得了。

如果你去看了,我怕你会“学习计算机编程,从入门到放弃”......

四、函数语法

函数返回值类型   函数名(参数列表)

{

//函数体

}

上面就是函数的语法形式。

就像是自然语言有语法一样,程序设计语言也是有语法的。

你写文章头疼,编程也会头疼。只不过编程要比写文章简单很多。

其中最难的是,参数列表的写法与解释。

无他,唯手熟尔。

只有多读程序,多写程序,才能够掌握。

可是,亲爱的计算机专业大学生们,每个学期那么多课程,怎么会有时间写程序呢?

无他,唯有舍得,舍弃哪些对你的人生目标不重要的科目,及格就行;把功夫放在编程上,才能得到!

1、简单数据传值

void func(int a,int b)

{.....}

参数 int a,int b;就是最普通的定义方法,因此是传值。

2、简单数据传地址

void func(int *a,int *b)

{.....}

参数 int *a,int *b; 是指针的形式,因此a、b中只能存储地址值

3、关于返回值

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

函数体中可以用 return语句返回一个值。那么return后面那个量的类型是什么,函数的返回值类型就设计成什么。

4、传递一维数组

void func(int a[],int n)

{.......}

void func(int *b,int n)

{.......}

这两种写法等价。或者说,前者的本质是后者,前者符合人们日常思维习惯,后者符合计算机计算思维。

5、传递二维数组

#define N 100

void func(int a[][N],int n)

{.......}

void func(int *b[100],int n)

{.......}

这两种写法等价。或者说,前者的本质是后者,前者符合人们日常思维习惯,后者符合计算机计算思维。

6、传递结构体

struct node

{

int a;

int b;

};

void func(struct node mynode){.....}

void func(struct node *mynode){.....}

结构体可以定义复杂类型,其和函数的结合,解释同普通变量

五、函数指针

本部分目的:基于函数指针,介绍C语言中快速排序函数的用法。

因此是一石二鸟,既介绍了函数指针,也介绍了快速排序函数。

在此基础上如果你能想到,啊,原理函数指针能够增加函数设计的通用性,有利于代码复用,那你是非常有悟性的。

qsort:quick sort,快速排序。

其出世之日,电闪雷鸣,震惊了世界,其他排序算法的速度不能望其项背。

1、项目驱动

对于一个整数数组,请分别对其中数据进行升序和降序排列。

2、函数原型

•#include <stdlib.h> //头文件

•void qsort( void *buf, size_t num, size_t size, int (*compare)(const void *, const void *) );

•buf:待排序数据的首地址

•num:待排序数据个数

•size:每个数据的大小,单位是字节

•compare:比较函数。

•可以通过重新定义compare比较函数,来调整是升序还是降序。

int (*compare)(const void *, const void *) 这是函数的原型,即你必须按照这种个数来自己定义该函数。

3、比较函数的写法

int Asending(const void *x,const void *y)
{//升序比较函数 int *a,*b;a=(int*)x;b=(int*)y;if(*a>*b)return 1;else if(*a==*b)return 0;elsereturn -1;
}int Desending(const void *x,const void *y)
{//升序比较函数 int *a, *b;a=(int*)x;b=(int*)y;if(*a>*b)return -1;else if(*a==*b)return 0;elsereturn 1;
}

注意:比较函数的名字无所谓,但是其参数和返回值类型是系统规定好的。你必须符合规则。

4、主函数

void printArray1D(int a[],int n)
{//打印数组中数据 int i;for(i=0;i<n;i++){printf("%d ",a[i]);}printf("\n");
}
int main()
{int a[]={1,4,6,2,5,3};//数组int n=sizeof(a)/sizeof(int);//数据个数//升序排列qsort(a,n,sizeof(int),Asending);   printArray1D(a,n) ;//降序排列qsort(a,n,sizeof(int),Desending);  printArray1D(a,n) ;return 0;
}

注意:主调函数在调用qsort时,把比较函数当作参数传递给qsort,其内部机制为:

x会指向a[i],y会指向a[j]

若compare(x,y)返回值为1,则交换a[i]和a[j]的值,否则不交换。

所以你调整比较函数的返回值是 1 还是 -1,就能调整是升序还是降序。

5、对复杂类型数据排序

当数据不是简单数据类型时,比如对平面上的点排序,先按照x的大小从小到大排,如果x相等,则按照y的值从小到大排。

#include<stdio.h>
#include<stdlib.h>
struct point
{int x;int y;
};
int Asending(const void *x,const void *y)
{//升序比较函数 struct point *a,*b;a=(struct point*)x;b=(struct point*)y;if(a->x > b->x)return 1;else if(a->x == b->x){if(a->y > b->y)return 1;else if(a->y == b->y)return 0;elsereturn -1;           }       elsereturn -1;
}int Desending(const void *x,const void *y)
{//升序比较函数 struct point *a,*b;a=(struct point*)x;b=(struct point*)y;if(a->x > b->x)return -1;else if(a->x == b->x){if(a->y > b->y)return -1;else if(a->y == b->y)return 0;elsereturn 1;          }       elsereturn 1;
}
void printArray1D(struct point a[],int n)
{//打印数组中数据 int i;for(i=0;i<n;i++){printf("(%d %d) ",a[i].x,a[i].y);}printf("\n");
}
int main()
{struct point a[]={{2,8},{2,6},{1,9},{1,7}};//数组int n=sizeof(a)/sizeof(struct point);//数据个数printArray1D(a,n) ;//升序排列qsort(a,n,sizeof(struct point),Asending); printArray1D(a,n) ;//降序排列qsort(a,n,sizeof(struct point),Desending); printArray1D(a,n) ;return 0;
}

运行结果:

(over)

C语言-函数-学会方程你的数学能力会乘风破浪突飞猛进-学会函数你的编程能力将百尺竿头更进一步相关推荐

  1. r语言集合补集_【高中数学必修1研读】之一“第一章 集合与函数概念”

    第一章:集合与函数概念 [导入例子] "神舟"五号载人航天飞船离地面的距离随时间的变化而变化:上网费用随着上网时间的变化而变化:出国旅游人数日益增多:城市绿化面积不断扩大..... ...

  2. R语言应用uniroot函数求解方程的根(一元解):仿真数据(方程式可视化、并添加y=0的水平横线)、uniroot函数求解方程的根(并添加方程根对应的垂直竖线)

    R语言应用uniroot函数求解方程的根(一元解):仿真数据(方程式可视化.并添加y=0的水平横线).uniroot函数求解方程的根(并添加方程根对应的垂直竖线) 目录

  3. 高中数学函数题:函数与方程【经典例题及解析】

    本文作者:vxbomath 大家好,今天分享高中数学函数与方程关系是高中生需要重点掌握的内容.下面是我整理2019年考题函数与方程习题希望能对大家有所帮助. 一.选择题 二.填空题 好了,今天分享就到 ...

  4. python数学库函数包括求最大公约数函数吗_pythonmathcot函数_math库是python语言的数学模块吗_Python中的数学模块:...

    Python部落(python.freelycode.com)组织翻译,禁止转载,欢迎转发. 当我们在日常生活中编写程序时,我们通常遇到需要使用数学来完成任务的情况.像其他编程语言一样,Python提 ...

  5. c语言 迭代法求方程的根,编写用牛顿迭代法求方程根的函数

    问题描述: 编写用牛顿迭代法求方程根的函数. 方程为:a*x^3 + b*x^2 + c*x + d = 0,系数a,b,c,d由主函数输入. 求x在1附近的一个实根.求出根后,由主函数输出. #in ...

  6. c语言求一元二次函数根,编写求一元二次函数的根的函数 C

    二次函数与一元二次方程,一元二次不等式的关系? 二次方程ax²+bx+c=0可以看做给定二次函数y=ax²+bx+c的函数值为0时的情况因此当函数与X轴没有交点时,二次方程也无解二次不等式可以看做是二 ...

  7. python求分段函数值_高中数学知识点整理(2)——函数概念及基本初等函数篇(上)...

    大家好!我是高考数学易老师,今天是我来知乎的第二天,今天更新函数概念及基本初等函数知识点.如果有任何关于高中数学知识点,可随时询问呢. 函数 1. 函数与映射(1) 函数的概念 设 是两个非空的数集, ...

  8. c语言中的关于数学问题的编程,C语言中具有代表性几种数学问题编程技巧探索.doc...

    C语言中具有代表性几种数学问题编程技巧探索 C语言中具有代表性几种数学问题编程技巧探索 [摘要]本文分析了C语言中几种常见的具有代表性的几类数学问题,从数学规律.语法结构分析.语句优化设计及应用方面, ...

  9. 二分法求解方程的根java_C语言二分法求解方程根的两种方法

    本文实例为大家分享了C语言二分法求解方程根的具体代码,供大家参考,具体内容如下 对于二分法求根,其实和弦截法思想很像,甚至更简单. 原理:先看如下的图 A,B两个点为跟的一个边界,通过一直缩小跟的边界 ...

最新文章

  1. 图像特征点检测与匹配评价准则——量化
  2. JavaScript 初学者必看“箭头函数”
  3. Boost:原子API的用法测试程序
  4. 什么是protobuf
  5. Python函数之返回多值
  6. php 网络是否通,测试网络连通性的命令是什么?
  7. 深度学习(00)——GPU版本的TensorFlow
  8. 子盒子width为父盒子width的百分比注意
  9. MATLAB-绘图-散点图绘制
  10. Android pda出入库管理,仓库PDA扫描出入库管理系统
  11. U盘量产大致研究思路
  12. APP测试与WEB测试
  13. tp1900芯片对比7621a_TP无线路由器WDR7660千兆版,厉害了单芯片TP1900
  14. 计算机网络共享自动关,启用网络发现,重新打开“高级共享设置”对话框,显示仍是关闭状态...
  15. 校园锐捷路由器使用指南
  16. 谷粒商城【商城系统】完整总结
  17. 华为手机提示更新包与已安装应用的签名不一致
  18. linux版高德导航软件下载,高德导航2017
  19. win10分屏设置一边竖屏_win10系统电脑屏幕竖屏改为横屏的详细办法
  20. speedoffice表格中怎样给文字添加删除线?

热门文章

  1. Qt程序在arm板上运行
  2. 成功解决ValueError: Duplicate plugins for name projector
  3. Leetcode 781 森林里的兔子(C++)
  4. 一个大专生的java从业心路历程
  5. 卸载vivo手机自带的应用程序
  6. Vulkan_Shader—高级光照_阴影_原理
  7. 基本粒子结构以及宇宙现象的徦说
  8. Centos7 安装coturn部署一套 STUN/TURN 服务 webRTC打洞服务器
  9. [刷题]leetcode #309 - Best Time to Buy and Sell Stock with Cooldown
  10. 删除控制文件中的磁带备份信息