第2章 指针
2.1 指针变量
指针是C语言中一个十分重要的概念,要学好C语言就要掌握好指针的使用。正确灵活地运用指针可以有效地表示复杂的数据结构、方便地进行数据存储、更有效地使用数组并能直接进行内存地址的处理操作等。本节通过几个实例介绍指针变量的基础知识,使读者能够初步了解指针。
实例051 使用指针实现数据交换
本实例是一个提高基础技能的程序
实例位置:光盘\mingrisoft\02\051
实例说明
本实例实现使用指针变量实现交换两个变量(a和b)的值。运行后,输入两个整型数值,将变量a,b中的值交换,然后输出到窗体上。程序运行效果如图2.1所示。
图2.1 实现数据交换
技术要点
本实例利用指针变量实现数据的交换。变量的指针就是变量的地址,存放地址的变量就是指针变量,用来指向另一个变量。在程序中使用一个“*”表示“指向”,定义指针变量的一般形式为:
基类型 *指针变量名
例如下面定义指针变量的语句都是正确的:
int *p; char *s; float *lp;
因为指针变量是指向一个变量的地址,所以将一个变量的地址值赋给这个指针变量后,这个指针变量就“指向”了该变量。例如,将变量i的地址存放到指针变量p中,p就指向i。其关系如图2.2所示。
图2.2 p、*p和i的关系
指针变量前面的“*”必不可少,表示该变量的类型为指针型变量。指针变量的名称为p。
注意:定义指针变量时必须指定基类型。因为要根据指定的类型决定分配的空间。例如,定义指针类型为整型,当指针移动一个位置时,其地址值加2;如果指针指向一个实型变量,则增加值为4。
本程序创建了一个自定义函数swap,用于实现交换两个变量的值。swap函数包括两个指针型的形参p1、p2。在主函数中定义了两个指针型的实参pointer1和pointer2。在函数调用时,将实参变量的值传递给形参变量。交换完成后,P1和pointer1都指向变量a,p2和pointer2都指向b。在主函数中输出的变量a和变量b得值是已经交换过的值。
实现过程
(1)在TC中创建一个C文件。
(2)创建自定义函数swap(),用来实现数据的交换。实现代码如下:
swap(int *p1, int *p2) { int temp; /*声明整型变量*/ /*交换两个指针指向的值*/ temp= *p1; *p1= *p2; *p2 = temp; }
(3)创建main()函数作为程序的入口程序,并在该函数中调用swap()函数,实现对输入数据的交换。程序代码如下:
main() { int a, b; int*pointer1, *pointer2; /*声明两个指针变量*/ scanf("%d,%d",&a,&b); /*输入两个数*/ pointer1 = &a; pointer2 = &b; swap(pointer1, pointer2); printf("\nThe result is:%d,%d\n",a,b);/*输出交换后的结果*/ getch(); }
举一反三
根据本实例,读者可以:
按照由小到大的顺序输出变量值。
使用指针比较两个数大小。
实例052 使用指针实现整数排序
这是一个可以启发思维的实例
实例位置:光盘\mingrisoft\02\052
实例说明
本实例实现输入3个整数,将这3个整数按照由大到小的顺序输出,显示在屏幕上。程序运行结果如图2.3所示。
图2.3 整数排序
技术要点
本程序用到了函数的嵌套调用,自定义函数swap与上个实例中的功能相同,用来实现两个数的互换;自定义函数exchange用来完成3个数的位置交换,它的内部嵌套使用了swap自定义函数。这两个函数的参数都是指针变量,实现了传址的功能,即改变形参的同时,实参也被改变。
实现过程
(1)在TC中创建一个C文件。
(2)创建自定义函数swap(),用来实现数据的交换。实现代码如下:
swap(int*p1,int*p2) /*交换两个数据*/ { int temp; /*声明整型变量,用于存储数据*/ /*实现数据交换*/ temp= *p1; *p1= *p2; *p2 = temp; }
(3)创建exchange()自定义函数,用于实现比较数值大小,并调用swap()自定义函数,交换数据的位置。实现代码如下:
exchange(int*pt1,int*pt2,int*pt3) /*比较数值大小并进行交换*/ { /*从大到小顺序排列*/ if(*pt1< *pt2) swap(pt1, pt2); if(*pt1< *pt3) swap(pt1, pt3); if(*pt2< *pt3) swap(pt2, pt3); }
(4)创建main()函数作为程序的入口程序,并在该函数中调用exchange()函数,实现对输入的3个数据比较大小并交换位置。程序代码如下:
main() { int a,b,c, *q1, *q2, *q3; /*声明变量*/ puts("Please input three key numbers you want to rank:"); scanf("%d,%d,%d",&a,&b,&c); /*输入3个数*/ q1 = &a; q2 = &b; q3 = &c; exchange(q1,q2,q3); /*比较大小交换位置*/ printf("\n%d,%d,%d\n",a,b,c); /*输出交换后的值*/ puts("\n Press any key to quit..."); getch(); }
举一反三
根据本实例,读者可以:
使用指针查找指定元素。
使用指针实现获取数列最大值。
实例053 指向结构体变量的指针
本实例是一个提高基础技能的程序
实例位置:光盘\mingrisoft\02\053
实例说明
本实例通过结构体指针变量实现在窗体上显示学生信息。运行程序后,将学生信息输出在窗体上。程序运行效果如图2.4所示。
图2.4 显示学生信息
技术要点
一个结构体变量的指针就是该变量所占据的内存段的起始地址。用一个指针变量指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件。代码如下:
#include "stdio.h"
(3)声明struct student类型:
struct student { int num; /*学生学号*/ char name[20]; /*学生姓名*/ char sex; /*学生性别*/ int age; /*学生年龄*/ float score; /*学生成绩*/ };
(4)创建main()函数作为程序的入口程序,在main()函数中定义struct student类型的变量。定义一个指针变量指向struct student类型的数据。实现代码如下:
void main() { struct student student1={1001,"liming",'M',20,92.5};/*定义结构体变量*/ struct student*p; /*定义指针变量指向结构体类型*/ p=&student1; /*使指针指向结构体变量*/ printf("Number:%d\n",p->num); /*输出学生学号*/ printf("Name:%s\n",p->name); /*输出学生姓名*/ printf("Sex:%c\n",p->sex); /*输出学生性别*/ printf("Age:%d\n",p->age); /*输出学生年龄*/ printf("Score:%f\n",p->score); /*输出学生成绩*/ getch(); }
举一反三
根据本实例,读者可以:
输出成绩大于90分的学生信息。
查找指定学生的成绩。
2.2 指针与数组
使用指针能更加灵活有效地操作数组。在C语言中一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。指针变量既然可以指向变量,当然也就可以指向数组元素。数组元素的指针就是数组元素对应的地址,通过指针指向数组元素的地址,能够快速地查找数组元素,提高程序质量。
实例054 使用指针输出数组元素
本实例是一个提高基础技能的程序
实例位置:光盘\mingrisoft\02\054
实例说明
本实例通过指针变量输出数组的各元素值,运行程序后,输入10个数值,运行后,可以看到输出的数组元素值。程序运行效果如图2.5所示。
图2.5 输出数组元素值
技术要点
本实例应用指向数组的指针实现输出数组元素。定义一个指向数组元素的指针变量的方法,与定义指向变量的指针变量相同。例如:
int a[10]; /*定义一个包含10个整型数据的数组*/ int*p; /*定义整型指针变量p*/ p=&a[0]; /*对指针变量赋值*/
上面第3句代码把数组a的a[0]元素的地址赋给指针变量p。也就是说,p指向a数组的首元素。如图2.6所示,指针变量p中存放a[0]的地址,因此p指向a[0]。C语言中数组名代表数组的首地址,也就是数组第一个元素的地址。因此,下面两个语句等价:
图2.6 指向数组的指针
p=&a[0]; p=a;
使用指针指向数组之后,就要通过指针引用数组元素。在C语言中,如果指针变量p指向数组中的一个元素,则p+1指向同一数组中的下一个元素。如图2.7所示,如果p的初值为&a[0],则p+1的值就是&a[1],也可表示为a+1。同理,p+i和a+i就是a[i]的地址,或者说,它们都指向a数组的第i个元素。则*(p+i)就是p+i所指向的数组元素,即a[i]。
图2.7 通过指针引用数组元素
本程序使用指针变量指向一个数组,使p的初始值为数值元素首地址。使用p+1移动指针,使指针指向数组的每个元素值。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件:
#include "stdio.h"
(3)创建main()函数,在main()函数中实现将用户输入的10个数值存入到数组中,使用指针变量指向这个数组,并实现数组元素的输出。
实现代码如下:
main() { int a[10]; int *p, i; puts("\nPlease input ten integer:\n"); for(i = 0; i < 10; i++) scanf("%d",&a[i]); /*输入数组元素*/ printf("\n"); for(p=&a;p<(a+10);p++) /*使用指针指向数组,并输出数组元素*/ printf("%d", *p); puts("\n\n Press any key to quit..."); getch(); return 0; }
举一反三
根据本实例,读者可以:
按照由小到大的顺序输出数组值。
查找数组中指定元素。
实例055 用指针实现逆序存放数组元素值
本实例是一个提高基础技能的程序
实例位置:光盘\mingrisoft\02\055
实例说明
本实例实现将数组中的元素值按照相反顺序存放。运行效果如图2.8所示。
图2.8 逆序存放数组
技术要点
本程序自定义创建了一个函数inverte(),用来实现对数组元素的逆序存放。自定义函数的形参为一个指向数组的指针变量x,x初始值指向数组a的首元素的地址。x+n是a[n]元素的地址。声明指针变量i、j和p,i初值为x,即指向数组首元素地址,j的初值为x+n-1,即指向数组最后一个元素地址,使p指向数组中间元素地址。交换*i与*j的值,即交换a[i]与a[j]的值。移动i和j,使i指向数组第二个元素,j指向倒数第二个元素,继续交换,直到中间值。这样就实现了数组元素的逆序存放。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件:
#include "stdio.h"
(3)创建自定义函数inverte()用来实现对数组元素的逆序存放:
inverte(int *x, int n) { int*p,temp, *i, *j,m=(n-1)/2; /*声明变量*/ i=x; /*变量i存放数组首地址*/ j=x+n-1; /*变量j存放数组末尾元素地址*/ p=x+m; /*变量p存放数组中间元素地址*/ for(;i<=p;i++,j--) /*交换数组前半部分和后半部分元素*/ { temp= *i; *i= *j; *j = temp; } return 0; }
(4)创建main()函数,在函数中调用inverte()函数,并将逆序后的数组输出显示在窗体上。实现代码如下:
void main() { /*void inverte(int *x,int n);*/ int i, a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; /*定义数组*/ printf("The elements of original array:\n"); for(i=0;i<10;i++) /*输出数组*/ printf("%d,", a[i]); printf("\n"); inverte(a,10); /*使数组元素逆序*/ printf("The elements has been inverted:\n"); for(i=0;i<10;i++) /*输出逆序后数组*/ printf("%d,", a[i]); printf("\n"); getch(); }
举一反三
根据本实例,读者可以:
使用指针实现从数组中删除元素。
使用指针实现向数组中插入元素。
实例056 输出二维数组有关值
本实例是一个提高基础技能的程序
实例位置:光盘\mingrisoft\02\056
实例说明
本实例实现在窗体上输出二维数组的有关值,指向二维数组的指针变量的应用。程序运行效果如图2.9所示。
图2.9 输出二维数组有关值
技术要点
要更清楚地了解二维数组的指针,首先要掌握二维数组数据结构的特性。二维数组可以看成是元素值为一维数组的数组。假设有一个3行4列的二维数组a,它定义为:
int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
a是数组名。a数组包含3行,即3个元素:即a[0]、a[1]、a[2]。而每个元素又是一个包含4个元素的一维数组。同一维数组一样,a的值为数组首元素地址值,而这里的首元素为4个元素组成的一维数组。因此,从二维数组角度看,a代表的是首行的首地址。a+1代表的是第一行的首地址。a[0]+0可表示为&a[0][0],即首行首元素地址;a[0]+1可表示为&a[0][1],即首行第二个元素的地址。
使用指针指向数组时,在一维数组中a[0]与*a[0]等价,a[1]与*a(+1)等价。因此,在二维数组中a[0]+1和*(a+0)+1 的值都是&a[0][1],如图2.3 所示的地址1002,a[1]+2和*(a+1)+2的值都是&a[1][2],如图2.10所示的地址1012。
图2.10 二维数组地址描述
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件。
(3)创建main()函数,实现输出与二维数组有关的值。
实现代码如下:
#include "stdio.h" void main() { int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; /*声明数组*/ printf("%d,%d\n",a,*a); /*输出第0行首地址和0行0类元素地址*/ printf("%d,%d\n",a[0],*(a+0)); /*输出0行0列地址*/ printf("%d,%d\n",&a[0],&a[0][0]); /*0行首地址和0行0列地址*/ printf("%d,%d\n",a[1],a+1); /*输出1行0列地址和1行首地址*/ printf("%d,%d\n",&a[1][0],*(a+1)+0); /*输出1行0列地址*/ printf("%d,%d\n",a[1][1],*(*(a+1)+1));/*输出1行1列元素值*/ getch(); }
举一反三
根据本实例,读者可以:
在窗体中打印二维数组。
查找二维数组中最大值。
实例057 输出二维数组任一行任一列值
本实例是一个提高基础技能的程序
实例位置:光盘\mingrisoft\02\057
实例说明
本实例实现在窗体上输出一个3行4列的数组,输入要显示数组元素的所在行数和列数,将在窗体上显示该数组元素值。程序运行效果如图2.11所示。
图2.11 输出二维数组值
技术要点
本实例使用指向由m个元素组成的一维数组的指针变量,实现输出二维数组中指定的数值元素。当指针变量指向一个包含m个元素的一维数组时,如果p初始指向了a[0],即p=&a[0],则p+1指向a[1],而不是a[0][1]。其示意图如图2.12所示。
图2.12 数组与指针关系示意图
定义一个指向一维数组的指针变量,可以按如下方式书写:
int(*p)[4]
上面语句表示定义一个指针变量p,它指向包含4个整型元素的一维数组。也就是p所指的对象是有4个整型元素的数组,其值为该一维数组的首地址。可以将p看成是二维数组中的行指针,p+i表示二维数组第i行的地址。因为p+i表示二维数组第i行的地址,所以*(p+i)+j表示二维数组第i行第j列的元素地址。*(*(p+i)+j)则表示二维数组第i行第j列的值,即a[i][j]的值。
实现过程
(1)在TC中创建一个C文件。
(2)创建main()函数,实现在窗体上显示一个3行4列的数组,并能够输出指定数组元素的值。
实现代码如下:
main() { int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; /*定义数组*/ int*p,(*pt)[4],i,j; /*声明指针、指针型数组等变量*/ printf("The array is:"); for(p=a[0];p<a[0]+12;p++) { if((p-a[0])%4==0)printf("\n"); /*每行输出4个元素*/ printf("%4d",*p); /*输出数组元素*/ } printf("\n"); printf("Plesase input the position like: i= ,j= \n "); pt=a; scanf("i=%d,j=%d",&i,&j); /*输入元素位置*/ printf("a[%d,%d]=%d\n",i,j,*(*(pt+i)+j)); /*输出指定位置的数组元素*/ getch(); }
举一反三
根据本实例,读者可以:
在窗体上输出一个4行4列二维数组。
用指针顺序输出二维数组的元素值。
实例058 用指针查找数列中最大值、最小值
这是一个可以提高分析能力的实例
实例位置:光盘\mingrisoft\02\058
实例说明
本实例实现在窗体上输入10个整型数,自动查找这些数中的最大值和最小值,并显示在窗体上。程序运行效果如图2.13所示。
图2.13 查找最大值、最小值
技术要点
本实例使用指向一维数组的指针,遍历一维数组中数据,从而实现查找数组中的最大值最小值。
在本实例中,自定义函数max_min()用于将求得的最大值和最小值分别存放在这两个变量max和min中。变量max和min是在main()函数中定义的局部变量,将这两个变量的地址作为函数参数传递给被调用函数max_min(),函数执行后将数组中最大值和最小值存储在max和min中并返回。这是数值的传递过程。
下面介绍如何实现查找数组中最大值和最小值。在自定义函数max_min()中,定义了指针变量p指向数组,其初值为a+1,也就是使p指向a[1]。循环执行p++,使p指向下一个元素。每次循环都将*p和*max与*min比较,将大值存放在max所指地址中,将小值存放在min所指地址中。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件:
#include "stdio.h"
(3)创建max_min()自定义函数实现查找数组中最大值和最小值:
void max_min(int a[], int n, int *max, int *min) { int *p; *max= *min= *a; /*初始化最大值最小值指针变量*/ for(p = a + 1; p < a + n; p++) if(*p> *max) *max= *p; /*最大值*/ else if(*p< *min) *min= *p; /*最小值*/ return 0; }
(4)创建main()函数,在此函数中调用max_min()函数,并将所得结果输出在窗体上。
实现代码如下:
main() { int i, a[10]; int max, min; printf("Input 10 integer numbers you want to operate:\n "); for(i = 0; i < 10; i++) scanf("%d",&a[i]); /*输入数组元素*/ max_min(a,10,&max,&min); /*返回最大值和最小值*/ printf("\nThe maximum number is:%d\n",max);/*输出最大值*/ printf("The minimum number is:%d\n",min); /*输出最小值*/ getch(); }
举一反三
根据本实例,读者可以:
使用指针将数组按照由大到小顺序输出。
使用指针实现合并两个有序数组。
实例059 用指针数组构造字符串数组
本实例是一个提高基础技能的程序
实例位置:光盘\mingrisoft\02\059
实例说明
本实例实现输入一个星期中对应的第几天,可显示其英文。例如,输入“3”,则显示星期三所对应的英文名。程序运行效果如图2.14所示。
图2.14 构造字符串数组程序运行效果
技术要点
本实例主要实现通过指针数组来构造一个字符串数组,并显示指定的数组元素值。指针数组,即数组中的元素都是指针类型的数据。指针数组中的每个元素都是一个指针。一维指针数组的定义形式为:
类型名 *数组名[数组长度];
“类型名”为指针所指向的数据的类型,“数组长度”为该数组中可以存放的指针个数。
例如:
int *p[4];
表示p是一个指针数组,该数组由4个数组元素组成,每个元素都相当于一个指针变量,都可以指向一个整型变量。
注意:*p[4]与(*p)[4]不要混淆。(*p)[4]中的p是一个指向一维数组的指针变量。前面已经介绍过,这里不再赘述。
指针数组比较适用于构造字符串数组。字符串本身就相当于一个字符数组,可以用指向字符串第一个字符的指针表示,字符串数组是由指向字符串第一个字符的指针组成的数组。
实现过程
(1)在TC中创建一个C文件。
(2)创建main()函数,在此函数中实现使用指针数组构造一个字符串数组,使用指针数组中的元素指向星期几的英文名字符串。
实现代码如下:
#include "stdio.h" int main(void) { char *Week[] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", }; /*声明指针数组*/ int i; printf("Please enter a number for week\n"); scanf("%d",&i); /*输入要查找星期几*/ printf("The week is:"); printf("%s\n", Week[i -1]); getch(); return 0; }
举一反三
根据本实例,读者可以:
在窗体上输出字符串数组中元素。
在字符串数组中删除指定字符串。
实例060 将若干字符串按照字母顺序输出
这是一个可以启发思维的实例
实例位置:光盘\mingrisoft\02\060
实例说明
本实例实现对程序中给出的几个字符串按照由小到大的顺序进行排序,并将排序结果显示在窗体上。程序运行效果如图2.15所示。
图2.15 将字符串排序输出
技术要点
本实例应用到了上面实例中使用的指针数组构造一个字符串数组,然后比较这个字符串数组中各元素值大小,实现对数组内容按照由大到小的顺序输出。自定义函数sort的作用是对字符串进行排序。sort函数的形参strings是指针数组名,接受实参传过来的strings数组的首地址,这里使用选择排序法进行排序。本实例应用了字符串函数strcmp()进行字符串比较。下面对这个函数进行介绍。
strcmp字符串比较函数:
函数原型:int strcmp(char *str1,char *str2)
应用的头文件:#include<string.h>
函数功能:比较两个字符串的大小,其实就是将两个字符串从首字符开始逐一进行比较,字符的比较是按照字符的ASCII码值进行比较。
返回值:返回结果为str1-str2的值。返回结果大于零,表示字符串str1大于字符串str2;返回结果等于零,表示两个字符串相等;返回结果小于零,表示字符串str1小于字符串str2。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件:
#include "stdio.h" #include "string.h"
(3)创建sort函数,实现对字符串进行排序:
sort(char*strings[],int n) /*对字符串排序*/ { char *temp; int i, j; for(i = 0; i < n; i++) { for(j = i + 1; j < n; j++) { if(strcmp(strings[i],strings[j])>0)/*比较字符大小,交换位置*/ { temp = strings[i]; strings[i] = strings[j]; strings[j] = temp; } } } }
(4)创建main()函数,实现使用指针数组构造一个字符串数组,调用sort函数对字符串进行排序,并显示排序后的数组结果。实现代码如下:
void main() { int n = 5; int i; char *strings[] = { "C language", "Basic", "World wide", "Hello world", "One world,one dream!" }; /*构造字符串数组*/ sort(strings,n); /*排序*/ for(i = 0; i < n; i++) printf("%s\n", strings[i]); getch(); }
举一反三
根据本实例,读者可以:
在字符串数组中查找指定字符串。
在字符串数组中插入指定字符串。
2.3 指针与函数
指针可以指向变量、数组,也可以指向一个函数。一个函数在编译的时候被分配给一个入口地址,使用指针指向这个地址,可以方便地对函数进行调用。这个入口地址就成为函数的指针。本节通过实例来介绍如何使用函数的指针和指针函数。
实例061 用指向函数的指针比较大小
这是一个可以启发思维的实例
实例位置:光盘\mingrisoft\02\061
实例说明
本实例实现输入两个整数后,将输入的较小值输出显示在窗体上,程序运行效果如图2.16所示。
图2.16 输出较小值
技术要点
这里使用指向函数的指针实现调用比较数值大小的函数。一个函数在编译时被分配一个入口地址,这个地址就称为函数的指针。所以也可以使用指针变量指向一个函数,然后通过该指针变量调用这个函数。
指向函数的指针变量的一般形式为:
数据类型(*指针变量名)();
这里的数据类型是指函数返回值的类型。
例如:
int(*pmin)();
(*p)()表示定义一个指向函数的指针变量,它用来存放函数的入口地址,在程序设计过程中,将一个函数地址付赋它,它就指向那个函数。函数指针变量赋值可按如下方式进行书写:
p=min;
可见在赋值时,只给出函数名称即可,不必给出函数的参数。
在使用函数指针变量调用函数时,要写出函数的参数,例如可按如下写法:
m=(*p)(a,b);
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件:
#include "stdio.h"
(3)创建自定义函数min()实现返回输入的两个整数中的较小值:
min(int a ,int b) { if(a<b)return a; /*如果a小于b则返回a*/ else return b; /*否则返回b*/ }
(4)创建main()函数,在此函数中实现定义指向函数的指针变量,并使此函数指针变量指向min()函数,将得到的结果输出在窗体上。实现代码如下:
void main() { int(*pmin)(); int a, b, m; pmin = min; printf("Please input two integer numbers: \n"); scanf("%d%d",&a,&b); /*输入两个值*/ m=(*pmin)(a,b); /*返回最小值*/ printf("min=%d", m); getch(); }
举一反三
根据本实例,读者可以:
用指向函数的指针查找数列中指定值。
用指向函数的指针对数列排序。
实例062 使用返回指针的函数查找最大值
这是一个可以启发思维的实例
实例位置:光盘\mingrisoft\02\062
实例说明
本实例实现在窗体上输入10个整数后,在窗体上输出这些整数中的最大值。程序运行效果如图2.17所示。
图2.17 输出最大值
技术要点
函数返回值可以是整型、字符型、实型等,同样也可以是指针型数值,即一个地址。
返回指针的函数的定义形式为:
int * fun(int x,int y)
在调用fun函数时,直接写函数名加上参数即可,返回一个指向整型数据的指针,其值为一个地址。x、y是函数fun的形参。在函数名前面直接添加*,表示此函数是指针型函数,即函数值是指针。最前面的int表示返回的指针指向整型变量。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件。
(3)创建自定义函数FindMax()实现返回输入的整数中的最大值。
(4)创建main()函数,在此函数中调用指针函数FindMax,将得到的最大值显示在窗体上。
实现代码如下:
#include "stdio.h" *FindMax(int *p, int n) { int i, *max; max = p; for(i = 0; i < n; i++) if(*(p+i)> *max) max=p+i; /*把最大数的地址赋给变量*/ return max; } void main() { int a[10], *max,i; printf("Please input ten integer:\n"); for(i = 0; i < 10; i++) { scanf("%d", &a[i]); } max = FindMax(a, 10); printf("The max number is:%d\n", *max);/*输出查找到的最大值*/ getch(); }
举一反三
根据本实例,读者可以:
使用指针函数实现查找最小值。
使用指针函数实现数值比较。
实例063 使用指针函数求学生成绩
本实例可以方便操作、提高效率
实例位置:光盘\mingrisoft\02\063
实例说明
本实例实现在窗体上输入学生序号,将在窗体上输出该序号对应的学生的成绩。程序运行效果如图2.18所示。
图2.18 显示学生成绩
技术要点
本实例应用指针函数实现查找指定序号的学生的程序,关于指针函数的相关知识参见实例070的介绍。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件:
#include "stdio.h"
(3)创建自定义指针函数search()实现按照学生序号进行查找:
float *search(float(*p)[4], int n) { float *pt; pt = *(p + n); return(pt); }
(4)创建main()函数,在此函数中调用指针函数search,将得到的结果输出在窗体上。实现代码如下:
void main() { float score[][4]={{60,75,82,91},{75,81,91,90},{51,65,78,84},{65,51,78,72}};/*声明数组*/ float *p; int i, j; printf("enter the student's number you want to search:"); scanf("%d",&j); /*输入学生学号*/ printf("This student's scores are:\n"); p = search(score, j); for(i = 0; i < 4; i++) printf("%5.1f\t", *(p + i)); getch(); }
举一反三
根据本实例,读者可以:
针对本实例找出有不及格课程的学生及其学号。
使用指针函数在数列中查找指定值。
实例064 寻找指定元素的指针
本实例是一个提高基础技能的程序
实例位置:光盘\mingrisoft\02\064
实例说明
本实例实现寻找指定元素的指针,程序运行后将给定一列数组数据,并显示数组首地址,输入要查询的数组元素,则显示该元素在数组中序号,并显示该元素所在位置,即该元素的指针。程序运行效果如图2.19所示。
图2.19 寻找指定元素的指针
技术要点
本实例应用返回指针的函数实现返回指定元素的指针,具体参见实例071。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件,声明数组:
#include <stdio.h> int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60 };
(3)创建自定义函数search(),实现查找指定值在数组中位置;创建自定义函数find()实现返回指定值的指针,即返回指定值的地址:
int search(int *pt, int n, int key) { int *p; for(p = pt; p < pt + n; p++) if(*p==key) /*如果指针指向的值等于指定值,返回在数组中位置*/ return p - pt; return 0; } int *find(int *pt, int n, int key) { int *p; for(p=pt;p<pt+n;p++) /*如果指针指向的值等于指定值,返回地址*/ if(*p = = key) return p; return 0; }
(4)创建main()函数,在此函数中调用search()函数和find()函数,将得到的结果输出在窗体上。实现代码如下:
main() { int i, key; int *j; printf("The elements of array a:\n"); for(i=0;i<sizeof(a)/sizeof(a[0]);i++) /*输入数组a的元素*/ printf("%d ", a[i]); printf("\nThe address of a[0] is :%d\n", &a[0]); printf("\nPlease input the key number you want to search:"); /*输入要查找的值*/ i = search(a, sizeof(a)/ sizeof(a[0]), key); scanf("%d", &key); printf("\nThe label number of the key number %d in the array is:%d",key, /*输出查找值在数组中位置*/ i); j = find(a, sizeof(a)/ sizeof(a[0]), key); printf("\nThe point value of the key number %d in the array is:%d",key,j)/*输出查找值所在位置*/ ; getch(); }
举一反三
根据本实例,读者可以:
寻找最大元素的指针。
使用指针函数实现数列排序。
实例065 寻找相同元素的指针
本实例可以方便操作、提高效率
实例位置:光盘\mingrisoft\02\065
实例说明
本实例实现比较两个有序数组中的元素,输出两个数组中第一个相同的元素值,程序运行效果如图2.20所示。
图2.20 寻找相同元素
技术要点
本实例应用返回指针的函数实现返回指定元素的指针,具体参见上个实例。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件:
#include "stdio.h"
(3)创建自定义函数find(),实现查找两个数组中第一个相同的元素值:
int *find(int *pa,int *pb,int an,int bn) { int *pta,*ptb; pta=pa;ptb=pb; while(pta<pa+an&&ptb<pb+bn) { if(*pta<*ptb)pta++; else if(*pta>*ptb)ptb++; else return pta; /*如果两个值相等,返回这个值的指针 } return 0; }
(4)创建main()函数,在此函数中调用find()函数,将得到的结果输出在窗体上。实现代码如下:
void main() { int *p, i; int a[] = { 1, 3, 5, 7, 9, 11, 13, 15 }; /*声明数组*/ int b[] = { 2, 4, 6, 8, 11, 15, 17 }; /*声明数组*/ printf("The elements of array a:"); for(i = 0; i < sizeof(a)/ sizeof(a[0]); i++) printf("%d",a[i]); /*输出数组a的元素*/ printf("\nThe elements of array b:"); for(i = 0; i < sizeof(b)/ sizeof(b[0]); i++) printf("%d",b[i]); /*输出数组b的元素*/ p = find(a, b, sizeof(a)/ sizeof(a[0]), sizeof(b)/ sizeof(b[0])); if(p) printf("\nThe first element in both arrays is %d\n", *p); else printf("Doesn't found the same element!\n"); getch(); }
举一反三
根据本实例,读者可以:
寻找数列中最小元素的指针。
寻找字符串数组中指定字符串的指针。
2.4 字符串与指针
指针同样可以指向一个字符串,用字符指针指向字符串中的字符可以方便地对字符串进行操作。C语言中对字符串是按字符数组处理的,在内存开辟了一个字符数组来存放该字符串常量,使用指针指向字符串,实际上是指向了字符串的第一个元素,及存放字符串的字符数组的首元素地址。通过下面的几个实例相信读者能够掌握字符串指针的使用。
实例066 使用指针实现字符串复制
本实例可以方便操作、提高效率
实例位置:光盘\mingrisoft\02\066
实例说明
本实例实现使用指针实现字符串的复制,并将字符串输出到窗体上,程序运行效果如图2.21所示。
图2.21 使用指针实现字符串复制
技术要点
本实例应用字符型指针变量和指向字符串的指针做函数的参数实现字符串的复制。在主函数中定义了两个字符型指针变量,指针变量str用于指向要被复制的字符串,指针变量p用于指向复制后的字符串。
在C语言中对字符串是按字符数组处理的,在内存开辟一个字符数组用来存放该字符串。使用字符串对字符指针变量str初始化,实际上是把字符串的第一个元素的地址赋给str。而不是把整个字符串里的几个字符赋给该字符串变量。如图2.22(a)所示,string为一个字符串数组,如图2.22(b)所示,为一个指针指向的字符串。定义字符串指针变量可写作如下形式:
图2.22 字符串数组和指针指向的字符串
char *str="Hello world!"
也可以写做下面两行的格式:
char *str; str="Hello world!";
本实例中自定义函数copy()用于实现字符串的复制。它的两个形参s和q,是字符型指针变量。在for循环中,当*s不为“\0”时,每次将*s赋给*q,然后使s和q增值,从而实现字符串的复制。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件,声明自定义函数:
#include <stdio.h> copy(char *s,char *q);
(3)创建自定义函数copy(),实现字符串的复制:
copy(char*s,char*q) /*实现字符串复制*/ { int i = 0; for(; *s!='\0';) { *q= *s; s++; q++; } *q='\0'; /*添加字符串结束符*/ }
(4)创建main()函数,在此函数中调用copy()函数,将得到的结果输出在窗体上。实现代码如下:
int main(void) { char*str, *p; /*声明字符型指针变量*/ str = "Hello world!"; copy(str,p); /*实现复制*/ printf("%s",p); /*输出复制后字符串*/ getch(); return 1; }
举一反三
根据本实例,读者可以:
使用指针查找字符串中指定字符。
使用指针计算字符串中字符出现次数。
实例067 字符串的连接
这是一个可以启发思维的实例
实例位置:光盘\mingrisoft\02\067
实例说明
本实例应用字符型指针变量和指向字符串的指针做函数的参数,实现字符串的连接,并将连接后的字符串输出到窗体上,程序运行效果如图2.23所示。
图2.23 使用指针实现字符串连接
技术要点
本实例应用字符型指针变量和指向字符串的指针做函数的参数实现字符串的连接。关于字符串指针的相关知识参见实例074“技术要点”部分的介绍。
本实例创建了自定义函数connect()用于实现字符串的连接。Connect()函数与实例065 中的自定义函数copy()实现方法基本相同,只不过connect()函数带有3个参数,两个用于连接的字符串,一个作为连接后的字符串。
实现过程
(1)在TC中创建一个C文件。
(2)引用头文件,声明自定义函数:
#include <stdio.h> connect(char *s,char *t,char *q);
(3)创建自定义函数connect(),实现字符串的连接:
connect(char *s, char *t, char *q) { int i = 0; for(; *s!='\0';) /*放入第一个字符串*/ { *q= *s; s++; q++; } for(; *t!='\0';) /*连接第二个字符串*/ { *q= *t; t++; q++; } *q = '\0'; }
(4)创建main()函数,在此函数中调用connect()函数,将得到的结果输出在窗体上。实现代码如下:
int main(void) { char*str, *t, *p; str="One world"; /*用于连接的字符串*/ t="one dream"; /*用于连接的字符串*/ printf("The first string is: %s\n", str); printf("The second string is: %s\n", t); connect(str,t,p); /*将两个字符串连接*/ printf("The connected string is:\n"); printf("%s",p); /*输出连接后的字符串*/ getch(); }
举一反三
根据本实例,读者可以:
字符串的逆序输出。
将一个字符串按照空格拆分成多个字符串。
实例068 字符串插入
这是一个可以启发思维的实例
实例位置:光盘\mingrisoft\02\068
实例说明
本实例实现将一个字符串插入到另一个字符串的指定位置,构成一个新的字符串,并输出到窗体上。程序运行效果如图2.24所示。
图2.24 字符串的插入
技术要点
本实例使用指向字符串的指针实现将一个字符串插入到另一个字符串的指定位置。关于字符串的指针的相关介绍参见本章实例065。
本实例中的字符串插入与字符串的复制实例设计思想基本相同,就是使用指向字符串的指针实现字符串复制的过程,不同的是将两个字符串复制到一个字符串中,将要插入的字符串,在指定的位置进行复制。
实现过程
(1)在TC下创建一个C文件。
(2)引用头文件,声明自定义函数:
#include <stdio.h> #include<string.h> insert(char *s,char *q,int i);
(3)创建自定义函数insert(),实现字符串插入操作:
insert(char s, char q, int n) { int i = 0; char *str, strcp[50]; str=strcp; /*把数组首地址赋给指针变量*/ for(i=0; *s!='\0';i++) { if(i = = n -1) { for(; q!='\0';) /*循环插入字符串*/ { str[i]= *q; /*插入字符*/ q++; i++; } } str[i]= *s; s++; } str[i + 1] = '\0'; return str; /*返回数组首地址*/ }
(4)创建main()函数,在此函数中调用insert()函数,将得到的结果输出在窗体上。实现代码如下:
int main(void) { char*strin, *str; int i; str = "Hello world!"; strin = "big "; printf("Please input the positon you want to insert:"); scanf("%d",&i); /*输入插入位置*/ str=insert(str,strin,i); /*在指定位置插入*/ printf("\n%s",str); /*输出插入后的字符串*/ getch(); }
举一反三
根据本实例,读者可以:
在字符串中查找指定字符集的子集的第一次出现位置。
查找两个字符串中相同字符个数。
实例069 字符串的匹配
这是一个可以启发思维的实例
实例位置:光盘\mingrisoft\02\069
实例说明
本实例实现对两个字符串进行匹配操作,即在第一个字符串中查找是否存在第二个字符串。如果字符串完全匹配,则提示匹配的信息,并显示第二个字符串在第一个字符串中的开始位置,否则提示不匹配。程序运行效果如图2.25所示。
图2.25 字符串的匹配
技术要点
本实例定义了自定义函数match()进行字符串的匹配操作。match()函数包含两个参数,参数B为要进行匹配操作的字符串,其类型为字符型指针;参数A为用来匹配的字符串。使用循环语句比较A字符串最后一个字符是否与B中字符相同,如果相同,使用循环语句比较A与B是否匹配。
实现过程
(1)在TC下创建一个C文件。
(2)引用头文件:
#include "stdio.h" #include <string.h>
(3)创建自定义函数match(),实现字符串匹配操作:
int match(char B, char A) /*此函数实现字符串的匹配操作*/ { int i,j,start =0; int lastB=strlen(B)-1; int lastA=strlen(A)-1; int endmatch= lastA; for(j=0;endmatch<=lastB;endmatch++,start++) { if(B[endmatch] = = A[lastA]) for(j=0,i=start;j<lastA&&B[i]= =A[j];) i++,j++; if(j = = lastA){ return(start+1); / */成功 */ } }*/ if(endmatch>lastB){ /*循环输出*/ printf("The string is not matchable!"); return -1; } }
(4)创建main()函数,在此函数中调用match()函数,将得到的结果输出在窗体上。实现代码如下:
void main() { char s[]="One world,one dream"; /*原字符串*/ char t[]="world"; /*要测试匹配的字符串*/ int p = match(s, t); if(p!= -1) /*如果匹配成功输出位置*/ { printf("Matchable!\n"); printf("The start position is %d", p); } printf("\n"); getch(); }
举一反三
根据本实例,读者可以:
删除字符串中指定字符。
字符串的比较。
2.5 指向指针的指针
指向指针的指针实际上就是指向指针数据的指针变量。通过下面的实例说明指向指针的指针的概念及如何进行使用。
实例070 使用指针的指针输出字符串
本实例是一个提高基础技能的程序
实例位置:光盘\mingrisoft\02\070
实例说明
本实例实现使用指针的指针输出字符串。首先要使用指针数组创建一个字符串数组,然后定义指向指针的指针,使其指向字符串数组,并使用其将数组中字符串输出。程序运行效果如图2.26所示。
图2.26 输出字符串
技术要点
本实例使用指针的指针实现对字符串数组中字符串的输出。指向指针的指针即是指向指针数据的指针变量。这里创建一个指针数组strings,它的每个数组元素相当于一个指针变量,都可以指向一个整型变量,其值为地址,如图2.27所示。strings是一个数组,它的每个元素都有相应的地址。数组名stirngs代表该指针数组的首单元的指针,就是说指针数组首单元中存放的也是一个指针。strings+i是strings[i]的地址。strings+i就是指向指针型数据的指针。
图2.27 指针数组结构示意图
指向指针数据的指针变量定义语句形式如下:
char **P;
p的前面有两个*号、*运算符是从右到左结合,**p就相当于*(*p),*p表示定义一个指针变量,在其前面再添加一个*号,表示指针变量p是指向一个指针变量。*p就表示p所指向的另一个指针变量,即一个地址。**p是p间接指向的对象的值。例如,这里*(p+2)就表示strings[2]中的内容,它也是一个指针,指向字符串“World wide”。因此,输出字符串时,语句为:
printf("%s\n",*(p+i));
实现过程
(1)在TC下创建一个C文件。
(2)创建main()函数,在此函数中使用指针数组创建字符串数组,并使用指向指针的指针将字符串数组中的字符串输出。实现代码如下:
main() { char *strings[]={"C language", "Basic", "World wide", "Olympic", "Great Wall"}; /*使用指针数组创建字符串数组*/ char**p,i; /*声明变量*/ p=strings; /*指针指向字符串数组首地址*/ for(i=0;i<5;i++) /*循环输出字符串*/ { printf("%s\n",*(p+i)); } }
举一反三
根据本实例,读者可以:
使用指针的指针输出整型数组中数据。
使用指针的指针实现输出字符串数组中指定位置的字符串。
实例071 实现输入月份号输出该月份英文名
这是一个可以启发思维的实例
实例位置:光盘\mingrisoft\02\071
实例说明
本实例使用指针数组创建一个含有月份英文名的字符串数组,并使用指向指针的指针指向这个字符串数组,实现输出数组中的制定字符串。运行程序后,输入要显示英文名的月份号,将输出该月份对应的英文名。程序运行效果如图2.28所示。
图2.28 输出月份对应英文名称
技术要点
与上个实例一样,本实例使用指针的指针实现对字符串数组中字符串的输出。这里首先定义了一个包含月份英文名的字符串数组,并定义了一个指向指针的指针变量指向该数组。使用该变量输出字符串数组的的字符串。详细介绍参见实例063中技术要点部分。
实现过程
(1)在TC下创建一个C文件。
(2)创建main()函数,在此函数中使用指针数组创建字符串数组,并使用指向指针的指针将字符串数组中的字符串输出。实现代码如下:
#include "stdio.h" int main() { char*Month[]={ /*定义字符串数组*/ "January", "February", "March", "April", "May", "June", "Junly", "August", "September", "October", "November", "December" }; int i; char**p; /*声明指向指针的指针变量*/ p=Month; /*将数组首地址值赋给指针变量*/ printf("Input a number for month\n"); scanf("%d",&i); /*输入要显示的月份号*/ printf("The month is:"); printf("%s\n",*(p+i-1)); /*使用指向指针的指针输出对应的字符串数组中字符串*/ getch(); return 0; }
举一反三
根据本实例,读者可以:
使用指针的指针对数组元素排序。
使用指针的指针实现查找数组中指定值。
实例072 使用指向指针的指针对字符串排序
这是一个可以启发思维的实例
实例位置:光盘\mingrisoft\02\072
实例说明
本实例使用指向指针的指针实现对字符串数组中的字符串排序输出,程序运行效果如图2.29所示。
图2.29 字符串排序
技术要点
本实例同样使用指向指针的指针实现对字符串数组中的字符串排序,这里定义了自定义函数sort(),使用函数strcmp()实现对给定字符串的比较,并进行排序。strcmp()函数的相关介绍参见本章实例068技术要点部分。关于指向指针的指针部分知识参见本章实例078技术要点部分。
实现过程
(1)在TC下创建一个C文件。
(2)引用头文件:
#include"stdio.h" /*引用头文件*/ #include "string.h"
(3)创建自定义函数sort()实现对字符串排序:
sort(char *strings[], int n) { char*temp; /*声明字符型指针变量*/ int i,j; /*声明整型变量*/ for(i=0;i<n;i++) /*外层循环*/ { for(j = i + 1; j < n; j++) { if(strcmp(strings[i],strings[j])>0)/*比较两个字符*/ { temp=strings[i]; /*交换字符位置*/ strings[i] = strings[j]; strings[j] = temp; } } } }
(4)创建main()函数,在此函数中调用sort()函数对字符串数组中字符串排序,并将排序结果显示在窗体上。实现代码如下:
void main() { int n = 5; int i; char**p; /*指向指针的指针变量 char *strings[] = { "C language", "Basic", "World wide", "Hello world", "Great Wall" }; /*初始化字符串数组*/ p=strings; /*指针指向数组首地址*/ sort(p,n); /*调用排序自定义过程*/ for(i=0;i<n;i++) /*循环输出排序后的数组元素*/ printf("%s\n", strings[i]); getch(); }
举一反三
根据本实例,读者可以:
使用指针的指针比较两个数大小。
使用指针的指针实现查找数列中最大值。