C语言程序设计第五版谭浩强第九章答案


C语言程序设计第五版谭浩强课后答案 第九章习题答案_C语言程序设计谭浩强课后答案

1.定义一个结构体变量(包括年、月、日)。计算该日在本年中是第几天,注意闰年问题。

解题思路及答案:

  • 用一个日期数组保存每一月的天数,二月的天数记为28天,后面根据输入的时间确定是否是闰年的二月,如果是,天数在加1。
#include <stdio.h>

struct Date{
int year;
int month;
int day;
};

int main(){
struct Date date;
printf("Please give date: ");
scanf("%d%d%d", &date.year, &date.month, &date.day);
int Days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

int i, days = 0;
for (i = 1; i < date.month; i++)
days += Days[i];
days += date.day;
//如果包含闰年的二月,天数加1
if(date.month > 2)
{
if (date.year%400 == 0 || (date.year%4 == 0 && date.year%100 != 0)){
++days;
}
}
printf("It's day %d in the year.\n", days);
return 0;
}

运行截图:

C语言程序设计第五版谭浩强课后答案 第九章习题答案_习题答案_02

2.写一个函数days,实现第1 题的计算。由主函数将年、月、日传递给days函数,计算后将日子数传回主函数输出。

#include <stdio.h>

struct Date{
int year;
int month;
int day;
};

