C语言的学习(十一)---递归、数组作为函数的参数、标识符

张开发
2026/4/15 1:06:38 15 分钟阅读

分享文章

C语言的学习(十一)---递归、数组作为函数的参数、标识符
一、递归递归 --- 1. 是一种特殊的循环2. 如果不加结束条件,最终也会结束 ----函数调用-- 栈空间耗尽用累加求和举例123 ...100递归解决问题的思路:1.要解决问题n,要看问题n-1的解决2.当一个函数需要被自身重复调用时---可以考虑递归1.递归实现编程: 两个要素要素1递推关系问题n 和 问题n-1之间关系sum(100) sum(99) 100|--- sum(98) 99sum(n) sum(n-1) n要素 2递归结束条件n 1递归结束2.递归程序的代码逻辑int sum(int n) //sum(n) { //判断是否到达递归结束条件 //是 --- 则返回 //否 --- 继续往下递归 (自己调用自己) if(n 1) { return 1; }else //递归结束调剂不满足 { return sum(n-1) n; } }//递归的限制1.层次不能太深 //栈空间不够2.有些问题的解决 --- 确实需要通过递归实现汉诺塔就是经典的递归问题汉诺塔思路:1、将n-1个盘子从A-B2、将剩下的那个盘子从A-C3、将n-1个盘子从B-C代码#include stdio.h void move(int n ,int pole1,int pole2) { static int step 1; printf(%03d:[disk %d] : %c -- %c\n,step,n,pole1,pole2); } //起始柱 辅助柱 目标柱 void hanoi(int n, int A, int B, int C) { if (1n) { move(n,A,C); }else { hanoi(n-1,A,C,B);//n-1 先挪走 puts(-------); move(n,A,C); // 将第n个 挪到 目标柱 puts(-------); hanoi(n-1,B,A,C); } } //n 3; //hanoi(2,A,C,B) // | -------------------- hanoi(1,A,B,C) // move(2,A,B); [2:A-B] // |-----------------------move(1,A,C) [1:A-C] // move(3,A,C); ----- [3:A-C] // hanoi(2,B,A,C); int main(void) { int n 0; printf(Input numbers of disk: ); scanf(%d,n); hanoi(n,A,B,C); return 0; }递归计算斐波那契数列的第 n 项// 递归计算斐波那契数列的第 n 项 int fib(int n) { if (n 0) return 0; if (n 1) return 1; return fib(n - 1) fib(n - 2); }递归求nn的阶乘// 递归求 n 的阶乘 // 定义0! 1, n! n * (n-1)! int factorial(int n) { if (n 0 || n 1) return 1; return n * factorial(n - 1); }二、一维数组在函数中作为参数//1.数组元素作为函数参数 void printArrayEle(int ele) { } //2.数组做函数参数 main() { int a[10] {1,2,3,4,5}; } printArray() { }//传递整个数组的数据 给 函数使用1.如果要传 整个数组数据 给 函数本质上传的不是整个数组传的是 首元素地址2.为什么函数中 只是接收了首元素地址,却可以访问到数组所有元素原因:数组特点a.连续性b.单一性c.有序性3. 整个数组做函数参数本质上 ,只需要把首元素地址传过去 即可函数的形参 形式上可以写成数组printArray(int a[]); //形式上printArray(int *a); //本质上 是 一个指针变量 (后面指针部分会再说)所以,函数内部 通过sizeof(a) 算出来的是 指针大小,而不是数组大小练习:实现一个函数,从数组中找出最大值实现一个函数,实现数组逆序实现一个函数实现数组排序实现一个函数实现数组查找#include stdio.h void printArray(int *a,int len) { int i 0; for( i0;ilen;i) { printf(%d ,a[i]); } putchar(\n); } int printArrayMax(int *a,int len) { int i; int max 0; for (i0;ilen;i) { if(a[i]max) { max a[i]; } } return max; } void reverseArray(int *a,int len) { int n,i; for(i0;ilen/2;i) { n a[i]; a[i] a[len-1-i]; a[len-1-i] n; } printArray(a,len); } void inputArray(int *a,int len) { int i 0; for(i0;ilen;i) { scanf(%d,a[i]); } } void xuanPai(int *a,int len) { int i,j,num; for(i0;ilen-1;i) { for(ji1;jlen;j) { if(a[i]a[j]) { num a[i]; a[i] a[j]; a[j] num; } } } printf(选择排序); printArray(a,len); } void maoPai(int *a,int len) { int i,j,num; for(i0;ilen-1;i) { for(j0;jlen-1-i;j) { if(a[j1]a[j]) { num a[j]; a[j] a[j1]; a[j1] num; } } } printf(冒泡排序); printArray(a,len); } void chaPai(int *a,int len) { int i,j,num; for(i0;ilen;i) { ji; while(j0 a[i]a[j-1]) { a[j] a[j-1]; j--; } a[j] a[i]; } printf(插入排序); printArray(a,len); } void erCha(int *a,int len) { int begin,end,mid,i; int k; printf(请输入要查找的值); scanf(%d,k); begin 0; end len-1; i0; while(begin end) { mid (beginend)/2; if(ka[mid]) { end mid-1; }else if(ka[mid]) { begin mid1; }else break; } if(beginend) { printf(found,a[%d]\n,a[mid]); }else { printf(not found\n); } } int main(void) { int a[10]; int len sizeof(a)/sizeof(a[0]); inputArray(a,len); //printArray(a,10); printf(max %d\n,printArrayMax(a,len)); reverseArray(a,len); xuanPai(a,len); // maoPai(a,len); // chaPai(a,len); erCha(a,len); return 0; }注意一维字符型数组做函数参数的话一维字符型数组 --- 用来存放字符串1.形参 只需要 数组形式,不需要数组长度 //原因,因为字符串有自己结束标志2.实参 只需要 传数组名即可自己尝试实现头文件中string.h的函数把三、二维数组作为函数的参数二维数组:整型二维数组做函数参数printArray(int a[][4],int row); //形式上printArray(int (*a)[4],int row); //本质上 a起始还是指针变量下面用二维数组作为函数的参数实现输入输出排序查找比大小等函数#include stdio.h #include string.h void putStr(char (*s)[10],int row) { int i 0; for (i 0;irow;i) { puts(s[i]); } } void getStr(char (*s)[10],int row) { int i; for (i 0; irow;i) { scanf(%s,s[i]); } } void Maxstr(char (*s)[10],int row) { int i; int m 0; char max[10]; strcpy(max,s[0]); for(i0;irow;i) { if(strcmp(s[i],max)0) { strcpy(max,s[i]); } } printf(max %s\n,max); } void xuanPai(char (*s)[10],int row) { int i,j; char max[10]; for(i0;irow -1;i) { for(ji1;jrow;j) { if(strcmp(s[j],s[i]) 0) { strcpy(max,s[i]); strcpy(s[i],s[j]); strcpy(s[j],max); } } } putStr(s,row); } void maoPai(char (*s)[10],int row) { int i,j; char max[10]; for(i0;irow-1;i) { for(j0;jrow-1-i;j) { if(strcmp(s[j],s[j1]) 0) { strcpy(max,s[j]); strcpy(s[j],s[j]1); strcpy(s[j1],max); } } } putStr(s,row); } void chaPai(char (*s)[10],int row) { //插入排序 int i,j; for(i1;irow;i) { ji; char k[10];//这里的k不能替换成str[i] strcpy(k,s[i]); while(j0 (strcmp(k,s[j-1]) 0) ) { strcpy(s[j],s[j-1]); j--; } strcpy(s[j],k); } putStr(s,row); } void chazhao(char (*s)[10],int row) { //二分查找 int begin 0; int end row; int mid; char n[10]; printf(请输入要查找的字符串); scanf(%s,n); int i 0; while(beginend) { mid (beginend)/2; if(strcmp(s[mid],n)0) { end mid -1; }else if(strcmp(s[mid],n)0) { begin mid 1; }else break; } if(beginend) { printf(found\n); }else { printf(not found\n); } } int main(void) { char s[3][10]; int row 3; getStr(s,row); // putStr(s,row); Maxstr(s,row); printf(选择排序:\n); xuanPai(s,row); printf(冒泡排序:\n); maoPai(s,row); printf(插入排序\n); chaPai(s,row); chazhao(s,row); return 0; }四、标识符标识符名字变量名函数名作用域指的是标识符起效的范围//局部作用域{}//全局作用域不在任何一个{}范围内可见性站在程序角度看,执行到某句代码时,哪些标识符可见例如int a10; main() { int a20; printf(a %d\n,a); } printf(a %d\n,a); 输出a20 a10标识符的可见性的规则:1.先定义后使用2.同一作用域中不能有同名标识符3.在不同的作用域同名标识符相互之间没有影响4.如果是不同的作用域但是作用域之间存在嵌套关系则内层的作用域的同名标识符会屏蔽外层的作用域的同名标识符。(就近原则)1.变量变量:局部变量放在 {} 范围内的 就是局部变量全局变量不在任何一个{} 范围内的,就是全局变量变量的生命周期(无到有再到无)局部变量生命周期当程序运行到对应的定义数据时,才创建当程序运行到标识符,所在作用域结束时,销毁全局变量生命周期从程序运行开始,就存在到程序运行结束,销毁存储类别的关键字auto --- 数据存储在 栈上 ---自动申请 自动释放static --- 静态 表示数据存储在 静态区静态区变量初始化, 不能用变量初始化,只能用常量初始化static 修饰的局部变量,值具有继承性,只需要初始化一次registerextern//五个区栈堆静态区/全局区字符串常量区antuint main() { auto int a; //局部变量 --- 一般空间开在栈上不写的话默认前面补auto }staticvoid func1(void) { static int a 10; a; printf(a %d(n”,a); } int main(void) { int i 0; for (i 0; i 10;i) func1(); } 输出结果 11 12 13 14 15 16 17 18 19/////可以看出用了static后a值在过了它的作用域后没有销毁五、小结今天的学习哈诺塔这个代码还没有完全搞懂。知识点总结//总结: 1.函数 递归 //1.递归过程 //2.递归思想 //3.递归函数的实现 // a.递推关系 // b.结束条件 //4.递归的优缺点 // 2.数组 做函数参数 形参 实参 整型 一维数组 数组形式长度 数组名长度 字符型 一维数组 数组形式 数组名 整型 二维数组 数组形式行数 数组名行数 字符型 二维数组 数组形式行数 数组名行数 ---------------------- //介绍新的语法 用新语法实现旧功能 3.函数 标识符 作用域 和 可见性 //空间 局部作用域 ---- 局部变量 全局作用域 ---- 全局变量 //时间 生命周期 static 变量 static 的局部变量 1.只能用常量初始化 2.值只需要初始化一次 3.值具有继承性

更多文章