C语言学习笔记---函数续章

news/2024/10/24 7:23:14/

C语言程序设计笔记---010

  • C语言函数 --- 续
    • 1、函数声明和函数的定义
      • 1.1、函数声明例程
    • 2、函数递归
      • 2.1、错误递归,栈溢出例程
      • 2.2、函数递归练习例程1
      • 2.3、递归的必要条件
        • 函数递归例程2
    • 3、递归与迭代
      • 递归与迭代例程1
      • 递归与迭代例程2
    • 4、结语

C语言函数 — 续

1、函数声明和函数的定义

函数在使用之前,先声明,再使用
通常放在头文件之后,主函数之前。

函数的定义:是指函数的具体体现,交代函数的功能实现。
通常放在.h头文件中声明和定义。

1.1、函数声明例程

说明
写一个函数,完成两个整数的相加

#include <stdio.h>
#include "test019.h"
//函数定义放main之前时,编译器判定执行顺序。相当于即定义也声明
//int Add(int a ,int b)
//{
//	return a + b;
//}
//函数声明
//int Add(int a, int b);
int main()
{int num1 = 0;int num2 = 0;scanf("%d %d",&num1,&num2);//计算两个整数的和//函数的调用(传值调用)int ret = Add(num1,num2);printf("%d\n",ret);return 0;
}
//函数定义放主函数之后,就需声明了
//int Add(int a, int b)
//{
//	return a + b;
//}

test019.h

// .h 头文件存放函数的声明//求和函数的声明
int Add(int a, int b);

test019.c

// .c 头文件存放函数的定义(执行函数功能)、
//调用 .c 文件更加方便//求和函数的定义
int Add(int a, int b)
{return a + b;
}

小结
在未来的多数工程中,代码较多,函数一般都是分别在.h文件中声明,在.c文件中定义功能实现的。
模块化编程,有利于对工程程序的分工、保护、移植等优势
(1)、多人协作
(2)、代码保护
(3)、方便理解性和移植性

2、函数递归

什么是递归?
程序调用自身的编程技巧称为递归

概念:递归作为一种算法在程序设计语言中广泛应用。
一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题来求解,递归策略只需要少量的程序就可以描述解题过程所需要的多次重复计算,大大减少了程序的代码量
主要编程思想”大事化小“

注意:首先,程序调用自身的编程技巧称为递归
但是得考虑栈溢出:Stack overflow
还得考虑数据类型得最大范围等问题

2.1、错误递归,栈溢出例程

#include <stdio.h>
int main()
{printf("溢出\n");main();return 0;
}

2.2、函数递归练习例程1

说明
按顺序打印数的每一位 ---- 递归实现
:1234 输出:1 2 3 4
思路:

1234
1234%10 = 4
1234/10 = 123
/23 %10 = 3
123/10  = 12
.....

循环写法

#include <stdio.h>
int main()
{int num = 0;scanf("%d",&num);//1234while (num){printf("%d ",num%10);//4 3 2 1num = num / 10;}return 0;
}

递归写法 – 思想:大事化小

#include <stdio.h>
void Print(int num)
{if (num > 9)Print(num/10);printf("%d ",num%10);
}
int main()
{int num = 0;scanf("%d",&num);//1234//实现将参数Num每一位按照顺序输出Print(num);//Print(1234)//Print(123) + 4 //Print(12) + 3 //Print(1) + 2return 0;
}

小结
递归:递推 + 回归
(1)、函数之所以能实现调用,都是因为,函数在调用时,会维护一个函数
(2)、函数的递归调用是在栈区里开辟的内存空间,层层递推,层层回归
(3)、递归的跟循环语句类似,需要一个重要的、必要的跳出/限制条件

2.3、递归的必要条件

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

(2)、每次递归调用之后越来越接近这个限制条件

函数递归例程2

说明
不创建临时变量,求字符串长度 ---- 模拟strlen函数功能 + 递归
正常写法:

#include <stdio.h>
//实现计算字符串长度
size_t my_strlen(char* str)
{size_t count = 0;while (*str != '\0'){count++;str++;}return count;
}int main()
{char arr[] = "abcdef";size_t len = my_strlen(arr);//数组名作为参数,传递的是首元素地址printf("%zd\n",len);//6return 0;
}

递归写法:

#include <stdio.h>
int my_strlen(char* str)
{if (*str == '\0')return 0;elsereturn 1 + my_strlen(str+1);//str+1下一个字符作为首元素。传递其地址
}int main()
{char arr[20] = "abc";int ret = my_strlen(arr);printf("%d\n",ret);return 0;
}

3、递归与迭代

迭代等价于循环
递归可以与迭代相转换,根据实际需求应用递归或迭代

递归与迭代例程1

说明
求阶乘 — 递归
思路:公式法
5! = 12345
4! = 1234
等价于:5! = 5
4!
即:
n <= 1 —>return 1
n >= 2 —>return n*Fac(n-1)

正常写法

