手写C语言之函数的嵌套调用和链式访问

简介: 手写C语言之函数的嵌套调用和链式访问

函数和函数之间可以根据实际的需求进行组合的,也就是互相调用的。


函数可以嵌套调用,但是不能嵌套定义。


#include <stdio.h>
void new_line()
{
printf("hehe\n");
}
void three_line()
{
  int i = 0;
for(i=0; i<3; i++)
 {
    new_line();
 }
}
int main()
{
three_line();
return 0;
}



链式访问

把一个函数的返回值作为另外一个函数的参数


#include <stdio.h>
#include <string.h>
int main()
{
char arr[20] = "hello";
int ret = strlen(strcat(arr,"bit"));//这里介绍一下strlen函数
printf("%d\n", ret);
return 0;
}
#include <stdio.h>
int main()
{
printf("%d", printf("%d", printf("%d", 43)));
//结果是啥?
//注:printf函数的返回值是打印在屏幕上字符的个数
return 0;
}




第一个代码出现的结果是数字:8,因为首先使用strcat()字符串函数将hello和bit拼接在一起,最后是strlen()函数计算个数


第二个代码最终打印在屏幕上的结果是4321,为什么呢?


首先打印43这是我们可以理解的,但是第二个printf接收的值是第一个内层的printf的返回值,也就是打印在屏幕的个数,也就是2,那么就会打印2,最后一个只接受到1个数,那么就是1

image.png


函数的声明和定义

  1. 告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但是具体是不是存在,函数声明决定不了。
  2. 函数的声明一般出现在函数的使用之前。要满足先声明后使用。
  3. 函数的声明一般要放在头文件中的
//函数的声明
int Add(int x, int y);


//函数Add的实现
int Add(int x, int y)
{
return x+y;
}


在我们编写代码的时候,我们的程序编译的特点是:


1、顺序性:严格的按照顺序执行

2、封闭性:程序运行时独占全机资源 资源状态只有本程序才能改变它,程序一旦开始执行,不受外界影响

3、可再现性:无论如何执行 都可缺获得相同的结果


按照顺序进行执行,所以我们在编写代码的时候,习惯性的将定义的功能函数放在前面,然后在主函数中进行调用,对功能函数,这样程序就不会出现警告提示,但是有时候我们在编写工程代码的时候,不可能每一次的函数调用都在函数声明好的前提之下,所以这里对函数进行声明,声明其返回值类型,声明其参数的类型。


但是在日常公司的代码实现中,每一个程序员写代码都是分模块的,所以下面需要介绍函数在不同文件中的声明


例如:


在一次工作任务当中,一共有三个人拿到了这个项目,在这个项目中目前需要开发出来个功能,一共功能是对用户的信息进行管理和展示,一个任务是对用户信息的数据进行存储和分析,一个是设计框架,展示图形界面。那么在此次的项目当中,不可能每一个程序员都等着对方写完了代码,然后再去主程序中继续加代码,这样的话,工作效率极低。所以我们需要让每一个程序员各司其职,让他们高效的协作并完成统一。


A程序员在工程中定义了两个文件,一个是头文件(用于对函数的声明),一个是功能模块函数.C文件,其次B程序员也是,C程序员对A和B写的.C文件进行引入:#include “A.h”


那么有的同学可能就会有所疑问,为什么在函数的声明和定义的时候,我们把头文件和功能代码分别分离了呢?为什么不直接写在一起呢?


这里给大家首先引入一个知识叫做:知识无价,拒绝白嫖的理念,不管以后你从事什么行业都需要记住这个,永远都不要把希望寄托在别人身上,不然你永远也无法战胜自己。


案例分享:


曾经,小王在编码中遇到一个困难,有一个代码不会写,但是由于时间比较的紧,他去找一个会写该功能的人,这个人就把这个功能模块给了他,并且打开头文件之后也介绍了这个函数的基本功能和参数(虽然不需要),然后小王发现这个代码功能实现依然比较的臃肿,所以他想在有限的时间自己去改进一下代码,当他打开同事给他的文件后,发现真正的功能代码里面的内容,乱码了,确切说是被隐藏了,小王直呼:“这哥们警惕性也太高了吧,给我一个功能函数,不开源思路”,给他的文件中有一个.lib文件,这也是为啥看不到代码思路的原因!


后面小王自己花了时间写出来了,完成了代码的交付工作。


这个虚构的故事就是解答大家的疑问,为什么要把头文件和功能函数分离开,这样是为了我们在有一个工程代码中,为了保密性需要要求程序员这样去做,这不仅仅是一个好的编码风格也是一种基本的职业素养!


函数的递归

程序调用自身的编程技巧称为递归( recursion)。 递归做为一种算法在程序设计语言中广泛应用。

一个过程或函数在其定义或说明中有直接或间接 调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解, 递归策略。

只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。 递归的主要思考方式在于:把大事化小。


递归的两个必要条件

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


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


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

例如:


输入:1234,输出 1 2 3 4


#include <stdio.h>
void print(int n)
{
if(n>9)
{
print(n/10);
}
printf("%d ", n%10);
}
int main()
{
int num = 1234;
print(num);
return 0;
}



这里的递归,需要自己画图理解,把每一个函数的流程理清楚,这是递归的非常重要的思想!自己调用自己!


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

#incude <stdio.h>
int Strlen(const char*str)
{
if(*str == '\0')
return 0;
else
return 1+Strlen(str+1);
}
int main()
{
char *p = "abcdef";
int len = Strlen(p);
printf("%d\n", len);
return 0;
}



递归注意:


不能死递归,要有跳出条件(逼近跳出条件),不要写太深


