第七章 指针
1.选择题
(1)设已定义“int a, *p;”,下列赋值表达式中正确的是(C)。
A.*p=a
B.p=*a
C.p=&a
D.*p=&a
指针变量的值是地址,* 为指针运算符,选择C。
(2)若已定义“int a[]={1,2,3,4},*p=a;”, 则下面表达式中值不等于2的是(C)。
A.*(a+1)
B.*(p+1)
C.*(++a)
D.*(++p)
a表示数组所在地址,并非可修改的左值,不可进行++a,C错误。
(3)若已定义“int a[]={1,2,3,4},*p=a+1;”则p[2]的值是(C)。
A.2
B.3
C.4
D.无意义
因为*p = a+1,p[2]同于a[1+2],即4,C正确。
(4)设已定义“char s[]="ABCD";”,printf("%s", s+1)的值为(C)。
A.ABCD1
B.B
C.BCD
D.ABCD
&s等于&s[0],s+1表示s[1]的地址,从s[1]始即从'B'开始输出。
(5)下面对字符串变量的初始化或赋值操作中,错误的是(C)。
A.char a[]="OK";
B.char *a="OK";
C.char a[10]; a="OK";
D.char *a; a="OK";
数组名无法接收对数组元素的整体赋值,C错误。
(6)设已定义 char *ps[2]={"abc","1234"}; 则以下叙述中错误的是(A)。
A.ps为指针变量,它指向一个长度为2的字符串数组
B.ps为指针数组,其两个元素分别存储字符串"abc"和"1234"的地址
C.ps[1][2]的值为'3'
D.*(ps[0]+1)的值为'b'
A中,该数组为二维数组,不能因为只有根据下标简单判断,A错误。
(7)以下程序运行后,输出结果是(C)。
#include<stdio.h>
int main(void)
{
char *s="abcde";
s+=2;
printf("%ld\n",s);
}
A.cde
B.字符c的ASCII码值
C.字符c的地址
D.出错
s储存的是数组"abcde"的首地址,s+2则是'c'的地址,以long int输出则为其地址,C正确。
(8)下面程序的输出是(D)。
#include<stdio.h>
#include<string.h>
int main(void)
{
char p1[10]="abc", *p2="ABC", str[50]="xyz";
strcpy(str+2,strcat(p1,p2));
printf("%s\n",str);
}
A.xyzabcABC
B.zabcABC
C.yzabcABC
D.xyabcABC
strcpy()函数作用是将字符串2复制到字符数组1中。strcat()函数作用是将字符串2连接在字符串1后。strcat(p1,p2)值为"abcABC",s+2地址上的值为str[2],即从'z'处开始延续"abcABC",D正确。
(9)执行以下程序后,y的值是(C)。
#include<stdio.h>
int main(void)
{
int a[] = { 2,4,6,8,10 };
int y = 1, x, * p;
p = &a[1];
for (x = 0; x < 3; x++)
y += *(p + x);
printf("%d\n", y);
}
A.17
B.18
C.19
D.20
y依次加上a[1],a[2],a[3],y = 1+4+6+8,故y值19,C正确。
(10)设已有定义: “char* st="how are you";”, 下列程序段中正确的是(A)。
A.char a[11], *p; strcpy(p=a+1,&st[4]);
B.char a[11]; strcpy(++a, st);
C.char a[11]; strcpy(a, st);
D.char a[], *p; strcpy(p=&a[1],st+2);
B中,a并非可修改的左值,语法错误;C中,a为数组名,无法给数组整体赋值;D中,数组a未完成初始化。
(11)若有说明“int i, j=7, *p=&i;”,则与“i=j”;等价的语句是(B)。
A.i=*p;
B.*p=*&j;
C.i=&j;
D.i=**p;
指针p的值即i的地址。A、D都未涉及j,B中,*p = *&j,即*p = 7,使地址p上的值为7,B正确;C中,i值为j的地址,显然不为7。
(12)以下程序的输出结果是(D)。
#include <stdio.h>
int main(void)
{
char a[] = "programming", b[] = "language";
char* p1, * p2;
int i;
p1 = a;
p2 = b;
for (i = 0; i < 7; i++)
if (*(p1 + i) == *(p2 + i))
printf("%c", *(p1 + i));
return 0;
}
A.gm
B.rg
C.or
D.ga
代码意在通过地址寻找数组a、b中相同的字符,其为ga,D正确。
(13)执行以下程序的输出结果是(A)。
#include <stdio.h>
#include <string.h>
int main(void)
{
char * p[10] = { "abc","aabdfg","dcdbe","abbd","cd" };
printf("%d\n", strlen(p[4]));
return 0;
}
A.2
B.3
C.4
D.5
strlen()函数计算字符串的长度,直到空字符。p[4]值为"cd",A正确。
(14)下面程序段的输出结果是(C)。
int a[][3]={1,2,3,4,5,6,7,8,9,10,11,12},(*p)[3];
p=a;
printf("%d\n",*(*(p+1)+2));
A.3
B.4
C.6
D.7
(*p)[3]表示的是数组长度为3的行变量指针,*(*(p+1)+2)表示第二的第3个元素,即a[1][2],6,C正确。
(15)设有如下函数定义:
int f(char *s)
{
char *p=s;
while(*p!='\0')
p++;
return(p-s);
}
如果在主程序中用下面的语句调用上述函数,则输出结果为(C)。|
printf("%d\n",f("goodbey!"));
A.3
B.6
C.8
D.0
s指向"goodbey!",p也指向该字符串。p指针的移动直到空字符,p和s的差值实际是计算该字符串的有效长度,其为8,C正确。
2.填空题
(1)若有语句int a[10], *p; p=a;,在程序中引用数组元素a[1]的形式还可以是: *(p+1) 、*(a+1) 、 p[1] 。
p=a 同于 p=&a[0]
(2)若有语句:int a[4]={1,2,3,4},*p; p=&a[1];,则printf("%d\n", *p++);的结果是 2 。
p++,先参与运算再自增。
(3)若有定义“int w[10]={23,54,10,33,47,98,72,80,61}, *p=w;”,则不移动指针p,且通过指针p引用值为98的数组元素的表达式是 *(p+5) 。
*p == a[0]
(4)函数sstrcmp()的功能是对两个字符串进行比较。当s所指字符串与t所指字符串相等时,返回值为0;当s所指字符串大于t所指字符串时,返回值大于0;当s所指字符串小于t所指字符串时,返回值小于0。
int sstrcmp( char *s, char *t)
{ while (*s && *t && *s== *t )
{ s++; t++; }
return *s-*t ;
}
入口条件处需判断两字符串同一位置的字符是否相等。返回值反映两字符串大小。
(5)执行下面的语句后,程序的输出是 5, 3 。
int m[]={1,2,3,4,5,6,7,8}, *p1=m+7, *p2=&m[2];
p1-=3;
printf("%d,%d\n",*p1,*p2);
初始化时,*p 等于 &m[7],p1-=3后,*p1值为5,*p2值同m[2],即3。
(6)已知“int a[5] = { 2, 3, 4, 5, 6 }; int *p = a+2;”,表达式 *p*a[3] 的值是 20 。
*p值同a[2],即4,4*5,故结果为20。
(7)以下fun函数的功能:累加数组元素中的值,n为数组元素个数,累加的和放入x所指的存储单元中。
fun(intb[], int n, int *x)
{
int k,r=0;
for (k=0;k<n;k++)
r= r+b[k] ;
*x =r;
}
r = r+b[k];负责累加元素,*x = r;负责存放累加和。
(8)已有定义char *names[]={"Wang","Li","Chen"};语句“printf("Second%sFirst%s",names[1], names[0]);”的运行结果为 SecondLiFirstWang 。
以names[1],names[0]代入即可。
(9)设有变量定义:“int a[]={1,2,3,4,5,6},*p=a+2;”,则计算表达式*(p+2)*p[2]的值是 25 。
*p值同于a[2],*(p+2)值同于a[4],即 5,p[0]同于a[2],p[2]同于a[4]。
(10)判断输入的字符串是否是“回文”,(顺读和倒读都一样的字符串称为“回文”,如level)。
#include "stdio.h"
#include "string.h"
int main(void)
{
char s[80], *t1, *t2;
int m;
gets(s) ;
m=strlen(s);
t1=s;
t2= s+m-1 ;
while(t1<t2)
{
if(*t1!=*t2) break;
else
{
t1++;
t2-- ;
}
}
if (t1<t2) printf("NO\n");
else printf("YES\n");
return 0;
}
第一处获取输入的字符串;第二处,将最后一个有效元素的地址赋给t2;第三处,向头部移动指针。
3.编程题
(1)输入2个字符串,每个字符串的长度均不超过80字符,用自己实现的cmpstr()函数完成这两个字符串的大小比较,cmpstr()函数的功能和字符串比较函数strcmp()的功能相同。
#include<stdio.h>
#include<string.h>
int cmpstr(char* s1, char* s2);
int main(void)
{
int res;
char s1[81], s2[81];
printf("输入字符串1:");
gets(s1);
printf("输入字符串2:");
gets(s2);
res = cmpstr(s1, s2);
if (res > 0)
{
printf("字符串2大于字符串1");
}
else if (res < 0)
{
printf("字符串2小于字符串1");
}
else
{
printf("字符串2等于字符串1");
}
return 0;
}
int cmpstr(char* s1, char* s2)
{
while (*s1 != 0 && *s2 != 0)
{//指针遍历比较
if (*s1 == *s2)
{
s1++;
s2++;
}
else return *s2 - *s1;
}//返回字符串2与字符串1在不同时对应字符的差值
return 0;
}
(2)定义一个函数float reverse(int p[], int n),该函数有两个参数,第一个参数p为形参数组名,第二个参数n为该数组中的元素个数,要求使用reverse()函数将该数组中的所有元素逆序排列,并返回该数组中所有元素的平均值。
float reverse(int p[], int n)
{
int k;
float res = 0;
for (int i = 0; i < n - 1; i++)
{//选择排序
k = i;
for (int j = i + 1; j < n; j++)
{
if (p[j] > p[k])
{
if (p[j] > p[k]) k = j;
}
}
if (k != i)
{
p[k] += p[i];
p[i] = p[k] - p[i];
p[k] -= p[i];
}
res += p[i];
}
res += p[n-1];//加上未取到的最后一个数
res /= n;
return res;
}
(3)定义一个函数delSubstr(),删除字符串中第k个字符开始的m个字符,例如删除字符串abcde第2个字符开始的3个字符,则删除后结果为ae;又如删除字符串abcde第4个字符开始的5个字符,则删除后结果为abc。
int delSubstr(char* s, int k, int m)
{
char* p = s;
int i;
if ((k + m - 1) > strlen(s))
{//移动不符合要求时,返回0
return 0;
}
for (i = k - 1; i < strlen(s) - 1; i++)
{//从第i个字符开始,将后面的值移动到前面
*(p + i) = *(p + i + m);
}
*(p + i) = '\0';
return 1;
}
(4)定义一个函数delSpechar(),使用字符指针删除字符串中的所有指定字符(如把字符串“I love you!”中的o字符删除,得到“I lve yu!”)。
char* delSpechar(char* s, char c)
{
char* p = s, * q = "";
while (*p != '\0')
{
if (*p == c)
{
q = p;
while (*q != '\0')
{
*q = *(q + 1);
q++;
}
}
else p++;
}
return s;
}
(5)求整型二维数组a[M][N]中的最大元素值及最大元素的位置(用指针法引用数组元素)。
void f(int* p, int m, int n)
{//m为二维数组行数,n为列数
int k1 = 0, k2 = 0, r = *p;
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
if (*p < *(p + n * i + j))
{
k1 = i;
k2 = j;
*p = *(p + n * i + j);
printf("%d\t%d\n", k1, k2);
}
}
}
printf("最大值为:%d,a[%d][%d]", *p, k1, k2);
*p = r;//归还*p原值
}
(6)已知字符串str[80],编写函数lstrchar(),实现在数组str中查找字符ch首次出现的位置,如果字符串中找不到该字符,则返回-1。
int lstrchar(char* p, char c)
{
int i = 0, res = -1;
while (*(p + i) != '\0')
{
if (*(p + i) == c)
{
res = i;
return res;//返回该字符下标
}
i++;
}
return res;//找不到则返回原值 -1
}
(7)定义一个整型二维数组并初始化,编程求该数组所有元素的和。要求:分别用数组下标法、一级指针法、二级指针法实现。
#include <stdio.h>
int f1(int s[3][4])
{
int sum = 0;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
sum += s[i][j];
}
}
return sum;
}
int f2(int* p)
{
int sum = 0;
for (int i = 0; i < 3 * 4; i++)
{
sum += *(p + i);
}
return sum;
}
int f3(int (*p)[4])
{
int sum = 0;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
sum += *(*(p + i) + j);
}
}
return sum;
}
int main(void)
{
int a[3][4] = { {4,2,7,9},{1,3,13,0},{-5,6,-11,10} };
printf("数组下标法:%d\n", f1(a));
printf("一级指针法:%d\n", f2(a[0]));
printf("二级指针法:%d\n", f3(a));
return 0;
/*运行结果
数组下标法:39
一级指针法:39
二级指针法:39*/
}
(8)输入一行数字字符存入字符数组str[80]中,用num[10]中的数组元素作为计数器来统计每个数字字符的个数。用下标为0的元素统计字符“0”的个数,用下标为1的元素统计字符“1”出现的次数,……。输出每个奇数字符出现的次数。
#include <stdio.h>
void f(char* p)
{
int num[10] = {0}, sum = 0;
while (*p != '\0')
{
num[*p - '0']++;
p++;//移动指针来实现遍历
}
for (int i = 1; i < 10; i += 2)
{
printf("%d出现的次数:%d\n", i, num[i]);
}
}
int main(void)
{
char str[80];
gets(str);
f(str);
return 0;
}
(9)在主函数中输入10个不等长字符串,用另一函数sort()对它们排序,然后在主函数中输出已排好序的字符串。要求:每个字符串长度均不超过30字符,用指针数组进行处理。
#include <stdio.h>
#include <string.h>
void sort(char * p[10])
{
char* t;
for (int i = 0; i < 9; i++)
{//冒泡
for (int j = 0; j < 10 - i - 1; j++)
{
if (strcmp(p[j], p[j + 1]) > 0)
{
t = p[j];
p[j] = p[j + 1];
p[j + 1] = t;
}
}
}
}
int main(void)
{
char s[10][81], *sp[10];
for (int i = 0; i < 10; i++)
{//指针数组存放二维字符数组的一维地址
gets(s[i]);
sp[i] = s[i];
}
sort(sp);
printf("排序后:\n");
for (int i = 0; i < 10; i++)
{
printf("%s\n", sp[i]);
}
return 0;
}
(10)输入一个字符串,内有数字字符和非数字字符如123a345bcd567,将其中连续的数字作为一个整数,依次存放到整型数组a中,例如,123放在a[0],345放在a[1]中,567放在a[2]中,……,统计共有多少个整数,并输出这些整数。
#include <stdio.h>
int main(void)
{
char ch[64], * p = ch;
int a[64] ={ 0 }, * q = a, count = 0;
gets(ch);
while (*p != '\0')
{
if (*p >= '0' && *p <= '9')
{
*q = *q * 10 + (*p - '0');
if (*(p + 1) < '0' || *(p + 1) > '9')
{//如果后一个字符不是数字,说明当前字符为该数最后一位
q++;
count++;//记录数的个数
}
}
p++;
}
printf("一共有%d个整数\n", count);
for (int i = 0; i < count; i++)
{
printf("%d\n", a[i]);
}
return 0;
}
如有错误不足之处,恳请批评指正。
题目来源:C程序设计教程与实验(第3版) 吉顺如主编
答案参照微信公众号:程序设计及信息技术学习平台