我用C实现了一个纸牌游戏,下面是我的代码:
甲板h:

#ifndef DECK_H
    #define DECK_H
    #define S_NUM 4
    #define V_NUM 12
    #define S_MAXLEN 9
    #define V_MAXLEN 6
    #define OFLEN 5

    typedef char deck_t
        [S_NUM * V_NUM]
            [S_MAXLEN + V_MAXLEN + OFLEN];

    typedef struct {
        deck_t *hand;
        deck_t *remaining_cards;
    } dealed_deck_t;

    deck_t *new_deck(void);
    void print_deck(const deck_t *);
    dealed_deck_t deal(const deck_t *, int);
    void free_deck(const deck_t *);

    static void deckcpy(const deck_t *const, deck_t *, int);

#endif

甲板c:
#include "deck.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

deck_t *new_deck() {
    int i, j, k;
    deck_t *cards = calloc(1, sizeof(deck_t));
    char suits[S_NUM][S_MAXLEN] = {
        "Spades", "Diamonds",
        "Hearts", "Clubs"
    };
    char values[V_NUM][V_MAXLEN] = {
        "Ace", "Two", "Three",
        "Four", "Five", "Six",
        "Seven", "Eight", "Nine",
        "Jack", "Queen", "King"
    };
    for (i = 0; i < S_NUM * V_NUM; ++i) {
        memset(*cards[i], 0, strlen(*cards[i]));
    }
    for (i = 0, j = 0; i < S_NUM; ++i) {
        for (k = 0; k < V_NUM; ++k, ++j) {
            strcat(*cards[j], values[k]);
            strcat(*cards[j], " of ");
            strcat(*cards[j], suits[i]);
        }
    }
    return cards;
}

void print_deck(const deck_t *deck) {
    for (int i = 0; i < S_NUM * V_NUM && strlen(*deck[i]); ++i) {
        printf("%s\n", *deck[i]);
    }
}

dealed_deck_t deal(const deck_t *deck, int handsize) {
    int i, j;
    dealed_deck_t dealed_deck;
    dealed_deck.hand = calloc(1, sizeof(deck_t));
    dealed_deck.remaining_cards = calloc(1, sizeof(deck_t));

    // print_deck(deck);

    return dealed_deck;
}

void free_deck(const deck_t *deck) {
    free((void *)deck);
}

static void deckcpy(const deck_t *const deck, deck_t *dest, int handsize) {
    for (int i = 0; i < handsize; ++i) {
        char temp[strlen(*deck[i])];
        for (int j = 0; j < strlen(*deck[i]); ++j) {
            temp[j] = (*deck[i])[j];
            temp[j] = '\0';
        }
        for (int j = 0; j < strlen(temp); ++j) {
            (*dest[i])[j] = temp[j];
            (*dest[i])[j] = '\0';
        }
    }
}

主要c:
#include "deck.h"

int main() {
    deck_t *cards = new_deck();
    deck_t *hand = deal(cards, 6).hand;
    // print_deck(cards);
    free_deck(cards);
    return 0;
}

问题是deck.c在deal函数中。
当我为dealed_deck.handdealed_deck.remaining_cards分配内存时,参数deck指向的数据会受到影响和更改,因此当我注释这两行时:
dealed_deck.hand = calloc(1, sizeof(deck_t));dealed_deck.remaining_cards = calloc(1, sizeof(deck_t));,当我取消对数据的注释时,数据是相同的。
我在这里使用calloc是因为当我使用malloc时,dealed_deck.handdealed_deck.remaining_cards所指的数据与deck所指的数据相同,但是当我使用calloc时,它们是空的。
我需要一种分配内存的方法,而不是弄乱我以前分配的内存和数据,如何做到这一点?
我正在使用MacOS和gcc编译。
谢谢。

最佳答案

线路memset(*cards[i], 0, strlen(*cards[i]));错误。首先,cards是用calloc分配的,因此它被零字节填充,这些字节充当空字符串。因此,如果*cards[i]指向cards中的某个内容,strlen返回零,并且memset将零字节设置为零。
不幸的是,*cards[i]只有在i为零时才有效。由于cards是指向deck_t的指针,cards[0]是第一个deck_t,它是char数组的数组。作为一个数组,它会自动转换为指向其第一个元素的指针,即char数组。那么*cards[0]就是char的数组。作为一个数组,它会自动转换为指向其第一个元素的指针,并传递给strlen。然而,当i是一个(或更多)时,cards[i]将是第二个(或更多)deck_t。但只分配了一个deck_t的空间。因此*cards[i]无效;它试图访问未分配的空间。
由于不需要该行(由于calloc),请将其删除并将其放入循环中。
strcat(*cards[j]中,存在同样的问题-*cards[j]仅当j为零时才有效。正确的表达式是(*cards)[j]
(*cards)[j]中,cards是指向adeck_t的指针,因此(*cards)是adeck_t,它是char数组的数组。那么(*cards)[j]是那个数组的元素j,所以它是一个char数组。
同样,在print_deck中,将*deck[i]更改为(*deck)[i]
(通过将deck[i]的类型更改为(*deck)[i],可以更改代码以使用deck而不是char (*MyType)[S_MAXLEN + V_MAXLEN + OFLEN]。但是,您可能希望先进行上述更改,并在更改类型之前理解这些更改。)

关于c - 如何动态分配内存而不影响其他动态分配的数据?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55827583/

10-10 22:16