你也能够上程序咖 (https://meta.chengxuka.com),关上大学幕题板块,岂但有答案,解说,还能够在线答题。
一、选择题
1. 上面程序段的运行后果是()。
int x[5] = {2, 4, 6, 8, 10}, *p, **pp;
p = x;
pp = &p;
printf("%d", *(p++));
printf("%d\n", **pp);
A.4 4
B.2 4
C.2 2
D.4 6
答:B
解析:
题目中先定义了 int 类型的数组 x,又定义两个指针。
而后 p = x,示意将 x 的基地址赋值给 p,所以 p 指向数组中第一个元素。
第一次打印 *(p++)
,获取 p 指向的元素,打印 2,而后指针地位向后挪动一个地位。
因为 pp = &p,示意将 p 的地址赋值给 pp,所以 pp 指向 p,p 通过上次打印时的 ++,曾经向后肯定一个,所以第二个打印 **pp
,打印的就是 4。
2. 对于以下变量定义,正确的赋值是()。
int *p[3], a[3];
A. p=a
B. *p=a[0]
C. p=&a[0]
D. p[0]=&a[0]
答:B
解析:
定义为 int *p[3],a[3];
可知这里 p 是一个指针数组,p 为数组名,所以不能作为赋值号的左操作数,所以选项 A 和 C 不对 *p
即 p[0],所以选项 B 等效于 p[0]=a,如上所说,数组 p 的元素是指针,所以选项 D 是不适合的
3. 下列程序段的输入是()。
int i, a[12] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, *p[4];
for (i = 0; i < 4; i++)
{p[i] = &a[i * 3];
}
printf("%d\n", p[3][2]);
A.12
B.8
C.6
D. 上述程序有谬误
答:A
解析:
题目中定义了一维数组 a[12],以及一个指针数组 p。
当 i=0 时,第一次循环:p[0]=&a[0],p[0] 指向 a[0]
当 i=1 时,第二次循环:p[1]=&a[3],p[1] 指向 a[3]
当 i=2 时,第三次循环:p[2]=&a[6],p[2] 指向 a[6]
当 i=3 时,第四次循环:p[3]=&a[9],p[3] 指向 a[9]
当 i=4 时,循环完结。
p[3][2]
,相当于 p[3]+2
,因为 p[3]
指向 a[9]
,所以 p[3][2]
指向 a[11],a[11] 所对应的值是 12,所以输入 12。
4. 设有如下定义的链表,则值为 7 的表达式是()。
struct st
{
int n;
struct st *next;
} a[3] = {5, &a[1], 7, &a[2], 9, NULL}, *p = a;
A. p->n
B. (p->n)++
C. p->next->n
D. ++p->n
答:C
解析:
题目中 *p=a
,示意指针 p 指向 a 的基地址。
选项 A,打印数组 a 中第一个元素的 n 的值,输入 5。
选项 B,也是打印 5。因为是后加。
选项 C,p 指向 a 的基地址,默认第一个元素,p->next,示意它的下一个元素,就是 7 和 &a[2],打印它的 n,就是 7。
选项 D,因为 -> 的优先级高于 ++,所以这里取 p -> n,数组中第一个元素的 n,为 5,前置 ++,所以打印 6。
5. 上面程序段输出一行字符,按输出的逆序建设一个链表。
struct node
{
char info;
struct node *link;
} * top, *p;
char c;
top = NULL;
while ((c = getchar()) != '\n')
{p = (struct node *)malloc(sizeof(struct node));
p->info = c;
___________;
top = p;
}
A. top->link=p
B. p->link= top
C. top=p->link
D. p=top->link
答:B
解析:
因为要逆序建设链表,所以让 p->link 赋值为 top,而后 top 赋值为 p。
二、填空题
1. 上面程序段的输入后果是()。
const char *s[3] = {"point", "continue", "break"};
for (int i = 2; i >= 0; i--)
for (int j = 2; j > i; j--)
printf("%s\n", s[i] + j);
答:
ntinue
int
oint
解析:
这里是两层循环嵌套,
i= 2 时,j= 2 时,内层循环条件不满足。
i= 1 时,j= 2 时,打印 s[i]+j,就是 s[1]+2,对应 continue,然而因为要加 2,所以从下标为 2 的字符开始,就是 ntinue。
j= 1 时,内层循环条件不满足。
i= 0 时,j= 2 时,打印 s[i]+j,就是 s[0]+2,对应 point,然而因为要加 2,所以从下标为 2 的字符开始,就是 int。
j= 1 时,打印 s[i]+j,就是 s[0]+1,对应 point,然而因为要加 2,所以从下标为 2 的字符开始,就是 o int。
2. 上面程序段的输入后果是()。
const char *st[] = {"Hello", "world", "!"}, **p = st;
p++;
printf("%s-%c\n", *p, **p);
(*p)++;
printf("%s-%c-%c\n", *p, **p, (**p) + 1);
答:
world-w
orld-o-p
解析:
首先定义了指针数组 st,存储的是 3 个字符串的地址。而后又定义了二级指针变量 p,这里 p 存储的是 st 的基地址。
而后 p++,那么指向了外面的第二个字符串的地址。*p
打印该字符串。world,**p
,打印字符 w。
而后 (*p)++
,那么指针向后挪动一位,从 o 开始,打印 orld,**p
打印 o, (**p) + 1
先取 **p
就是 o 而后再加 1,就是 p。
3. 上面程序段的输入后果是()。
static int a[4][4];
int *p[4], i, j;
for (i = 0; i < 4; i++)
p[i] = &a[i][0];
for (i = 0; i < 4; i++)
{*(p[i] + i) = 1;
*(p[i] + 4 - (i + 1)) = 1;
}
for (i = 0; i < 4; i++)
{for (j = 0; j < 4; j++)
printf("%2d", p[i][j]);
printf("\n");
}
答:
1 0 0 1
0 1 1 0
0 1 1 0
1 0 0 1
解析:
首先定义了一个 4X4 的矩阵,默认都是 0。
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
而后又定义了一个指针数组 p。
第一个 for 循环中:p[0]
存储 a[0][0]
的地址。p[1]
存储 a[1][0]
的地址。p[2]
存储 a[2][0]
的地址。p[3]
存储 a[3][0]
的地址。
第二个 for 循环中:
i = 0 时,
*(p[i] + i) = 1
,示意 *(p[0]+0)
,示意 第一行第一个元素批改值为 1。
*(p[i] + 4 - (i + 1)) = 1
,示意 *(p[0]+3)
,示意第一行第四个元素批改值为 1。
i = 1 时,
*(p[i] + i) = 1
,示意 *(p[1]+1)
,示意 第二行第二个元素批改值为 1。
*(p[i] + 4 - (i + 1)) = 1
,示意 *(p[1]+2)
,示意第二行第三个元素批改值为 1。
i = 2 时,
*(p[i] + i) = 1
,示意 *(p[2]+2)
,示意 第三行第三个元素批改值为 1。
*(p[i] + 4 - (i + 1)) = 1
,示意 *(p[2]+2)
,示意第三行第二个元素批改值为 1。
i = 3 时,
*(p[i] + i) = 1
,示意 *(p[3]+3)
,示意 第四行第四个元素批改值为 1。
*(p[i] + 4 - (i + 1)) = 1
,示意 *(p[3]+0)
,示意第四行第一个元素批改值为 1。
第三个 for 循环,打印这个矩阵,所以最终后果为:
1 0 0 1
0 1 1 0
0 1 1 0
1 0 0 1
4. 找出最小字符串。输入多个字符串中最小的字符串。请填空。
const char *st[] = {"bag", "good", "This", "are", "zoo", "park"};
const char *smin = _________;
for (int i = 1; i < 6; i++)
if (_________ < 0)
smin = st[i];
printf("The min string is %s \n",_________);
答:
*st
strcmp(st[i], smin)
smin
解析:
首先定义了一个字符指针数组,想找到外面的最小字符串,首先取第一个字符串赋值给 smin,所以 *smin = *st
,而后循环中顺次比拟字符串大小,strcmp(st[i], smin) <0,那么就取 st[i] 赋给 smin,循环完结后打印 smin 即可。
5. 查找最高分。输出 n(n<=10)个问题,查找最高分并输入。请填空。
#include <stdio.h>
int *GetMax(int score[], int n);
int main(void)
{int i, n, score[10], *p;
scanf("%d", &n);
for (i = 0; i < n; i++)
scanf("%d", &score[i]);
p = _____________;
printf("Max:%d\n", *p);
return 0;
}
int *GetMax(int score[], int n)
{
int i, temp, pos = 0;
temp = score[0];
for (i = 0; i < n; i++)
if (score[i] > temp)
{temp = score[i];
pos = i;
}
return _____________;
}
答:
GetMax(score, n)
score + pos 或者 &score[pos]
解析:
就是定义一个函数,找到数组中的最大值,返回它的地址。所以第一个空调用函数,参数传入数组和 n 的值。第二个空,就是函数中返回后果。数组的实质就是存储数组的基地址,加上 pos 即可。
6. 输入链表中不及格学生的学号和问题。已建设学生 ” 英语 ” 课程的问题链表(问题存于 score 域中,学号存于 num 域中),下列函数的性能是输入不及格学生的学号和问题。请填空。
void require(struct student *head)
{
struct student *p;
if (head != NULL)
{
____________;
while (p != NULL)
{if (____________)
printf("%d%.1f\n", p->num, p->score);
p = p->next;
}
}
}
答:
p = head
p->score < 60
解析:
第一个空将 head 赋值给 p,第二个空判断问题是否及格。
三、程序设计题
题目 1:输入月份英文名:输出月份,输入对应的英文名称。要求用指针数组示意 12 个月的英文名称。例如,输出 5,输入 May。试编写相应程序。
答案代码:
#include <stdio.h>
char *getmonth(int n);
int main()
{// 习题 (11.3.1)
/*
输入月份英文名:输出月份,输入对应的英文名称。要求用指针数组示意 12 个月的英文名称。例如,输出 5,输入 May。试编写相应程序。*/
char *p;
int n;
printf("input n:");
scanf("%d", &n);
p = getmonth(n);
if (p == NULL)
printf("wrong input!\n");
else
printf("%s\n", p);
return 0;
}
char *getmonth(int n)
{
int month;
char *a[12] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November"};
if (n > 0 && n < 13)
{switch (n)
{
case 1:
month = 1;
break;
case 2:
month = 2;
break;
case 3:
month = 3;
break;
case 4:
month = 4;
break;
case 5:
month = 5;
break;
case 6:
month = 6;
break;
case 7:
month = 7;
break;
case 8:
month = 8;
break;
case 9:
month = 9;
break;
case 10:
month = 10;
break;
case 11:
month = 11;
break;
case 12:
month = 12;
break;
}
return a[--month];
}
else
return 0;
}
运行后果:
题目 2:查找星期:定义一个指针数组,将下表的星期信息组织起来,输出一个字符串,在表中查找,若存在,输入该字符串在表中的序号,否则输入 -1。试编写相应程序。
序号 | 星期 |
---|---|
0 | Sunday |
1 | Monday |
2 | Tuesday |
3 | Wednesday |
4 | Thurday |
5 | Friday |
6 | Saturday |
答案代码:
#include <stdio.h>
#include <string.h>
int main()
{// 习题 (11.3.2)
/*
查找星期:定义一个指针数组,将下表的星期信息组织起来,输出一个字符串,在表中查找,若存在,输入该字符串在表中的序号,否则输入 -1。试编写相应程序。*/
char *p[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
char s[10];
printf("input string:");
scanf("%s", s);
int i = 0, j = -2;
for (i = 0; i < 7; i++)
{if (!strcmp(p[i], s))
{
j = i;
break;
}
}
printf("%d\n", j);
return 0;
}
运行后果:
题目 3:计算最长的字符串长度:输出 n(n<10)个字符串,输入其中最长字符串的无效长度。要求自定义函数 int max_ len(char *s[], int n)
,用于计算有 n 个无素的指针数组 s 中最长的字符串的长度。试编写相应程序。
答案代码:
#include <stdio.h>
#include <string.h>
int max_len(char *s[], int n);
int main()
{// 习题 (11.3.3)
/*
计算最长的字符串长度:输出 n(n<10)个字符串,输入其中最长字符串的无效长度。要求自定义函数 int max_ len(char *s[],int n),用于计算有 n 个无素的指针数组 s 中最长的字符串的长度。试编写相应程序。*/
int i, n;
char *s[10];
char a[10][10];
printf("input n(n<10):");
scanf("%d", &n);
printf("input %d string :\n", n);
for (i = 0; i < n; i++)
{scanf("%s", a[i]);
s[i] = a[i];
}
printf("%d\n", max_len(s, n));
return 0;
}
int max_len(char *s[], int n)
{
int i, j = 0;
for (i = 0; i < n; i++)
{if (strlen(s[i]) > strlen(s[j]))
{j = i;}
}
return strlen(s[j]);
}
运行后果:
题目 4:字符串的连贯:输出两个字符串,输入连贯后的字符串。要求自定义函数 char *streat(char *s, char *t)
,将字符串 t 复制到字符串 s 的末端,并且返回字符串 s 的首地址。试编写相应程序。
答案代码:
#include <stdio.h>
char *streat(char *s, char *t);
int main()
{// 习题 (11.3.4)
/*
字符串的连贯:输出两个字符串,输入连贯后的字符串。要求自定义函数 char *streat(char *s, char *t),将字符串 t 复制到字符串 s 的末端,并且返回字符串 s 的首地址。*/
char s[80], t[80];
printf("input 1 string s:");
gets(s);
printf("input 2 string t:");
gets(t);
printf("%s\n", streat(s, t));
return 0;
}
char *streat(char *s, char *t)
{
int i = 0;
int j = 0;
while (s[i] != '\0')
{i++;}
while (t[j] != '\0')
{s[i] = t[j];
i++;
j++;
}
return s;
}
运行后果:
题目 5:指定地位输入字符串:输出一个字符串后再输出两个字符,输入此字符串中从与第 1 个字符匹配的地位开始到与第 2 个字符匹配的地位完结的所有字符。例如,输出字符串 “program” 与 2 个字符 “r” 和 “g” 后,输入 “rog”。要求自定义函数 char *match(char *s,char ch1, char ch2)
返回后果字符串的首地址。试编写相应程序。
答案代码:
#include <stdio.h>
#include <string.h>
char *match(char *s, char ch1, char ch2);
int main()
{// 习题 (11.3.5)
/*
指定地位输入字符串:输出一个字符串后再输出两个字符,输入此字符串中从与第 1 个字符匹配的地位开始到与第 2 个字符匹配的地位完结的所有字符。例如,输出字符串 "program" 与 2 个字符 "r" 和 "g" 后,输入 "rog"。要求自定义函数 char *match(char *s,char ch1, char ch2) 返回后果字符串的首地址。*/
char s[100], *p;
char ch1, ch2;
printf("input string:");
scanf("%s", s);
getchar();
printf("input two char:");
scanf("%c %c", &ch1, &ch2);
p = match(s, ch1, ch2);
if (p != NULL)
printf("%s\n", p);
else
printf("Not found!\n");
return 0;
}
char *match(char *s, char ch1, char ch2)
{char c[100], *p;
int i = 0;
int j = 0;
int start = -1;
int end = -1;
int k;
while (s[i] != '\0')
{if (s[i] == ch1) // 找到起始下标
{start = i;}
if (s[i] == ch2) // 找到完结下标
{
end = i;
break; // 如果找到了,就能够间接完结 while 循环了。}
i++;
}
if (start >= 0 && start <= end)
{
// 遍历 start 到 end 的字符
k = start;
while (k <= end)
{c[j] = s[k];
k++;
j++;
}
c[j] = '\0';
p = c;
return p;
}
else
{return NULL;}
}
运行后果:
题目 6:查找子串:输出两个字符串 s 和 t,在字符串 s 中查找子串 t,输入起始地位,若不存在,则输入 -1。要求自定义函数 char *search(char *s, char *t)
返回子串 t 的首地址,若未找到,则返回 NULL。试编写相应程序。
答案代码:
#include <stdio.h>
#include <string.h>
char *search(char *s, char *t);
int main()
{// 习题 (11.3.6)
/*
查找子串:输出两个字符串 s 和 t,在字符串 s 中查找子串 t,输入起始地位,若不存在,则输入 -1。要求自定义函数 char *search(char *s, char *t) 返回子串 t 的首地址,若未找到,则返回 NULL。*/
char s[100], t[100], *p;
printf("input string:");
scanf("%s", s);
printf("input substring:");
scanf("%s", t);
p = search(s, t);
if (p != NULL)
{printf("%ld\n", p - s);
}
else
{printf("-1\n");
}
return 0;
}
char *search(char *s, char *t)
{int size_t = strlen(t), size_s = strlen(s), T, i, j;
char *p = NULL;
for (i = 0; i <= (size_s - size_t); i++)
{
p = s + i;
T = 1;
for (j = 0; j < size_t; j++)
{if (*p != *(t + j))
{
T = 0;
break;
}
p++;
}
if (T == 1)
break;
}
if (T == 0)
return NULL;
else
return s + i;
}
运行后果:
题目 7:奇数值结点链表:输出若干个正整数(输出 -1 为完结标记)建设一个单向链表,头指针为 L,将链表 L 中奇数值的结点从新组成个新的链表 NEW,并输入新建链表的信息。试编写相应程序。
答案代码:
#include <stdio.h>
#include <stdlib.h>
struct ListNode
{
int data;
struct ListNode *next;
};
struct ListNode *readlist();
struct ListNode *getodd(struct ListNode **L);
void printlist(struct ListNode *L);
int main()
{// 习题 (11.3.7)
/*
奇数值结点链表:输出若干个正整数(输出 -1 为完结标记)建设一个单向链表,头指针为 L,将链表 L 中奇数值的结点从新组成个新的链表 NEW,并输入新建链表的信息。*/
struct ListNode *L, *Odd;
L = readlist();
Odd = getodd(&L);
printlist(Odd);
printlist(L);
return 0;
}
void printlist(struct ListNode *L)
{
struct ListNode *p = L;
while (p)
{printf("%d", p->data);
p = p->next;
}
printf("\n");
}
struct ListNode *readlist()
{
int data; // 输出数据
int size = sizeof(struct ListNode); // 单个链表结点占据的内存
struct ListNode *head, *tail, *p;
head = tail = NULL;
printf("input number:");
scanf("%d", &data);
while (data != -1)
{p = (struct ListNode *)malloc(size);
p->data = data;
p->next = NULL;
if (head == NULL)
{head = p;}
else
{tail->next = p;}
tail = p;
scanf("%d", &data);
}
return head;
}
struct ListNode *getodd(struct ListNode **L)
{
int data;
int size = sizeof(struct ListNode);
struct ListNode *head, *tail, *pNew; // 链表 New
struct ListNode *ptr1, *ptr2;
head = tail = NULL;
// L 链表的 head 是奇数
while (*L != NULL && (*L)->data % 2 != 0)
{data = (*L)->data;
// 将 L 链表的奇数从新组成一个新的链表
pNew = (struct ListNode *)malloc(size);
pNew->data = data;
pNew->next = NULL;
if (head == NULL)
{head = pNew;}
else
{tail->next = pNew;}
tail = pNew;
// 删除 L 链表的奇数
ptr2 = *L;
*L = (*L)->next;
free(ptr2);
}
if (*L == NULL)
{return NULL;}
// L 链表的 head 非奇数
ptr1 = *L;
ptr2 = (*L)->next;
while (ptr2 != NULL)
{
data = ptr2->data;
if (data % 2 != 0)
{
// 将 L 链表的奇数从新组成一个新的链表
pNew = (struct ListNode *)malloc(size);
pNew->data = data;
pNew->next = NULL;
if (head == NULL)
{head = pNew;}
else
{tail->next = pNew;}
tail = pNew;
// 删除 L 链表的奇数
ptr1->next = ptr2->next;
free(ptr2);
}
else
{ptr1 = ptr2;}
ptr2 = ptr1->next;
}
return head;
}
运行后果:
题目 8:删除结点:输出若干个正整数(输出 -1 为完结标记)建设一个单向链表,再输出一个整数 m,删除链表中值为 m 的所有结点。试编写相应程序。
答案代码:
#include <stdio.h>
#include <stdlib.h>
struct ListNode
{
int data;
struct ListNode *next;
};
struct ListNode *readlist();
struct ListNode *deletem(struct ListNode *L, int m);
void printlist(struct ListNode *L);
int main()
{// 习题 (11.3.8)
/*
删除结点:输出若干个正整数(输出 -1 为完结标记)建设一个单向链表,再输出一个整数 m,删除链表中值为 m 的所有结点。*/
int m;
struct ListNode *L = readlist();
printf("input m:");
scanf("%d", &m);
L = deletem(L, m);
printlist(L);
return 0;
}
void printlist(struct ListNode *L)
{
struct ListNode *p = L;
while (p)
{printf("%d", p->data);
p = p->next;
}
printf("\n");
}
struct ListNode *readlist()
{
int data;
int size = sizeof(struct ListNode);
struct ListNode *head, *tail, *p;
head = tail = NULL;
printf("input number:");
scanf("%d", &data);
while (data != -1)
{p = (struct ListNode *)malloc(size);
p->data = data;
p->next = NULL;
if (head == NULL)
{head = p;}
else
{tail->next = p;}
tail = p;
scanf("%d", &data);
}
return head;
}
struct ListNode *deletem(struct ListNode *L, int m)
{
struct ListNode *ptr1, *ptr2;
// 要被删除结点为表头结点
while (L != NULL && L->data == m)
{
ptr2 = L;
L = L->next;
free(ptr2);
}
// 链表空
if (L == NULL)
{return NULL;}
// 要被删除结点为非表头结点
ptr1 = L;
ptr2 = L->next; // 从表头的下一个结点搜寻所有合乎删除要求的结点
while (ptr2 != NULL)
{if (ptr2->data == m) // ptr2 所指结点合乎删除要求
{
ptr1->next = ptr2->next;
free(ptr2);
}
else
{ptr1 = ptr2; // ptr1 后移一个结点}
ptr2 = ptr1->next; // ptr2 指向 ptr1 的后一个结点
}
return L;
}
运行后果: