从文件中读取各种形式的数据并存储在C中的链表中
Reading various forms of data from a file and storing them in a linked list in C
我没有看到类似这样的东西,所以我决定自己问问。我正在尝试为我的 class 编写一个程序,您可以在其中从文件中读取一组关于杂货的数据并将其存储在堆栈中。
我无法弄清楚如何读入所有不同的数据类型。
数据格式:
(String)Produce, (String) Type, (String) Sold By [quantity], (float) price, (int) In Stock [quantity].
我怎样才能读取这些不同的数据类型并将它们保存到我的产品结构中。
struct produce_Item
{
char produce[20];
char type[20];
char sold_By[20];
float price;
int quantity_In_Stock;
struct produce_Item *next;
}
struct produce_Item *list, **newItem = &list;
do
*newItem = malloc(sizeof(struct produce_Item));
while (*newItem != NULL &&
5 == fscanf(file, "%19s,%19s,%19s,%f,%d",
(*newItem)->produce,
(*newItem)->type,
(*newItem)->sold_By,
&(*newItem)->price,
&(*newItem)->quantity_In_Stock)
&& (newItem = &(*newItem)->next));
free(*newItem);
*newItem = NULL;
请注意,这不会处理描述太长、描述包含空格或数据错误等错误。但是如果保证数据是有序的,如果我没有犯错的话,这应该可以工作。
编辑。它也没有处理内存不足。否则这与 chuxs 的回答相同,只是有点难读:)
读取 link 列表的典型方法是创建一个临时头节点并仅使用其 .next
字段。
#include <stdlib.h>
...
struct produce_Item Head;
struct produce_Item *p = &Head;
p->next = NULL;
然后遍历文件。虽然这是另一个步骤,但如果输入是通过首先读取带有 fgets()
的行来完成的,事情就会容易得多。然后根据需要解析带有 sscanf()
或 strtok()
、strtol()
等的行。一旦扫描成功完成,为新节点分配内存,将数据保存在其中并前进p
。
FILE *file;
char buf[100];
while (fgets(buf, sizeof buf, file) != NULL) {
struct produce_Item Item;
if (5 != sscanf(buf, "%19s ,%19s ,%19s ,%f ,%d", Item.produce, Item.type,
Item.sold_By, &Item.price, &Item.quantity_In_Stock)) Handle_BadData();
Item.next = NULL;
// At this point, all 6 fields are set.
struct produce_Item *Next = malloc(sizeof *Next);
if (Next == NULL) Handle_OOM(); // Out of memory
*Next = Item; // Copy Item to *Next
// Advance p
// Notice that the first time this executes, it set Head.next
p->next = Next;
p = Next;
}
return Head.next; // The head of the list
我没有看到类似这样的东西,所以我决定自己问问。我正在尝试为我的 class 编写一个程序,您可以在其中从文件中读取一组关于杂货的数据并将其存储在堆栈中。
我无法弄清楚如何读入所有不同的数据类型。
数据格式:
(String)Produce, (String) Type, (String) Sold By [quantity], (float) price, (int) In Stock [quantity].
我怎样才能读取这些不同的数据类型并将它们保存到我的产品结构中。
struct produce_Item
{
char produce[20];
char type[20];
char sold_By[20];
float price;
int quantity_In_Stock;
struct produce_Item *next;
}
struct produce_Item *list, **newItem = &list;
do
*newItem = malloc(sizeof(struct produce_Item));
while (*newItem != NULL &&
5 == fscanf(file, "%19s,%19s,%19s,%f,%d",
(*newItem)->produce,
(*newItem)->type,
(*newItem)->sold_By,
&(*newItem)->price,
&(*newItem)->quantity_In_Stock)
&& (newItem = &(*newItem)->next));
free(*newItem);
*newItem = NULL;
请注意,这不会处理描述太长、描述包含空格或数据错误等错误。但是如果保证数据是有序的,如果我没有犯错的话,这应该可以工作。
编辑。它也没有处理内存不足。否则这与 chuxs 的回答相同,只是有点难读:)
读取 link 列表的典型方法是创建一个临时头节点并仅使用其 .next
字段。
#include <stdlib.h>
...
struct produce_Item Head;
struct produce_Item *p = &Head;
p->next = NULL;
然后遍历文件。虽然这是另一个步骤,但如果输入是通过首先读取带有 fgets()
的行来完成的,事情就会容易得多。然后根据需要解析带有 sscanf()
或 strtok()
、strtol()
等的行。一旦扫描成功完成,为新节点分配内存,将数据保存在其中并前进p
。
FILE *file;
char buf[100];
while (fgets(buf, sizeof buf, file) != NULL) {
struct produce_Item Item;
if (5 != sscanf(buf, "%19s ,%19s ,%19s ,%f ,%d", Item.produce, Item.type,
Item.sold_By, &Item.price, &Item.quantity_In_Stock)) Handle_BadData();
Item.next = NULL;
// At this point, all 6 fields are set.
struct produce_Item *Next = malloc(sizeof *Next);
if (Next == NULL) Handle_OOM(); // Out of memory
*Next = Item; // Copy Item to *Next
// Advance p
// Notice that the first time this executes, it set Head.next
p->next = Next;
p = Next;
}
return Head.next; // The head of the list