问题出在这里......
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中使用通用链接列表。我制作了一个列表实现,我已经测试并且知道使用字符。我试图在链表中添加股票(我创建了一个股票结构),链表的每个节点都有一个股票结构,但是当我读完股票时,所有节点都指向相同的结构我无法弄清楚原因。这是我的代码的一些片段
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; 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++;
}
来自股票结构的代码:
#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;
通用功能可能看起来有点矫枉过正,但这是作业(如果你不能说的话),所以我们被要求专门使用它们。我不认为这与问题有任何关系。
以下是这些功能的定义
float getPriceF(void *S) {
stock_t *stock = (stock_t*)S;
return stock->closingSharePrice;
}
float getTotalDollarAmountF(void *S) {
stock_t *stock = (stock_t*)S;
return ((stock->closingSharePrice) * (stock->numberOfShares));
}
float getPercentChangeF(void *S) {
stock_t *stock = (stock_t*)S;
return ((stock->closingSharePrice - stock->openingSharePrice)/(stock->openingSharePrice));
}
char *toStringF(void *S) {
stock_t* stock = (stock_t*)S;
char *name = malloc(20*sizeof(char));
//sprintf(name, "Symbol is: %s. ", (stock->stockSymbol));
return stock->stockSymbol;
}
void printStock(void *S) {
char *str = toStringF(S);
printf("%s \n", str);
}
这就是我浏览列表的方式:
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);
答案 0 :(得分:1)
我无法发现您的代码有任何问题(这会导致您的问题,无论如何 - 有些地方您不会检查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;
}
输出:
paul@MacBook:~/Documents/src$ ./list
1: 1 2
2: 3 4
3: 5 6
paul@MacBook:~/Documents/src$
证明您有一个3节点列表,所有节点都不同,以及您希望它们在哪里。
在您未显示的代码中存在其他一些问题,或者出于某种原因,您认为每个节点在实际上都没有指向相同的struct
。
一种可能性是您的stock结构中有一个char *
数据成员。从您提供的代码中无法判断,但您可能真的在创建不同的节点,但它们最终都指向同一个name
,所以它们看起来就像是& #39;同样如此。如果您要指定name
指针,则应确保每次都重新分配内存,并且您不仅仅是strcpy()
进入相同的内存并为每个股票struct
分配相同的地址。
name = (char *) malloc(sizeof(char)*20);
....
name = strtok(buffer, " ");
应该是:
name = (char *) malloc(sizeof(char)*20);
....
strcpy(name, strtok(buffer, " "));
现在,您malloc()
新内存并在name
中存储对它的引用,但是当您使用strtok()
返回的地址覆盖它时,您将丢失该引用和内存。相反,您需要将该令牌复制到新分配的内存中,如图所示。