#6:C语言复习:函数与变量;

函数的定义:

                    格式:    类型标识符    函数名(形参表)    

                            {
                                说明部分;
                                执行部分;
                            }

                        类型标识符:    说明了函数返回值的类型,    int 可省略;    void 为无返回值
                        函数名:        同一程序,函数名唯一;
                        函数名:        圆括号不可省略;

例:

定义函数: 乘方

float power (float x,int n)
{
	int i;
	float t=1.0;
	for (i=1;	i<=n;	i++)
		t=t*x;
	return t;				//	return的数据与定义格式不符时,以定义为准;
}

有参函数调用的问题:

                        一:    函数调用结束之后,即刻释放分配的内存单元;形参只在函数内部有效

                        二:    形参、实参在数量,类型上严格一致

                        三:    形参只能是变量。

                        四:    实参和形参可以同名,但分配在不同的存储空间

函数参数的传递:

                                                   只能由实参到形参,不能被带回:

例:

在函数中交换两个元素

void swap(int a,int b)
{
	int i;
	printf("a=%d,b=%d\n",a,b);
	i=a;
	a=b;
	b=i;
	printf("a=%d,b=%d\n",a,b);		//	在函数中形参交换数据;
}
void main()
{
	int x=6,y=9;
	printf("x=%d,y=%d\n",x,y);
	swap(x,y);
	printf("x=%d,y=%d\n",x,y);		//	在定义函数之外,实参并未变化;
}

因为并未对地址中的数据进行操作,所以只有在函数中的输出是变化的,而函数之外的原数据不发生变化;


函数的声明:

                                    若把函数的定义放在了调用之后,需要在函数调用之前,对函数进行声明

                                    格式:

                                    类型标识符    函数名(类型标识符    形参1,类型标识符    形参2,……);

                                    分号不可省略;

函数的嵌套调用:

                                    在一个函数中完整的包含另一个函数

                                    main→ 函数a(含有函数b)→ 函数b → 返回继续函数a → 结束

例:

                                        计算 s=1^2!+2^2!+……+x^2!
                                               编写两个函数,一个计算平方,一个计算阶乘

long f1(int p);						//	函数声明;
void main()
{
	int i,x;
	long s=0;
	printf("请输入平方阶乘和的最大一个数:\n");
	scanf("%d",&x);

	for	(i=1;	i<=x;	i++)		//	借助函数进行计算;	
		s=s+f1(i);

	printf("\ns=%ld\n",s);
}

long f1(int p)					
{
	int k;
	long r;
	long f2(int);					
	
	k=p*p;					//	计算乘方;并执行f2;
	r=f2(k);

	return r;				//	输出结果;
}

long f2(int q)
{
	long c=1;
	int i;
	for(i=1;	i<=q;	i++)		//	计算阶乘;
		c=c*i;
	return c;
}

函数的递归调用;

                                        函数对它本身的调用;

例:

                                x(n)=x(n-1)+2;    x(1)=10;    求x(5);

x(int n)
{
	int c;
	if(n==1)
		c=10;
	else
		c=x(n-1)+2;		//	等价于 x(5)=x(4)+2=x(3)+2+2=x(2)+2+2+2=.....
	return(c);
}

void main()
{
	printf("%d\n",x(5));
}

例:

反向输出一个整数:

void main()
{
	void output(int x);
	int n;
	scanf("%d",&n);

	if(n<0)							//	若输入为负数,先输出负号;
	{
		n=-n;
		putchar('-');
	}

	output(n);						//	执行调换函数;

	printf("\n");
}

void output(int x)					//	调换函数;
{

	if(x>=0	&&	x<=9)				//	如果x是个位数(仅有一位),输出x;
		printf("%d",x);

	else							
	{
		printf("%d",x%10);			//	分离出个位;
		output(x/10);			//	执行下一个数;

	}
}

数组作为函数:

                                    一:数组元素作为实参使用;与普通变量一样;

                                    二:数组名作为实参和形参使用;

一:数组元素作为实参使用:


例:

比较两个字符串的大小

void main()
{
	int i,flag;						//	flag为ASCII码之差,与零比大小,来判断谁大谁小;
	int compchar(char ,char);
	char str1[80],str2[80];
	gets(str1);
	gets(str2);
	i=0;

	do							//	数组元素作为函数实参,执行比较函数;
	{
		flag=compchar(str1[i],str2[i]);
		i++;
	}

	while (	(str1[i]!='\0'||str2[i]!='\0')&&(flag==0));	//	若flag不为零,直接输出结果;
	
								//	字符串相同时,字符串若结束,再比较一次,使得flag不为零,结束循环;


	if	(flag==0)					//	判断flag的正负来输出结果;
		printf("%s	= %s",str1,str2);
	else if (flag>0)
		printf("%s	> %s",str1,str2);
	else 
		printf("%s	< %s",str1,str2);

	printf("\n");
}

int compchar (char c1,char c2)
{
	int t;
	t=c1-c2;						//	计算两个字符的差;
	return t;
}

二:数组名作为实参和形参使用:


                                    1.    形参与实参都用数组名,且实参与形参的类型、维数相同;                                        

                                    2.    将实参的地址传递给形参,形参与实参共用相同的存储区域

                                    3.    若形参数组的数据发生了变化,则主函数的实参数组也变化

例:

利用选择排序法对数组元素由大到小进行排序;

void nzp(int a[80], int n)			//	在定义数组名函数的时候,一般返回值为空,定义可多加数组长度;

{
	int i,j,k,t;


	for (i=0;	i<n-1;	i++)		//	n个数需要比较n-1次,下标从0	~ n-2;i为比较次数;
	{
		k=i;				//	用k记录排序范围的第一个元素;

		for(j=i+1;	j<n;	j++)	//	找出最大元素的位置;!!!!!!
			if(a[j]>a[k])
				k=j;

		if(k!=i)			//	如果最大的元素不是排序范围内的第一个元素,
		{
			t=a[k];			//	将最大的元素与排序的第一个元素互换;
			a[k]=a[i];
			a[i]=t;
		}
	}
}

void main()
{
	int b[80],i,n;
	printf("请输入要排序的数的个数:\n");
	scanf("%d",&n);

	printf("\n请输入数据:\n");
	for(i=0;	i<n;	i++)
		scanf("%d",&b[i]);

	printf("\n原始数据为:\n");		//	输出原始数据,检查输入是否正确;
	for(i=0;	i<n;	i++)
		printf("%4d",b[i]);
	printf("\n\n");

	nzp(b,n);				//	排序;

	printf("处理后的从大到小的数据为:\n");
	for(i=0;	i<n;	i++)
		printf("%4d",b[i]);
	printf("\n\n");

}

三、多维数组名作为函数参数:

                                        1.    指定一维数组中各元素的大小(列数,即一行中的元素个数);    

                                        2.    可以省去第一维的长度:

                                            int fun(int a[][10])

                                            但是在进行函数计算的时候,要标好行列的长度;

                                        3.    不能省略第二维;

例:

求二维数组c每行中的最大元素,并依次放入一维数组b中:

void fun(int c[80][40],int b[40],int m,int n)			//	定义二维数组的长度需要两个变量;
{
	int max,i,j;

	for(i=0;	i<m;	i++)				//	从第一行开始,寻找最大值;


	{															
		max=c[i][0];					//	最大值附为开头开始比较大小;

		for(j=1;	j<n;	j++)			//	将第i行的最大值附给max;
			if(c[i][j]>max)
				max=c[i][j];


		b[i]=max;					//	将max附给数组b;
	}
}


void main()
{
	int c[80][40],b[40],i,j,m,n,k;								

	printf("请输入将要排序的二维数组的行数与列数:\n\n");	//	标准的二维数组输入;
	scanf("%d%d",&m,&n);
	printf("请分别按行输入将要排序的二维数组:\n\n");
	for(i=0;	i<m;	i++)
		for(j=0;	j<n;	j++)
			scanf("%d",&c[i][j]);


	printf("\n\n原始数据为:\n\n");				//	输出原始数据,便于检查
	for(i=0;	i<m;	i++)
	{
		for(j=0;	j<n;	j++)
		{
			printf("%4d",c[i][j]);
		}
	printf("\n");
	}
	printf("\n");


	fun(c,b,m,n);						//	计算函数,将最大值计算完赋值给数组b;

	for(k=0;	k<n;	k++)				//	输出数组b;					
		printf("%4d\n",b[k]);

}	

四、变量的作用域:

                                                 一、 局部变量(内部变量)


                                只能在本函数内或复合语句中使用;如形参就是局部变量;

                                作用域:    定义位置到他按所在的函数或复合语句结束;

                                1.    同一作用域内不能出现同名变量;
                                       不同的作用域可以出现同名变量;

例:

                   for( int i = 0; ...   );   for( int i = 0; .... );  可以重复定义循环变量


                                2.    局部变量的定义必须放在所在函数の全部可执行语句之前

                                3.    当作用域发生嵌套时;以内层函数的局部变量定义为准,外层被屏蔽;

                                4.    主函数不能使用其他函数中定义的局部变量;

局部变量的作用域:

void prt(void);
void main()
{																//	x=1作用域:
	int x=1;														//**
	{															//**
		int x=2;									//	x=2作用域;		//**
		{										//**				//**
			int x=3;				//	x=3作用域;		//**				//**
			prt();					//**				//**				//**
			printf("(2)x=%d\n",x);			//**				//**				//**
		}										//**				//**
		printf("(3)x=%d\n",x);								//**				//**
	}															//**
	printf("(4)x=%d\n",x);			//	外层函数被内层定义屏蔽						        //**

}
void prt(void)
{					//	x=5作用域;
	int x=5;			//**
	printf("(1)x=%d\n",x);		//**
}


