c语言程序设计案例教程(第2版)笔记(二)—函数、递归
零散知识点
- 模块化:将一个问题分解成若干个子问题的过程成为模块化。
- 模块化的优点:不但可以将一个复杂的问题分解成几个相对简单的问题;还可以提高程序代码的重用性。
- 函数:函数是构成C程序的基本单位。函数由函数首部和函数体两个部分组成,函数首部包含函数的返回类型、函数名称和参数表声明;函数体包含实现特定功能所需要执行的语句序列。
- 函数调用原则:C语言中规定,所有函数必须“先定义后使用”。即:如果被调用的函数在前面定义,则可以直接调用;否则,需要将被调用函数的函数原型在前面声明,以便通告C编译程序,这个函数的完整定义在后面。
- 常用标准函数头文件
- math.h——包含与数学有关的函数
- ctype.h——包含与字符处理有关的函数
- string.h——包含与字符串处理有关的函数
- stdio.h——包含与输入输出有关的函数
- stdlib.h——包含与动态分配存储空间和产生随机值有关的函数
- 递归
- 递归定义:定义一个概念的时候用到自身概念的定义形式被称为递归定义。
- 递归算法:具有“求解子问题的基本方法与求解整个问题所采用的方法一样”特征的求解算法称为递归算法。
- 递归函数特征:在函数的执行体中出现了调用函数本身。
- 例子——实现阶乘递归算法的递归函数如下:
1 //计算n! 2 long factorial(int n) 3 { 4 if (n == 0) 5 return 1; 6 else 7 return n * factorial(n - 1); 8 }
- 利用递归函数实现二分查找
二分查找算法描述:对于一个已经从小到大排序的数据序列,用给定数据key与查找区间中间位置的数据比较,如果相等表明查找成功;否则,如果key比中间位置的数据小,则在前半个区间用同样的方法继续查找;否则在后半个区间用同样的方法继续查找。
实现代码如下:
1 #include<stdio.h> 2 #pragma warning(disable:4996) 3 #include<stdlib.h> 4 #define NUM 10 5 void input(int value[]); 6 void output(int value[]); 7 int search(int value[], int key, int low, int high); 8 9 main() 10 { 11 int value[NUM], result, key; 12 input(value); 13 output(value); 14 printf("\nEnter the key : "); 15 scanf("%d\n", &key); 16 17 result = search(value, key, 0, NUM - 1); 18 if (result != 1) 19 printf("\n%d is the %dth element", key, result); 20 else 21 printf("\nfail to find %d", key); 22 } 23 24 void input(int value[]) 25 { 26 int i; 27 for (i = 0; i < NUM; i++){ 28 scanf("%d", &value[i]); 29 } 30 } 31 32 void output(int value[]) 33 { 34 int i; 35 for (i = 0; i < NUM; i++){ 36 printf("%4d", value[i]); 37 } 38 } 39 40 int search(int value[], int key, int low, int high) 41 { 42 int mid; 43 if (low>high) 44 return -1; 45 mid = (low + high) / 2; 46 if (value[mid] == key) 47 return mid; 48 if (key < value[mid]) 49 return search(value, key, low, mid - 1); 50 else 51 return search(value, key, mid + 1, high); 52 }
- 自定义函数
- 基本格式
<函数返回类型> <函数名> (<参数表>)
{
<函数体>;
}
- 说明:
- <函数返回类型> 是指函数执行完毕后函数返回值所属的数据类型。
- <函数名> 的命名应该符合C语言的用户自定义标识符规则,并且最好“见名知意”,最好用一个能够反映操作功能的动词命名;。
- <参数表> 指出了调用函数时,需要向函数提供的参数个数和每个参数所属的数据类型,是函数之间交换信息的接口;若形参是一维数组类型,则无需指出一维数组的元素个数。
- 在调用函数之后,参数传递经历两个基本步骤:1)根据形式参数的声明格式,为每一个形式参数分配存储空间。2)再将实际参数的值赋给对应的形式参数。函数执行完毕后,释放为函数调用分配的所有存储空间,并回到调用函数的位置。
- 将实际参数传递给形式参数的过程具有以下基本特征:a)具有单向性,实际参数既可以是变量,也可以是表达式;b)实际参数的值赋给形式参数之后,实际参数与形式参数不再有任何关系。
- 在函数没有被调用的时候,系统不会为任何参数分配空间,因此称为形参。
- <函数体> 由若干条需要执行的语句组成的语句序列,是函数的核心部分。
- C语言中,一个函数可以有返回值,也可以没有返回值。如果有返回值,返回值的类型在函数名前声明,并在函数体中利用return语句将返回值返回(若函数有返回值,在函数返回时,可以立即引用这个返回值,也可以将它保留在一个相应类型的变量中;否则,返回值将会丢失);如果没有返回值,在函数名前声明void,默认的返回类型是int。
- 函数的调用
函数调用语句的基本格式:<函数名> (<实际参数表>);
- <函数名> 是需要调用的函数名称。
- <实际参数表> 中的参数与这个函数的形式参数表相对应。
- 例子:
1 int dataArray[100]; 2 int n; 3 double ave; 4 5 //自定义函数 6 double average(int value[], int num){ 7 int i, sum = 0; 8 for (i = 0; i < num; i++){ 9 sum += value[i]; 10 return sum*1.0 / num; 11 } 12 } 13 14 //函数调用 15 ave = average(dataArray, n);
自定义函数的应用实例
-
输出乘法口诀表
1 #include<stdio.h> 2 void drawline(int n, char ch); //必须存在 3 4 main() 5 { 6 int i, j; 7 printf("\n 9*9 table\n"); 8 drawline(45, '='); 9 printf("\n 1 2 3 4 5 6 7 8 9"); 10 drawline(45, '='); //此处必须为单引号'',否则会产生乱码 11 for (i = 1; i <= 9; i++){ 12 printf("\n%4d", i); 13 for (j = 1; j <= 9; j++){ 14 printf("%4d", i*j); 15 } 16 if (i < 9) 17 drawline(45, '_'); 18 else 19 drawline(45, '='); 20 } 21 } 22 23 void drawline(int n, char ch){ 24 int i; 25 putchar('\n'); 26 for (i = 1; i <= n; i++){ 27 putchar(ch); 28 } 29 }
-
计算最长文本行
1 #include<stdio.h> 2 #include<string.h> 3 #pragma warning(disable:4996) 4 void readline(char maxline[]); 5 6 main() 7 { 8 char maxline[100] = ""; 9 readline(maxline); 10 printf("the longest line is:\n"); 11 puts(maxline); 12 } 13 14 void readline(char maxline[]) 15 { 16 char line[100]; 17 int maxlength; 18 int n; 19 20 maxlength = 0; 21 printf("\nEnter the line:\n"); 22 do{ 23 gets(line); 24 n = strlen(line); 25 if (n > strlen(maxline)){ 26 maxlength = n; 27 strcpy(maxline, line); 28 } 29 } while (n > 0); 30 }
本博客内容为原创,版权所有违者必究,转载请注明来源 http://www.cnblogs.com/sunshine-blog/