c语言判断素数squ,第五讲C语言函数.doc

44cb7578e1df5412b94317daaa3307ba.gif第五讲C语言函数.doc

下载提示(请认真阅读)1.请仔细阅读文档,确保文档完整性,对于不预览、不比对内容而直接下载带来的问题本站不予受理。

2.下载的文档,不会出现我们的网址水印。

3、该文档所得收入(下载+内容+预览)归上传者、原创作者;如果您是本文档原作者,请点此认领!既往收益都归您。

文档包含非法信息?点此举报后获取现金奖励!

下载文档到电脑,查找使用更方便

20

积分

还剩页未读,继续阅读

关 键 词:第五

语言

函数

资源描述:

第5讲 函数

5.1函数的概念

C程序由一个main和任意个函数组成。

例1 在主函数中调用其他函数。

#includevoid printstar(void)

{

puts("**********************\n");

}

void print_message(void)

{

puts(" Welcome to C!\n");

}

main()

{

printstar();

print_message();

printstar();

return 0;

}

程序运行后输出:

**********************

Welcome to C!

**********************

3)函数不可嵌套定义,具有全局性、平行性,

4)函数分为有参与无参函数

5)程序从main开始执行,最后又回到main函数结束。

5.1.5 定义函数的一般形式

1. 定义无参数的一般形式

类型标识符 函数名([void])

{

声明部分

语句

}

调用方式

函数名( ) ;

若有返回值可出现在表达式中,无返值可单独出现

2. 定义有参数的一般形式

函数的定义通常包含以下内容:

函数返回值类型 函数名(形参表说明)//函数首部,函数头

{

声明语句 //函数体

执行语句

}

说明:

(1)函数的类型,是指函数返回值的类型。当不指明函数类型时,系统默认的是int型。

(2)函数名本身也有值,它代表了该函数的入口地址,使用指针调用该函数时,将用到此功能。

(3)形参全称为"形式参数"。形参表是用逗号分隔的一组变量说明(即定义),包括形参的类型和形参标识符,其作用是指出每一个形参的类型和形参的名称,当调用函数时,接受来自主调函数的数据,确定各参数的值。如:

int func (int x, int y )

{ …… }。

(4)用{ }括起来的部分是函数的主体,称为函数体。我们可以得到一个C语言中最简单的函数:

void dumy ( ){ }

5.2 函数参数和函数的值

C语言中采用参数、返回值和全局变量三种方式进行数据传递。

◆当调用函数时,通过函数的参数,主调函数为形参提供数据;

◆调用结束时,被调函数通过返回语句将函数的运行结果(称为返回值)带回主调函数中;

◆函数之间还可以通过使用全局变量,在一个函数内使用其他函数中的某些变量的结果。

1. 形式参数和实际参数

形式参数(形参)——是函数定义时由用户定义的形式上的变量。实际参数(实参)——是函数调用时,主调函数为被调函数提供的原始数据。

按值传递参数——数值传递

若实参和形参均为普通变量,则实参向形参传送数据的方式是"按值传递"。等价于:

数据类型 形参变量名=实参变量名;

◇形式参数是函数的局部变量,仅在函数内部才有意义,不能用它来传递函数的结果。

例:调用函数的数据传递。

#includeint max ( int x, int y ) //x和y为形参,接受来自主调函数的原始数据

{

int z;

z=x>y?x:y;

return(z); //将函数的结果返回主调函数

}

main()

{

int a,b, c;

puts("please enter two integer numbers");

scanf("%d %d",&a,&b);

c=max(a,b);//主函数内调用功能函数max,实参为a和b

printf("max=%d\n",c);

return 0;

}

说明:实参与形参必须类型相同,个数相等,一一对应。当调用函数时,实参的值传给形参,在被调函数内部,形参的变化不会影响实参的值。

当实参之间有联系时,实参的求值顺序在不同的编译系统下是不同的,VC是从右向左。

例2:

