C 链表实现上的结构指针
我正在用C编写一个链表实现,以掌握指针和结构的窍门。以下是my LL数据结构的基本代码:C 链表实现上的结构指针,c,C,我正在用C编写一个链表实现,以掌握指针和结构的窍门。以下是my LL数据结构的基本代码: struct Node { void *data; struct Node *next; }; struct List { struct Node *head; }; void initList(struct List *list) { list->head = 0; } struct Node *addFront(struct List *list, void
struct Node {
void *data;
struct Node *next;
};
struct List {
struct Node *head;
};
void initList(struct List *list) {
list->head = 0;
}
struct Node *addFront(struct List *list, void *data) {
struct Node *newNode;
newNode->data = data;
newNode->next = list->head;
list->head = newNode;
return newNode;
}
以下是我在int main函数中对其运行的测试:
int main() {
/* test addFront */
double *data1;
double *data2;
*data1 = 10.5;
*data2 = 10.7;
struct List *newList;
initList(newList);
addFront(newList, data1);
printf("%s\n", newList->head->data);
addFront(newList, data2);
printf("%s\n", newList->head->data);
return 0;
}
我的问题是printf没有打印输出。现在,它显然没有打印,因为%s与数据类型不匹配,这是双精度的。如果将字符串格式更改为%d,则会出现分段错误。如果我添加一个双精度转换,它会说第二个参数的类型是double*,这让我很困惑,因为我认为->符号取消了指针的引用
我迷路了 您正在解除对数据1和数据2的引用,而没有为它们分配内存。尝试:
double data1 = 10.5;
addFront(newList, &data1);
或者你可以做一个malloc,虽然我认为你不应该在这种情况下
此外,如果要打印它们,请尝试:
printf("%f\n", *(double *)newList->head->data);
您正在解除对data1和data2的引用,而没有为它们分配内存。尝试:
double data1 = 10.5;
addFront(newList, &data1);
或者你可以做一个malloc,虽然我认为你不应该在这种情况下
此外,如果要打印它们,请尝试:
printf("%f\n", *(double *)newList->head->data);
为了解决这个问题,你做了什么 尝试使用assert.h来确保您的断言是正确的,或者如果语句带有put/exit 特别是,如果它不打印某些内容,很明显,您正在打印的内容不是您想要打印的内容,因此,在某些方面,断言肯定会失败,您的大脑会在您错过某个步骤的地方发出咔哒声 我不能马上这么做的原因是因为我不是你,我不知道你在说什么,所以我要花比你更长的时间来解释 另外,如上所述,您没有为newNode分配内存,也没有访问任意内存,这会导致分段错误 我把它修好了
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
struct Node {
void *data;
struct Node *next;
};
struct List {
struct Node *head;
};
void initList(struct List **newList)
{
struct List* tmpList = 0;
assert(newList != 0);
tmpList = (struct List*)malloc(sizeof(struct List*));
assert(tmpList != 0);
tmpList->head = 0;
*newList = tmpList;
}
void addFront(struct List* list, void* data)
{
struct Node* currNode = 0;
struct Node* prevNode = 0;
assert(list != 0);
assert(data != 0);
currNode = list->head;
while (currNode != 0) {
prevNode = currNode;
currNode = currNode->next;
}
if (prevNode == 0) {
list->head = (struct Node*)malloc(sizeof(struct Node));
list->head->data = data;
list->head->next = 0;
} else {
prevNode->next = (struct Node*)malloc(sizeof(struct Node));
prevNode->next->data = data;
prevNode->next->next = 0;
}
}
void test(const struct List *list)
{
const struct Node *iter;
assert(list != 0);
assert(list->head != 0);
iter = list->head;
while (iter != 0) {
assert(iter->data != 0);
printf("%f\n", *((double*)iter->data));
iter = iter->next;
}
}
int main()
{
double* data1 = (double*)malloc(sizeof(double));
double* data2 = (double*)malloc(sizeof(double));
*data1 = 10.5;
*data2 = 10.7;
struct List* newList = 0;
initList(&newList);
assert(newList->head == 0);
puts("pass[0].");
addFront(newList, data1);
assert(newList->head != 0);
assert(newList->head->data == data1);
puts("pass[1].");
addFront(newList, data2);
assert(newList->head != 0);
assert(newList->head->data == data1);
assert(newList->head->next != 0);
assert(newList->head->next->data == data2);
puts("pass[2].");
test(newList);
return 0;
}
为了解决这个问题,你做了什么 尝试使用assert.h来确保您的断言是正确的,或者如果语句带有put/exit 特别是,如果它不打印某些内容,很明显,您正在打印的内容不是您想要打印的内容,因此,在某些方面,断言肯定会失败,您的大脑会在您错过某个步骤的地方发出咔哒声 我不能马上这么做的原因是因为我不是你,我不知道你在说什么,所以我要花比你更长的时间来解释 另外,如上所述,您没有为newNode分配内存,也没有访问任意内存,这会导致分段错误 我把它修好了
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
struct Node {
void *data;
struct Node *next;
};
struct List {
struct Node *head;
};
void initList(struct List **newList)
{
struct List* tmpList = 0;
assert(newList != 0);
tmpList = (struct List*)malloc(sizeof(struct List*));
assert(tmpList != 0);
tmpList->head = 0;
*newList = tmpList;
}
void addFront(struct List* list, void* data)
{
struct Node* currNode = 0;
struct Node* prevNode = 0;
assert(list != 0);
assert(data != 0);
currNode = list->head;
while (currNode != 0) {
prevNode = currNode;
currNode = currNode->next;
}
if (prevNode == 0) {
list->head = (struct Node*)malloc(sizeof(struct Node));
list->head->data = data;
list->head->next = 0;
} else {
prevNode->next = (struct Node*)malloc(sizeof(struct Node));
prevNode->next->data = data;
prevNode->next->next = 0;
}
}
void test(const struct List *list)
{
const struct Node *iter;
assert(list != 0);
assert(list->head != 0);
iter = list->head;
while (iter != 0) {
assert(iter->data != 0);
printf("%f\n", *((double*)iter->data));
iter = iter->next;
}
}
int main()
{
double* data1 = (double*)malloc(sizeof(double));
double* data2 = (double*)malloc(sizeof(double));
*data1 = 10.5;
*data2 = 10.7;
struct List* newList = 0;
initList(&newList);
assert(newList->head == 0);
puts("pass[0].");
addFront(newList, data1);
assert(newList->head != 0);
assert(newList->head->data == data1);
puts("pass[1].");
addFront(newList, data2);
assert(newList->head != 0);
assert(newList->head->data == data1);
assert(newList->head->next != 0);
assert(newList->head->next->data == data2);
puts("pass[2].");
test(newList);
return 0;
}
您没有为双指针data1和data2分配内存 看起来,实际上,您几乎没有为任何指针分配内存 指针本身所做的只是引用内存中的地址。它不分配支持引用的结构或变量所需的内存 如果你有
double *data1; // or any other kind of pointer
你需要像这样的东西
data1 = (double *) malloc(sizeof(double));
然后你可以随心所欲地取消引用
*data1 = 12.34;
但如果没有这一点,你就引用了一个指向加尔各答黑洞的指针。你没有为双指针data1和data2分配内存 看起来,实际上,您几乎没有为任何指针分配内存 指针本身所做的只是引用内存中的地址。它不分配支持引用的结构或变量所需的内存 如果你有
double *data1; // or any other kind of pointer
你需要像这样的东西
data1 = (double *) malloc(sizeof(double));
然后你可以随心所欲地取消引用
*data1 = 12.34;
但是如果没有这个,你引用的是一个指向加尔各答黑洞的指针。除了2个printf%f外,还缺少4个malloc:
我用以下标记更改的行:
除了2个printf%f外,还缺少4个malloc:
我用以下标记更改的行:
好吧,这是有道理的。但有一件事仍然让我感到困惑,那就是printf语句中的去引用*。我认为->操作符已经用指针解除了对结构数据的引用。或者他们只是去引用结构本身?如果是这样的话,那么我使用head->data是否是错误的,因为head不是指针?head->data是*head.data。因此,您取消了头指针的引用,并将void*数据放在手中,但还没有double。您是否运行了修改后的代码?它在我的机器上运行得很好,明白了。我忘了head实际上是一个指针,而不是一个结构节点。是的,现在很好,谢谢。当然。如果出现任何问题,请再次评论。好的,这是有道理的。但有一件事仍然让我感到困惑,那就是printf语句中的去引用*。我认为->操作符已经用指针解除了对结构数据的引用。或者他们只是去引用结构本身?如果是这样的话,那么我使用head->data是否是错误的,因为head不是指针?head->data是*head.data。因此,您取消了头指针的引用,并将void*数据放在手中,但还没有double。您是否运行了修改后的代码?它在我的电脑上运行得很好
机器,明白了。我忘了head实际上是一个指针,而不是一个结构节点。是的,现在很好,谢谢。当然。如果出现任何问题,请重新评论。修复了答案中所有错误的建议和语法错误。请不要误导没有经验的人。你想说你最初的作业double data1=double*malloc是对的吗?将double*分配给double?或者这是对的?两个人都没有。sizeof运算符中的更改只是一个额外的改进-以防data1的类型发生变化。我还原了我的原始代码,显式转换malloc的返回类型没有什么问题,实际上应该分配的是sizeofdouble。并且在声明有效后分配指针;事实上,应该分配的是sizeofdouble——现在是的,但是如果您将类型更改为struct foo,它将失败并调用UB;并且在声明之后分配指针也是有效的。-是的,但将double*分配给double并不是您所做的。我没有double data1=double malloc。。。。我有数据1=double*malloc。。。。强制转换malloc*的返回值是完全合法的。它不是C中需要的,但它是C++的。参考:修复了答案中所有错误的建议和语法错误。请不要误导没有经验的人。你想说你最初的作业double data1=double*malloc是对的吗?将double*分配给double?或者这是对的?两个人都没有。sizeof运算符中的更改只是一个额外的改进-以防data1的类型发生变化。我还原了我的原始代码,显式转换malloc的返回类型没有什么问题,实际上应该分配的是sizeofdouble。并且在声明有效后分配指针;事实上,应该分配的是sizeofdouble——现在是的,但是如果您将类型更改为struct foo,它将失败并调用UB;并且在声明之后分配指针也是有效的。-是的,但将double*分配给double并不是您所做的。我没有double data1=double malloc。。。。我有数据1=double*malloc。。。。强制转换malloc*的返回值是完全合法的。它不是C中需要的,但它是C++的。参考: