C--第十章

 递归程序设计:

适用范围:操作步骤类型不多,有重复的要求,但重复步骤不尽相同,很难描述出明确的重复性规律,难以用递推法循环实现。此时,就选择递归法,使用递归函数解决。

递归的两个关键点:递归出口和递归调用式子。

函数递归调用的两种形式:

(1)直接递归调用:

int f(int x){

   int y;

...

   y=f(x-1)

...

   return y;

}

(2)间接递归调用:

int f(int x){

   int y;

...

   y=g(x)

...

   return y;

}

int g(x){

     int z;

...

     z=f(x-1)

...

     return z;

}

用递归函数求1+2+.....+n.

#include<stdio.h>
int fact(int n);
int main()
{
	int n;
	printf("Enter n:");
	scanf("%d",&n);
	printf("Number of sum is %d\n",fact(n));
    return 0;
}
int fact(int n){
	
	
	if(n<1){
		return 0;
	}else{
	    return n+fact(n-1);
	}
}

用递归函数求两整数最大公约数

#include<stdio.h>
int gcd(int m,int n);
int main()
{
	int m,n;
	printf("Enter m,n:");
	scanf("%d %d",&m,&n);
    gcd(m,n);
	printf("%d",n);	
}
int gcd(int m,int n){
	if(m%n==0){
		return 0;
	}else{
		return gcd(n,m%n);
	}
}

函数的嵌套调用:归根到底就是通过嵌套函数把复杂的问题细分,简单化,交给不同函数处理

(1)限时函数长度

(2)避免函数之间功能的重复

