C - 创建动态结构数组,结构成员打印错误的值?

时间:2022-12-15 19:56:06

I am trying to create a dynamic array of players which I can add to during run time - however if I create 3 players with x-coords: 4,7 and 15, then try to print these values the output is: 0, 33, 20762704.

我正在尝试创建一个动态的玩家阵列,我可以在运行时添加 - 但是如果我创建3个带有x-coords的玩家:4,7和15,那么尝试打印这些值,输出为:0,33, 20762704。

I am new to C and pointers and am struggling to work out where it is going wrong.

我是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;

}

2 个解决方案

#1


1  

In order to add the first player to the list, you must pass a pointer-to-pointer-to-playerList to addPerson because the first node address will become the list address. Otherwise, you must return type *playerList and assign the return to your list variable back in the calling function. It is just as easy to pass the playerList ** parameter to your function and return a pointer to indicate success/failure as well as for convenience. e.g.:

为了将第一个播放器添加到列表中,必须将指针指向播放器指针传递给addPerson,因为第一个节点地址将成为列表地址。否则,您必须返回类型* playerList并将返回值分配给调用函数中的列表变量。将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;
}

Then in main

然后在主要

addPlayer(&players, 4,3);
...

(note: the addPlayer is no longer recursive. As your list size grows, the additional resources needed for recursive calls can become significant, further, there is no need for a recursive call as the procedural iteration to the end of list to add a new player is straight forward.)

(注意:addPlayer不再是递归的。随着列表大小的增加,递归调用所需的额外资源可能变得非常重要,此外,不需要递归调用作为程序迭代到列表末尾添加新的球员很直接。)

Look over the change and let me know if you have any additional questions. (note: I have not checked the remainder of your code for further errors)

查看更改并告诉我您是否还有其他问题。 (注意:我没有检查代码的其余部分是否存在进一步的错误)

#2


1  

In the list, you have a node that you are going to save some data on it, and it points to the next node too. So, you could define list structure to maintain the head of your list, and probably some other required information such length of the list or garbage handling or ...

在列表中,您有一个节点,您要在其上保存一些数据,它也指向下一个节点。因此,您可以定义列表结构以维护列表的头部,以及可能的一些其他所需信息,例如列表的长度或垃圾处理或......

For initialization you should set the length with zero and head pointer of list to NULL, these steps show the empty status of the list.

对于初始化,您应将列表的长度设置为零,并将列表的头指针设置为NULL,这些步骤将显示列表的空状态。

When you want to add to the list, you could add at the end of it, or at the head of it. In your program, you choose the second insertion policy, at the end. So, to add, you should traverse the list (all nodes), to find the last node, to add new node after that one. You should be aware of adding the new node when the list is empty, in this case you should update the head of your list. For printing, there is a similar way, you should traverse the list and print the node information of that, until you reach the null pointer at the end of list.

如果要添加到列表中,可以在其末尾添加,也可以添加到列表的末尾。在您的程序中,最后选择第二个插入策略。因此,要添加,您应该遍历列表(所有节点),以查找最后一个节点,以在该节点之后添加新节点。当列表为空时,您应该知道添加新节点,在这种情况下,您应该更新列表的头部。对于打印,有类似的方法,您应该遍历列表并打印该节点的节点信息,直到您到达列表末尾的空指针。

After any allocation you should check the allocation success, if the pointer is not null, it was successful.

在任何分配之后,您应该检查分配成功,如果指针不为null,则表示成功。

Another point, when you can handle adding the new node with using a simple loop, why you should use the recursive function? In this cases, it is better to use the loop.

另一点,当您可以使用简单循环处理添加新节点时,为什么要使用递归函数?在这种情况下,最好使用循环。

The last point, dynamic allocation memory used commonly when the number of the list is specified in the run time, for example. It is a good point, to less memory allocation if you don't have to use. For instance, in the main you could define the list variable as a static variable, and send the address of that to the functions.

