Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 链表实现上的结构指针_C - Fatal编程技术网

C 链表实现上的结构指针

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

我正在用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 *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++的。参考: