实验9指针
1、实验目的、要求:
(1)掌握指针的概念,会定义和使用指针变量。
(2)能正确使用字符串的指针和指向字符串的指针变量。
(3)正确使用数组的指针和指向数组的指针变量。
(4)正确使用字符串的指针和指向字符串的指针变量。
(5)正确使用指向函数的指针变量;了解指向指针的指针的概念及其使用方法。
2、实验内容
(1)、输入程序并运行,观察实验结果并分析。
#include<stdio.h>
int main()
{int a,b,c;
sub(10,5,&a);
sub(7,a,&b);
sub(a,b,&c);
printf("%4d,%4d,%4d\n",a,b,c);
return(0);}
sub(int x,int y,int*z)
{*z=y-x;}
实验分析:
在该程序中,函数sub中含有三个参数,即整形变量x,y,和指针变量z,z所指向的数值为y与x的差;
第一次输入10和5,得到差为-5,此时指针变量z的值为a的地址,z指向a的值,即-5;第二次输入7和a,a的值为-5,故此时可得b的值为-12,z存储的值为b的地址值;
第三次输入a和b,a,b的值分别为-5和-12,得到差为-7,此时同理可得,c的值为-7;故最后输出的a,b,c的值分别为-5,-12,-7;
运行该程序,没有错误,显示结果与预期相同,故程序正确。在此程序中,要时刻注意函数中形参与定义函数时的形参的一致性,并注意函数中参数值和变量类型的不断变化。(2)
补全程序并运行。
c语言指针实验总结按字符顺序比较两个字符串s、t的大小,如果s大于t,则返回正值,等于返回0,小于则返回负值。
#include<stdio.h>
sub(char*s,char*t)
{for(;*s==*t;s++,t++)
if(*s=='\0')return(0);
return(*s-*t);
}
#include<stdio.h>
int main()
{char a[20],b[10],*p,*q;
int i;
p=a;
q=b;
scanf("%s%s",a,b);
i=sub(q,p);
printf("%d",i);
return(0);}
比较两个字符串的大小的思想为:将两个字符串的字母的ASC码依次相比,若相同,则向后推,比较
下一个字母,遇到不同的字母,就输出两个不同字母的ASC码的差值,并结束程序;若两个字符串比到其中一个字符串结束时仍相同,则自动结束比较。
实验分析:在此实验中,,a、b分别为有20个和10个元素的字符数组,故在比较中应该为b数组先结束;在子函数中,有条件语句“if(*s==‘\0’)”,且在形参中s为第一个变量,把b数组赋给q指针变量,故在实参中应把q放在前面。
运行程序,向两个数组输入象征性的几个字符,b数组为a,b,c,d,a数组为e,f,g,h,得到结果为-4,与预期一致,故程序正确。
(3)编写程序:输入a,b,c,d四个数,按从小到大的顺序输出这四个数。应用指针变量做函数参数实现。
实验分析:在该程序中,可以将数组地址赋给一个指针,然后在子函数中将四个数进行两两比较,并进行排序,在主函数中输出排序后的数组。对数组元素进行比较和重新排序时,可以考虑使用冒泡法排序和选择法排序,在这里选择使用选择法排序。
#include<stdio.h>
int main()
{void sort(int x[],int n);
int i,*p,a[4];
p=a;
for(i=0;i<4;i++)
scanf("%d",p++);
p=a;
sort(p,4);
for(p=a,i=0;i<4;i++)
{printf("%d\n",*p);
p++;}
return(0);}
void sort(int x[],int n)
{int i,j,k,l;
for(i=0;i<n-1;i++)
{k=i;
for(j=i+1;j<n;j++)
if(x[j]>x[k])k=j;
if(k!=i)
{l=x[i];x[i]=x[k];x[k]=l;}
}
}
运行程序,输入1234,得到结果为4321,程序正确。
(4)编写程序:
将一个3*3矩阵转置,在主函数中用scanf输入矩阵元素,将数组名作为函数参数,在子函数中实现矩阵转置,在主函数中输出转置后的矩阵。
实验分析:在上述程序中,应用的是一个指针变量来代表一个数组,指针变量中存储的是数组首字符的地址,可以考虑将程序进行变化,使用指针数组实现该功能,即定义一个指针数组,数组中的每一个元素都是一个指针,可以代表一个原数组中的元素故可以将程序改为如下形式:
#include<stdio.h>
Int main()
{void range(int*p[3][3]);
Int I,j,*p[3][3],a[3][3];
Printf(“\n”);
For(i=0;i<3;i++)
For(j=0;j<3;j++)
Scanf(“%d”,&a[i][j]);
For(i=0;i<3;i++)
For(j=0;j<3;j++)
P[i][j]=&a[i][j];
Range(p);
For(i=0;i<3;i++)
{For(j=0;j<3;j++)
Printf(“%4d”,*(*(p+i)+j));
Printf(“\n”);}
Return(0);}
V oid range(int*p[3][3])
{int I,j,t;
For(i=0;i<3;i++)
For(j=i;j<3;j++)
{t=*p[i][j];*p[i][j]=*p[j][i];*p[j][i]=t;}
}
运行该程序,得到结果为三成三的矩阵,但各个元素均为11,程序错误。
错误分析:在程序中若想使用指针表示一个数组,不能想当然的用一个指针数组中的每个元素来储存每个元素的地址,即*a[3][3]每个元素都是一个指针的想法是错误的,指针数组只能在一维的范围内定义,要用指针数组来实现该功能,需表示为:
*p[3]=a,并利用循环语句把数组元素的地址整行赋给指针数组。
故可将程序改为:
#include<stdio.h>
int main()
{void range(int a[3][3]);
int i,j,k,a[3][3];
for(i=0;i<3;i++)
for(j=0;j<3;j++)
scanf("%d",&a[i][j]);
range(a);
for(i=0;i<3;i++)
{for(j=0;j<3;j++)
{printf("%4d",a[i][j]);}
printf("\n");}
return(0);}
void range(int a[3][3])
{int i,j,k;
for(i=0;i<3;i++)
for(j=i;j<3;j++)
{k=a[i][j];a[i][j]=a[j][i];a[j][i]=k;}
}
运行该程序,输入数组元素为123456789,得到新的数组为转置之后的数组,程序正确。
实验分析:引用子函数时,实参为数组名,但在主函数和子函数之间传递的是数组的地址,在子函数中对数组进行转置后,主函数中数组元素值也发生变化,输出为转置数组。
3、思考与总结:如何理解“指针变量做函数参数,实参变量与形参变量之间的数据传递是
单向的‘值传递’方式,调用函数不可能改变指针变量的值,但可以改变实参指针变量所指变量的值”这条理论?
在使用指针变量作参数时,变量储存的是一个变量,一个数组或者一个字符串的地址,调用函数时可以将该地址值赋给子函数,并在子函数中实现相应的功能,但将该地址值赋给子函数时,只是一个复制”的过程,是从主函数指向子函数的,故是一个单向的传递过程;并且,子函数的使用不能改变指针变量存储的地址的值,但可以通过运算改变该地址所指向的变量的值。
例题:
(1)若有定义int a[2][3]={2,4,6,8,10,12};则*(&a[0][0]+2*2+1)的值为:12。
分析:虽然该数组为二元数组,但该数组中的元素的地址是相连的,故
&a[0][0]+2*2+1代表的是该数组中第6个元素的地址,再取值,即为第六个元素
的值,为a[1][2]=12;
*(a[1]+2)的值为:10
分析:a[1]即为&a[1][0],&a[1][0]+2即为&a[1][2],所指向的值即为10(2)若有以下定义语句int a[4]={0,1,2,3},*p;p=&a[2];则*--p的值为:1。
分析:指针变量p所存储的是a[2]的地址,在—p中,先自减,后使用,自减后p为a[1]的地址,指向a[1]的值,即1。
(3)若有以下定义语句int s[2][3]={0},(*p)[3];p=s;则p+1表示:数组第二行首元素的地址。
分析:p表示数组第一行元素的地址,即第一行首元素的地址。P+1为第二行的地址,即为第二行首元素的地址。
(4)认真理解教材中p225表10.1的含义即p225表10.2各种指针的含义。
4、易犯错误及纠正方法:
(1)在做实验1时,先分析实验结果,在上机运行,对照结果是否一致。
(2)在做实验2时,先分析实验结果,注意静态局部变量的特性,再上机运行,对照结果是否一致。
(3)实验内容四的编程思路为:四个数两两比较大小,子函数完成比较大小的功能,按照题目要求完成数值顺序的调整。
(4)在做实验内容五时,注意实际参数和形式参数的设置和传递方式。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论