你也能够上程序咖(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;}
运行后果: