大家好,感谢所有愿意阅读的人!我目前正在开发一个程序,该程序使用单链表打印出一个基于color元素的第一个字母和details int地址数组中的第一个元素的模式,如下所示。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct Node{
char* color;
int** details;
struct Node* next;
}Node;
Node* light_info(char *filename){
Node* head = malloc(sizeof(Node));
Node* second = malloc(sizeof(Node));
Node* third = malloc(sizeof(Node));
Node* fourth = malloc(sizeof(Node));
Node* fifth = malloc(sizeof(Node));
Node* sixth = malloc(sizeof(Node));
head->next = second;
second->next = third;
third->next = fourth;
fourth->next = fifth;
fifth->next = sixth;
sixth->next = NULL;
FILE* fp = fopen(filename, "r");
char* token;
int num1, num2;
int* ptr1 = &num1;
int* ptr2 = &num2;
char line[250];
Node* current = head;
if(head==NULL||second==NULL||third==NULL||fourth==NULL||fifth==NULL||sixth==NULL){
printf("Error. Program has amnesia, not allocating memory...");
}
else{
while((fgets(line,250,fp)!=NULL)&&(current!=NULL)){
token = strtok(line, ",n");
current->color = malloc(20);
current->color = token;
current->details = malloc(sizeof(ptr1)*2);
token = strtok(NULL, ",n");
num1 = atoi(token);
current->details[0]=ptr1;
token = strtok(NULL, ",n");
num2 = atoi(token);
current->details[1]=ptr2;
current = current->next;
}
}
return head;
}
/*Takes a Node pointer as a parameter, and iterates through the linked list,
printing out a number of dashes for each light's brightness score.*/
void off(Node* h){
printf("n***Turning lights off:n");
while(h!=NULL){
int i;
int* ptr = h->details[0];
int b = *ptr;
for(i=0;i<b;i++){
printf("-");
}
printf(" ");
h=h->next;
}
printf("n");
}
/*Takes a Node pointer as a parameter, and iterates through the linked list,
printing out the first letter of each color the amount of times each light is bright.*/
void on(Node* h){
printf("n***Turning lights on:n");
while(h!=NULL){
int i;
int* ptr = h->details[0];
int b = *ptr;
for(i=0;i<b;i++){
printf("%c",h->color[0]);
}
printf(" ");
h=h->next;
}
printf("n");
}
/*Frees data using Node's head and prints exit message.*/
void Exit(Node* h){
printf("Exiting...n");
Node* temp;
while(h!=NULL){
free(h->color);
free(h->details);
temp = h;
h = h->next;
free(temp);
}
}
int main(int argc, char **argv){
if(argc < 2||argc >= 3){
printf("Error. Enter one filename and one filename only.");
}
else{
char* filename = argv[1];
Node* head = light_info(filename);
int vibe_check = 1;
int Switch = 0;
char resp[10];
while(vibe_check){
if(head == NULL){
printf("Head memory not allocated...");
vibe_check = 0;
}
else{
scanf("%s", resp);
if(strcmp(resp,"off")==0){
if(Switch==0){
printf("n--Lights are already off.n");
}
else{
Switch = 0;
off(head);
}
}
else if(strcmp(resp,"on")==0){
if(Switch==1){
printf("n--Lights are already on.n");
}
else{
Switch = 1;
on(head);
}
}
else if(strcmp(resp,"exit")==0){
Exit(head);
}
else{
printf("Invalid command, type in off, on, or exit.");
}
}
}
}
}
这个程序的数据来自一个格式化为这样的文件,
blue,2,0
green,1,0
red,1,0
red,2,1
yellow,2,1
blue,1,1
每当有人在灯亮后打字时,程序的预期输出应该是bb g r rr yy b
,用破折号代替字母。然而,当运行程序时,经过几轮调试和valgrind,我注意到两件事:
- 节点结构没有逐行分配,导致节点与最后一行重复而不是基于行读取的单个数据段
- 根据valgrind的说法,他们在on函数中是一个未初始化的值,我找不到
如果这很长,很抱歉,但如果有任何帮助,我们将不胜感激!如果有必要,我愿意编辑我的帖子和任何建设性的评论!
在light_info
中处理输入的方式有几个错误。
首先,current->color
被分配了一些已分配的内存,然后该内存由于下一行(current->color = token;
(上的分配而丢失。此赋值不会复制token
指向的字符串,但会将color
的值更改为指向同一位置——该位置位于局部变量line
中,并且在函数返回后将悬空。您需要使用strcpy
(或更安全的版本strncpy
(将字符串复制到您分配的空间中。
您可以对current->details[0]=ptr1;
执行类似的操作。ptr1
指向本地num1
变量,因此当函数返回时,该指针也将变为悬空。我不知道为什么details
是一个指针数组。int
数组(可以直接存储值(似乎是更好的选择。(同样适用于details[1]
和ptr2
(。
与此问题无关,针对某个malloc失败的错误检查位于错误的位置。在检查这些指针是否为NULL之前,您已经取消了对它们的引用。该检查应该在完成最后一个malloc
之后,在开始分配所有next
指针之前立即进行。
其他地方也缺乏错误检查。