C语言程序设计P6-5【应用指针进行程序设计 | 第五节】——指针与函数
知识要点:指针与函数
一、任务分析
有若干个学生的成绩(每个学生有4门课),要求在用户输入学号后,能输出学生的全部成绩,用指针函数实现。
1.定义search为指针型函数,它的形参pointer是指向包含4个元素的一维数组的指针变量;
2.主函数调用search函数,将score数组的首地址传给pointer(注意score也是指向行的指针,而不是指向列元素的指针)。m是要查找的学生学号;
3.调用search函数后,得到一个地址(指向第m个学生第0门课程),赋给p。然后将此学生的4门课的成绩打印出来。
二、必备知识与理论
1.函数指针变量的定义
在C语言中,每一个函数都对应一段程序,函数在运行时其程序必须调入内存占据一段连续的存储空间,而函数名就是该函数所占的存储空间的首地址。我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使该指针变量指向该函数。然后通过指针变量就可以找到并调用这个函数。我们把这种指向函数的指针变量称为“函数指针变量”。
函数指针变量定义的一般形式为:类型说明符 (*指针变量名)();
2.函数指针变量的赋值
与其它指针的定义一样,函数指针定义后,应给它赋一个函数的入口地址,即只能使它指向一个函数,才能使用这个指针。C语言中,函数名代表该函数的入口地址。因此,可用函数名给指向函数的指针变量赋值:
指向函数的指针变量=函数名;
3.函数指针变量的引用
函数指针主要用于函数的参数和用它来调用函数,通过函数指针来调用函数的一般格式是:
(*函数指针)(实参表)
4.返回指针值的函数
前面我们介绍过,所谓函数的类型是指函数返回值的类型。在C语言中允许一个函数的返回值是一个指针(即地址),这种返回指针值的函数称为指针型函数。
定义指针型函数的一般形式为:
类型说明符 *函数名(形参表)
{
… /*函数体*/
}
应该特别注意的是函数指针变量和指针型函数在写法和意义上的区别。如 int (*p)()和int *p()是两个完全不同的量。int (*p)()是一个变量说明,说明p是一个指向函数入口的指针变量,该函数的返回值是整型量,(*p)的两边的括号不能少。int *p()则不是变量说明而是函数说明,说明p是一个指针型函数,其返回值是一个指向整型量的指针,*p两边没有括号。作为函数说明,在括号内最好写入形式参数,这样便于与变量说明区别。对于指针型函数定义,int *p()只是函数头部分,一般还应该有函数体部分。
三、任务实施
1.有若干个学生的成绩(每个学生有4门课),要求在用户输入学号后,能输出学生的全部成绩,用指针函数实现。
算法分析:
(1)定义search为指针型函数,它的形参pointer是指向包含4个元素的一维数组的指针变量。
(2)主函数调用search函数,将score数组的首地址传给pointer(注意score也是指向行的指针,而不是指向列元素的指针)。m是要查找的学生学号。
(3)调用search函数后,得到一个地址(指向第m个学生第0门课程),赋给p。然后将此学生的4门课的成绩打印出来。
程序代码如下:
#include <stdio.h>
main()
{ float score[][4]={
{66,76,86,96},{56,89,67,88},{34,78,90,66}};
float *search(float (*pointer)[4],int n);
float *p;
int i,m;
printf("Enter the number of student:");
scanf("%d",&m);
printf("The scores of No.%d are:\n",m);
p=search(score,m);
for(i=0;i<4;i++)
printf("%6.2f",*(p+i));
}
float *search(float (*pointer)[4],int n)
{ float *pt;
pt=*(pointer+n);
return(pt); }
程序的运行结果如下:
Enter the number of student:2↙
The scores of No.2 are:
34.00 78.00 90.00 66.00
典型程序实例
有两个数组,要求将两个数组合并,且新数组中的元素按照递增排序。
假设数组a中的元素为{8,11,3,5,2,9,15,20,14,26},数组b中元素为{49,8,6,38,65,97,12,50,22,6},那么合并以后数组c中的元素为{2,3,5,6,6,8,8,9,11,12,14,15,20,22,26,38,49,50,65,97},是有序数组。
算法分析: 首先将两个数组a、b排序,各自形成递增有序的数组。具体可以采用直接插入法对数组中的元素进行排序。
直接插入排序法的思想是,把数组分成两个部分:有序部分和无序部分,每次从无序部分取出一个元素插入到有序部分中,直到数组中的所有元素有序。初始情况下有序部分仅有一个元素,其它都是无序部分的元素。然后利用循环从无序部分取出一个元素,保存到中间变量,再从有序区的高地址开始,逐个元素进行比较,如果小于有序部分的元素,把有序部分的元素后移。否则插入该元素到找到的位置。 依次比较a、b中的元素,依次存放到数组c中。
具体的过程是,设两个指针变量pa、pb,在循环中分别指向数组a和数组b中的每一个元素。然后利用下面的公式为c中的元素赋值,同时相应的指针依次后移。当循环退出的时候,假设数组a或者数组b中还有剩余元素,那么全部写到数组c中。
#include <stdio.h>
void merge(int *p_a,int *p_b,int *p_c,int n);
void sort(int b[ ],int n);
main()
{ int a[10],b[10];
int c[20];
int i,j;
printf("input 10 elem to array a:\n");
for(i=0;i<10;i++)
scanf("%d",a+i);
printf("input 10 elem to array b:\n");
for(i=0;i<10;i++)
scanf("%d",b+i); merge(a,b,c,10); /*数组名作为实参,实现数组合并*/
for(i=0;i<20;i++)
{ printf("%3d",*(c+i));
if((i+1)%4==0) printf("\n"); } /*控制每一行输出的元素个数*/
}
void sort(int b[ ],int n) /*排序函数,使用数组名作为形参*/
{ int *p,*q;
int temp;
for(p=b+1;p<b+n;p++) /*循环处理数组中的每一个元素*/
if(*p<*(p-1)) /*如果指针变量p指向的元素小于前一个元素*/
{ temp=*p; /*保存当前元素的值*/
*p=*(p-1); /*当前元素后移*/
for(q=p-2;q>=b&&*q>temp;q--)
/*从p-2所指元素开始寻找第一个小于temp的元素*/
*(q+1)=*q; /*实现后移*/
*(q+1)=temp; } /*元素插入*/
}
void merge(int *p_a,int *p_b,int *p_c,int n)
/*使用指针作为形参*/
/*函数实现数组p_a数组p_b有序合并*/
{ int *pa=p_a,*pb=p_b,*pc=p_c;
sort(pa,n); /*首先排序*/
sort(pb,n);
while(pa<p_a+n&&pb<p_b+n)
if(*pa<=*pb) /*当前*pa小则写入pc*/
{ *pc=*pa++;pc++;}
else if(*pa>*pb) /*当前*pb小则写入pc*/
{ *pc=*pb++;pc++;}
while(pa<p_a+n) /*若pa有剩余则一次写入pc*/
{ *pc=*pa++;pc++;}
while(pb<p_b+n) /*若pb有剩余则一次写入pc*/
{ *pc=*pb++;pc++;}
}