【发布时间】:2020-04-08 11:20:51
【问题描述】:
我已经为这个项目工作了一周,它将于今晚午夜完成。我是一名计算机科学专业的大一学生,对编程很陌生,所以我看不出这段代码有什么问题。该代码应该将事件标题、事件时间和事件日期读入链接列表,并使用事件标题按字母顺序排序。
这是来自文件的输入:
生日 12 30 2018 年 10 月 1 日 婚礼 06 30 2018 年 6 月 15 日 研讨会 05 00 2019 年 2 月 15 日 生日 04 00 2018 年 6 月 15 日 周年纪念日 08 30 2019 年 12 月 9 日由于某种原因,它从未将婚礼事件连接到链表,并且在打印整个链表时,有一个空白节点作为头节点。我一直在研究这个问题,即使在跟踪代码时我也无法弄清楚出了什么问题。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//struct for event time
typedef struct{
int hour;
int minute;
} event_time_t;
//struct for event date
typedef struct{
int month;
int day;
int year;
} event_date_t;
//struct for all event info
struct event{
char event_title[20];
event_time_t event_time;
event_date_t event_date;
struct event *next;
};
typedef struct event event_t;
void add_events (event_t **head_ptr);
void print_event(event_t *head_ptr);
void print_slected_event (event_t *head_ptr, int month, int day, int year);
int main () {
event_t *head_ptr = malloc(sizeof(event_t));
add_events(&head_ptr);
print_event(head_ptr);
print_slected_event(head_ptr,6,15,2018);
return 0;
}
void add_events (event_t **head_ptr){
event_t *temp;
event_t *temp_head = *head_ptr;
event_t *new_node;
scanf(" %s",temp_head->event_title);
scanf("%d",&temp_head->event_time.hour);
scanf("%d",&temp_head->event_time.minute);
scanf("%d",&temp_head->event_date.month);
scanf("%d",&temp_head->event_date.day);
scanf("%d",&temp_head->event_date.year);
temp_head->next = NULL;
while(!feof(stdin)){
new_node = malloc(sizeof(event_t));
scanf(" %s",new_node->event_title);
scanf("%d",&new_node->event_time.hour);
scanf("%d",&new_node->event_time.minute);
scanf("%d",&new_node->event_date.month);
scanf("%d",&new_node->event_date.day);
scanf("%d",&new_node->event_date.year);
if(temp_head->next == NULL){
temp_head->next = new_node;
}
else if(strcmp(temp_head->event_title,new_node->event_title)>0){
new_node->next = temp_head;
temp_head = new_node;
*head_ptr = temp_head;
}
else{
temp = temp_head;
while(temp->next!=NULL){
if(strcmp(temp->event_title,new_node->event_title)==0){
break;
}
if(strcmp(temp->event_title,new_node->event_title)<0){
break;
}
temp = temp->next;
}
new_node->next = temp->next;
temp->next = new_node;
}
}
}
void print_event(event_t *head_ptr){
event_t *temp;
temp = malloc(sizeof(event_t));
temp = head_ptr;
printf("Scedule of Events:\n");
while(temp->next!=NULL){
printf("\t%-13s at: %02d:%02d ",temp->event_title,temp->event_time.hour,temp->event_time.minute);
printf("on: %02d/%02d/%d\n",temp->event_date.month,temp->event_date.day,temp->event_date.year);
temp = temp->next;
}
}
void print_slected_event (event_t *head_ptr, int month, int day, int year){
event_t *temp;
temp = malloc(sizeof(event_t));
temp = head_ptr;
printf("Date: %02d/%02d/%d\n",month,day,year);
printf("Events:\n");
while(temp->next!=NULL){
if(temp->event_date.month == month){
if(temp->event_date.day == day){
if(temp->event_date.year == year){
printf("\t%-13s at: %02d:%02d\n",temp->event_title,temp->event_time.hour,temp->event_time.minute);
}
}
}
temp = temp->next;
}
}
【问题讨论】:
-
仅供参考,
while(!feof(stdin))is wrong。最好你现在而不是以后知道。您的实际 IO 读取都没有经过任何验证,这是一个巨大错误。 -
我的建议是重新设计。与其使用一个读取数据的函数,将其插入列表,然后对列表进行排序,不如将其拆分为多个责任有限的较小函数。遵循KISS 和single-responsibility 原则。因此,一个函数从文件中读取 一个 记录,一个函数将数据插入列表,一个函数对列表进行排序。
-
而且仅供参考,您的
print函数都不应该进行 any 分配。这两个函数的前三行会立即泄漏内存(准确地说,第二行和第三行一致)。 -
打印时,不应测试
temp->next是否为空,而应测试temp。这会让你错过你的婚礼活动。 (打印和插入的不同之处在于打印只需要查看当前节点,插入必须查看两个连续的节点,以便更新它们的链接。) -
@WhozCraig 好的,我做了一些阅读以找出为什么
!feof(stdin)总是错误的,而且它非常有意义,所以我将其更改为while(scanf(" %s",new_node->event_title)==1),它摆脱了那个随机的空头节点。我还摆脱了将内存分配给临时节点的打印功能。 @M Oehm 这更有意义,当我更改它时,它立即开始打印婚礼活动。非常感谢你们,自从课程被取消以来,链表一直很难,但由于阅读了你们的建议,我现在有了更好的理解。
标签: c pointers struct linked-list singly-linked-list