第一部分 知识训练
【知识要点】
1. 地址与指针
指针变量的概念:用一个变量专门来存放另一个变量的地址。 2. 指向变量的指针变量
指针变量的形式:基类型 *指针变量名;&: 取地址运算符;*:指针运算符。 3. 指针与数组
引用一个数组元素可以用下标法和指针法;可以用数组名作函数的参数。 4. 指针与函数
函数指针变量定义的一般形式为:类型说明符 (*指针变量名)(); 一个函数的返回值可以是一个函数。
【典型习题与解析】
5. char * const p;
char const * p const char *p 上述三个有什么区别? 【解析】
char * const p; //常量指针,p的值不可以修改;
char const * p;//指向常量的指针,指向的常量值不可以改; const char *p; //和char const *p。 6. main()
{
int a[5]={1,2,3,4,5}; int *ptr=(int *)(&a+1);
printf(\"%d,%d\ }
输出结果是什么? 【解析】
答案:输出:2,5
*(a+1)就是a[1],*(ptr-1)就是a[4],执行结果是2,5。
&a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int)。
int *ptr=(int *)(&a+1);则ptr实际是&(a[5]),也就是a+5。 原因如下:
1) &a是数组指针,其类型为 int (*)[5];而指针加1要根据指针类型加上一定的
值,不同类型的指针+1之后增加的大小不同。
2) a是长度为5的int数组指针,所以要加 5*sizeof(int),所以ptr实际是a[5],
但是prt与(&a+1)类型是不一样的(这点很重要),所以prt-1只会减去sizeof(int*) a,&a的地址是一样的,但意思不一样。
3) a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,a+1是数组下
一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5]。
【练习题】
一、填空题
1. 指针变量是把内存中另一个数据的 作为其值的变量。 2. 能够直接赋值给指针变量的整数是 。 3. 如果程序中已有定义:int k;
1) 定义一个指向变量k的指针变量p的语句是 。 2) 通过指针变量,将数值6赋值给k的语句是 。 3) 定义一个可以指向指针变量p的变量pp的语句是 。 4) 通过赋值语句将pp指向指针变量p的语句是 。 5) 通过指向指针的变量pp,将k的值增加一倍的语句是 。
4. 当定义某函数时,有一个形参被说明成int *类型,那么可以与之结合的实参类型可以是 、 等。
5. 以下程序的功能是:将无符号八进制数字构成的字符串转换为十进制整数。例如,输入的字符串为:556,则输出十进制整数366。请填空。 #include 2 char *p,s[6]; int n; p=s; gets(p); n=*p-‵0‵; while( != '\\0') n=n*8+*p-‵0‵; printf(\"%d \\n\} 二、选择题 1.变量的指针,其含义是指该变量的( )。 A)值 B)地址 C)名 D)一个标志 2.下面程序的运行结果是( )。 #include char *s1=\"AbDeG\"; char *s2=\"AbdEg\"; s1+=2;s2+=2; printf(\"%d\\n\ } A)正数 B)负数 C)零 D)不确定的值 3.若有以下定义,则对a数组元素的正确引用是( )。 int a[5],*p=a; A)*&a[5] B)a+2 C)*(p+5) D)*(a+2) 4.若有以下定义,则p+5表示( )。 int a[10],*p=a; A)元素a[5]的地址 B)元素a[5]的值 C)元素a[6]的地址 D)元素a[6]的值 3 5. 以下Delblank函数的功能是删除字符串s中的所有空格(包括Tab、回车符和换行符)。 void Delblank(char *s) { int i,t; char c[80]; for(i=0,t=0; ① ;i++) if(!isspace( ② ))c[t++]=s[i]; c[t]=‘\\0’; strcpy(s,c); } ① A) s[i] B) !s[i] C) s[i]=‘\\0’ D) s[i]==‘\\0’ ② A) s+i B) *c[i] C) *(s+i)=‘\\0’ D) *(s+i) 6. 以下conj函数的功能是将两个字符串s和t连接起来。 char *conj(char *s,char *t) { char *p=s; while(*s) ① ; while(*t) { *s= ② ;s++;t++; } *s=‘\\0’; ③ ; } ① A) s-- B) s++ C) s D) *s ② A) *t B) t C) t-- D) *t++ ③ A) return s B) return t C) return p D) return p-t 7. 下列程序的输出结果是( )。 #include 4 { int **k,*a,b=100; a=&b; k=&a; printf(“%d\\n”,**k); } A) 运行出错 B) 100 C) a的地址 D) b的地址 8. 若定义了以下函数: void f(……) { …… p=(double *)malloc(10*sizeof(double)); …… } p是该函数的形参,要求通过p把动态分配存储单元的地址传回主调函数,则形参p的正确定义应当是( )。 A) double *p 三、编程题 1. 编写一个程序,将用户输入的字符串中的所有数字提取出来。 2. 通过指针处理下面的问题:利用随机函数模拟产生 300 个 1~12 月出生的人数,统计各月所占的出生率。 B) float **p C) double **p D) float *p 【练习题参考答案】 一、填空题 1. 首地址 2. 0 3. 1)int *p=&k; 2)*p=6; 3)int **pp; 4)pp=&p; 5)(**pp)*=2; 4. 整型数组名、指向整型数据的指针值 5. *(p++) 二、选择题 1. B 2. B 3. D 4. A 5. BD 6. BAC 7. B 8. C 三、编程题 1. 编写一个程序,将用户输入的字符串中的所有数字提取出来。 5 #include { char string[81],digit[81]; } 2. 通过指针处理下面的问题:利用随机函数模拟产生 300 个 1~12 月出生的人数,统计 各月所占的出生率。 #include int main(int argc, char* argv[]) { int month[12],*m_pt,i; m_pt=month; srand( (unsigned)time( NULL ) ); //srand()函数产生一个以当前时间开始的随机 种子 char *ps; int i=0; printf(\"enter a string:\\n\"); gets(string); ps=string; while(*ps!='\\0') {if(*ps>='0' && *ps<='9') } digit[i]='\\0'; printf(\"string=%s digit=%s\\n\ { digit[i]=*ps; } ps++; i++; 6 for (i=0;i<12;i++) *(m_pt+i)=0; for (i=0;i<300;i++) (*(m_pt+rand()%12)) ++; printf(\"月份 出生人数 出生率 (总数300)\\n\"); for (i=0;i<12;i++) printf(\"%3d %6d %2.1f℅ \\n\; getchar(); return 0; } 第二部分 上机实训 一、 目的要求 1.掌握指针的概念。 2.学会通过指针处理普通变量和一维数组。 3.学会通过指针处理动态分配的内存。 二、 预习内容 掌握指针变量的使用方法、“&”和“*”的用法、指针变量的赋值、指向数组的指针和指向函数的指针用法。 三、 实验内容及实验步骤 1.要求使用指针处理下面的问题,输入四个整数,按由小到大的顺序输出然后将程序改为:(1)将程序修改为由大到小顺序输出;(2)输入四个字符串,按由小到大顺序输出。 参考程序: 行号 程序代码 1 #include \"stdio.h\" 2 void main() 3 { int a,b,c,d,t; 4 int *pa=&a,*pb=&b,*pc=&c,*pd=&d; 5 printf(\"请输入四个整数:\"); 6 scanf(\"%d%d%d%d\; 7 7 if (*pa>*pb) //第一个数和第二个数比较 8 { t=*pa;*pa=*pb;*pb=t; } //两个数交换 9 if (*pb>*pc) //第二个数和第三个数比较 10 { t=*pb;*pb=*pc;*pc=t; } 11 if (*pc>*pd) //第三个数和第四个数比较 12 { t=*pc;*pc=*pd;*pd=t; } 13 if (*pa>*pb) //第一个数和第二个数比较 14 { t=*pa;*pa=*pb;*pb=t; } 15 if (*pb>*pc) //第二个数和第三个数比较 16 { t=*pb;*pb=*pc;*pc=t; } 17 if (*pa>*pb) //第一个数和第二个数比较 18 { t=*pa;*pa=*pb;*pb=t; } 19 printf(\"\\n 排序结果如下:\"); 20 printf(\"%d,%d,%d,%d\\n\; 21 } 问题 1:将程序修改为由大到小顺序输出。 提示:将程序第 7、9、11、13、15、17 行的“<”号改为“>”号。 问题 2:完成题目的第二部分 提示:对上面的程序作如下修改: 1、打开字符串处理函数的头文件 在第 1 行下面增加 1 行 #include \"string.h\" 2、将整型变量改为字符串变量 第 3、4 行改为: char a[100],b[100],c[100],d[100],t[100]; char *pa=a,*pb=b,*pc=c,*pd=d; 3、将输入整数改为输入字符串 第 6 行改为: scanf(\"%s%s%s%s\; 4、将整数比较大小改为字符串比较大小 8 第 7、9、11、13、15、17 行中原比较整数大小使用字符串比较函数来比较,如第 7 行改为:if (strcmp(pa,pb)>0) 5、将整数赋值改为字符串拷贝 第 8、10、12、14、16、18 行中整数赋值改为使用字符串拷贝函数,如第 8行第 1 个赋值语句改为:strcpy(t,pa); 6、将整数输出改为字符串输出 第 20 行改为: printf(\"\\n%s\\n%s\\n%s\\n%s\\n\\n\; 2. 完善程序,要求使用函数功能:将一个数字字符串转换成一个整数(不得调用C语言提供的将字符串转换为整数的函数)。例如,若输入字符串“-1234”,则函数把它转换为整数值-1234。 #include #include long fun(char *p) { 填写程序 } void main() { char s[6]; long n; printf(\"Enter a string:\\n\"); gets(s); n=fun(s); printf(\"%ld\\n\} 3. 分析下列程序 (1)#include main() { 9 char a[10]=””,*p; p=a; puts(p); } (2) #include main() { int max,x,y,*p1,*p2; printf(“Input x and y:”); scanf(“%d%d”,&x,&y); p1=&x; p2=&y; if(*p1>*p2) max=*p1; else max=*p2; printf(“The max number is %d”,max); } 要求:输入程序,并调试、编译、连接、运行 输出结果 程序(1) 功能为 程序(2) p=&a[3] 你的输入是 输出结果 若将p=a改为输出结果 4. 输入10个整数,将其中最小的数和第一个数对换,把最大的数和最后一个数对换,即把最小数放到最前面,把最大数放到最后面。(用指针实现) 5. 用指向指针的指针的方法对n个整数排序并输出。要求将排序单独写成一个函数。整数和n在主函数中输入。最后在主函数中输出。 10 因篇幅问题不能全部显示,请点此查看更多更全内容