C语言知识点整理3.docx
《C语言知识点整理3.docx》由会员分享,可在线阅读,更多相关《C语言知识点整理3.docx(29页珍藏版)》请在冰豆网上搜索。
C语言知识点整理3
C源程序是由函数组成的。
虽然在前面各章的程序中经常只有一个主函数main(),但实用程序往往由多个函数组成。
函数是C源程序的基本模块,通过对函数模块的调用实现特定的功能。
函数调用的简单例子
main()
{printstar();
print_message();
printstar();
}
printstar()
{printf(“*************************”);}
print_message()
{printf(“Howdoyoudo!
”);}
函数的分类
从函数定义的角度看,函数可分为库函数和用户定义函数两种。
1.库函数:
由C系统提供,用户无须定义,只需在程序前包含有该函数原型的头文件即可在程序中直接调用。
如:
printf,scanf,getchar,putchar,gets,puts
2.用户定义函数。
有返回值函数和无返回值函数
1.有返回值函数
此类函数被调用执行完后将向调用者返回一个执行结果,称为函数返回值。
如数学函数即属于此类函数(如:
fabs())。
2.无返回值函数
此类函数用于完成某项特定的处理任务,执行完成后不向调用函数返回函数值。
(如:
printstar())
无参函数和有参函数
1.无参函数
函数定义、函数说明及函数调用中均不带参数。
此类函数通常用来完成一组指定的功能,可以返回或不返回函数值。
(如:
printstrar())
2.有参函数
在函数定义及函数说明时都有参数,称为形式参数及函数调用时都给出参数,称为实际参数(简称为实参)如:
(max(inta,intb))
无参函数定义的一般形式:
类型说明符函数名()
{声明部份
语句
}
一般无参函数没有返回值,此时函数类型符可以写为void,也可不写。
无参函数调用的一般形式:
函数名();
有参函数定义的一般形式:
类型说明符函数名(形式参数表列)
{声明部份
语句
}
有参函数比无参函数多了形式参数表列,在形参表列中给出的参数称为形式参数,它们可以是各种类型的变量,各参数之间用逗号间隔
有参函数调用的一般形式:
函数名(实参表列)
函数的参数(形参和实参)
形参出现在函数定义中,在整个函数体内都可以使用。
实参出现在函数的调用中,即调用时写在函数括号中的参数。
调用时将实参数据传递给对应的形参。
形参只有在函数内部有效。
●实参可以是常量、变量、表达式、函数等
●必须具有确定的值,以便把这些值传送给形参。
●实参和形参在数量上,类型上,顺序上应严格一致
●函数调用中发生的数据传送是单向的。
即只能把实参的值传送给形参,而不能把形参的值反向地传送给实参。
形参的值发生改变,而实参中的值不会变化
#include
main()
{intx=7,y=11;
printf("x=%d,y=%d\n",x,y);
printf("swapped:
\n");
swap(x,y);
printf("x=%d,y=%d\n",x,y);
}
swap(inta,intb)
{inttemp;
temp=a;a=b;b=temp;
printf(“a=%d,b=%d”,a,b);
}
函数的值是指函数被调用之后,执行函数体中的程序段所取得的,并返回给主调函数的值。
C语言函数的值只能通过return语句返回函数的值。
return语句使用的一般形式:
return表达式;
或者为:
return(表达式);
该语句的功能是计算表达式的值,并返回给主调函数。
在函数中允许有多个return语句,但每次调用只能有一个return语句被执行,因此只能返回一个函数值。
函数返回值的类型和函数定义中函数的类型应保持一致。
如果两者不一致,则以函数类型为准,自动进行类型转换。
如函数值为整型,在函数定义时可以省去类型说明。
不返回函数值的函数,可以明确定义为“空类型”(void)。
如:
voids(intn)
{……
}
注意:
一旦函数被定义为空类型后,就不能在主调函数中使用被调函数的函数值了
例:
sum=s(n);
定义一个函数求:
1+2+……+n,并编写主函数调用它。
floatsum(intn)
{inti;
floats=0;
for(i=1;i<=n;i++)
s=s+i;
returns;
}
main()
{intnum;
floatresult;
scanf("%d",&num);
result=sum(num);
printf("Theresultis:
%f",result);
getch();
}
对用户自定义函数,如果被调函数的定义在主调函数之后,且在同个文件中,须先声明
声明的作用是把函数的名字、函数类型以及形参的类型、个数和顺序通知编译系统,声明一般放在调用函数的变量定义之前。
对被调函数声明的二种格式:
类型说明符被调函数名(类型形参1,类型形参2…);
类型说明符被调函数名(类型,类型…);
例:
intmax(inta,intb);
intmax(int,int);
main()
{floatadd(float,float);/*函数声明*/
floata,b,c;
scanf("%f,%f",&a,&b);
c=add(a,b);
printf("sumis%f",c);
}
floatadd(floatx,floaty)
{floatz;
z=x+y;
return(z);
}
如果被调函数的返回值是整型时,可以不对被调函数作声明,而直接调用,但不提倡。
当被调函数的函数定义出现在主调函数之前时,在主调函数中也可以不对被调函数再作说明而直接调用。
如在所有函数定义之前,在函数外预先说明了各个函数的类型,则在以后的各主调函数中,可不再对被调函数作声明。
语言允许在一个函数的定义中出现对另一个函数的调用。
这样就出现了函数的嵌套调用。
即在被调函数中又调用其它函数。
其关系可表示如下图。
函数的递归调用一个函数直接或间接调用该函数本身称为递归调用。
这种函数称为递归函数。
执行递归函数将反复调用其自身。
用递归法
算法:
n!
=1(n=0,1)
n!
=n×(n-1)!
(n>1)
floatfun(intnum)
{floatf;
if(num<0)
printf("Inputerror!
\n");
elseif(num==0||num==1)
f=1;
else
f=num*fun(num-1);
return(f);
}
main()
{floatresult;
intnum;
scanf("%d",&num);
result=fun(num);
printf("Theresultis:
%f",result);
getch();
}
用递归法计算1+2+…+n
算法:
y=0(n=0)
y=n+(1+2+…+n-1)(n>1)
floatf(intnum)
{floaty;
if(num<0)
printf("Inputerror!
");
elseif(num==0)
y=0;
else
y=num+f(num-1);
returny;
}
main()
{floatresult;
intnum;
printf("Inputnumber:
");
scanf("%d",&num);
result=f(num);
printf("Theresultis:
%f",result);
getch();
}
构成递归的条件
归结束条件及结束时的值;(如f=1)
能用递归形式表示,并且递归向终止条件发展。
(如:
f=fun(n-1)*n;)
两个数组大小比较
a和b为有10个元素的整型数组比较两数组对应元素变量n,m,k记录a[i]>b[i],a[i]==b[i],
a[i]k,认为数组a>b若n#include
main()
{inta[10],b[10],i,n=0,m=0,k=0;
printf("Enterarraya:
\n");
for(i=0;i<10;i++)
scanf("%d",&a[i]);
printf("Enterarrayb:
\n");
for(i=0;i<10;i++)
scanf("%d",&b[i]);
for(i=0;i<10;i++)
{if(large(a[i],b[i])==1)n=n+1;
elseif(large(a[i],b[i])==0)
m=m+1;
elsek=k+1;
}
/*Output*/
}
intlarge(intx,inty)
{intflag;
if(x>y)flag=1;
elseif(xelseflag=0;
return(flag);
}
数组a中存放了10个学生的成绩,求平均成绩。
floata数组名作为函数参数_形式一
ver(floata[10])
{inti;
floatav,s=a[0];
for(i=1;i<10;i++)
s=s+a[i];
av=s/10;
returnav;
}
voidmain()
{floatsco[10],av;
inti;
printf("\ninput10scores:
\n");
for(i=0;i<10;i++)
scanf("%f",&sco[i]);
av=aver(sco);
printf("averageis:
%5.2f",av);
数组名作为函数参数_形式二
floataver(floata[],intn)
{inti;
floatav,s=a[0];
for(i=1;is=s+a[i];
av=s/n;
returnav;
}
main()
{floatsco[10],av;
inti;
printf("\ninput10scores:
\n");
for(i=0;i<10;i++)
scanf("%f",&sco[i]);
av=aver(sco,10);
printf("averageis:
%5.2f",av);
getch();
}
数组元素作为函数参数是值传递
#include
voidswap2(intx,inty)
{intz;
z=x;x=y;y=z;
}
main()
{inta[2]={1,2};
swap2(a[0],a[1]);
printf("a[0]=%d\na[1]=%d\n",a[0],a[1]);
}
数组名作函数参数是地址传递
#include
voidswap2(intx[])
{intz;
z=x[0];x[0]=x[1];x[1]=z;
}
main()
{inta[2]={1,2};
swap2(a);
printf("a[0]=%d\na[1]=%d\n",a[0],a[1]);
}
有一个3X4的矩阵,求其中的最大值
max_value(intarray[3][4])
{inti,j,k,max;
max=array[0][0];
for(i=0;i<3;i++)
for(j=0;j<4;j++)
if(array[i][j]>max)max=array[i][j];
return(max);
}
main()
{inta[3][4]={1,3,5,7,2,4,6,8,15,17,34,12};
printf("Themaxvalueis:
%d",max_value(a));
getch();
}
变量的作用域
概念:
变量的有效性范围称变量的作用域。
C语言中所有的量都有自己的作用域。
C语言中的变量,按作用域范围可分为两种,即局部变量和全局变量。
局部变量也称为内部变量。
局部变量是在函数内作定义说明的。
其作用域仅限于函数内,离开该函数后再使用这种变量是非法的。
intf1(inta)/*函数f1*/
{intb,c;
……
}a,b,c作用域
intf2(intx)/*函数f2*/
{inty,z;
}x,y,z作用域
main()
{intm,n;
}m,n作用域
局部变量作用域的几点说明:
一个函数不能使用其他函数的局部变量
形参变量是属于被调函数的局部变量,实参变量是属于主调函数的局部变量。
允许在不同的函数中使用相同的变量名,它们代表不同的对象,分配不同的单元,互不干扰,也不会发生混淆。
在复合语句中也可定义变量,其作用域只在复合语句范围内。
inta[10];
voidmain()
{floatf;
scanf("%f",&f);
{intk;
k=f*2;
printf("%d",k);
}
}
voidmain()
{inta;
{intk;
scanf("%d",&k);
}
a=k;/*出错*/
printf("%d",a);
}
}
全局变量
在函数外部定义的变量称为全局变量。
全局变量可为本文件中的其他函数所共用,作用域为从定义变量的位置到本源文件结束。
inta,b;/*全局变量*/
voidf1()/*函数f1*/
{……
}
floatx,y;/*全局变量*/
main()/*主函数*/
{……
}
inta=10;
voidmain()
{inta=100;
printf("locala=%d\n"”,a);
}
输出locala=100
用递归方法求n阶勒让德多项式的值,递归公式为:
1(n=0)
Pn(x)=x(n=1)
((2n-1)*x-pn-1(x)-(n-1)*Pn-2(x))/n(n>=1)
intp(intn,intx)
{ints;
if(n<0)
printf("InputError!
\n");
elseif(n==0)
s=1;
elseif(n==1)
s=x;
elseif(n>=1)
{
s=((2*n-1)*x-p(n-1,x)-(n-1)*p(n-2,x))/n;
}
returns;
}
main()
{intn,x;
printf("inputn,x:
\n");
scanf("%d,%d",&n,&x);
printf("result:
%d",p(n,x));
getch();
}
charfun(charx,chary)
{
if(xreturny;
}
main()
{inta='9',b='8',c='7';
printf("%c\n",fun(fun(a,b),fun(b,c)));
}
执行结果:
7
voidf(intv,intw)
{intt;
t=v;v=w;w=t;
}
main()
{intx=1,y=3,z=2;
if(x>y)f(x,y);
elseif(y>z)f(y,z);
elsef(x,z);
printf("%d,%d,%d",x,y,z);
}
执行结果:
1,3,2
intf1(inta)
{returna%2;
}
main()
{ints[8]={1,3,5,2,4,6},i,d=0;
for(i=0;f1(s[i]);i++)d+=s[i];
printf("%d\n",d);
}
执行结果:
9
longfun(intn)
{longs;
if(n==1||n==2)s=2;
elses=n-fun(n-1);
returns;
}
main()
{printf("%ld\n",fun(3));
}
执行结果:
1
写一个判断素数的函数,在主函数输入一个整数,输出是否素数的信息.
main()
{intn;
scanf("%d",&n);
if(su(n)==1)
printf("Yes!
");
else
printf("No!
");
getch();
}
intsu(intm)
{inti;
for(i=2;i<=m-1;i++)
if(m%i==0)
return0;
if(i>m-1)
return1;
}
输入一位三位数求出各个数字的和
main()
{inta;
printf("Pleaseinput:
\n");
scanf("%d",&a);
printf("sum=%d",sum(a));
getch();
}
intsum(intb)
{ints,e,f,g;
e=b/100;
f=(b-e*100)/10;
g=b-e*100-f*10;
s=e+f+g;
return(s);
}
一个素数,当它的数字对换以后仍为素数,这样的数称为绝对素数,编写一个程序求出所有的两位绝对素数
intsu(intn);
intjdsu(intn);
main()
{inti;
for(i=10;i<=99;i++)
if(jdsu(i))
printf("%d",i);
getch();
}
intsu(intn)
{inti;
for(i=2;i<=n-1;i++)
if(n%i==0)
return0;
if(i>n-1)
return1;
}
intjdsu(intn)
{inti,j,m;
i=n/10;
j=n%10;
m=10*j+i;
if(su(n)==1&&su(m)==1)
return1;
else
return0;
}
用递归法将一个整数n转换成字符串.例如输入483,应输出“483”
#include
voidconvert(intn)
{inti;
if((i=n/10)!
=0)
convert(i);
putchar(n%10+'0');
}
main()
{intnum;
scanf("%d",&num);
if(num<0)
{
putchar('-');
num=-num;
}
convert(num);
getch();
}
在前面各章中,已多次使用过以“#”号开头的预处理命令。
如包含命令#include,宏定义命令#define等。
在源程序中这些命令都放在函数之外,而且一般都放在源文件的前面,它们称为预处理部分。
C语言提供了多种预处理功能,如宏定义、文件包含、条件编译等。
9.1无参宏定义
一般形式为:
#define标识符字符串
例:
#definePI3.1415926
被定义为“宏”的标识符称为“宏名”。
在编译预处理时,对程序中所有出现的“宏名”,都用宏定义中的字符串去代换,这称为“宏展开”。
说明
其中的“#”表示这是一条预处理命令。
凡是以“#”开头的均为预处理命令。
“define”为宏定义命令。
“标识符”为所定义的宏名。
“字符串”可以是常数、表达式、格式串等。
例如:
#defineM(y*y+3*y)
#defineM(y*y+3*y)
main()
{ints,y;
printf("inputanumber:
");
scanf("%d",&y);
s=5*M;
printf("s=%d\n",s);
}
输入1,其执行结果是20
几点说明
字符串中可以含任何字符,可以是常数,也可以是表达式,预处理程序对它不作任何检查。
如有错误,只能在编译已被宏展开后的源程序时发现。
宏定义不是说明或语句,在行末不必加分号,如加上分号则连分号也一起置换。
宏定义必须写在函数之外,其作用域为宏定义命令起到源程序结束。
#defineMy*y+3*y
main()
{ints,y;
printf("inputanumber:
");
scanf("%d",&y);
s=5*M;
printf("s=%d\n",s);
}
输入1,其执行结果是8
结束宏定义语句
如要终止其作用域可使用#undef命令
例如:
#definePI3.14159
main()
{
……
}
#undefPI/*终止PI的作用域*/
f1()
.…
表示PI只在main函数中有效,在f1中无效。
几点说明
●宏名在源程序中若用引号括起来,则预处理程序不对其作宏代换。
#defineOK100
main()
{printf("OK\n");
}
●习惯上宏名用大写字母表示,以便于与变量区别。
●宏定义允许嵌套,在宏定义的字符串中可以使用已经定义的宏名。
在宏展开时由预处理程序层层代换。
例如:
#definePI3.1415926
#defineSPI*y*y
printf("S=%f",S);
在宏代换后变为?
printf("S=%f",3.1415926*y*y);
带参数的宏定义
格式:
#define宏名(参数表)字符串
例:
#defineS(a,b)a*b
area=S(3,2);
则宏展开后为:
area=3*2;
#definePI3
#defineS(r)PI*r*r
main()
{floata,area;
a=3.0;
area=S(a);
printf("a=%f,area=%f",a,area);
}
程序执行结果:
a=3,area=27
#definePI3
#defineS(r)PI*r*r
main()
{
floata,area;
a=3.0;
area=S(a+1);
printf("a=%f,area=%f",a,area);
}
程序