我正在尝试创建一个动态数组的玩家,我可以在运行时添加 - 但是如果我用x-coords创建3个玩家: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;
}
答案 0 :(得分:1)
在列表中,您有一个节点,您要在其上保存一些数据,它也指向下一个节点。因此,您可以定义列表结构以维护列表的头部,可能还有一些其他所需的信息,例如列表的长度或垃圾处理或...
对于初始化,您应该将列表的长度设置为零,将列表的头指针设置为NULL,这些步骤将显示列表的空状态。
如果要添加到列表中,可以在其末尾添加,或者添加到列表的末尾。在您的程序中,您最后选择第二个插入策略。因此,要添加,您应该遍历列表(所有节点),以查找最后一个节点,以在该节点之后添加新节点。您应该知道在列表为空时添加新节点,在这种情况下,您应该更新列表的头部。 对于打印,有类似的方法,你应该遍历列表并打印它的节点信息,直到你到达列表末尾的空指针。
在任何分配之后你应该检查分配是否成功,如果指针不为null,则表示成功。
另一点,当您可以使用简单循环处理添加新节点时,为什么要使用递归函数?在这种情况下,最好使用循环。
最后一点,例如,当在运行时指定列表编号时,通常使用动态分配内存。如果您不必使用内存分配,这是一个好点。例如,在main中,您可以将列表变量定义为静态变量,并将其地址发送给函数。
我测试了程序,输出没问题。
#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;
}
答案 1 :(得分:1)
为了将第一个播放器添加到列表中,您必须将指向指针指向播放器的指针传递给addPerson
,因为第一个节点地址将成为列表地址。否则,您必须返回类型*playerList
并将返回值分配给调用函数中的list
变量。将playerList **
参数传递给函数并且返回指示成功/失败以及方便的指针同样容易。 e.g:
/* 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
不再是递归的。随着列表大小的增加,递归调用所需的额外资源会变得很大,而且不需要递归调用作为程序迭代到列表末尾以添加新玩家是直截了当的。)
查看更改并告诉我您是否还有其他问题。 (注意:我没有检查代码的其余部分是否存在其他错误)