(3)减少全局变量的使用(丰田汽车案例是个惨痛的教训

用嵌套函数设计有序表操作(这个源程序有一点问题,如果有人知道可以找出来)

/*有序表的操作*/ 
#include<stdio.h>
#define MAXN 100
int count=0;          /*用全局变量表示count表示数组a中待处理的元素个数*/ 
void select(int a[],int option,int value);       /*决定对有序数组a进行何种操作的控制函数*/
void input_array(int a[]);                       /*输出数组a的函数*/ 
void print_array(int a[]);                       /*输入....*/ 
void insert(int a[],int value);                  /*插入一个值为value的元素*/ 
void delete(int a[],int value);                  /*删除....*/ 
void query(int a[],int value);                   /*使用二分法在有序数组a中查找元素value的函数*/

int main(void)
{
	int option,value,a[MAXN];
	
	input_array(a);         /*调用函数输入数组a*/
	/*菜单*/ 
	printf("[1] Insert\n");
	printf("[2] Remove\n");
	printf("[3] Query\n");
	printf("[Other option]end\n");
	
	while(1){
		printf("Enter option:");      /*输入编号*/      
		scanf("%d",&option);
		if(option<1||option>3){
			break;
		}
		printf("Input value:");       /*输入参数*/ 
		scanf("%d",&value);
		select(a,option,value);       /*调用控制函数*/ 
		printf("\n");
	}
	printf("Thanks.\n");
	return 0; 
}
/*控制函数*/ 
void select(int a[],int option,int value){
	switch(option){
		case1:
			insert(a,value);
			break;
		case2:
		    delete(a,value);
			break;	
	    case3:
	    	query(a,value);
	    	break;
	}
} 
/*有序表输入函数*/
void input_array(int a[]){
	int i;
	printf("Input the number of array elementa:");
	scanf("%d",&count);
	printf("Input an ordered array element:");
	for(i=0;i<count;i++){
		scanf("%d",&a[i]);
	}
}
/*有序表输出函数*/
void print_array(int a[]){
	int i;
	printf("The ordered array a is:");
	for(i=0;i<count;i++){         /*输出时相邻数字用一个空格分开,行末无空格*/ 
		printf("%d",a[i]);
	}
}
/*有序表插入函数*/
void insert(int a[],int value){
	int i,j;
	for(i=0;i<count;i++){             /*定位:找到待插入的位置,即退出循环时i的值*/ 
		if(value<a[i]){
			break;
		}
	}
	for(j=count-1;j>=i;j--){          /*腾位:将a[i]-a[count-1]向后顺移一位*/ 
		a[j+1]=a[j];
			}
		a[i]=value;
		count++;
		print_array(a);	
} 
/*有序表删除函数*/
void delete(int a[],int value){
	int i,index=1;
	for(i=0;i<count;i++){             /*定位:如果找到待删除的元素,用index记录其下标*/ 
		if(value==a[i]){
			index=i;
			break;
		}
	}
	if(index==-1){
		printf("Failed to find the data,deletion failed.");
	}else{
		for(i=index;i<count-1;i++){   /*将a[count-1]-a[index+1]向前移一位*/ 
			a[i]=a[i+1];
		}
	}
	count--;
	print_array(a);
}
/*有序表二分法查询函数*/
void query(int a[],int value){
	int mid,left=0,right=count-1;
	while(left<right){
		mid=(left+right)/2;
		if(value==a[mid]){
			printf("The index is:%d",mid);
			return;
		}else if(value<a[mid]){
			right=mid-1;
		}else{
			left=mid+1;
		}
	}
	printf("This element does not exist.");
} 

宏定义#define

宏定义的格式:

     #define  宏名   宏定义字符串

宏允许嵌套定义。

宏定义结束末尾不能加   ‘ ;’

宏的用途:

(1)符号常量,如 : PI ,数组大小定义。用来增加程序的灵活性,可读性。

(2)简单的函数功能实现。

(3)当程序需要多次书写一些相同内容时,将它简写为宏。

如:#define MAXN  "It has 100 \

value."

     printf(MAXN);

其中的  \ 表示该行未结束,与下一行连接。

注意:宏的引用方式和函数调用的实现过程完全不相同。

.h 文件通常被称为头文件。除了像stdio.h等系统的头文件,也可以自己编写头文件。

将长度转换的宏定义成头文件 length.h ,并写出主函数文件:

/*头文件 length.h 源程序*/
#define Mile_to_meter 1609
#define Foot_to_centimeter 30.48
#define Inch_to_centimeter 2.54

/*主函数文件 prog.c 源程序*/
#include<stdio.h>
#include "length.h"
int main(void)
{
	...
 } 

                                                             常用标准头文件

字符处理

ctype.h
与数学处理函数有关的说明与定义math.h
输入输出函数中使用的有关说明与定义stdio.h
字符串函数的有关说明和定义string.h
定义某些常用内容stddef.h
杂项说明stdlib.h
支持系统时间函数time.h

编译预处理:

      这里只讲条件编译,一般的程序经过编译后,所有的C语句都生成到目标程序中,如果只想把源程序中的一部分语句生成目标代码,可以使用条件编译。

      条件编译运用广泛,可以为一个程序提供不同版本,不同的用户使用不同的版本,

例如:

#define FLAG 1
#if FLAG
   程序段1
#else
   程序段2
#endif

     

/*用带参宏实现输出三个数中最大的数*/
#include<stdio.h>
#define  max(a,b,c)  (a>b?a:b)>c?(a>b?a:b):c
int main()
{
	double a,b,c;
	printf("Enter a,b,c:");
	scanf("%lf %lf %lf",&a,&b,&c);
	printf("%.2f",max(a,b,c));
	return 0;
}

“?:”是一个三目运算符(唯一的)

?的前面是一个逻辑语句,?和:之间表示语句为真时的值,:后面是语句不成立的值。

条件编译指令均以 # 开头,其意义与C语言中的 if - else 语句完全不同,if - else 语句两个分支程序段都会被生成到目标代码1中,由程序运行时根据条件决定执行哪一段,而条件编译的另一段会被舍弃。#if 的条件只能是宏名,不能是程序表达式,因为在编译预处理时是无法计算表达式的。

      采用条件编译的好处:

(1)目标代码精简,不包含无关代码。

(2)系统代码保护性强

这是转载的:

#define      定义一个预处理宏
#undef       取消一个预处理宏
#ifdef         判断某个预处理宏是否被定义,若定义则编译后续程序段
#ifndef       判断某个预处理宏是否没有被定义,若没定义则编译后续程序段
#if              判断某个预处理宏的值是否不为0,不为0则编译后续程序段,相当于C语法中的if语句
#elif           相当于C语法中的else if 与#if配套使用
#else         相当于C语法中的else 与#if、#elif配合使用
#endif'      结束条件命令的判断,与#if、#ifdef、#ifndef配套使用

程序文件模块:

       首先应明白程序  ,程序文件模块 与函数之间的关系:一个大程序可由几个程序文件模块组成,每一个程序文件模块又可能包含若干个函数。

文件模块间的通信:

       外部变量:全局变量在整个程序所有的文件模块中起作用,如果在每一个文件模块中都定义一次全局变量,模块单独编译时不会发生错误,一旦把各模块连接一起时,就会产生对同一全局变量多次定义的错误。全局变量只能在某一模块定义一次,其他模块要使用需要通过外部变量的声明。

其格式为:

        extern  类型名   变量名表;

       静态全局变量:当程序由多个文件模块构成时,静态全局变量用于限时全局变量作用域的扩展,即不影响其他不相关的文件模块。即使其他文件使用外部变量声明,也不能使用该变量。

        对于函数也是同样的道理:调用外部函数时用 extern 声明,同样的,也可以把函数设为静态函数,静态函数的定义格式为:static 函数类型 函数名(参数表说明);

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DDsoup

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值