iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C语言函数使用实例分析
  • 901
分享到

C语言函数使用实例分析

2023-06-30 02:06:56 901人浏览 独家记忆
摘要

这篇文章主要介绍了C语言函数使用实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C语言函数使用实例分析文章都会有所收获,下面我们一起来看看吧。函数的声明和定义函数声明告诉编译器有一个函数叫什么,参数是什么

这篇文章主要介绍了C语言函数使用实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C语言函数使用实例分析文章都会有所收获,下面我们一起来看看吧。

函数的声明和定义

函数声明

  • 告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但是具体是不是存在,函数声明决定不了

  • 函数的声明一般出现在函数的使用之前。要满足先声明后使用

  • 函数的声明一般要放在头文件中的

函数定义

函数的定义是指函数的具体实现,交待函数的功能实现

举例

简单的求和函数

一般写简单的求和函数,求和功能直接写在main( )函数了。

//简单的求和函数int main(){int a = 10;int b = 20;int sum = a+b;printf("%d\n", sum);return 0;}
把加法单独改写成函数

把加法功能单独写成一个函数,放在主函数前面。如果将函数add放在主函数后面,则会报错,因为程序自上而下进行的,主函数执行后,发现add函数未定义,找不到。

//之前的有函数的写法.函数放在前面int add(int x, int y){return x + y;}int main(){int a = 10;int b = 20;int sum = add(a, b);printf("%d\n", sum);return 0;}
添加函数声明
int add(int x, int y);//函数的声明int main(){int a = 10;int b = 20;int sum = add(a, b);printf("%d\n", sum);return 0;}int add(int x, int y)//定义放在主函数后面,需要先声明{return x + y;}
带头文件和函数声明

实际上,当函数代码较多时,一般采用模块化编程,每个函数实现功能尽量单一,函数间要低耦合、高内聚。因此,针对上面的加单的加法函数,用带头文件的写法重写一遍。

先定义源文件 test.c 、源文件 add.c和头文件 add.h

//源文件test. C#include "add.h"int main(){int a = 10;int b = 20;int sum = add(a, b);printf("%d\n", sum);return 0;}//源文件add.cint add(int x, int y)//定义放在主函数后面,需要先声明{return x + y;}//头文件add.hint add(int x, int y);//函数的声明
静态库(.lib)的生成

当编程写了一个减法的函数给别人用,但是又不想把源码直接分享给别人,这时候就可以将代码编译成静态库(就是.lib文件)。

静态库的特点:将函数编译成静态库,别人可以正常使用封装好的代码,但是又看不到源码。

下面举例说明,如何生成静态库(.lib):

新建VS工程,新建源文件 sub.c和 头文件 sub.h,编写一个减法函数 sub

//源文件 sub.cint sub(int x, int y)//函数定义需要先声明{return y - x;}//头文件 sub.hint sub(int x, int y);

依次点击解决方案资源管理器——项目名称——右键选属性,弹出对话框。

C语言函数使用实例分析

然后依次点击——配置属性——常规——项目默认值——配置类型——下拉菜单选择静态库(.lib)——应用——确定。

C语言函数使用实例分析

接着点击生成——生成解决方案。

C语言函数使用实例分析

最终会在工程文件夹下的——Debug文件夹——看到静态库.lib文件。

C语言函数使用实例分析

用记事本打开静态库,可以看到是乱码。

C语言函数使用实例分析

静态库文件的使用方法

接下来说明如何使用别人或者自己生成好的静态库文件:

(1)将函数对应的同名头文件.h文件 和 同名静态库.lib拷贝至自己的工程文件中。

C语言函数使用实例分析

(2)在头文件中添加上t头文件 sub0119.h

C语言函数使用实例分析

(3)在源文件中添加减法头文件引用 和静态库的引用,

#include "add.h"//加法头文件#include "sub0119.h"//减法头文件#pragma comment(lib,"sub0119.lib")//静态库必须加上

(4)程序运行时,会通过上面的引用将生成的静态库加载进来。在主函数直接使用 减法函数sub即可。

//带头文件的写法int main(){int a = 10;int b = 20;int sum = add(a, b);//一般的函数调用int subnum = sub(a, b);//使用静态库printf("%d\n", sum);printf("%d\n", subnum);return 0;}

运行程序见下图:

C语言函数使用实例分析

函数递归

什么是递归?

  • 递归做为一种算法在程序设计语言中广泛应用。

  • 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法

  • 它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解

  • 只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量

  • 递归的主要思考方式在于:把大事化小,将问题转化为可以重复有限次的小问题解决

递归的两个必要条件

  • 存在限制条件,当满足这个限制条件的时候,递归便不再继续

  • 每次递归调用之后越来越接近这个限制条件

练习1

接受一个整型值(无符号),按照顺序打印它的每一位。

输入:1234,输出 1 2 3 4

一般方法
void print(num)//自定义打印函数{int arr[10] = { 0 };//定义数组for (int i = 0; i < 4; i++){//将数字存放在数组里arr[i] = num % 10;//取数字最后一位num = num / 10;//取整数}for (int i = 3; i >= 0; i--){//倒着打印printf("%d ", arr[i]);}}int main(){int num = 1234;print(num);return 0;}
递归的方法

分析:打印1234可以分解成下图那样拆解,分别把不同位上的数字取出,最终把数字拆解剩最后一位时,开始打印:

  • print(1234),数字大于9表明数字还不是个位数,于是将1234拆解成123 和 4,分别通过取余和取模操作。把取余的123再次传给函数print

  • print(123),数字大于9表明数字还不是个位数,于是将123拆解成12 和 3,分别通过取余和取模操作,把取余的12再次传给函数print

  • print(12),数字大于9表明数字还不是个位数,于是将12拆解成1 和 2,分别通过取余和取模操作,把取余的1再次传给函数print

  • print(1),数字小于9表明数字是个位数,也就是分解到最后一步了,这就是递归的限制条件,于是将1取模操作,打印出来

C语言函数使用实例分析

代码如下所示:

void print(int num){if (num>9){print(num/10);//取余}printf("%d ",num % 10);//取模}int main(){int num = 1234;print(num);return 0;}

通过调试,我们分析整个递归程序的运行逻辑见下图,红色圆圈的1 2 3 4表示程序的执行顺序:

  • 第一次调用函数print,此时 num=1234, n>9, 满足if条件, 执行print(123), 调用函数print自身

  • 第二次调用函数print,此时 num=123, n>9, 满足if条件, 执行print(12), 调用函数print自身

  • 第三次调用函数print,此时 num=12, n>9, 满足if条件, 执行print(1), 调用函数print自身

  • 第四次调用函数print,此时 num=1, n<9, 不满足if条件, 执行printf(“%d”, num%10), 此时num=1, 打印1

此时函数已经拆解到最后一层了,函数执行结束返回到上一次调用的地方,绿色圆圈的1 2 3 4表示程序的返回顺序:

  • 在绿色圆圈1处,函数printf打印1后,将会返回到上一次调用print的地方,即绿色圆圈2

  • 在绿色圆圈2处,if语句已经执行完毕,按顺序执行printf(“%d”, num%10),此时num=12, 打印2。接着将会返回到上一次调用print的地方,即绿色圆圈3处

  • 在绿色圆圈3处,if语句已经执行完毕,按顺序执行printf(“%d”, num%10),此时num=123, 打印3。接着将会返回到上一次调用print的地方,即绿色圆圈4处

  • 在绿色圆圈4处,if语句已经执行完毕,按顺序执行printf(“%d”, num%10),此时num=1234, 打印4。接着将会返回到上一次调用print的地方,即主函数main中。

在函数运行过程中,每调用一次函数,在内存栈中就会开辟空间存放num的值,如下面蓝色方框显示,第一次调用函数存放的1234 在最底层, 以此类推,1是最后调用函数存放的,就在最上面。

在函数返回时,看绿色圆圈 1 2 3 4, num的值就从上向下取值,

  • 在绿色圆圈1处,num数值为1。打印1后,函数运行结束,存放1的空间就销毁了

  • 此时返回到绿色圆圈2里,num数值为12,打印2后,函数运行结束,存放12的空间也销毁了

  • 此时返回到绿色圆圈3里,num数值为123,打印3后,函数运行结束,存放123的空间也销毁了

  • 此时返回到绿色圆圈2里,num数值为1234,打印4后,函数运行结束,存放1234的空间也销毁了

C语言函数使用实例分析

运行结果见下图:

C语言函数使用实例分析

练习2

编写函数不允许创建临时变量,求取字符串的长度

一般方法
//编写函数不允许创建临时变量,求取字符串的长度void getlen(char* arr){int count = 0;//计数while (*arr!='\0'){count++;//计数加1arr++;//地址移动到下一个字符}printf("%d", count);}int main(){char arr[] = "abcd";getlen(arr);//数组名就是首元素地址return 0;}
递归方法

分析:自定义函数getlen,计算字符串 abcd,字符串以 '\0&rsquo;结尾,这是隐藏的,实际字符串为"abcd\0"自定义函数可以分解成下图那样拆解,每次取出一个字符,最终把字符都取完,返回值:

  • getlen(abcd),判断字符是不是&rsquo;\0&rsquo;, 不是,于是将getlen(abcd) 拆解成 1+ getlen(bcd)

  • getlen(bcd), 判断字符是不是&rsquo;\0&rsquo;, 不是,于是将getlen(bcd) 拆解成 1+ getlen(cd)

  • getlen(cd), 判断字符是不是&rsquo;\0&rsquo;, 不是,于是将getlen(cd) 拆解成 1+ getlen(d)

  • getlen(d), 判断字符是不是&rsquo;\0&rsquo;, 不是,于是将getlen(d) 拆解成 1+ getlen(&rsquo;\0&rsquo;),已经到字符串结尾了

  • getlen(&rsquo;\0&rsquo;), 判断字符是不是&rsquo;\0&rsquo;, 是,于是返回值0,代表字符串结束了,这就是递归的限制条件

C语言函数使用实例分析

下面是实现代码:

//递归方法int getlen(char* arr){if (*arr != 0){arr++;return 1 + getlen(arr);}return 0;//等于0,字符串结束了,返回0}int main(){char arr[] = "abcd";int sz = getlen(arr);printf("%d", sz);return 0;}

程序运行结果见下图,红色路线是递归按顺序调用函数,绿色的路线是递归达到限制条件后,返回值

C语言函数使用实例分析

C语言函数使用实例分析

练习3

求n的阶乘。(不考虑溢出)

一般方法
//求n的阶乘void fact(int n){int num = 1;for (int i = 1; i <= n; i++){num = num * i;}printf("%d", num);}int main(){fact(3);//阶乘return 0;}
递归方法

分析:自定义函数fact,求n的阶乘。自定义函数可以分解成下图那样拆解:

  • fact(n)=n!=n*(n-1)&hellip;1=nfact(n-1),

  • fact(n-1)=(n-1)!=(n-1)&hellip;*1=(n-1)*fact(n-2),

  • 依次类推, fact(2)=2!=2*fact(1),

  • 判断n已经推到1了,返回fact(1) =1,这就是递归的限制条件。

C语言函数使用实例分析

//递归方法int fact(int n){if (n >= 1){return n*fact(n - 1);n--;}else{return 1;}}int main(){int num=fact(3);//阶乘printf("%d", num);return 0;}

运行结果见下图:

C语言函数使用实例分析

练习4

求第n个斐波那契数。(不考虑溢出)

一般方法
//一般方法void fib(int n){int num1 = 1;int num2 = 1;int num3 = 0;for (int i = 1; i <=(n-2); i++){num3 = num1 + num2;num1 = num2;num2 = num3;}printf("%d", num3);//输出5}int main(){fib(5);//第五个斐波那契数列是5return 0;}
递归方法

分析:自定义函数fib,求第n个斐波那契数列。自定义函数可以分解成下图那样拆解:

  • fib(1)=1,fib(2)=1

  • fib(3)=fib(2)+fib(1),fib(4)=fib(3)+fib(2),

  • 依次类推, fib(n)=fib(n-1)+fib(n-2),

  • 求fib(6),就往前递推,fib(6)=fib(5)+fib(4)

  • 一直推到 fib(3)=fib(2)+fib(1), fib(1),fib(2)为已知值,数列推到此结束了,直接给返回值就行, 这就是递归的限制条件。

C语言函数使用实例分析

//递归方法方法int fib(int n){if (n <= 2){return 1;}return fib(n - 1) + fib(n - 2);}int main(){int num=fib(5);printf("%d", num);return 0;}

递归与迭代

递归隐藏的问题

在前面7.2.2.4 小节练习4中,发现有一个问题,举例fib(6)说明,下面是计算fib(6)时用的递归方法,分析会发现fib(3)居然重复计算了3次,如果计算fib(40)时,这样的重复计算会更多,大量的重复计算势必会降低计算速度。

C语言函数使用实例分析

通过程序来验证一样,计算fib(6)时,fib(3)总共计算了几次:

int count = 0;//全局变量int fib(int n){if (n == 3)count++;//计算fib(3)计算了多少次if (n <= 2)return 1;return fib(n - 1) + fib(n - 2);}int main(){int num=fib(6);printf("%d\n", num);printf("%d\n", count);return 0;}

结果如下所示:fib(6) = 8,fib(3)总共计算了3次:**

C语言函数使用实例分析

当计算fib(40)时,fib(3)总共计算了几次?

结果见下图,fib(40) = 102334155,fib(3)总共计算了39088169次,惊呆了居然3千多万次。而且很耗时间,计算效率低。

C语言函数使用实例分析

而用一般的方法计算fib(40)时,fib(3)只计算了一次。

如何改进
  • 在调试 factorial 函数的时候,如果你的参数比较大,那就会报错: stack overflow(栈溢出)这样的信息。例如计算fib(50)时,结果为负数,就是溢出了。

C语言函数使用实例分析

  • 系统分配给程序的栈空间是有限的,但是如果出现了死循环,或者(死递归),这样有可能导致一

直开辟栈空间,最终产生栈空间耗尽的情况,这样的现象我们称为栈溢出。

那如何解决上述的问题:

  • 将递归改写成非递归。例如计算fib(40)时,就采用一般方法计算。

  • 使用static对象替代 nonstatic 局部对象。 在递归函数设计中,可以使用 static 对象替代 nonstatic 局部对象(即栈对象),这不仅可以减少每次递归调用和返回时产生和释放 nonstatic 对象的开销,而且 static 对象还可以保存递归调用的中间状态,并且可为各个调用层所访问。

选递归还是迭代
  • 许多问题是以递归的形式进行解释的,这只是因为它比非递归的形式更为清晰。

  • 但是这些问题的迭代实现往往比递归实现效率更高,虽然代码的可读性稍微差些。

  • 当一个问题相当复杂,难以用迭代实现时,此时递归实现的简洁性便可以补偿它所带来的运行时开销。

  • 当发现递归的算法很耗时间,都没结果出来,那可能要考虑迭代实现了。

关于“C语言函数使用实例分析”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“C语言函数使用实例分析”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网其他教程频道。

--结束END--

本文标题: C语言函数使用实例分析

本文链接: https://www.lsjlt.com/news/327073.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C语言函数使用实例分析
    这篇文章主要介绍了C语言函数使用实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C语言函数使用实例分析文章都会有所收获,下面我们一起来看看吧。函数的声明和定义函数声明告诉编译器有一个函数叫什么,参数是什么...
    99+
    2023-06-30
  • C语言的div()函数实例分析
    本文小编为大家详细介绍“C语言的div()函数实例分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“C语言的div()函数实例分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。...
    99+
    2022-10-19
  • C语言之函数知识点实例分析
    这篇文章主要介绍了C语言之函数知识点实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C语言之函数知识点实例分析文章都会有所收获,下面我们一起来看看吧。一、引入引例:定义6个整型变量a,b,c,d,e,f,...
    99+
    2023-07-02
  • C语言函数加里化和偏函数应用实例分析
    今天小编给大家分享一下C语言函数加里化和偏函数应用实例分析的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。【名词解释】Curr...
    99+
    2023-06-17
  • C语言指向函数的指针实例分析
    这篇文章主要介绍“C语言指向函数的指针实例分析”,在日常操作中,相信很多人在C语言指向函数的指针实例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C语言指向函数的指针实例分析”的疑惑有所帮助!接下来,请跟...
    99+
    2023-07-02
  • C语言中库函数的示例分析
    这篇文章主要为大家展示了“C语言中库函数的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C语言中库函数的示例分析”这篇文章吧。1 返回整数的getchar函数代码:#include<...
    99+
    2023-06-29
  • C语言指针使用实例分析
    今天小编给大家分享一下C语言指针使用实例分析的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。何为指针指针这玩意说白了,就是用来...
    99+
    2023-07-02
  • C语言中函数递归的示例分析
    这篇文章主要介绍C语言中函数递归的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!什么是递归?递归(recursion):程序调用自身的一种编程技巧。如何理解函数递归:从调用自身层面:函数递归就是函数自己调用自...
    99+
    2023-06-29
  • C语言分支语句实例分析
    这篇文章主要介绍了C语言分支语句实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C语言分支语句实例分析文章都会有所收获,下面我们一起来看看吧。C语言的语句C语句可分为以下五类: 表达式语句 函数调用语句 ...
    99+
    2023-06-30
  • C语言数组入门实例分析
    本篇内容主要讲解“C语言数组入门实例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C语言数组入门实例分析”吧!1.一维数组数组的定义: 数组是一组相同类型元素的集合a.一维数组的创建数组的创...
    99+
    2023-06-30
  • C语言操作符使用实例分析
    本篇内容介绍了“C语言操作符使用实例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!算术操作符主要是 (+ - * / %) 五种算数操作...
    99+
    2023-07-02
  • C语言中main函数与命令行参数实例分析
    这篇文章主要介绍了C语言中main函数与命令行参数实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C语言中main函数与命令行参数实例分析文章都会有所收获,下面我们一起来看看吧。一、main 函数的概念C...
    99+
    2023-06-30
  • C语言函数返回值与参数传递实例分析
    本篇内容介绍了“C语言函数返回值与参数传递实例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一:参数传...
    99+
    2022-10-19
  • C语言分支句实例分析
    今天小编给大家分享一下C语言分支句实例分析的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。何为语句C语言中由一个分号;隔开的就...
    99+
    2023-06-29
  • C语言函数封装及变量的作用域实例分析
    这篇“C语言函数封装及变量的作用域实例分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C语言函数封装及变量的作用域实例分析...
    99+
    2023-06-30
  • C++语言举例分析
    这篇文章主要介绍“C++语言举例分析”,在日常操作中,相信很多人在C++语言举例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++语言举例分析”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!因为依赖开...
    99+
    2023-06-17
  • c语言abort函数实例用法
    1、abort函数的作用是异常终止一个进程,意味着abort后面的代码将不再执行。 2、当调用abort函数时,会导致程序异常终止,而不会进行一些常规的清除工作。 实例 #inc...
    99+
    2022-11-12
  • C语言转义字符使用实例分析
    这篇文章主要介绍“C语言转义字符使用实例分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“C语言转义字符使用实例分析”文章能帮助大家解决问题。1.认识转义字符所有的ASCII码都可以用“”加数字(一...
    99+
    2023-06-17
  • C语言指针应用实例分析
    这篇文章主要讲解了“C语言指针应用实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C语言指针应用实例分析”吧!1、指针是什么指针理解的2个要点:平时口语中说的指针,通常指的是指针变量,...
    99+
    2023-06-30
  • C语言深入分析函数与宏的使用
    目录一、函数与宏二、宏的妙用三、小结一、函数与宏 宏是由预处理器直接替换展开的,编译器不知道宏的存在函数是由编译器直接编译的实体,调用行为由编译器决定多次使用宏会导致最终可执行程序的...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作