【发布时间】:2015-04-17 15:21:51
【问题描述】:
我正在制作一个包含在数组中的节点的链接列表。尽管这可能没有意义,即使节点是物理顺序的,因为它们在一个数组中,但它们按照“链接”字段的值是逻辑顺序的。
我创建了一个库以利用链表及其相关功能。将其视为 Java 中 LinkedList 类的 C 等价物。因此,每个节点都能够通过 void 指针引用任何类型的数据类型。
这是linkedlist.h头文件:
#define listSize 100
struct Node
{
union{
void *dataPtr;
int countr;
}dataItem;
int link;
};
void initializeList(struct Node[], int);
int findEmptyNode(struct Node[], int);
void attachNode(struct Node[], int, int);
void displayList(struct Node[], int, void(*)(void*));
void insertNode(struct Node[], int, int, int);
int search2Insert(struct Node[], int, int);
void deleteNode(struct Node[], int, int);
int search2delete(struct Node[], int, int);
int searchList(struct Node[], int, int, int(*)(void*, void*), int);
void initializeList(struct Node LL[], int Head)
{
LL[Head].link = -5;
LL[Head].dataItem.countr = 0;
for (int x = 1; x < listSize; x++)
LL[x].link = -1;
}
int findEmptyNode(struct Node LL[], int head)
{
int temp = head;
while (LL[temp].link != -1)
temp++;
return temp;
}
void attachNode(struct Node LL[], int Header, int index)
{
int temp = Header;
while (LL[temp].link != -5)
temp = LL[temp].link;
LL[index].link = LL[temp].link;
LL[temp].link = index;
LL[Header].dataItem.countr++;
}
void displayList(struct Node LL[], int Head, void(*ptr)(void*))
{
int temp = LL[Head].link;
while (temp != -5)
{
ptr(LL[temp].dataItem.dataPtr);
temp = LL[temp].link;
}
}
void insertNode(struct Node LL[], int current, int index, int head)
{
LL[index].link = LL[current].link;
LL[current].link = index;
LL[head].dataItem.countr++;
}
void deleteNode(struct Node LL[], int Head, int current)
{
int oldNode = LL[current].link;
LL[current].link = LL[oldNode].link;
LL[oldNode].link = -1;
LL[Head].dataItem.countr--;
}
int searchList(struct Node LL[], int head, int ndex, int(*ptr)(void*, void*), int relation)
{
int temp = head;
int nodeRef, found = 0;
while (LL[temp].link != -5 && found == 0)
{
nodeRef = LL[temp].link;
if (ptr(LL[nodeRef].dataItem.dataPtr, LL[ndex].dataItem.dataPtr) == relation)
found = 1;
else
temp = LL[temp].link;
}
return temp;
}
我正在利用这个头文件来保存产品结构的链接列表。我遇到的问题是我的应用程序特定 c 文件的更新部分不起作用。
作为一个快速概览,我在下面的“更新”sn-p 中评论了每条指令的作用
if (choice == 4)
{
newIndex = findEmptyNode(LinkedList, Header);// this retrieves the index of an empty node
printf("\nUpdate item by searching for it by product code\n");
getProdCode(&LinkedList[newIndex]);// this fills out a "template" with the product structure that contains the "product code" you're looking for
current = searchList(LinkedList, Header, newIndex, comparInt, 0);//this takes that new template node and compares it against all other nodes until it finds on with the same product structure and returns the index of that node
readData(&LinkedList[current]);// this takes that index and fills out the product structure that is attached to the void pointer in that node
}
我意识到这有点抽象,所以为了进一步参考,这是c文件:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "linkedlist.h"
#define listSize 100
typedef struct Product{
int code;//product code – integer
char name[31];//product name – 30 characters
int quantity;//quantity on hand – integer
double cost;//unit cost – double
double price;//retail price – double(30 % markup from unit cost)
char loc[7];//location code – 6 characters
} product;
void addFromFile(struct Node[], int);
int Display(struct Node[], int);
void readData(struct Node*);
void getProdCode(struct Node*);
void displayData(void *);
int comparInt(void *D1, void *D2);
void main()
{
struct Node LinkedList[listSize];
int Header = 0;
int newIndex, current;
int choice;
void(*stuff)(void *) = displayData;
int(*item)(void*, void*);
initializeList(LinkedList, Header);
//displayList(LinkedList, Header, stuff);
choice = Display(LinkedList, Header);
addFromFile(LinkedList, Header);
while (choice != 0)
{
if (choice == 1)
{
newIndex = findEmptyNode(LinkedList, Header);
readData(&LinkedList[newIndex]);
current = searchList(LinkedList, Header, newIndex, comparInt, 1);
insertNode(LinkedList, current, newIndex, Header);
}
if (choice == 2)
{
printf("\n%7s%30s%10s%7.2s%10.2s%10s", "CODE", "NAME", "QUANTITY", "COST", "PRICE", "LOC");
displayList(LinkedList, Header, stuff);
}
if (choice == 3)
{
newIndex = findEmptyNode(LinkedList, Header);
printf("\nDelete item by searching for it by product code\n");
getProdCode(&LinkedList[newIndex]);
current = searchList(LinkedList, Header, newIndex, comparInt, 0);
deleteNode(LinkedList, Header, current);
}
if (choice == 4)
{
newIndex = findEmptyNode(LinkedList, Header);
printf("\nUpdate item by searching for it by product code\n");
getProdCode(&LinkedList[newIndex]);
current = searchList(LinkedList, Header, newIndex, comparInt, 0);
readData(&LinkedList[current]);
}
if (choice != 1 && choice != 2 && choice != 3 && choice != 4)
{
printf("\n\nThe value you entered is not a valid choice\n\tplease try again\n\n");
}
choice = Display(LinkedList, Header);
}
printf("\n\n\t\tTHE APPLICATION HAS TERMINATED\n\n\n ");
}
int Display(struct Node LL[], int Head)
{
int choice;
printf("\n\nProduct Catalog\n");
//printf("there are %d items in the list\n", LL[Head].dataItem.countr);
printf("enter a value to indicate what you would like to do\n ");
printf("a value of zero entered will terminate the application\n");
printf(" a value of 1 will add an item to the list\n");
printf(" a value of 2 will display the contents of the list\n");
printf(" a value of 3 will delete an item from the list\n");
printf(" a value of 4 will update the item");
printf(" your choice is >> ");
/*fflush(stdin);*/
scanf("%d", &choice);
return choice;
}
void addFromFile(struct Node LL[], int Head){
//int i = 0;
int newIndex;
int current;
FILE *fp = fopen("product.txt", "r");
product *ptr = (product *)malloc(sizeof(struct Product));
struct Node *node;
while (EOF != fscanf(fp, "%d %30[^\n] %d %lf %6[^\n]", &(ptr->code), ptr->name, &ptr->quantity, &ptr->cost, &ptr->loc))
{
ptr->price = (ptr->cost/0.7);//calculate the cost
newIndex = findEmptyNode(LL, Head);
LL[newIndex].dataItem.dataPtr = ptr;
current = searchList(LL, Head, newIndex, comparInt, 1);
insertNode(LL, current, newIndex, Head);
//printf("\n%s\n", ((product*)(node->dataItem.dataPtr))->name);
ptr = (product *)malloc(sizeof(struct Product));
}
}
void readData(struct Node *node)
{
product *ptr = (product *)malloc(sizeof(struct Product));
printf("Product Code: ");
scanf("%d", &(ptr->code));
printf("Name: ");
fflush(stdin);
scanf("%[^\n]", ptr->name);
printf("Quantity: ");
scanf("%d", &(ptr->quantity));
printf("Cost: ");
scanf("%lf", &(ptr->cost));
ptr->price = (ptr->cost/0.7);
printf("Location: ");
fflush(stdin);
scanf("%[^\n]", ptr->loc);
node->dataItem.dataPtr = ptr;
}
void getProdCode(struct Node *node){
product *ptr = (product *)malloc(sizeof(struct Product));
printf("Product Code: ");
scanf("%d", &(ptr->code));
node->dataItem.dataPtr = ptr;
}
void displayData(void *ptr)
{
product* test = (product *)(ptr);
printf("\n%7d%30s%10d%7.2f%10.2f%10s", test->code, test->name, test->quantity, test->cost, test->price, test->loc);
//printf("\n\n");
}
int comparInt(void *D1, void *D2)
{
int temp;
if (((product*)D1)->code > ((product*)D2)->code)
temp = 1;
else
if (((product*)D1)->code < ((product*)D2)->code)
temp = -1;
else
temp = 0;
return temp;
}
并且引用的“product.txt”文件可以是found here
我对此有点困惑,因为在删除节点选项中搜索的相同关系正在更新节点选项中搜索;但是,删除节点选项有效,更新节点选项无效。
我是否忽略了一些关键组件?任何建议将不胜感激。
免责声明:这是在 Microsoft Visual Studios 2012 中编译的。我知道 gcc 和特定于 VS 的编译器之间存在一些差异。
【问题讨论】:
-
不相关:用
switch-case语句替换主循环中的if序列。更清洁的方式。您还应该评论您的图书馆。参数并不总是很清楚。 -
这里有太多单独的问题。使用
scanf提示用户输入非常快速和肮脏。例如,键入一个数字然后换行不会消耗换行,这可能会导致空字符串被后续%[^\n]格式扫描。此外,为%d获取像“abc”这样的错误输入将重置缓冲区并尝试一遍又一遍地读取相同的输入。在提示选择时尝试一下 - 你会得到一个无限循环。考虑一个两步提示:首先是fgets,然后是sscanf。 -
基于索引的链表和基于指针的链表有同样的问题:当你添加到一个ampty链表或删除第一项时,必须更新头部。因此,在这种情况下,您应该传递指向头索引的指针。使用联合作为在虚拟尾部中保持计数并作为常规节点中的数据要求麻烦。并决定是否使用 -1 或 -5 作为哨兵值。 -1 看起来是更明显的选择。
-
@MOehm -1 和 -5 是完全不同的东西。 -1 表示列表的元素是空的可用空间。 -5 表示该元素是列表的末尾。
-
啊哈,没有意识到这一点。我可能在
initialzeList中看到了这一点。 (该函数只有在head为 0 时才能正常工作。)
标签: c linked-list nodes updates