初阶C语言:函数的嵌套、链式访问、递归、迭代

1. 函数的嵌套调用

   函数可以嵌套调用,不可以嵌套定义

#include<stdio.h>
void print()
{
    printf("hehehehe\n");
}
void three_print()
{
    int i = 1;
    for(i = 0;i <= 3;i++)
    {
        print();    
    }
}
int main()
{
    three_print();
    return 0;
}

2. 链式访问

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

#include <stdio.h>
#include <string.h>
int main()
{
    // 普通访问
    int len = strlen("abcdefg");
    printf("%d\n",len);
    
    // 链式访问(将函数串起来)
    printf("%d\n",strlen("abcdefg"));
}

3. 函数的递归:程序调用自身的编程技巧

(1)递归的定义

  • 递归是一种常用的程序算法,一个程序或函数在其定义或说明中 直接 或 间接 调用自身的一种方法
  • 通常,把一个大型的复杂问题层层转化为一个与原问题相似的、规模较小的问题求解 —— 递归策略
  • 作用:只需少量的代码就可以描述出接替过程中需要的多次重复计算,大大减少了程序的代码量

(2)核心:大事化小

  • 例如:接收一个整型值(无符号),按照顺序打印它的每一位
#include <stdio.h>
void print(int n)
{
    if(n > 9)
    {
        print(n / 10);            
    }
    printf("%u  ",n % 10); 
}
int main()
{
    unsigned num = 1234;
    printf("请输入整数:");
    scanf("&u",&num);
    print(num);
    return 0;
}

(3)递归的必要条件

  • 存在限制条件,当满足这个限制,递归便不再继续
  • 每次递归之后,越来越接近这个限制条件

(4)例题:编写函数允许创建临时变量时,求字符串长度

#include<stdio.h>
//int my_strlen(char str[])    //参数部分写成数组形式
int my_strlen(char* str)    //参数部分写成指针形式
{
    int count = 0;    // 临时变量
    while(*str != '\0')
    {
         count++;
         str++;    //找些一个字符,指针++       
    }    
}
int main()
{
    //int len = my_strlen("abc");    // 实参传给函数形参的时首字符的 地址,相当于如下:
    char arr[] = "abc";    // [a ,b, c, \0]
    int len = my_strlen(arr);    // 传给函数形参的是 一个字符的地址,所以函数参数为 char*
    printf("%d",len);
    return 0;
}

(5)例题:编写函数不允许创建临时变量时,求字符串长度

#include<stdio.h>
int my_strlen(char* str)
{
    if(*str != '\0')
    {
         return 1 + my_strlen(str+1);    //str++ : 前置,先使用后++ ————> 会导致死递归;  ++str : 最终值一样,但会导致 str的值变化     
    }
    else
    {
        return 0;    
    }
}
int main()
{
    //int len = my_strlen("abc");    // 实参传给函数形参的时首字符的 地址,相当于如下:
    //char arr[] = "abc";
    int len = my_strlen(arr);
    printf("%d",len);
    return 0;
}

4. 迭代

   在 C 语言中,迭代通常通过循环结构来实现。主要的循环结构有for循环、while循环和do - while循环。

(1)迭代在 C 语言函数中的应用

  • 可以将迭代过程封装在函数中。例如,编写一个函数来计算一个数的阶乘。
#include <stdio.h>
int factorial(int n)
{
    int result = 1;
    for(int i = 1; i <= n; i++)
    {
        result *= i;
    }
    return result;
}
int main()
{
    int n = 5;
    int fact = factorial(n);
    printf("%d的阶乘为:%d\n", n, fact);
    return 0;
}

5. 递归与迭代

(1)练习1:求 n 的阶乘(不考虑溢出)

  • 递归实现 

#include<stdio.h>
int fac(int n)                                // 5! = 5*4! 
{                                        // 4!= 4*3!
    if(n<=1)                             // 3!= 3*2!
        return 1;                        // 2!= 2*1!
    else                                 // 1! = 1  此时 n=1;,递延完成
        return n*fac(n-1);    
}
int main()
{
    int n = 0;
    scanf("%d",&n);
    int ret = fac(n);
    printf("ret = %d\n",ret);
    return 0;
}
  • 迭代实现(非递归)

int fac(int n)                                 
{                                        
    int i = 0;
    int ret = 1;
    for(i = 1;i <= n; i++)
    {
        ret = ret * i;    
    }   
    return ret;
}
int main()
{
    int n = 0;
    scanf("%d",&n);
    int ret = fac(n);
    printf("ret = %d\n",ret);
    return 0;
}

(2)练习2:求第n个斐波那契数

  • 递归实现

#include<stdio.h>
int count = 0;
int Fib(int n)
{
    if(n = 5)
    {
        count++ ;   
    }
    if(n <= 2)
        return 1;
    else
        return Fib(n-2) + Fib(n-1);
}
int main() 
{
    int n = 0;
    scanf("%d",&n);
    int ret = Fib(n);
    printf("%d\n", ret);
    printf("%d",count);
    return 0;
}
  • 迭代实现

#include<stdio.h>
int fib(int n)
{
    int a = 1, b = 1;
    int c = 1;
    while(n >= 3)
    {
        c = a + b;
        a = b;
        b = c; 
        n--; 
    }
    return c;
}
int main()
{
    int n = 1;
    scanf("%d",&n);
    int ret = fib(n);
    printf("%d\n",ret);
    return 0;
}
#include<stdio.h>
int fib(int n)
{
    int a = 1, b = 1;
    int c = 1;
    for(int i = 1; i <= n-2; i++)
    {
        c = a + b;
        a = b;
        b = c;    
    }
    return c;
}
int main()
{
    int n = 1;
    scanf("%d",&n);
    int ret = fib(n);
    printf("%d\n",ret);
    return 0;
}

6. 总结

        许多题目可以使用都会进行解释,这是因为 递归 比 非递归的显示更清晰,但是这些问题的的迭代实现可能往往比递归实现效率更高(虽然代码可读性稍微差一点),当一个问题相当复杂,无法使用迭代实习时,此时使用递归实现的简洁性以补偿它所带来的允许时的开销

7. 函数递归经典问题

(1)汉诺塔问题

        是一个经典的递归和迭代问题。它由三根柱子(通常标记为 A、B、C)和若干个大小不同的圆盘组成。初始时,所有圆盘按照从大到小的顺序堆叠在一根柱子(比如 A 柱)上。

#include<stdio.h>
void move(char f, char t)
{
    printf("%c --> %c\n", f, t);
}
void fn_num(int n, char A, char B, char C)
{
    if (n == 1)
        move(A, C);
    else
    {
        fn_num(n - 1, A, C, B);
        move(A, C);
        fn_num(n - 1, B, A, C);
    }
}
int main()
{
    int n = 0;
    char a = 'A', b = 'B', c = 'C';
    printf("请输入塔盘数:");
    scanf("%d", &n);
    fn_num(n, a, b, c);
    return 0;
}

(2)青蛙跳台阶问题

        有一只青蛙要跳上 n 级台阶,青蛙每次可以跳 1 级台阶,也可以跳 2 级台阶,问青蛙跳上 n 级台阶总共有多少种不同的跳法。

#include<stdio.h>
int fb(int n)
{
	if (n == 1)
		return 1;
	else if (n == 2)
		return 2;
	return fb(n - 1) + fb(n - 2);
}
int main()
{
	int n = 0;
	printf("一共有多少个台阶:");
	scanf("%d", &n);
	int sum = fb(n);
	printf("%d", sum);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值