C 链表中的所有节点都指向同一对象

C 链表中的所有节点都指向同一对象,c,linked-list,C,Linked List,问题就在这里的某个地方 char buffer[80]; char *name; while (1) { fgets(buffer, 80, inf); //reads in at most 80 char from a line if (feof(inf)) //this checks to see if the special EOF was read break; //if so, break out of while and con

问题就在这里的某个地方

char buffer[80];
char *name;
while (1) {
    fgets(buffer, 80, inf); //reads in at most 80 char from a line
        if (feof(inf)) //this checks to see if the special EOF was read
            break;     //if so, break out of while and continue with your main
        name = (char *) malloc(sizeof(char)*20);
        ....
        name = strtok(buffer, " ");//get first token up to space
        stock = newStock(name,...)
        ....
    }
我在用C语言编写通用链表。我制作了一个列表实现,我已经测试过,并且知道它可以与chars一起使用。我试图将股票(我创建了一个股票结构)添加到链表中,链表的每个节点都持有一个股票结构,但是当我在股票中完成读取时,所有节点都指向同一个结构,我不知道为什么。下面是我的一些代码片段

list *list = malloc(sizeof(list));
newList(list, sizeof(stock_t));

while(1) {
    ...
    (read from file)
    ...
    stock_t *stock;
    stock = newStock(name, closes, opens, numshares, getPriceF, getTotalDollarAmountF,getPercentChangeF,toStringF);
    addToBack(list, stock);
}
以下是newStock函数:

stock_t *newStock(char *name, float closingSharePrice, float openingSharePrice, int numberOfShares, getPrice getP, getTotalDollarAmount getTotal, getPercentChange getPercent, toString toStr) {

    stock_t *stock = malloc(sizeof(stock));
    stock->stockSymbol = name;
    stock->closingSharePrice = closingSharePrice;
    stock->openingSharePrice = openingSharePrice;
    stock->numberOfShares = numberOfShares;
    stock->getP = getP;
    stock->getTotal = getTotal;
    stock->getPercent = getPercent;
    stock->toStr = toStr;
    return stock;
}
在某种程度上,我看到了问题所在。newStock每次都返回一个新指针,但它总是存储在变量'stock'中,这是每个节点指向的,所以它将等于newStock返回的最后一个指针的值……但我不知道如何解决这个问题。我试着让newStock返回一个stock\t,并执行addToBack(list,&stock),但这也没有解决问题

任何帮助都将不胜感激

下面是列表中的一些代码:

typedef struct node {
    void *data;
    struct node *next;
}node_t;

typedef struct {
    int length;
    int elementSize;
    node_t *head;
    node_t *tail;
} list;


void newList(list *list, int elementSize) {
    assert(elementSize > 0);
    list->length = 0;
    list->elementSize = elementSize;
   list->head = list->tail = NULL;
}

void addToBack(list *list, void *element) {

    node_t *node = malloc(sizeof(node_t));
    node->data = malloc(list->elementSize);
    node->next = NULL; //back node

    memcpy(node->data, element, list->elementSize);

    if (list->length == 0) { //if first node added
        list->head = list->tail = node;
    }
    else {
        list->tail->next = node;
        list->tail = node;
    }

    list->length++;
}
typedef void (*iterate)(void *); //this is in the list.h file, just putting it here to avoid confusion


void traverse(list *list, iterate iterator) {
    assert(iterator != NULL);

    node_t *current = list->head;

    while (current != NULL) {
        iterator(current->data);
        current = current->next;
    }
}
下面是stock结构中的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

typedef float (*getPrice)(void *S);
typedef float (*getTotalDollarAmount)(void *S);
typedef float (*getPercentChange)(void *S);
typedef char *(*toString)(void *S);

typedef struct stock{
    char *stockSymbol;
    float closingSharePrice;
    float openingSharePrice;
    int numberOfShares;
    getPrice getP;
    getTotalDollarAmount getTotal;
    getPercentChange getPercent;
    toString toStr;
   }stock_t;
这就是我浏览列表的方式:

typedef struct node {
    void *data;
    struct node *next;
}node_t;

typedef struct {
    int length;
    int elementSize;
    node_t *head;
    node_t *tail;
} list;


void newList(list *list, int elementSize) {
    assert(elementSize > 0);
    list->length = 0;
    list->elementSize = elementSize;
   list->head = list->tail = NULL;
}

void addToBack(list *list, void *element) {

    node_t *node = malloc(sizeof(node_t));
    node->data = malloc(list->elementSize);
    node->next = NULL; //back node

    memcpy(node->data, element, list->elementSize);

    if (list->length == 0) { //if first node added
        list->head = list->tail = node;
    }
    else {
        list->tail->next = node;
        list->tail = node;
    }

    list->length++;
}
typedef void (*iterate)(void *); //this is in the list.h file, just putting it here to avoid confusion


void traverse(list *list, iterate iterator) {
    assert(iterator != NULL);

    node_t *current = list->head;

    while (current != NULL) {
        iterator(current->data);
        current = current->next;
    }
}
然后在我的主要工作中,我刚刚打了电话

traverse(list, printStock);

我找不到您的代码有任何问题(无论如何,这会导致您的问题-有些地方您不检查
malloc()
之类的返回,但这些与此问题无关)。您没有提供
stock\t
的定义,因此我创建了一个新的数据结构和一对新函数,否则我只是复制并粘贴了您提供的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

/*  Your code starts here */

typedef struct node {
    void *data;
    struct node *next;
}node_t;

typedef struct {
    int length;
    int elementSize;
    node_t *head;
    node_t *tail;
} list;


void newList(list *list, int elementSize) {
    assert(elementSize > 0);
    list->length = 0;
    list->elementSize = elementSize;
    list->head = list->tail = NULL;
}

void addToBack(list *list, void *element) {

    node_t *node = malloc(sizeof(node_t));
    node->data = malloc(list->elementSize);
    node->next = NULL; //back node

    memcpy(node->data, element, list->elementSize);

    if (list->length == 0) { //if first node added
        list->head = list->tail = node;
    }
    else {
        list->tail->next = node;
        list->tail = node;
    }

    list->length++;
}

/* Your code ends here */

/*  I made a new struct, rather than stock, since you didn't supply it  */

struct mydata {
    int num1;
    int num2;
};

/*  I use this instead of newStock(), but it works the same way  */

struct mydata * newNode(const int a, const int b) {
    struct mydata * newdata = malloc(sizeof *newdata);
    if ( newdata == NULL ) {
        fputs("Error allocating memory", stderr);
        exit(EXIT_FAILURE);
    }
    newdata->num1 = a;
    newdata->num2 = b;
    return newdata;
}

/*  I added this function to check the list is good  */

void printList(list * list) {
    struct node * node = list->head;
    int n = 1;
    while ( node ) {
        struct mydata * data = node->data;
        printf("%d: %d %d\n", n++, data->num1, data->num2);
        node = node->next;
    }
}

/*  Main function  */

int main(void) {
    list *list = malloc(sizeof(list));
    newList(list, sizeof(struct mydata));

    struct mydata * data;

    data = newNode(1, 2);
    addToBack(list, data);
    data = newNode(3, 4);
    addToBack(list, data);
    data = newNode(5, 6);
    addToBack(list, data);

    printList(list);

    return 0;
}
演示您有一个3节点列表,其中所有节点都不同,并且您希望它们位于何处

要么是代码中存在一些其他问题而没有显示,要么是由于某种原因,您认为每个节点都指向相同的
struct
,而实际上它没有

一种可能性是,您的stock结构中有一个
char*
数据成员。无法从您提供的代码中分辨出来,但也有可能您确实在创建不同的节点,但它们最终都指向相同的
名称
,因此它们看起来就像是相同的。如果要将指针分配给
名称
,则应确保每次都是新分配的内存,并且不只是将
strcpy()
插入同一内存,并将同一地址分配给每个库存
结构

编辑:看来这是你的问题。这:

name = (char *) malloc(sizeof(char)*20);
....
name = strtok(buffer, " ");
应该是:

name = (char *) malloc(sizeof(char)*20);
....
strcpy(name, strtok(buffer, " "));

现在,您可以
malloc()
新建内存,并在
name
中存储对它的引用,但是如果您使用从
strtok()返回的地址覆盖它,则会丢失该引用和内存。相反,您需要将该令牌复制到新分配的内存中,如图所示。

问题出在您的列表代码中,而不是您在此处显示的内容。好的,让我编辑原始帖子并将部分代码放入。但是我很困惑,因为我在int和char数组上测试了这个列表,它工作得很好。
stock\u t*stock=malloc(sizeof(stock))-->
stock\u t*stock=malloc(sizeof*stock)感谢您的所有努力。我也用int和char数组尝试了我的代码,它成功了,这就是为什么我如此迷茫的原因。我很确定它指向同一个结构。我沿着下一个字段遍历列表,直到它为空,然后打印出node->data->stockSymbol。我已经进入调试器并进行了检查,以确保我不仅仅是迭代错误,而且它们都是相同的。i、 e.如果我打印出节点->数据->库存符号和节点->下一步->数据->库存符号,它们是相同的。我将分享股票结构代码,也许它会揭示一些东西。我会把它编辑成原稿post@user3344699当前位置检查我刚才添加的答案的最后一段,如果您使用股票符号来检查所有这些,可能就是这样。如果它们都指向同一个股票符号,这可以解释它们看起来是如何相同的,但实际上它们是独立的节点,就像您尝试使用
int
和friends时一样。你可以试着打印出股票价格或类似的价格,我敢打赌,它们都会像你预期的那样不同。另外,为了安全起见,检查一下你不是在一遍又一遍地从文件中读同一行。啊!你是对的,价格的数字是对的。只是名字是一样的。我想我应该仔细检查一下。我现在将查看我的代码,看看我是否能找出我的char*@user3344699的问题:几乎可以肯定,您正在使用一个
char
缓冲区来读取文件中的符号,并将该缓冲区的地址分配给每个节点。因此,缓冲区最终包含从文件中读取的最后一个符号,并且所有节点都指向它。您每次都需要
malloc()
新内存,并将缓冲区复制到其中(或者使用
strdup()
一次性完成),然后将新内存的地址分配给新节点。我仍然没有看到它,我将把我正在做的事情放在OP中。谢谢您的帮助!