#includeint add(int x,int y);

main()

{

int x=2;

printf("%d\n",add(x,++x));

return 0;

}

int add(int x,int y)

{

return (x+y);

}

运行结果:

6

例3:调用按值传递的函数不能实现两个实参变量值的交换。

若在主函数中变量a=5,b=10,编写一个函数交换主函数中两个变量的值,使变量a=10,b=5。

#includevoid swapf(int x,int y);

main()

{

int a, b;

a=5; b=10; //说明两个变量并赋初值

printf("before swapf a=%d b=%d\n",a,b);

swapf(a, b); //用变量a和b作为实际参数调用函数

printf("after swapf a=%d b=%d\n",a,b);

return 0;

}

void swapf(int x,int y)

{

int temp; //借助临时变量交换两个形参变量x和y的值

temp=x; //①

x=y; //②

y=temp; //③

printf("in swapf x=%d y=%d\n",x,y);

}

程序的实际运行结果为:

before swapf a=5, b=10

in swapf x=10, y=5

after swapf a=5, b=10。

按地址传递参数——地址传递

函数的参数可以是指针类型。它的作用是将一个变量的地址传送到另一个函数中。

例:同上例。今用函数处理,而且用指针类型的数据作函数参数。

#includevoid swapf(int * p1,int * p2);

main()

{

int a, b;

a=5; b=10; //说明两个变量并赋初值

printf("before swapf a=%d b=%d\n",a,b);

swapf( &a, &b); //用变量a和b作为实际参数调用函数

printf("after swapf a=%d b=%d\n",a,b);

return 0;

}

void swapf(int * p1,int * p2)

{

int temp; //借助临时变量交换两个形参变量x和y的值

temp=*p1; //①

*p1=*p2; //②

*p2=temp; //③

printf("in swapf *p1=%d *p2=%d\n",*p1,*p2);

}

运行程序:

before swapf a=5 b=10

in swapf *p1=10 *p2=5

after swapf a=10 b=5

所以可以通过指针作为函数的参数,实现在函数体中,对实参指针变量所指向的变量的操作。

实参指针变量的作用仅是在调用函数时,为定义的形参指针变量赋初值:

数据类型符 * 形参指针变量名=实参指针变量名;

例:输入a、b、c三个整数,按大小顺序输出。

#includevoid swap(int *pt1,int *pt2) //交换两变量的值

{

int temp;

temp=*pt1;

*pt1=*pt2;

*pt2=temp;

}

void exchange(int *q1,int *q2,int *q3)//三变量排序

{

if(*q1

int func(int x);

main()

{

int a,c;

scanf("%d",&a);

c=func(a);

printf("%d\n",c);

return 0;

}

int func(int x)

{

int z;

if(x>=0)

z=2*x*x-x;

else

z=2*x*x;

return z;

}

说明

(1)函数的返回值只能有一个。

(2)当函数中不需要指明返回值时,可以写成:

return;

若用void声明函数的返回类型,也可以不写。

(3)一个函数体内可以有多个返回语句,不论执行到哪一个,函数都结束,回到主调函数。如上例可改写为:

if ( x >= 0 )

return (2*x*x-x);

else

return (2*x*x);

(4)当函数没有指明返回值,即return; 或没有返回语句时,可以定义无类型函数,其形式为:

void 函数名(形参表)

{ …… }

⑸函数定义时的类型就是函数返回值的类型。

例5:分析程序的运行结果。

#includeint max(float x,float y);

main()

{

float a,b;

int c;

scanf("%f %f",&a,&b);

c=max(a,b);

printf("MAX is %d\n",c);

return 0;

}

int max(float x, float y)

{

float z;

z=x>y?x:y;

return(z);

}

运行时,若从键盘输入:4.5 6.8

结果为:6

2. 通过指针类型的参数返回值

函数要向调用函数返回值,还可以通过指针类型的参数,向主调用函数返回值,且这种方式可以返回多个值。

例6:输入一个整数,计算其平方根、平方和立方。

#include#includevoid f(int x, double * psqrt,double * psquare,double * pcube);

main()

{

int x;

double sqrt,square,cube;

scanf("%d",&x);

f(x,&sqrt,&square,&cube);

printf("%d:square_root=%f,square=%f,cube=%f\n",x,sqrt,square,cube);

return 0;

}

void f(int x, double * psqrt,double * psquare,double * pcube)

{

*psqrt=sqrt(x);

*psquare=x*x;

*pcube=x*x*x;

}

运行程序:

6

6:square_root=2.449490,square=36.000000,cube=216.000000

3.指针类型的函数——函数返回地址类型的数据

例7 在一个数组中搜索一个关键数字。

分析:写一个搜索函数,返回在数组中存储该关键数字的存储单元的指针(地址)。

#include#include#includeint * search(int *pi,int n,int key);

void main()

{

int s[15];

int i,k,*p;

srand((unsigned)time(NULL));

for(i=0;i<15;i++)

s[i]=rand()%100; //用随机数向元素赋值

for(i=0;i<15;i++)

printf("%d ",s[i]);

puts("\n Input Key_number:");

scanf("%d",&k);

p=search(s,15,k);

if(p!=NULL)printf("Key_number=%d\n",*p);

}

int * search(int *pi,int n,int key)

{

int i;

for(i=0;i#include#includeint * search(int *pi,int n,int key);

void main()

{

int s[15];

int i,k;

srand((unsigned)time(NULL));

for(i=0;i<15;i++)

s[i]=rand()%100; //用随机数向元素赋值

for(i=0;i<15;i++)

printf("%d ",s[i]);

puts("\n Input Key_number:");

scanf("%d",&k);

*(search(s,15,k))=100; //向返回指针的函数赋值

for(i=0;i<15;i++)

printf("%d ",s[i]);

putchar(\n);

}

int * search(int *pi,int n,int key)

{

int i;

for(i=0;ifloat * search(float (* pointer)[4],int n);

//参数pointer是指向含有4个float型数据元素的一维数组的指针

main()

{

float score[][4]={{60,70,80,90},{56,88,87,90,},{38,90,78,47}};

float * p;

int i,m;

printf("enter the number of student:");

scanf("%d",&m);

printf("The score of No.%d are:\n",m);

p=search(score,m);

for(i=0;i<4;i++)

printf("%5.2f\t",*(p+i));

return 0;

}

float * search(float (* pointer)[4],int n)

{

float * pt;

pt=*(pointer+n);

return pt;

}

说明:pointer+n指向二维数组score的第n行,*(pointer+n)为指向二维数组score第n行首元素的float型指针。

5.3 函数的调用

5.3.1 函数调用的一般形式

函数调用的一般形式:

函数名([实参表])

注意:函数调用前,必须先定义或说明(引用性声明)。

5.3.3 函数调用的方式

1.函数语句

被调函数在主调函数中,以语句的方式出现。通常只完成一种操作,不带回返回值。

例8:分析程序的执行过程。

#includevoid func()

{

puts("This is a programm!\n");

}

void main()

{

func(); //函数调用语句

}

2.函数表达式

将函数的调用结果作运算符的运算分量,这种函数是有返回值的。

例9:库函数pow(a,b)的功能是求ab,在主函数中调用该函数的程序为:

#include#include main( )

{

int a,b,i,j;

double c;

scanf("%d %d %d %d",&a,&b,&i,&j);

c=pow(a,i)+pow(b,j);

printf("%f\n",c);

return 0;

}

将函数pow(a,i)和pow(b,j)作为"+"运算符的运算分量。

3.函数参数

函数的调用结果进一步做其他函数的实参,这种函数也是有返回值的。上例中,若c=pow(a,pow(b,i));

此时,pow(b,i)作为下一次调用pow函数的实参。比如:

int max(x,y){return (x>y?x:y);}

用该函数求a、b、c三数中的最大者:

d=max(c,max(a,b);

例10求100至200间的全部素数。(参见P144例5.7)

分析:编写一个判断一个整数是否是素数的函数int_prime(),若是素数返回1,否则返回0。

#include#includeint int_prime(int);

main()

{

int m,n=0;

for(m=101;m<=200;m=m+2)

{

if(int_prime(m))

{

printf("%5d",m);

n=n+1;

}

if(n%10==0)printf("\n");

}

printf("\n");

return 0;

}

int int_prime(int m)

{

int prime=1,k,i;

k=(int)(sqrt(m));

for(i=2;i<=k;i++)

if(m%i==0)

{

prime=0;

break;

}

return prime;

}

例5.8 输入多个字符用一个函数把大写字母转换为小写字母作为函数值返回,[email protected]

#includechar myupper(char ch)

{

if(ch>=A && ch<=Z)ch=ch+32;

return ch;

}

void main()

{

char c;

while((c=getchar())!=@)

{

c=myupper(c);

putchar(c);

}

putchar(\n);

}

大写小转换的位运算方法:

#includechar myupper(char ch)

{

//return ch|0x20; //大写转换为小写

//return ch&0xDF; //小写转换为大写

return ch^0x20; //大写转换为小写,小写转换为大写

}

void main()

{

char c;

while((c=getchar())!=@)

{

c=myupper(c);

putchar(c);

}

putchar(\n);

}

对被调用函数的声明和函数原型

主调函数调用被调函数之前,必须对被调函数作声明,其形式是:

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

或:

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

例:

#include void main( )

{

float fun1(float x,float y); //对函数fun1的声明

float a,b;

float c;

scanf("%d,%d",&a,&b);

c=fun1(a,b);

printf("%f\n",c);

}

float fun1(float x,float y)

{ …… }

5.4 指向函数的指针及常用的几种参数传递方式

5.4.1 指向函数的指针

◇ 函数名就是一个指针常量,其值为该函数所占内存区的首地址,即函数的入口地址,也称为函数的指针。

◇ 指向函数的指针变量称为函数指针变量。

1. 函数指针变量定义的一般形式为:

类型说明符 (*指针变量名)();

其中:

类型说明符 表示被指函数的返回值的类型。

(* 指针变量名) 表示*后面的变量是定义的指针变量,注意括号不能省略。

() 表示指针变量所指的是一个函数。

例如:

int (*pf)();

表示pf是一个指向的函数入口的指针变量,该函数的返回值(函数值)是整型。

使用该指针变量调用函数时与用函数名调用函数一样要用参数表,其格式为:

指针变量名(实参数表)

例: 求两数中的大者。

#includeint max(int x,int y)

{

return(x>y?x:y);

}

int main()

{

int(*p)(); //定义指向函数的指针变量

int a,b,m;

p=max; //指针变量p指向函数max()

puts("input two numbers:\n");

scanf("%d %d",&a,&b);

m=p(a,b); //用指针变量调用函数

printf("max=%d\n",m);

return 0;

}

注意:通过指针调用函数有两种完全等价的形式:

指变量名(实参表)

(*指针变量名)(实参表)

如上例中的”m=p(a,b);”可以写成:

m=(*p)(a,b);

2.用指向函数的指针作函数参数

例5.10 输入两个数,分别求大者、小者及和。

#includeint max(int x,int y){return (x>y?x:y);}

int min(int x,int y){return (xa(1),令k=1,小者的下标存放在k中;

② a(k)又与a(2),a(3),……,直到a(n-1),重复①的工作,结束后,实现n个数中的最小者的下标存放在k中,当前最小为a(k)。

③a(i)与a(k)交换,把最小者存放在a(i),即a(0)中。

④分别令i=1,2,3,4,….,9重复①②③的操作.

#include#include#includevoid sort(int array[],int n);

void main()

{

int a[100];

int i,n;

puts("Input number:");

scanf("%d",&n);

srand((unsigned)time(NULL));

for(i=0;iarray[j])k=j;

t=array[i];array[i]=array[k];array[k]=t;

}

}

运行程序:

Input number:

10

Before sort:

10 84 58 50 90 11 44 21 58 46

After sort:

10 11 21 44 46 50 58 58 84 90

3. 指针作函数参数

具体的形式有:

⑴形参为数组名(指针常量):实参可以是:

①数组名;

②指向数组首地址的指针变量。

⑵形参为指针变量:实参可以是:

①指针变量(指向某变量或数组)

②指向某变量的指针常量,如&a,&b等

③数组名(指针常量)

例5.14 编写一个函数,统计字符串的长度。

#includeint strlen(char *s);

void main()

{

char * p,s[]="1234567890";

p="abcdefghklomn";

printf("%d\n",strlen(p)); //实参为指针变量

printf("%d\n",strlen(s)); //实参为指针常(数组名)

}

int strlen(char * s)

{

int i;

for(i=0;*s++;i++);

return i;

}

运行程序输出:

13

10

4. 二维数组在函数参数中的应用

二维数组名做函数参数时,形参的语法形式是:

类型说明符 形参名[ ][常量表达式M]

形参数组可以省略第一维的长度。

例如:int array[ ][10]

◇形参数组中第二维的长度是不能省略的。

◇实参数组必须也是一个二维数组,而且它的第二维的长度与形参数组的第二维的长度必须相等。

◇若形参为一维数组名,实参也可以是二维数组名、二维数组的第一个元素或任何表示二维数组的首地址的实参形式,也可以是二维数组中某行的首地址。

例:

#include#include#includevoid tran(int n,int x[]);

void main()

{

int a[5][5];

int i,j;

srand((unsigned)time(NULL));

for(i=0;i<5;i++)

for(j=0;j<5;j++)

a[i][j]=rand()%100; //用随机数向元素赋值

for(i=0;i<5;i++)

{

for(j=0;j<5;j++)

printf("%-3d",a[i][j]);

putchar(\n);

}

putchar(\n);

tran(3,(int *)a); //二维数组名作实参

tran(3,a[0]); //二维数组的首行名(一维数组名)作实参

tran(3,(int *)&a[0]);//&a[0]与a[0]等价,类型为int (*)[5]

tran(0,a[3]); //二维数组a的第4行名为作实参

tran(0,&a[3][0]);//数组a第4行首元素的地址为实参

}

void tran(int n,int x[])//参数n指定从x[]开始越过的行数

{

int i;

for(i=0;i<5;i++)

printf("%d ",x[n*5+i]);

putchar(\n);

}

运行程序输出:

70 70 1 68 57

65 35 64 88 96

34 64 13 38 62

14 29 23 1 40

97 54 99 62 57

14 29 23 1 40

14 29 23 1 40

14 29 23 1 40

14 29 23 1 40

14 29 23 1 40

5.5 函数的嵌套调用与函数的递归调用

5.5.1 函数的嵌套调用

在函数体中再调用其它函数称为函数的嵌套调用。

例:分析程序的执行过程。

#includevoid func7();

void func8();

void func9();

main( )

{

puts("I am in main\n");

func7();

puts("I am finally back in main\n");

return 0;

}

void func7()

{

puts("I am in the first function\n");

func8();

puts("I am in back in the first function\n");

}

void func8()

{

puts("Now I am in the section function\n");

func9( );

puts("Now I am back in the section function\n");

}

void func9()

{

puts("Now I am in the third function\n");

}

程序的运行结果如下:

I am finally back in main

I am in the first function

Now I am in the section function

Now I am in the third function

Now I am back in the section function

I am in back in the first function

I am finally back in main

例5.16: 用牛顿迭代法求一个正数的平方根。

方法:求x的平方根

⑴设置猜测初值guess=1.0

⑵如果:|guess-x|float squ_root(float x);

float abs_value(float x);

void main()

{

float x,s;

do

{

printf("Enter a float number:");

scanf("%f",&x);

}while(x<=0);

s=squ_root(x);

printf("x=%f,s=%f\n",x,s);

}

float squ_root(float x)

{

double guess=1.0,e=1e-5;

while(abs_value(guess*guess-x)>e)

guess=(x/guess+guess)/2.0;

return guess;

}

float abs_value(float x)

{

if(x<0)x=-x;

return x;

}

5.5.2 函数的递归调用

1. 递归的基本概念

递归是在连续执行某一处理过程时,该过程中的某一步要用到它自身的上一步(或上几步)的结果。在一个程序中,若存在函数自己调用自己的现象就是构成了递归。

◇如果函数funA在执行过程又调用函数funA自己,则称函数funA为直接递归。

◇如果函数funA在执行过程中先调用函数funB,函数funB在执行过程中又调用函数funA,则称函数funA为间接递归。程序设计中常用的是直接递归。

在数学中递归定义的数学函数是非常常见的。例如,当n为自然数时:

0!=1

n!=n * (n-1)! (当 n>0)

从数学角度来说,如果要计算出f(n)的值。就必须先算出f(n-1),而要求f(n-1)就必须先求出f(n-2)。这样递归下去直到计算f(0)时为止。由于已知f(0),就可以向回推,计算出f(n)。

包含递归调用的函数称为递归函数

2. 递归程序的执行过程

我们首先从一个简单的递归程序开始分析递归程序的执行过程。

例5.17:用递归函数求n!。

#includeint facto(int);

main()

{

int n, p;

puts("N=?");

scanf("%d",&n);

p=facto(n);

printf("%d!=%d\n",n,p);

return 0;

}

int facto(int n)

{

int r;

if(n==0)

r=1;

else

r=n*facto(n-1);

return (r);

}

在返回过程中不断地执行递归调用没有执行的语句:

r=n*facto(n-1);

//执行该语句的r=n*返回值return (r);

注:facto函数可以简化为:

int facto(int n)

{

return n==0?1:n*facto(n-1);

}

例:采用递归方法计算x的n次方。

分析:

这正是求x的n次方的递归算法公式。

#includeint power(int,int);

main()

{

int x, n;

printf("x=? n=? ");

scanf("%d %d",&x,&n);

printf("%d ** %d =%d\n",x,n,power(x,n));

return 0;

}

int power(int x,int n)

{

return(n==0?1:(x*power(x, n-1)));

}

在power函数中,( n==0?)是递归的结束条件。

3. 数值型递归问题的求解方法

一要找出正确的递归算法;

二要确定算法的递归结束条件;

对于数值问题编写递归程序的一般方法是:

建立递归数学模型,确立递归终止条件,将递归数学模型转换为递归程序。

例:请用递归的方法计算下列函数的值:

px(x,n) = x - x2 + x3 - x4 + ...... (-1)n-1xn (n>0)

这是一个数值型问题。函数的定义不是递归定义形式。对原来的定义进行数学变换:

px(x,n) = x - x2 + x3 - x4 + ...... (-1)n-1xn

= x * ( 1 - x + x2 - x3 + x4 - ...... (-1)n-1xn-1 )

= x * ( 1 - ( x - x2 + x3 - ...... (-1)n-2xn-1 ) )

= x * ( 1 - px(x,n-1))

经变换后,可以将原来的非递归定义形式转化为等价的递归定义:

px(x,1)=x

px(x,n)=x*(1-px(x,n-1) ) 当 n>1 时

由此递归定义,可以确定递归算法和递归结束条件。递归程序如下:

#includedouble px( double x, int n)

{

if(n==1) return ( x ); //当n=1时,结束递归

else return(x*(1-px(x,n-1)));//否则递归调用

}

main()

{

double x; int n;

printf("Enter X and n:");

scanf("%lf %d",&x,&n);

printf("px=%f\n",px(x,n)); //调用函数px

return 0;

}

4. 非数值型递归问题的求解方法

对于非数值问题编写递归程序的一般方法是:

① 确定问题的最小模型并使用非递归算法解决

② 分解原来的非数值问题建立递归模型

③ 确定递归模型的终止条件

④ 将递归模型转换为递归程序。

可以按照下列步骤进行分析:

(1)从化简问题开始。将问题进行简化,将问题的规模缩到最小,分析问题在最简单情况下的求解方法。此时找到的求解方法应当十分简单。

(2)对于一个一般的问题,可将这个大问题分解为两个(或若干个)小问题,使原来的大问题变成这两个(或若干个)小问题的组合,其中至少有一个小问题与原来的问题有相同的性质,只是在问题的规模上与原来的问题相比较有所缩小。

(3)将分解后的每个小问题作为一个整体,描述用这些较小的问题来解决原来大问题的算法。

由第3步得到的算法就是一个解决原来问题的递归算法。由第1步将问题的规模缩到最小时的条件就是该递归算法的递归结束条件。

例:输入一个正整数,要求以相反的顺序输出该数各位。用递归方法实现。

第1步,先将问题进行简化。假设要输出的正整数只有一位,则该问题就简化为"反向"输出一位正整数。对一位整数实际上无所谓"正"与"反",问题简化为输出一位整数。这样简化后的问题可以很容易实现。

第2步,对于一个大于10的正整数,在逻辑上可以将它分为两部分:个位上数字和个位以前的全部数字。

第3步,将个位以前的全部数字看成一个整体,则为了反向输出这个大于10的正整数,可以按如下步骤进行操作:

①输出个位上的数字

②反向输出个位以前的全部数字

这就是将原来的问题分解后,用较小的问题来解决原来大问题的算法。其中操作②中的问题"反向输出个位以前的全部数字"只是对原问题在规模上进行了缩小。这样描述的操作步骤就是一个递归的操作步骤。

整理上述分析结果,把第1步中化简问题的条件作为递归结束条件,将第3步分析得到的算法作为递归算法,可以写出如下完整的递归算法描述。

①若要输出的整数为一位,则输出该整数,否则输出整数的个位数字;

②反向输出除个位以外的全部数字;

③结束;

按照这样的算法可以编出如下程序:

#includevoid printn(int n);

void main()

{

int num;

puts("Enter number:");

scanf("%d",&num);

printn(num);

putchar(\n);

}

void printn(int n) //反向输出整数n的函数

{

if(0<=n && n<=9) //若n为一位整数

printf("%d\n",n); // 则输出整数n

else //否则

{

printf("%d",n%10);//输出n的个位数字

printn(n/10); //递归操作反向输出除个位以外的全部数字

}

}

5.6 带命令行参数的主函数

main函数可以带参数,格式如下:

main(int argc,char *argv[])

argc:是整型变量,说明命令行中参数的个数(包括命令本身),

argc的最小值为1。

argv[]: 是字符指针数组,给出程序从程序头缓冲区读取命令行

参数(字符串)的地址。其中

argv[0]是第一个参数,即命令字符串的首地址

argv[1]是第二个参数的首地址

……在程序中,通过argv[i]来读取各命令行参数。

带命令行参数的程序只能在命令提示符下,通过输入命令及参数来执行,其格式为:

命令名(程序文件名) 参数1 参数2 ……

例:在屏幕上输出命令行输入的各个参数。

#includeint main(int argc,char * argv[])

{

int i;

for(i=0;ivoid func11()

{

int x=3;

{

int x=2; //第一个复合语句中的局部变量

{

int x=1; //第二个复合语句中的局部变量

printf("*x=%d\n",x);

}

printf("**x=%d\n",x);

}

printf("***x=%d\n",x);

}

void main()

{

int x=10;

printf("1: x=%d\n",x);

func11();

printf("2:x=%d\n",x);

}

程序的运行结果是:

1: x=10 //输出主函数内的变量 x

*x=1 //输出第一个复合语句中的变量x

**x=2 //输出第二个复合语句中的变量x

***x=3 //输出函数func11中的变量x

2: x=10 //输出主函数内的变量x

5.7.2 全局变量

变量在所有函数之外定义称为全局变量(global variable),其作用范围为从定义开始,到本文件结束。

全程变量一经定义,编译系统为其分配固定的内存单元,在程序运行的自始至终都占用固定单元。

如果在定义之前使用该全局变量,用extern加以说明,则可扩展全局变量的作用域。

使用全局变量与局部变量,应注意以下几点:

①不同函数内的局部变量可以重名,互不影响。

②全局变量与局部变量可以同名,在局部变量起作用的范围内,全局变量不起作用。

③全局变量的初始化只能有一次,是在对全局变量说明的时候。

例:分析以下程序的运行结果。

#includeint x=100; //全局变量的定义

void f()

{

int x=500; //局部变量,函数内有效

x+=100;

printf("%d\n",x);

}

void ff()

{

x+=100; //使用全局变量

printf("%d\n",x);

}

void func12()

{

int x=10; //局部变量,函数内有效

f();

ff();

printf("%d\n",x);

}

main()

{

func12();

return 0;

}

程序运行结果:

600 //调用函数f( )的输出的局部变量的值

200 //调用函数ff()输出的全局变量的值

10 //函数func12( )中输出的局部变量的值

5.8 变量的存储类别

C中的变量有四个方面的属性:

存储的数据类型——用数据类型描述。

使用空间——用作用域描述。

使用时间——用存储期(生存期)描述,分为静态和动态存储期

存储方法(类型)——用存储类别描述,分为自动(auto)、静态(static)、寄存器(register)和外部(extern)四种存储类型,且自动存储(在动态存储区)和寄存器存储(在CPU内)是动态的,静态存储和外部存储(在静态存储区)是静态的。

动态存储期与静态存储期

变量从在程序执行过程中生存的时间来看,都有其生存期,也称为存储期,分为两种:

(1)静态存储期(static storage duration):变量存储在内存中的静态存储区,在编译时就分配了存储空间,在整个程序运行期间,该变量占有固定的存储单元,变量的值都始终存在,程序结束后,这部分空间才释放。这类变量的生存期为整个程序。全局变量便分配存储在静态存储区。

(2)动态存储期(dynamic storage duration):变量存储在内存中的动态存储区,在程序运行过程中,只有当变量所在函数被调用时,编译系统临时为该变量分配一段内存单元,该变量有值,函数调用结束,变量值消失,这部分空间释放。我们说这类变量的生存期仅在函数调用期间。分配在动态存储区的有:

①函数体内的形参。

②函数体中定义的自动变量。

③调用函数时,系统保护主调函数的断点、现场等数据。

5.8.1 自动变量

自动变量是是最常见的一类变量,将变量的存储属性定义为自动变量的形式是:

auto 数据类型名 变量名;

数据类型名 变量名;

一般地说,不加说明的变量都属于自动变量,因此:

auto int a; 等价于 int a;

auto float b; 等价于 float b;

auto char str[100] 等价于 char str[100];

◇自动变量的说明必须在一个函数体的内部进行,函数的形参也是自动变量。

◇自动变量实质上是一个函数内部的局部变量。

◇自动变量随函数的引用与否而存在和消失。

5.8.2 用static声明静态局部变量

静态变量是存放在内存

展开阅读全文

温馨提示:

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。

2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。

3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。

4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。

5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。

6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。

7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

bb6249c6567dd4384e6ab3556cfc22ed.gif 

人人文库网所有资源均是用户自行上传分享,仅供网友学习交流,未经上传用户书面授权,请勿作他用。

关于本文

本文标题:第五讲C语言函数.doc

链接地址:https://www.renrendoc.com/p-75880650.html


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部