函数(详解)

一、函数的声明、实现和调用。


函数是一个完成特定功能的代码模块,其程序代码独立,通常要求有返回值,也可以是

空值。

一般形式如下:

<数据类型> <函数名称>( <形式参数说明>){

语句序列;

return[(<表达式>)];

}


<数据类型>是整个函数的返回值类型。

return[( <表达式> )]语句中表达式的值,要和函数的<数据类型>保持一致。 如无返回值应

该写为void型。

<形式参数说明>是逗号","分隔的多个变量的说明形式

大括弧对{<语句序列> } ,称为函数体; <语句序列>是大于等于零个语句构成的.


函数的说明就是指函数原型.其中, <形式参数说明>可以缺省说明的变量名称,但类型不能缺省.

例如:

double Power(doublex, int n),

double Power(double, int);

#include <stdio. h> 
void show()
{
printf("Hello everyone!\n" );
}
int main()
{
printf( start----\n );
show();
printf(”end----\n" );
return 0;
}

定义求x值的函数( x是实数,n为正整数)

#include <stdio. h> 
double power(double x, int n)
{
double r = 1;
int, 1;
for(i=1;i<=n;i++)
r*= X;
return r;
}
int main()
{
double X,ret;
int n;
printf( "input:" ") ;
scanf("%lf%d", &x,&n);
ret = power(x, n);
printf("%lf %d = %lf\n", X,n, ret);
return 0;
}
#include <stdio. h> 
double power(double x, int n);
int main()
{
double X,ret;
int n;
printf( "input:" ") ;
scanf("%lf%d", &x,&n);
ret = power(x, n);
printf("%lf %d = %lf\n", X,n, ret);
return 0;
}
double power(double x, int n)
{
double r = 1;
int, 1;
for(i=1;i<=n;i++)
r*= X;
return r;
}

函数的使用也叫函数的调用,形式如下:

函数名称( <实际参数>)

实参就是在使用函数时,调用函数传递给被调用函数的数据。需要确切的数据.

函数调用可以作为一个运算量出现在表达式中也可以单独形成一个语句。 对于无返回值的函数

来讲,只能形成一个函数调用语句。

函数可以先说明实现再调用,也可以先声明再调用再实现。

头文件中有函数的声明,不想用头文件删除只需要加上所需的头文件声明即可。


二、函数的参数传递。

函数之间的参数传递方式

①全局变量

全局变量就是在函数体外说明的变量,它们在程序中的每个函数里都是可见的。全局变量一经定义后就会在程序的任何地方可见。函数调用的位置不同,程序的执行结果可能会受到影响。不建议使用

#include <stdio. h> 
double x=2;
int n=3;
double power();
int main( )
{
//double X;
double ret;
//int n;
printf( "input:" ") ;
scanf("%lf%d", &x,&n);
ret = power(x, n);
printf("%lf %d = %lf\n", X,n, ret);
return 0;
}
double power( )
{
double r = 1;
int, 1;
for(i=1;i<=n;i++)
r*= X;
return r;
}

②复制传递方式

调用函数将实参传递给被调用函数,被调用函数将创建同类型的形参并用实参初始化。形参是新开辟的存储空间,因此,在函数中改变形参的值,不会影响到实参。

#include <studio.h>
int main()
{
double x=2;
int n=3;
double ret;
printf("&x=%p &n=%pn", &x, &n);
ret = power(x, n);
printf("%lf %d = %lf\n", x, n, ret)
return 0;
}
double power(double a, int b) //double a =x ,double b=n .
{
double r = 1;
int i;
printf("&a=%p &b=%p\n", &a, &b);
for(i=1;i<=b;i++)
r*=a;
return  r;
}

③地址传递方式

按地址传递,实参为变量的地址,而形参为同类型的指针被调用函数中对形参的操作,将直接改变实参的值(被调用函数对指针的目标操作相当于对实参本身的操作)。

void swap(int * X,int * y);
int main( )
{
int a=10;
int b=20;
printf( "before:%d %d\n", a, b);
swap(&a, &b);
printf("after:%d %d\n", a, b);
return 0 ;
}
//int *x=&a;int*y=&b;
void swap(int *x,int*y)
{
int t;
t=*x;//a
*x = *y;
*y = t;
}

练习:编写一个函数,统计字符串中小写字母的个数,并把字符串中的小写字母转化成大写字母.

#include <stdio.h>
int str_fun(char* p);
int main(int argc,char *argv[])
{
char s[] = "welcome2017Beijing";
int n;
n = str_fun(s);
printf("n=%d  %s\n",n,s);
return 0;
}
int str_fun(char * p)//char * p= S;
{
int num = 0;
while(*p !='0'){  //while (*p)
if(*p<='z'&&*p >= 'a'){
num++;
*p-='  ';
}
p++;
}
return num;
}

三、函数中传递数组参数。

①全局数组传递方式

②复制传递方式

实参为数组的指针,形参为数组名(本质是一个指针变量)

③地址传递方式

实参为数组的指针,形参为向类型的指针变量

 #include <stdio.h>
int array_ sum(int data[], int n);//int array_ sum(int *data, int n);
int main(int argc, const char *argv[ ] )
{
int a[ ]={1,2,3,4,5,6,7,8};
int sum=0;
sum=array_ sum(a, sizeof(a)/sizeof(int));
printf( "sum=%d\n",sum) ;
return 0;
}
int array_ sum(int data[], int n){//int array_ sum(int *data, int n){
int ret=0;
int i;
for(i=0;i<n;i++){
ret+=data[i];
}
return ret;
}

练习二:编写函数,删除字符串中的空格

#include <stdio.h>
#include <string.h>
void del_ space(char *s1);
int main(int argc, const char *argv[ ] )
{
char s[]="a d sd" ;
puts(s);
del_ space(s);
puts(s);
return 0;
void del_ space(char *s1)
{
char *s2;
s2=s1:
while(*s1){
if(*s1==' ')
{
s1++ ;
}else{
*s2=*s1;
s1++ ;
s2++ ;
}
}
*s2='\0';
}

四、指针函数。

指针函数是指一个函数的返回值为地址量的函数。

指针函数的定义的一般形式如下:

<数据类型> *<函数名称>(<参数说明>){

语句序列;

}

返回值可以返回:全局变量的地址/static变量的地址/字符串常量的地址/堆的地址

练习1:编写一个指针函数,删除一个字符串中的空格。

#include <stdio.h>
char *del_space(char *s);
int main( int argc, const char *argv[]){
char *r;
char str[]="la la l a";r=del_space(str);
printf(" %s\n" ,r);
puts(str);
return 0;
}
char *del_space(char *s){
char *p=s;
char *r=s;while(*s){
if(*s==' ')
S++;
else{
*p=*s;p++;s++;
}
}
*p='\0';
return r;
}

练习2:编写一个指针函数,实现字符串中的连接。

#include <stdio. h>
char *strcat(char *a,char *b);
int main(int argc,
const char *argv[])
{
char a[50]="hello";
char b[ ]="word";
puts(strcat(a,b));
return 0;
}
char *strcat(char *a,char *b){
char *c=a;
while(*a){
a++ ;
}
while(*b){
*a=*b;
a++ ;
b++ ;
*a='\0' ;
return C;
}

练习2:编写一个指针函数,实现把整数转换成字符串。

方法1、新开辟一个空间p

#include <stdio. h>
char * zhuan(int n);
int main(int argc, const char *argv[ ] )
{
char *S;
int n;
printf("请输入要转换为字符串的整数\n" );
scanf( " %d" ,&n); 
S= zhuan(n);
puts(s);
return 0,
char * zhuan(int n){
int r,i=0,j;
static char p[50];
while(n){
r=n%10 ;
n=n/10;
p[i]=r+'0' ;
i++ ;
}
p[i]='\0';
j=i-1;
i=0;
while(i<j){
r=p[i];
p[i]=p[j];
p[j]=r:
i++;
j--;
}
return p;
}

方法2、在原有空间s[ ]保存

#include <stdio.h>
char * zhuan(char *p,int n);
int main(int argc, const char *argv[])
{
char s[50].*r;
int n;
printf("请输入要转换为字符串的整数\n" );
scanf( " %d" ,&n); 
r=zhuan(s,n);
puts(r );
puts(s);
return 0;
}
char * zhuan(char *p,int n){
int r ,i=0,j;
while(n){
r=n%10;
n=n/10;
p[i]=r+'0';
i++;
p[i]='\0';
j=i-1;
i=0;
while(i<j){
r=p[i];
p[i]=p[j];
p[j]=r;
i++;
j--;
}
return p;
}

五、递归函数和函数指针。

1、递归函数

递归函数是指一 个函数的函数体中直接或间接调用了该函数自身。

递归函数调用的执行过程分为两个阶段:

①递推阶段:从原问题出发(按递归公式递推从未知到已知,最终达到递归终止条件。

②回归阶段:按递归终止条件求出结果,逆向逐步代入递归公式,回归到原问题求解。

练习一:求n!

#include <stdio. h>
int fac(int n);
int main(int argc, char *argv[])
int n;
printf(" input:" );
scanf("%d",&n);
printf("%d\n", fac(n));
return 0;
}
int fac(int n)
{
if(n==0||n==1)
return 1;
return n * fac(n-1);
}

练习二:斐波那契数列

#include <stdio. h>
int main(int argc, char *argv[])
{
int n=1;
while (n<=10) {
printf("%d",fib(n));
n++:
}
printf("\n" );
return 0
}

int fib(int n)
{
if(n==1||n==2)
return 1 ;
return fib(n-1)+fib(n-2);
}

2、函数指针

函数指针用来存放函数的地址,这个地址是一个函数的入口地址。

函数名代表了函数的入口地址;

函数指针变量说明的一般形式如下:

<数据类型> (*<函数指针名称>)( <参数说明列表>) ;

<数据类型>是函数指针所指向的函数的返回值类型。

<参数说明列表>应该与函数指针所指向的数的形参说明保持一致。

(*<函数指针名称>)中,*说明为指针( )不可缺省, 表明为函数的指针。

#include <stdio.h>

int add(int a, int b) {
        return a+b;
}
int sub(int a, int b) {
        return a-b;
}
int mul(int a, int b) {
        return a*b;
}

int main(int argc, char *argv[])
{
        int m = 10, n = 20;
        
        int  (* p)(int, int);    //函数指针的声明

        p = add;                  //函数指针的赋值

        //printf("%d\n", add(m, n));
        printf("%d\n", (*p)(m, n));   //函数指针的调用

        p = sub;
        printf("%d\n", (*p)(m, n));

        return 0;
}

函数指针数组

函数指针数组是一个保存若干个函数名的数组

一般形式如下:

<数据类型> (*<函数指针数组名称>[<大小>])(<参数说明列表>);

•其中,<大小>是指函数指针数组元数的个数

•其它同普通的函数指针

#include <stdio.h>

int add(int a, int b) {
        return a+b;
}
int sub(int a, int b) {
        return a-b;
}
int mul(int a, int b) {
        return a*b;
}

int main(int argc, char *argv[])
{
        int m = 10, n = 20;
        
        int  (* p[2])(int, int);//int * p[3]

        p[0] = add;

        //printf("%d\n", add(m, n));
        printf("%d\n", (*p[0])(m, n));

        p[1] = sub;
        printf("%d\n", (*p[1])(m, n));

        return 0;
}

qsort函数的使用

#include <stdio.h>
#include <stdlib.h>

int compare(const void *, const void *);

int main(int argc, char *argv[])
{
        int s[] = {89, 23, 10, 8, 7, 61}, n, i;

        n = sizeof(s)/sizeof(int);

        qsort(s, n, sizeof(int), compare);

        for (i = 0; i < n; i++)
                printf("%d ", s[i]);
        puts("");

        return 0;
}

int compare(const void * p, const void * q) 
{
        return (*(int *)p - *(int *)q);

}

猜你喜欢

转载自blog.csdn.net/qq_52049228/article/details/129680510