最后一点,例如,当在运行时指定列表的编号时,通常使用动态分配存储器。如果您不必使用内存分配,这是一个好点。例如,在main中,您可以将列表变量定义为静态变量,并将其地址发送给函数。

I tested the program, and its output was okay.

我测试了程序,它的输出没问题。

#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  

In order to add the first player to the list, you must pass a pointer-to-pointer-to-playerList to addPerson because the first node address will become the list address. Otherwise, you must return type *playerList and assign the return to your list variable back in the calling function. It is just as easy to pass the playerList ** parameter to your function and return a pointer to indicate success/failure as well as for convenience. e.g.:

为了将第一个播放器添加到列表中,必须将指针指向播放器指针传递给addPerson,因为第一个节点地址将成为列表地址。否则,您必须返回类型* playerList并将返回值分配给调用函数中的列表变量。将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;
}

Then in main

然后在主要

addPlayer(&players, 4,3);
...

(note: the addPlayer is no longer recursive. As your list size grows, the additional resources needed for recursive calls can become significant, further, there is no need for a recursive call as the procedural iteration to the end of list to add a new player is straight forward.)

(注意:addPlayer不再是递归的。随着列表大小的增加,递归调用所需的额外资源可能变得非常重要,此外,不需要递归调用作为程序迭代到列表末尾添加新的球员很直接。)

Look over the change and let me know if you have any additional questions. (note: I have not checked the remainder of your code for further errors)

查看更改并告诉我您是否还有其他问题。 (注意:我没有检查代码的其余部分是否存在进一步的错误)

#2


1  

In the list, you have a node that you are going to save some data on it, and it points to the next node too. So, you could define list structure to maintain the head of your list, and probably some other required information such length of the list or garbage handling or ...

在列表中,您有一个节点,您要在其上保存一些数据,它也指向下一个节点。因此,您可以定义列表结构以维护列表的头部,以及可能的一些其他所需信息,例如列表的长度或垃圾处理或......

For initialization you should set the length with zero and head pointer of list to NULL, these steps show the empty status of the list.

对于初始化,您应将列表的长度设置为零,并将列表的头指针设置为NULL,这些步骤将显示列表的空状态。

When you want to add to the list, you could add at the end of it, or at the head of it. In your program, you choose the second insertion policy, at the end. So, to add, you should traverse the list (all nodes), to find the last node, to add new node after that one. You should be aware of adding the new node when the list is empty, in this case you should update the head of your list. For printing, there is a similar way, you should traverse the list and print the node information of that, until you reach the null pointer at the end of list.

如果要添加到列表中,可以在其末尾添加,也可以添加到列表的末尾。在您的程序中,最后选择第二个插入策略。因此,要添加,您应该遍历列表(所有节点),以查找最后一个节点,以在该节点之后添加新节点。当列表为空时,您应该知道添加新节点,在这种情况下,您应该更新列表的头部。对于打印,有类似的方法,您应该遍历列表并打印该节点的节点信息,直到您到达列表末尾的空指针。

After any allocation you should check the allocation success, if the pointer is not null, it was successful.

在任何分配之后,您应该检查分配成功,如果指针不为null,则表示成功。

Another point, when you can handle adding the new node with using a simple loop, why you should use the recursive function? In this cases, it is better to use the loop.

另一点,当您可以使用简单循环处理添加新节点时,为什么要使用递归函数?在这种情况下,最好使用循环。

The last point, dynamic allocation memory used commonly when the number of the list is specified in the run time, for example. It is a good point, to less memory allocation if you don't have to use. For instance, in the main you could define the list variable as a static variable, and send the address of that to the functions.

最后一点,例如,当在运行时指定列表的编号时,通常使用动态分配存储器。如果您不必使用内存分配,这是一个好点。例如,在main中,您可以将列表变量定义为静态变量,并将其地址发送给函数。

I tested the program, and its output was okay.

我测试了程序,它的输出没问题。

#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;

}