6. 函数的嵌套调用和链式访问
6.1 嵌套调用
代码语言:javascript复制#include <stdio.h>
int test(int a, int b)
{
return a b;
}
void fun()
{
int ret = test(2, 3);
printf("hehen");
}
int main()
{
return 0;
}
注: 函数可以嵌套调用,但是不存在嵌套定义
代码语言:javascript复制//以下写法是错误的
#include <stdio.h>
int test(int a, int b)
{
return a b;
void fun()
{
printf("hehen");
}
}
int main()
{
return 0;
}
6.2 链式访问
代码语言:javascript复制把一个函数的返回值作为另外一个函数的参数。
#include <stdio.h>
#include <string.h>
int main()
{
//int len = strlen("abcdef");
//printf("%dn", len);
//链式访问
printf("%dn", strlen("abcdef"));
return 0;
}
代码语言:javascript复制#include <stdio.h>
int main()
{
printf("%d", printf("%d", printf("%d", 43)));
return 0;
}
//4321
代码语言:javascript复制#include <stdio.h>
int main()
{
printf("%d ", printf("%d ", printf("%d ", 43)));
return 0;
}
//43 3 2
7. 函数的声明和定义
7.1 函数声明
- 告诉编译器有一个函数叫什么,参数是什么,返回类型是什么,但是具体是不是存在,函数声明决定不了。
- 函数的声明一般出现在函数的使用之前,要满足先声明后使用。
- 函数的声明一般要放在头文件中。
#include <stdio.h>
//函数声明
//int Add(int, int);
int Add(int x, int y);//这两种写法都可以
int main()
{
int a = 0;
int b = 0;
//输入
scanf("%d %d", &a, &b);
//加法
int c = Add(a, b);//函数调用
//打印
printf("%dn", c);
return 0;
}
//函数的定义
int Add(int x, int y)
{
return x y;
}
7.2 函数定义
代码语言:javascript复制函数的定义是指函数的具体实现,交待函数的功能实现。
#include <stdio.h>
//函数的定义-定义是一种特殊的声明
int Add(int x, int y)
{
return x y;
}
int main()
{
int a = 0;
int b = 0;
//输入
scanf("%d %d", &a, &b);
//加法
int c = Add(a, b);//函数调用
//打印
printf("%dn", c);
return 0;
}
- 函数的声明和定义其实通常不是这样使用的
- 函数的声明是放在头文件中的
//add.h
//函数的声明
int Add(int x, int y);
代码语言:javascript复制//add.c
//函数定义
int Add(int x, int y)
{
return x y;
}
代码语言:javascript复制//test.c
#include <stdio.h>
#include "add.h"
int main()
{
int a = 0;
int b = 0;
//输入
scanf("%d %d", &a, &b);
//加法
int c = Add(a, b);//函数调用
//打印
printf("%dn", c);
return 0;
}
再举一个简单的例子:假设有一位程序员写了一个能够求两数相加之和的函数,他想卖给别人使用,但又不想让别人看到他的源代码,他应该怎么做呢?
首先,他需要写一个.h文件(在.h文件中声明函数,同时可以通过注释来解释函数的功能、参数和返回值)
代码语言:javascript复制//add.h
//函数
//函数的功能
//参数
//返回值
int Add(int x, int y);
接着,他需要写一个.c文件
代码语言:javascript复制int Add(int x, int y)
{
return x y;
}
最后,将其改为静态库;之后就可以将静态库和头文件卖给别人。(买方买到静态库后打开查看只能看到一堆乱码,因为代码已经转换为二进制了,不需要担心源代码会被看到。)
买方买到他的静态库和头文件后,先将其添加到他所写的项目的文件夹中,之后用如下代码:
代码语言:javascript复制#include <stdio.h>
#include "add.h"
//.lib - 静态库
//导入静态库
#pragma comment(lib, "add.lib")
int main()
{
int a = 0;
int b = 0;
//输入
scanf("%d %d", &a, &b);
//加法
int c = Add(a, b);//函数调用
//打印
printf("%dn", c);
return 0;
}
8. 函数递归
8.1 什么是递归
- 程序调用自身的编程技巧称为递归(简单来说就是函数自己调用自己;递 --> 递推 归 --> 回归)。
- 递归做为一种算法在程序设计语言中广泛应用,是一个过程或函数在其定义或说明中有直接或间接 调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问 题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程 序的代码量。
- 递归的主要思考方式在于:把大事化小。
//以下就是一个简单的递归;但是这个递归会死递归,导致栈溢出
#include <stdio.h>
int main()
{
printf("hehen");
main();
return 0;
}
8.2 递归的两个必要条件
- 存在限制条件,当满足这个限制条件的时候,递归便不再继续。
- 每次递归调用之后越来越接近这个限制条件。
以下为两个例题,用以更好地理解递归的两个必要条件
代码语言:javascript复制接收一个整型值(无符号),按照顺序打印它的每一位。 例如: 输入:1234 输出: 1 2 3 4
void print(unsigned int n)//1234
{
if (n > 9)
{
print(n / 10);
}
printf("%d ", n % 10);
}
int main()
{
unsigned int num = 0;
//输入
scanf("%d", &num);
print(num);
return 0;
}
编写函数不允许创建临时变量,求字符串的长度。
首先,我们先写一个求字符串长度的代码
代码语言:javascript复制#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "abc";
int len = strlen(arr);
printf("%dn", len);
return 0;
}
上面用的是库函数,那能不能自己编写一个函数来求字符串长度呢
代码语言:javascript复制#include <stdio.h>
int my_strlen(char* s)
{
int count = 0;
while (*s != '