#include <stdio.h>
//实现阶乘计算
int Fac(int n)
{int i = 0;int k = 1;for (i = 1; i <= n; i++){//k = k * i;k *= i;}return k;
}
int main()
{int n = 0;scanf("%d", &n);int ret = Fac(n);printf("%d\n", ret);return 0;
}

递归写法

#include <stdio.h>
//递归实现阶乘计算
int Fac(int n)
{if (n <= 1)return 1;elsereturn n * Fac(n - 1);
}int main()
{int n = 0;scanf("%d",&n);int ret = Fac(n);printf("%d\n",ret);return 0;
}

小结
(1)、递归层次太深入可能导致栈溢出,还有类型数据范围超出
(2)、迭代/循环写法一般不会有栈溢出的情况

递归与迭代例程2

说明
求第n个斐波那契数列,如:1 1 2 3 5 8 13 21 34 55 …

#include <stdio.h>
//递归写法:
//int Fib(int n)
//{
//	if (n <= 2)
//		return 1;
//	else
//		return Fib(n - 1) + Fib(n - 2);
//}
//迭代写法:
int Fib(int n)
{int a = 1;int b = 1;int c = 1;while (n >= 3){c = a + b;a = b;b = c;n--;}return c;
}
int main()
{int n = 0;scanf("%d", &n);int ret = Fib(n);printf("%d\n",ret);return 0;
}

小结
权衡何时使用递归,何时使用迭代
一般情况下,递归较容易想到,写出的代码没有明显的额缺陷,就可以使用递归写法 ,
如:套公式这种较多,但如果写出的递归,有明显的问题,
如:栈溢出。效率缓慢等问题就不建议使用递归的写法。

解决上述递归易错的问题,一般可优化的方法
(1)、使用静态区,分担栈区的空间,防止栈溢出
(2)、递归转化为迭代

4、结语

利用好递归函数,对于思维能力是非常有用的,能够帮助程序员在编写程序时,使用恰当能够大大提高程序的简洁性,事半功倍,以少量代码完成指定功能。
因此,编写程序时应该充分发挥函数的作用,并合理地搭配其他语句和特性使用,以便更好地保证程序的正确性、可靠性以及严谨性。


http://www.ppmy.cn/news/989961.html

相关文章

Java基础_网络编程

Java基础_网络编程 网络编程三要素InetAddress网络模型 UDP通信程序单播发送数据接收数据聊天室 组播广播 TCPTCP通信程序三次握手和四次挥手 来源Gitee地址 网络编程三要素 IP: 设备在网络中的地址&#xff0c;是唯一的标识端口号: 应用程序在设备中唯一的标识。协议: 数据在…

只出现1次的数字(总结欢迎补充)

1.找只出现1次的数字,其余数出现n次 给你一个整数数组 nums &#xff0c;除某个元素仅出现 一次 外&#xff0c;其余每个元素都恰出现n次 。请你找出并返回那个只出现了一次的元素 当n等于2时 这道题可以使用异或运算来解决。我们知道&#xff0c;异或运算有以下性质&#xf…

【技巧】通过 CMD 走代理下载 Vue

通过 CMD 走代理下载 Vue 在学习或者工作中&#xff0c;有时上网走的是代理模式&#xff0c;就是在浏览器里面配置代理服务的那种。后来在下载 Vue 组件的时候显示请求超时。此时才发先&#xff0c;浏览器代理只能在浏览器里生效&#xff0c;cmd 中不生效&#xff0c;那该怎么办…

井字棋(TicTacToe)

目录 三种游戏 习题 1. 传统设置 2. 中间的网格 三种游戏 “选15”、“井字棋”、“魔幻15”游戏本质上是同一个游戏。 function tictactoe(job) % TICTACTOE Pick15, TicTacToe, and Magic3. % % Pick15. Pick single digit numbers. Each digit can be chosen % on…

区块链 2.0笔记

区块链 2.0 以太坊概述 相对于比特币的几点改进 缩短出块时间至10多秒ghost共识机制mining puzzle BTC:计算密集型ETH&#xff1a;memory-hard(限制ASIC) proof of work->proof of stake对智能合约的支持 BTC&#xff1a;decentralized currencyETH&#xff1a;decentral…

【代码review、审核开发工程师的设计与研发质量工作经验之谈】

作为一个开发工程师&#xff0c;代码review与审核是我们日常工作不可或缺的一环。它不仅有助于提高代码质量&#xff0c;还可以避免不必要的错误和漏洞。下面我将分享一下我的经验&#xff0c;重点讨论代码review与审核方面的工作。 一、准备工作 在进行代码review和审核之前&…

Python不是一门伟大的语言

作为一门简洁易用、生态蓬勃且具有高泛用性的编程语言&#xff0c;Python一直以来都被不少人称作“编程语言中的瑞士军刀”。 尤其随着近来AI热潮席卷全球&#xff0c;Python在编程语言圈中的地位也随之水涨船高&#xff0c;甚至一度被视作AI专用语言或大数据专用语言。 然而…

AI 绘画Stable Diffusion 研究(二)sd模型ControlNet1.1 介绍与安装

部署包作者:秋葉aaaki 免责声明: 本安装包及启动器免费提供 无任何盈利目的 大家好&#xff0c;我是风雨无阻。 众所周知&#xff0c;StableDiffusion 是非常强大的AI绘图工具&#xff0c;需要详细了解StableDiffusion的朋友&#xff0c;可查看我之前的这篇文章&#xff1a; …