提问人:jvkloc 提问时间:12/12/2022 最后编辑:Ken Whitejvkloc 更新时间:12/12/2022 访问量:51
在循环中,链表似乎是可以的,但在循环之外是空的
Inside a loop a linked list seems to be ok but outside it is empty
问:
我刚开始学习 C,我迷失了试图从文本文件中读取汽车及其制造年份的尝试。该程序显示,当我尝试使用包含以下行的 .txt 文件时,它找不到任何汽车:
Lada 1976
Ferrari 2005
Suzuki 1985
Volvo 1963
Toyota 1993
Honda 2011
我做了一个类似的链表程序,它从用户那里读取一个整数以添加到列表中,而不是一个文件。我认为这是完全相同的,只是现在程序从文件中读取。指针某处出错(我从调试打印中得出的最佳猜测,我添加到了几个地方),或者可能是我以某种方式设法仅在 while 循环内更改节点(另一个猜测)。有人可以指出这里出了什么问题吗?first
#include <stdlib.h>
#include <stdio.h>
typedef struct car {
char brand[15];
int year;
struct car *prev;
struct car *next;
} car;
void readCars(char *fname, car *newCar, car *first, car *last);
void printCars(car *ptr, car *first);
void freeMemory(car *ptr, car *first);
int main(int argc, char *argv[]) {
car *first = NULL; // a pointer to the first node of the linked list
car *last = NULL; // a pointer to the last node of the linked list
car *newCar; // a pointer for new nodes
car *ptr; // a pointer for iterating the linked list
if(argc != 2) {
printf("No filename provided.\n");
exit(0);
}
printf("Reading the file %s.\n", argv[1]);
readCars(argv[1], newCar, first, last);
printCars(ptr, first);
freeMemory(ptr, first);
printf("Program ended.\n");
return(0);
}
void readCars(char *fname, car *newCar, car *first, car *last) {
FILE *tiedosto;
char rivi[22];
if ((tiedosto = fopen(fname, "r")) == NULL) {
printf("Failed to open the file.\nProgram ended.\n");
exit(0);
}
while (fgets(rivi, 22, tiedosto) != NULL) {
if ((newCar = (car*)malloc(sizeof(car))) == NULL) { // allocate memory for a new node
perror("Memory allocation failure.\n");
exit(1);
}
sscanf(rivi, "%s %d", newCar->brand, &newCar->year); // set the car brand and age to the new node
newCar->next = NULL; // set the pointer to next node to NULL as there is no next node
newCar->prev = last; // set the pointer to the previous node to the previous last node (NULL if there was no previous)
if (first == NULL) {
first = newCar; // the new node is the only node so it is the first node
last = newCar; // the new node is the only node so it is also the last node
} else {
last->next = newCar; // the new node is next node of the previous last node
last = newCar; // the new node is now the last node
}
}
fclose(tiedosto);
printf("File read into a linked list.\n");
}
void printCars(car *ptr, car *first) {
if(first == NULL) {
printf("No cars found.\n");
} else {
ptr = first;
int count = 1;
while (ptr != NULL) {
printf("%d. car: %s from the year %d.\n", count, ptr->brand, ptr->year);
count += 1;
ptr = ptr->next;
}
}
}
void freeMemory(car *ptr, car *first) {
ptr = first;
while (ptr != NULL) {
first = ptr->next;
free(ptr);
ptr = first;
}
printf("Memory freed.\n");
}
答:
线条
if (first == NULL) {
first = newCar; // the new node is the only node so it is the first node
last = newCar; // the new node is the only node so it is also the last node
} else {
last->next = newCar; // the new node is next node of the previous last node
last = newCar; // the new node is now the last node
}
在函数中仅修改变量,在函数中修改变量。它们不会修改变量和函数。readCars
first
last
readCars
first
last
main
因此,函数中的变量将保留,因此,就该函数而言,链表保持为空。first
main
NULL
为了解决这个问题,函数不应该将变量的副本传递给函数,而应该传递指向这些变量的指针(即引用)。因此,您应该将函数的参数更改为以下内容:main
first
last
readCars
readCars
void readCars(char *fname, car *newCar, car **first, car **last)
您还应该将上面引用的行更改为以下内容:
if ( *first == NULL ) {
*first = newCar; // the new node is the only node so it is the first node
*last = newCar; // the new node is the only node so it is also the last node
} else {
(*last)->next = newCar; // the new node is next node of the previous last node
(*last) = newCar; // the new node is now the last node
}
此外,函数的参数不作为参数使用。相反,您将其用作局部变量,因此您应该将其声明为局部变量并将其从函数的参数列表中删除。newCar
readCars
编辑:如下面的评论中指出的那样,您正在对函数和中的参数执行相同的操作。您也应该从这些函数中删除该参数。ptr
printCars
freeMemory
评论
car = newCar
ptr = ptr
nullptr
nullptr
std=c2x
std=gnu2x
7. car: from the year 0
fgets
NULL
sscanf
sscanf
if ( sscanf(rivi, "%s %d", newCar->brand, &newCar->year ) != 2 ) { free( newCar ); continue; }
我的解决方案是:
#include <stdlib.h>
#include <stdio.h>
typedef struct car {
char brand[15];
int year;
struct car *prev;
struct car *next;
} car;
void readCars(char *fname, car *newCar, car **first, car **last);
void printCars(car *ptr, car *first);
void freeMemory(car *ptr, car *first);
int main(int argc, char *argv[]) {
car *first = NULL; // a pointer to the first node of the linked list
car *last = NULL; // a pointer to the last node of the linked list
car *newCar; // a pointer for new nodes
car *ptr; // a pointer for iterating the linked list
if(argc != 2) {
printf("No filename provided.\n");
exit(0);
}
printf("Reading the file %s.\n", argv[1]);
readCars(argv[1], newCar, &first, &last);
printCars(ptr, first);
freeMemory(ptr, first);
printf("Program ended.\n");
return(0);
}
void readCars(char *fname, car *newCar, car **first, car **last) {
FILE *tiedosto;
char rivi[22];
if ((tiedosto = fopen(fname, "r")) == NULL) {
printf("Failed to open the file.\nProgram ended.\n");
exit(0);
}
while (fgets(rivi, 22, tiedosto) != NULL) {
if ((newCar = (car*)malloc(sizeof(car))) == NULL) { // allocate memory for a new node
perror("Memory allocation failure.\n");
exit(1);
}
sscanf(rivi, "%s %d", newCar->brand, &newCar->year); // set the car brand and age to the new node
newCar->next = NULL; // set the pointer to next node to NULL as there is no next node
newCar->prev = *last; // set the pointer to the previous node to the previous last node (NULL if there was no previous)
if (*first == NULL) {
*first = newCar; // the new node is the only node so it is the first node
*last = newCar; // the new node is the only node so it is also the last node
} else {
(*last)->next = newCar; // the new node is next node of the previous last node
*last = newCar; // the new node is now the last node
}
}
fclose(tiedosto);
printf("File read into a linked list.\n");
}
void printCars(car *ptr, car *first) {
if(first == NULL) {
printf("No cars found.\n");
} else {
ptr = first;
int count = 1;
while (ptr != NULL) {
printf("%d. car: %s from the year %d.\n", count, ptr->brand, ptr->year);
count += 1;
ptr = ptr->next;
}
}
}
void freeMemory(car *ptr, car *first) {
ptr = first;
while (ptr != NULL) {
first = ptr->next;
free(ptr);
ptr = first;
}
printf("Memory freed.\n");
}
主要区别在于 readCars 需要一个指向第一个和最后一个的指针的指针。这样,当函数结束时,first 和 last 的值不会更改为初始值(在 NULL 中)。 如果您已经理解,请告诉我。
评论
7. car: from the year 0
上一个:MATLAB 散点图图例
评论