[英]C - Creating a dynamic array of structs, struct members printing wrong values?
我正在尝试创建一个可以在运行时添加的动态播放器数组-但是,如果我创建3个具有x坐标的播放器:4,7和15,则尝试打印这些值,输出为:0、33, 20762704。
我是C和指针的新手,正在努力找出问题出在哪里。
#include <stdio.h>
#include <stdlib.h>
// contains data of a player
struct player {
int posX;
int posY;
int gold;
};
// struct for creating a list of players of dynamic size
struct playerList {
struct player p;
struct playerList *next;
};
// add a new player to the list with given coords
struct playerList *make(int x, int y) {
struct playerList *new_player;
new_player = (struct playerList *)malloc(sizeof(struct playerList));
new_player->p.posX = x;
new_player->p.posY = y;
new_player->p.gold = 0;
new_player->next = NULL;
return new_player;
}
// add a player to the list
void addPlayer(struct playerList *list, int x, int y) {
if(list->next) {
addPlayer(list->next,x,y);
}
else {
list->next = make(x,y);
}}
int main() {
struct playerList *players = (struct playerList *)malloc(sizeof(struct playerList));
addPlayer(players, 4,3);
addPlayer(players, 7,7);
addPlayer(players,15,1);
printf("%d\n",players[0].p.posX);
printf("%d\n",players[1].p.posX);
printf("%d\n",players[2].p.posX);
return 0;
}
在列表中,您将有一个节点要在其中保存一些数据,并且它也指向下一个节点。 因此,您可以定义列表结构以维护列表的开头,并可能定义其他一些必需的信息,例如列表的长度或垃圾处理或...
对于初始化,应将长度设置为零,并将列表的头指针设置为NULL,这些步骤将显示列表的空白状态。
当您想添加到列表中时,可以在列表的末尾或顶部添加。 在程序中,最后选择第二个插入策略。 因此,要添加,您应该遍历列表(所有节点),找到最后一个节点,并在该节点之后添加新节点。 您应该知道在列表为空时添加新节点,在这种情况下,您应该更新列表的开头。 对于打印,有一种类似的方法,您应该遍历列表并打印其节点信息,直到到达列表末尾的空指针为止。
进行任何分配后,您应检查分配是否成功,如果指针不为null,则表明分配成功。
还有一点,当您可以使用简单的循环处理添加新节点时,为什么要使用递归函数? 在这种情况下,最好使用循环。
最后一点,例如,在运行时指定列表编号时通常使用的动态分配存储器。 这是一个好主意,如果不必使用,减少内存分配。 例如,在主目录中,您可以将list变量定义为静态变量,然后将其地址发送给函数。
我测试了该程序,其输出正常。
#include <stdio.h>
#include <stdlib.h>
// contains data of a player
struct player {
int posX;
int posY;
int gold;
};
// struct for creating a list of players of dynamic size
struct playerNode {
struct player p;
struct playerNode *next;
};
struct playerList {
struct playerNode *head;
int len;
// Add other required variables here
};
// add a new player to the list with given coords
struct playerNode *make(int x, int y) {
struct playerNode *new_player;
// you need to check memory allocation success
new_player = malloc(sizeof(struct playerNode));
new_player->p.posX = x;
new_player->p.posY = y;
new_player->p.gold = 0;
new_player->next = NULL;
return new_player;
}
// add a player to the list
void addPlayer(struct playerList *list, int x, int y) {
struct playerNode *player = list->head;
if(!player)
// you need to check memory allocation success
list->head = make(x, y);
else
{
while (player->next) {
player = player->next;
}
// you need to check memory allocation success
player->next = make(x, y);
}
list->len++;
}
void showPlayers(struct playerList *list) {
struct playerNode *player = list->head;
while (player) {
printf("%d\n", player->p.posX);
printf("%d\n", player->p.posY);
printf("%d\n", player->p.gold);
printf("--------------------\n");
player = player->next;
}
}
int main() {
struct playerList players;
players.len = 0;
players.head = NULL;
addPlayer(&players, 4, 3);
addPlayer(&players, 7, 7);
addPlayer(&players, 15, 1);
showPlayers(&players);
return 0;
}
为了将第一个播放器添加到列表中,您必须将指针指向播放器列表传递给addPerson
因为第一个节点地址将成为列表地址。 否则,您必须返回*playerList
类型,并将返回值分配给调用函数中的list
变量。 将playerList **
参数传递给函数并返回一个指示成功/失败的指针也很方便,这很容易。 例如:
/* add a player to the list */
playerList addPlayer (struct playerList **list, int x, int y) {
struct playerList *node = make (x, y);
if (!node) { /* validate new player created */
fprintf (stderr, "error: make player failed for (%d,%d).\n", x, y);
return NULL;
}
if (!*list) /* if first node, set list address to node & return */
return *list = node;
struct playerList *iter = *list; /* list pointer to iterate to end */
/* insert all other nodes at end */
for (; iter->next; iter = iter->next) {}
iter->next = node; /* add new player at end, return original *list */
return *list;
}
然后在main
addPlayer(&players, 4,3);
...
( 注意: addPlayer
不再是递归的。随着列表大小的增加,递归调用所需的其他资源addPlayer
重要,此外,由于列表末尾的过程迭代不需要添加新的递归调用,因此无需递归调用玩家直截了当。)
查看更改,让我知道是否还有其他问题。 ( 注意:我尚未检查其余代码是否有其他错误)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.