一些背景知识:
我的问题:当我尝试访问“播放器”结构中各个元素的值时,我得到了废话。我几乎可以肯定这是一个指针问题,因为到目前为止,这是我对C的最大弱点。 相关代码:
我正在展示结构,以防万一我不清楚。注意Node中的void指针,它最终指向一个Player结构:
struct Node;
typedef struct Node {
void *data;
struct Node *prev;
struct Node *next;
} Node;
typedef struct Player {
char *name;
char *pos;
double *num;
} Player ;
我包含了我编写的代码,我将数组中的数据添加到列表中并打印结果。我还显示了结果控制台输出。
// char *vals[linesInFile][3] has already been declared.
// List playerList has already been created and initialized; it currently has 0 nodes.
// int i represents the number of nodes in the list.
// getNode and addNode do just what you'd expect them to do. Both functions have been thoroughly tested.`
Player *player = calloc(1, sizeof(Player));
int n;
for(n = 0; n < i; n++) {
if(vals[n][0] != NULL) {
addNode(playerList, n, NULL);
getNode(playerList, n)->data = &player;
((Player *)getNode(playerList, n)->data)->name = vals[n][0];
((Player *)getNode(playerList, n)->data)->pos = vals[n][1];
((Player *)getNode(playerList, n)->data)->num = vals[n][2];
printf("%d: %s\n", n, ((Player *)getNode(playerList, n)->data)->name);
printf("%d: %s\n", n, ((Player *)getNode(playerList, n)->data)->pos);
printf("%d: %s\n", n, ((Player *)getNode(playerList, n)->data)->num);
printf("\n");
}
}
0:Mike Trout
0:CF
0:42761:布莱斯哈珀 1:LF
1:45992:Jose Fernandez
2:SP
2:5023
到目前为止一切正常。最后,我包含了我编写的代码片段,试图从main函数中找到播放器结构的值。
// The getSize method has been tested and correctly returns the size of a list.
int i;
for(i = 0; i < getSize(playerList); i++) {
printf("%d: %s\n", i, ((Player *)getNode(playerList, i)->data)->name);
// The output from this is garbage.
char *playerName = ((Player *)getNode(playerList, i)->data)->name;
printf("%d: %s\n", i, playerName);
// The output from this is garbage.
}
我不肯定最后一个块之前的所有代码都是正确的,但至少它似乎产生了所需的输出。希望这只是最后一段代码的一个简单的指针问题。无论如何,我们将非常感谢任何帮助。
答案 0 :(得分:2)
这条线似乎错了:
getNode(playerList, n)->data = &player;
player
已经是指向Player
的指针,因此,这一行实际上是将新节点的data
字段设置为指向的指针到{ {1}},其余的代码使用它,好像它是指向Player
的指针 - 类型不匹配,这就是你的问题。
相反,该行应为:
Player
也就是说,您不需要应用运算符的地址。其余的代码看起来还不错。
代码似乎没问题,因为您的打印声明具有误导性。您只分配一个节点,并不断反复更改其值。问题是,每次更改该节点上的字段时,都会打印它,因此输出看起来正确,但程序一次只能存储一个节点和一条信息。您可以存储,打印,覆盖,打印,覆盖,打印....
要解决此问题,您需要在每次迭代时显式分配一个新节点:
getNode(playerList, n)->data = player;
然后,填充列表后,打印出来:
Player *player;
int n;
for(n = 0; n < i; n++) {
if(vals[n][0] != NULL) {
player = calloc(1, sizeof(Player));
addNode(playerList, n, NULL);
getNode(playerList, n)->data = player;
((Player *)getNode(playerList, n)->data)->name = vals[n][0];
((Player *)getNode(playerList, n)->data)->pos = vals[n][1];
((Player *)getNode(playerList, n)->data)->num = vals[n][2];
}
}
此外,如果您不想复制数组中的指针但复制其内容,则可以使用for(n = 0; n < i; n++) {
if(vals[n][0] != NULL) {
printf("%d: %s\n", n, ((Player *)getNode(playerList, n)->data)->name);
printf("%d: %s\n", n, ((Player *)getNode(playerList, n)->data)->pos);
printf("%d: %s\n", n, ((Player *)getNode(playerList, n)->data)->num);
printf("\n");
}
}
:
strdup()
但是,请记住,在释放节点本身之前,您现在必须 /* ... */
((Player *)getNode(playerList, n)->data)->name = strdup(vals[n][0]);
((Player *)getNode(playerList, n)->data)->pos = strdup(vals[n][1]);
free()
和name
中的每一个。{1}}。此外,由于pos
是指向double的指针,因此您无法在其上使用num
。相反,您必须手动分配内存并复制其内容:
strdup
答案 1 :(得分:2)
以及&amp; FilipeGonçalves指出的问题,你还有其他一些问题。
您只需分配一个Player结构,然后将其用于列表中的每个项目。这意味着他们都指向相同的数据,你最终会打印最后一个玩家的详细信息。您应该将calloc移动到for n循环内。
您也只是复制vals中name,pos和num值的指针。这可能没问题,但它确实意味着vals需要在播放器列表的生命周期内保持在范围内(或不被释放)。