int Days(struct Date date)
{
static int Days[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

int i, days = 0;
for (i = 1; i < date.month; i++)
days += Days[i];
days += date.day;
//如果包含闰年的二月,天数加1
if (date.month > 2)
{
if (date.year % 400 == 0 || (date.year % 4 == 0 && date.year % 100 != 0)){
++days;
}
}
return days;
}

int main(){
struct Date date;
printf("Please give date: ");
scanf("%d%d%d", &date.year, &date.month, &date.day);
int days = Days(date);
printf("It's day %d in the year.\n", days);
return 0;
}

运行截图:

C语言程序设计第五版谭浩强课后答案 第九章习题答案_C语言程序设计谭浩强课后答案_03

3.编写一个函数print,打印一个学生的成绩数组,该数组中有5个学生的数据记录,每个记录包括num,name,score[3],用主函数输人这些记录,用print函数输出这些记录。

#include <stdio.h>

#define
//定义一个student结构体数组,包含5个元素
struct student_t{
int num;
char name[NAMLEN];
int score[3];
} students[5];

void print(struct student_t *stu);

int main(){
for (int i = 0; i < 5; i++){
scanf("%d%s%d%d%d", &students[i].num, students[i].name, &students[i].score[0],
&students[i].score[1], &students[i].score[2]);
}
print(students);
return 0;
}

void print(struct student_t *stu){
for (int i = 0; i < 5; i++){
printf("%d %s %d %d %d\n", students[i].num, students[i].name, students[i].score[0],
students[i].score[1], students[i].score[2]);
}
}

运行截图

C语言程序设计第五版谭浩强课后答案 第九章习题答案_习题答案_04

4.在第3题的基础上,编写一个函数input,用来输人5个学生的数据记录。

#include <stdio.h>

#define
//定义一个student结构体数组,包含5个元素
struct student_t{
int num;
char name[NAMLEN];
int score[3];
} students[5];

void print(struct student_t *stu);
void input(struct student_t *stu);

int main(){
input(students);
print(students);
return 0;
}

void input(struct student_t *stu)
{
for (int i = 0; i < 5; i++){
scanf("%d%s%d%d%d", &students[i].num, students[i].name, &students[i].score[0],
&students[i].score[1], &students[i].score[2]);
}
}

void print(struct student_t *stu){
for (int i = 0; i < 5; i++){
printf("%d %s %d %d %d\n", students[i].num, students[i].name, students[i].score[0],
students[i].score[1], students[i].score[2]);
}
}

运行截图:

C语言程序设计第五版谭浩强课后答案 第九章习题答案_C语言程序设计谭浩强课后答案_05

5.有10个学生,每个学生的数据包括学号、姓名、3门课程的成绩,从键盘输人10个学生数据,要求输出3门课程总平均成绩,以及最高分的学生的数据(包括学号、姓名、3门课程成绩、平均分数)。

#include <stdio.h>

#define
#define

typedef struct student_t{
int num;
char name[NAMLEN];
int score[3];
} student;

int main(){
student students[STUCNT];
int maxi = 0, maxsum = 0;
double aver_0 = 0, aver_1 = 0, aver_2 = 0;
for (int i = 0; i < STUCNT; i++){
scanf("%d%s%d%d%d", &students[i].num, students[i].name, &students[i].score[0], &students[i].score[1], &students[i].score[2]);
int sum = students[i].score[0] + students[i].score[1] + students[i].score[2];
if (sum > maxsum){
maxsum = sum;
maxi = i;
}
aver_0 += students[i].score[0];
aver_1 += students[i].score[1];
aver_2 += students[i].score[2];
}
aver_0 /= STUCNT;
aver_1 /= STUCNT;
aver_2 /= STUCNT;
printf("%lf %lf %lf\n", aver_0, aver_1, aver_2);
printf("%d %s %d %d %d %lf\n", students[maxi].num, students[maxi].name, students[maxi].score[0], students[maxi].score[1], students[maxi].score[2],
(students[maxi].score[0] + students[maxi].score[1] + students[maxi].score[2]) / 3.0);
return 0;
}

运行截图:

C语言程序设计第五版谭浩强课后答案 第九章习题答案_链表_06

6.13个人围成一圈,从第1个人开始顺序报号1,2,3。凡报到3者退出圈子。找出最后留在圈子中的人原来的序号。要求用链表实现。

解题思路及答案:

创建一个环形链表,给链表中的每一个节点从1~13编号,然后开始淘汰过程,对于淘汰的节点,序号置为0,淘汰完成之后,找到序号不为0的即为最后留下的。

#include <stdio.h>
#define
typedef struct people
{
int num;
struct people *next;
} people;

int main()
{
int count = NUM;
people p[NUM];
people *head;
head = p; //head 指向p[0]
//1~13编号
for (int i = 0; i < NUM; i++)
{
head->num = i + 1;
head->next = &p[i + 1];
head = head->next;
}
//最后一个元素指向第一个元素 , 形成环
p[NUM - 1].next = p;

int i = 1;
head = p;
while (count > 1)
{
//跳过已经被淘汰的节点
if (head->num == 0)
{
head = head->next;
continue;
}
if (i == 3)
{
//被淘汰的节点,num置为0
printf("第 %d 位置被淘汰\n", head->num);
head->num = 0;
count--;
}
head = head->next;
i++;
if (i > 3)
{
i = 1;
}
}
printf("--------------\n");
while (head->num == 0)
{
//非0节点即为最后留下的
head = head->next;
if (head->num != 0)
{
printf("留到最后的是 %d \n", head->num);
}
}

return 0;
}

运行截图:

C语言程序设计第五版谭浩强课后答案 第九章习题答案_链表_07

7.在第9章例9.9和例9.10的基础上,写一个函数del,用来删除动态链表中指定的节点

解题思路及答案:

首先创建一个带头的单链表,然后让用户输入需要删除的节点,调用del函数,找到需要删除的节点,把待删除节点的前驱和后继重新链接。

#include <stdio.h>
#include <stdlib.h>

typedef struct LNode
{
int num;
struct LNode *next;
} LNode;

//创建含有n个值的节点
LNode* creat(int n)
{
LNode *head, *p;
head = (LNode *)malloc(sizeof(LNode));
p = head; //头节点为0 加上头节点共n + 1个节点
head->num = 0;
head->next = NULL;
for (int i = 1; i <= n; i++)
{
LNode *newNode = (LNode *)malloc(sizeof(LNode));
newNode->num = i;
newNode->next = NULL;
p->next = newNode;
p = p->next;
}
return head;
}

//删除值为n的节点
void del(int n, LNode *head)
{
LNode *pre, *current;
pre = head;
current = head->next;
//从第一个有效节点开始查找待删除节点
printf("delete node %d\n", n);
while (current != NULL)
{
//找到待删除节点,重新链接,释放待删除节点
if (current->num == n)
{
pre->next = current->next;
free(current);
break;
}
//更新查找位置
pre = current;
current = current->next;
}
}

int main()
{
LNode *head, *p;
int n;
head = creat(10);
printf("请输入需要删除的节点:1-10\n");
scanf("%d", &n);
del(n, head);
int i = 1;
p = head->next;
while (p != NULL)
{
printf("p %d.num -> %d\n", i, p->num);
p = p->next;
i++;
}
return 0;
}

运行截图:

C语言程序设计第五版谭浩强课后答案 第九章习题答案_链表_08

8.写一个函数insert,用来向一个动态链表插入结点

#include <stdio.h>
#include <stdlib.h>

typedef struct LNode
{
int num;
struct LNode *next;
} LNode;

void insert(int n, LNode *node)
{
//创建新节点
LNode *newNode = (LNode *)malloc(sizeof(LNode));
newNode->num = n;

LNode* next = node->next;

// node ---> newNode ---> next
newNode->next = next;
node->next = newNode;
}

LNode* creat(int n)
{
LNode *head, *p;
head = (LNode *)malloc(sizeof(LNode));
p = head; //头节点为0 加上头节点共11个节点
head->num = 0;
head->next = NULL;
for (int i = 1; i <= n; i++)
{
LNode *newNode = (LNode *)malloc(sizeof(LNode));
newNode->num = i;
newNode->next = NULL;
p->next = newNode;
p = p->next;
}
return head;
}

void printNode(LNode* head)
{
LNode* p = head->next;
while (p != NULL)
{
printf("num -> %d\n", p->num);
p = p->next;
}
}

int main()
{
LNode *head;
int n;
head = creat(10);
printNode(head);
printf("请输入需要插入的节点:\n");
scanf("%d", &n);
insert(n, head);
printf("链表的新内容:\n");
printNode(head);
return 0;
}

运行截图:

C语言程序设计第五版谭浩强课后答案 第九章习题答案_C语言程序设计谭浩强课后答案_09

9.综合本章例9.9(建立链表的函数creat)、例9.10(输出链表的函数print)和本章习题第7题(删除链表中结点的函数del)、第8题(插入结点的函数insert),再编写一个主函数,先后调用这些函数。用以上5个函数组成一个程序,实现链表的建立、输出、删除和插入,在主函数中指定需要删除和插人的结点的数据。

#include <stdio.h>
#include <stdlib.h>
#define
typedef struct LNode
{
int num;
struct LNode *next;
} LNode;

LNode* create(int n)
{
LNode *head, *p;
head = (LNode *)malloc(sizeof(LNode));
p = head; //头节点为0 加上头节点共11个节点
head->num = 0;
head->next = NULL;
for (int i = 1; i <= n; i++)
{
LNode *newNode = (LNode *)malloc(sizeof(LNode));
newNode->num = i;
newNode->next = NULL;
p->next = newNode;
p = p->next;
}
return head;
}
//在指定位置插入数据
void insert(int n, int positon, LNode *root)
{
//首先找到指定位置
while (positon--)
{
root = root->next;
}
//插入新的数据,重新链接插入点的前后节点关系
LNode *newNode = (LNode *)malloc(sizeof(LNode));
newNode->num = n;
newNode->next = root->next;
root->next = newNode;
}
void del(int n, LNode *root)
{
LNode *pre;
while (root->num != n)
{
pre = root;
root = root->next;
}
pre->next = root->next;
}
void printList(LNode *root)
{
printf("----\n");
int i = 0;
while (root != NULL)
{
printf("node %d -> %d\n", i, root->num);
root = root->next;
i++;
}
}

int main()
{
int n, position;
printf("请输入插入/删除的数,及插入的位置,位置最大为:%d\n", COUNT);
scanf("%d %d", &n, &position);
LNode *head = create(COUNT);
printList(head->next);
insert(n, position, head->next);
printList(head->next);
del(n, head->next);
printList(head->next);
return 0;
}

运行截图:

C语言程序设计第五版谭浩强课后答案 第九章习题答案_C语言程序设计谭浩强课后答案_10

10.已有a,b两个链表,每个链表中的结点包括学号、成绩。要求把两个链表合并, 按学号升序排列。

解题思路及答案:

首先合并两个链表,然后采用选择排序,给合并之后的链表进行排序。

#include <stdio.h>
typedef struct student
{
int num;
double grade;
struct student *next;
} student;

student *merge(student *a, student *b)
{
//先合并,后排序
student *head = a;
while (a->next != NULL)
{
a = a->next;
}
a->next = b;
//选择排序,每次选最小的,放在未排序的链表头部
student *pre;
pre = head;
while (pre->next != NULL)
{
a = pre->next;
while (a != NULL)
{
if (pre->num > a->num)
{
int num = pre->num;
double grade = pre->grade;
pre->num = a->num;
pre->grade = a->grade;
a->num = num;
a->grade = grade;
}
a = a->next;
}
pre = pre->next;
}
return head;
}
int main()
{
student a[3] = {{1, 79}, {4, 36}, {5, 79}};
for (int i = 0; i < 2; i++)
{
a[i].next = &a[i + 1];
}

student b[2] = {{2, 38}, {6, 98}};
for (int i = 0; i < 1; i++)
{
b[i].next = &b[i + 1];
}
student *combine = merge(a, b);
while (combine != NULL)
{
printf("%d -> %.2lf\n", combine->num, combine->grade);
combine = combine->next;
}

return 0;
}

运行截图:

C语言程序设计第五版谭浩强课后答案 第九章习题答案_C语言程序设计谭浩强课后答案_11

11.有两个链表a和b,设结点中包含学号、姓名。从a链表中删去与b链表中有相同学号的那些结点。

解题思路及答案:

对于b链表中的每一个节点,都从a链表的表头开始查找,如果可以找到,直接删除,如果找不到,继续从a链表表头找下一个b的节点。

#include <stdio.h>
typedef struct student
{
int num;
double grade;
struct student *next;
} student;
student *del(student *a, student *b)
{
student *pre, *current, *head;
head = a;

while (b != NULL)
{
//重置指针指向a链表的头部
pre = head;
current = head->next;
//a 链表的头等于b
if (pre->num == b->num)
{
pre->next = NULL;
pre = current;
current = current->next;
//更新表头
head = pre;
}
else
{
while (pre->next != NULL)
{
if (current->num == b->num)
{
//找到就删除
pre->next = current->next;
break;
}
else
{
//否则继续遍历
pre = pre->next;
current = current->next;
}
}
}
b = b->next;
}
return head;
}

void printList(student *root)
{
printf("----\n");
int i = 0;
while (root != NULL)
{
printf("student %d -> %d -> %.2lf\n", i, root->num, root->grade);
root = root->next;
i++;
}
}

int main()
{
student a[3] = { { 1, 79 }, { 4, 36 }, { 5, 79 } };
for (int i = 0; i < 2; i++)
{
a[i].next = &a[i + 1];
}
a[2].next = NULL;
printf("链表a:\n");
printList(&a[0]);

student b[2] = { { 5, 38 }, { 4, 98 } };
for (int i = 0; i < 1; i++)
{
b[i].next = &b[i + 1];
}
b[1].next = NULL;
printf("链表b:\n");
printList(&b[0]);
student *combine = del(a, b);
printf("删除之后:\n");
while (combine != NULL)
{
printf("%d -> %.2lf\n", combine->num, combine->grade);
combine = combine->next;
}

return 0;
}

运行截图:

C语言程序设计第五版谭浩强课后答案 第九章习题答案_C语言程序设计谭浩强课后答案_12

12.建立一个链表,每个结点包括:学号、姓名、性别、年龄。输入一个年龄,如果链表中的结点所包含的年龄等于此年龄,则将此结点删去。

#include <stdio.h>
#include <stdio.h>
typedef struct student
{
int num;
char sex[10];
char name[100];
int age;
struct student *next;
} student;

void printList(student *root)
{
printf("----\n");
while (root != NULL)
{
printf("num:%d, sex: %s, name: %s, age: %d\n", root->num, root->sex, root->name, root->age);
root = root->next;
}
}

int main()
{
student a[] = { { 1, "woman", "apple", 12 }, { 4, "woman", "banbana", 36 }, { 5, "man", "candy", 79 }, { 5, "man", "danny", 36 }, { 4, "man", "enjoy", 98 } };
for (int i = 0; i < 4; i++)
{
a[i].next = &a[i + 1];
}
a[4].next = NULL;

printList(&a[0]);

int n;
printf("请输入要删除的年龄:\n");
scanf("%d", &n);
student *pre = a, *current = a->next, *head;

head = a;
while (current != NULL)
{
//如果头结点需要删除,则更新头结点
if (head->age == n)
{
pre->next = NULL;
pre = current;
current = current->next;
head = pre;
}
else
{
//删除节点,重新链接
if (current->age == n)
{
pre->next = current->next;
}
pre = current;
current = current->next;
}
}
printList(head);

return 0;
}

运行截图:

C语言程序设计第五版谭浩强课后答案 第九章习题答案_习题答案_13

C语言程序设计第五版谭浩强更多答案