相关文章
|
4月前
|
存储 C语言
`scanf`是C语言中用于按格式读取标准输入的函数
`scanf`是C语言中用于按格式读取标准输入的函数,通过格式字符串解析输入并存入指定变量。需注意输入格式严格匹配,并建议检查返回值以确保读取成功,提升程序健壮性。
1064 0
|
6月前
|
安全 C语言
C语言中的字符、字符串及内存操作函数详细讲解
通过这些函数的正确使用,可以有效管理字符串和内存操作,它们是C语言编程中不可或缺的工具。
347 15
|
9月前
|
Linux C语言 iOS开发
C语言结合AWTK开发HTTP接口访问界面
这样,我们就实现了在C语言中使用libcurl和AWTK来访问HTTP接口并在界面上显示结果。这只是一个基础的示例,你可以根据需要添加更多的功能和优化。例如,你可以添加错误处理机制、支持更多HTTP方法(如POST、PUT等)、优化用户界面等。
482 82
|
11月前
|
人工智能 Java 程序员
一文彻底搞清楚C语言的函数
本文介绍C语言函数:函数是程序模块化的工具,由函数头和函数体组成,涵盖定义、调用、参数传递及声明等内容。值传递确保实参不受影响,函数声明增强代码可读性。君志所向,一往无前!
460 1
一文彻底搞清楚C语言的函数
|
12月前
|
存储 编译器 C语言
【C语言程序设计——函数】分数数列求和2(头歌实践教学平台习题)【合集】
函数首部:按照 C 语言语法,函数的定义首部表明这是一个自定义函数,函数名为fun,它接收一个整型参数n,用于指定要求阶乘的那个数,并且函数的返回值类型为float(在实际中如果阶乘结果数值较大,用float可能会有精度损失,也可以考虑使用double等更合适的数据类型,这里以float为例)。例如:// 函数体代码将放在这里函数体内部变量定义:在函数体中,首先需要定义一些变量来辅助完成阶乘的计算。比如需要定义一个变量(通常为float或double类型,这里假设用float。
557 3
|
12月前
|
存储 算法 安全
【C语言程序设计——函数】分数数列求和1(头歌实践教学平台习题)【合集】
if 语句是最基础的形式,当条件为真时执行其内部的语句块;switch 语句则适用于针对一个表达式的多个固定值进行判断,根据表达式的值与各个 case 后的常量值匹配情况,执行相应 case 分支下的语句,直到遇到 break 语句跳出 switch 结构,若没有匹配值则执行 default 分支(可选)。例如,在判断一个数是否大于 10 的场景中,条件表达式为 “num> 10”,这里的 “num” 是程序中的变量,通过比较其值与 10 的大小关系来确定条件的真假。常量的值必须是唯一的,且在同一个。
424 2
|
12月前
|
存储 算法 C语言
【C语言程序设计——函数】素数判定(头歌实践教学平台习题)【合集】
本内容介绍了编写一个判断素数的子函数的任务,涵盖循环控制与跳转语句、算术运算符(%)、以及素数的概念。任务要求在主函数中输入整数并输出是否为素数的信息。相关知识包括 `for` 和 `while` 循环、`break` 和 `continue` 语句、取余运算符 `%` 的使用及素数定义、分布规律和应用场景。编程要求根据提示补充代码,测试说明提供了输入输出示例,最后给出通关代码和测试结果。 任务核心:编写判断素数的子函数并在主函数中调用,涉及循环结构和条件判断。
731 23
|
12月前
|
算法 C语言
【C语言程序设计——函数】利用函数求解最大公约数和最小公倍数(头歌实践教学平台习题)【合集】
本文档介绍了如何编写两个子函数,分别求任意两个整数的最大公约数和最小公倍数。内容涵盖循环控制与跳转语句的使用、最大公约数的求法(包括辗转相除法和更相减损术),以及基于最大公约数求最小公倍数的方法。通过示例代码和测试说明,帮助读者理解和实现相关算法。最终提供了完整的通关代码及测试结果,确保编程任务的成功完成。
656 15
【C语言程序设计——函数】利用函数求解最大公约数和最小公倍数(头歌实践教学平台习题)【合集】
|
12月前
|
C语言
【C语言程序设计——函数】亲密数判定(头歌实践教学平台习题)【合集】
本文介绍了通过编程实现打印3000以内的全部亲密数的任务。主要内容包括: 1. **任务描述**:实现函数打印3000以内的全部亲密数。 2. **相关知识**: - 循环控制和跳转语句(for、while循环,break、continue语句)的使用。 - 亲密数的概念及历史背景。 - 判断亲密数的方法:计算数A的因子和存于B,再计算B的因子和存于sum,最后比较sum与A是否相等。 3. **编程要求**:根据提示在指定区域内补充代码。 4. **测试说明**:平台对代码进行测试,预期输出如220和284是一组亲密数。 5. **通关代码**:提供了完整的C语言代码实现
269 24
|
12月前
|
存储 C语言
【C语言程序设计——函数】递归求斐波那契数列的前n项(头歌实践教学平台习题)【合集】
本关任务是编写递归函数求斐波那契数列的前n项。主要内容包括: 1. **递归的概念**:递归是一种函数直接或间接调用自身的编程技巧,通过“俄罗斯套娃”的方式解决问题。 2. **边界条件的确定**:边界条件是递归停止的条件,确保递归不会无限进行。例如,计算阶乘时,当n为0或1时返回1。 3. **循环控制与跳转语句**:介绍`for`、`while`循环及`break`、`continue`语句的使用方法。 编程要求是在右侧编辑器Begin--End之间补充代码,测试输入分别为3和5,预期输出为斐波那契数列的前几项。通关代码已给出,需确保正确实现递归逻辑并处理好边界条件,以避免栈溢出或结果
679 16