二、全局变量:

                        函数外部的任意位置上定义的变量;

                        作用域:    从变量定义的位置开始,到他所在的源文件结束为止;所有函数都能使用;

                        允许全局变量与局部变量同名
;在局部变量的作用域内,全局变量不起作用;

int x=10;				//	定义全局变量,赋值为10;
void fun(void);
void main()
{
	printf("main1:%d\n",x);		//	输出全局变量;

	x=20;				//	定义局部变量,与全局变量同名,屏蔽全局变量;

	fun();				//	执行fun函数;
				
	printf("main2:%d\n",x);		//	输出局部变量x=20;

}
void fun(void)				//	定义同名局部变量x,屏蔽全局变量;
{
	int x;
	x=30;
	printf("fun:%d\n",x);
}

三、变量的存储类别:


一。变量的生存期:


                                    变量的存储类别分为:动态类和静态类;

                                    动态存储类别:

                                    1.    存储在动态存储器和寄存器中;

                                    2.    生存期从变量定义开始到函数运行结束为止;        

                                    3.    可用的定义:auto(自动);register(寄存器);

                                    静态存储类别:

                                    1.    存储在静态静态存储器中;

                                    2.    生存期从程序运行开始一直延续到程序运行结束

                                    3.    可用的定义:static(静态);extern(外部);


                                    一般的定义形式:

                                    存储类别说明符 类型标识符    变量名表列; static int a;

二。局部变量的存储类别:


                                内部定义局部变量时,没有指定类别,或者使用了auto就是自动变量

                                    2.静态局部变量

                                1.    静态局部变量生存期虽然延伸至整个程序结束但是只能在定义该变量的函数中使用;

                                    退出该函数后,虽然变量依然存在,但是不能使用;    

                                2.    静态局部变量初值是在编译时赋予的;不是在程序执行时初始化的,所以只能够赋值一次;
                    
                                    所以初值只能是常量表达式

                                3.    若定义静态变量不附初值的话,编译系统直接附初值(数值赋值0;字符赋值空字符)

                                4.    自动变量,编译系统不附初值;    

例:

静态局部变量的使用:

void main()
{
	int i;
	void f1();
	void f2();
	for (i=1;	i<=5;	i++)
	{	
		printf("第%d次循环\n",i);
		f1();
		f2();
		printf("\n");
	}

}
void f1()
{
	static int j;					//	静态变量定义时若不赋值,自动赋值为0;

	++j;						//	静态变量的定义只执行一次;所以j随循环变化;
	printf("j=%d\n",j);
}
void f2()
{
	int k=0;
	++k;						//	动态变量定义时随循环继续执行,所以k一直输出为1;
	printf("k=%d\n",k);
}

三。寄存器变量:

                                存放在CPU寄存器之中,寄存器个数有限,虽然速度快,但是一般不使用;

                                                                 且不能调用指针操作;

例:

使用寄存器变量

void main()
{
	register int i,s=0;
	for(i=1;	i<=100;	i++)
		s=s+i;
	printf("s=%d\n",s);
}

四。全局变量的存储类别:


                                全局变量(外部变量),只有静态类别,生存期是整个程序的运行期;

                                初始化在编译时完成,赋值只能是常量表达式;

                                一。extern声明全局变量:

                            扩展变量作用域:


                            1.    作用域扩展到定义之前;    

                            2.    扩展到一个工程的其他原文件当中

例:


F1.C的内容如下:

int x=0;                       //    外部变量的定义;

extern int b;                //    扩展外部变量,使整个源文件可用;

void main()
{
    ……

        ……
        …………

    extern int a;            //    扩展外部变量,使整个main函数可用;

}

void fun11()
{    ……    }

int a,b,c;                    // fun11中不能使用全局变量a,但是可以使用全局变量b全局变量c没有进行声明也不能使用

void fun12()
{    ……    }


F2.C的内容如下:


extern int x;                //    声明外部变量,使F2.C可用F1.C中定义的外部变量x;

void fun21(int a,int b)

{    ……    }


注: extern 可以在别的源文件中使用,用于扩展其他的全局变量的范围到本文件!!


二。静态外部变量:


                            静态外部变量不能使用extern让其它源文件调用作用域限制在定义该变量的源文件中

                            可以让其它源文件定义重名外部变量,不会引起混乱;

例:


F1.C的内容:

static int x,y;
char z;
main()
{
    ……
        ……
}    

F2.C的内容:

extern int x;                    //    由于F1.C中定义的静态全局变量,所以在F2.C中无法引用;

extern char z;                 //    z可以被引用;

int y;                              //    此处定义的y与F1.C中的y不同;(覆盖

void func (int a,char ch)
{
    x=a;
    z=ch;
}


五。内部与外部函数


                                1.    内部函数(静态函数):

                            定义的函数只能在本文件中调用,

                            定义格式:

                            static 类型标识符    函数名(形参表)    {函数体}


                                2.    外部函数:

                            外部函数在整个源文件中有效。

                            定义格式:

                            extern …………

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值