我正在使用C实现纸牌游戏,这是我的代码:
#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
#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';
}
}
}
#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;
}
问题是deal函数中的deck.c。
当我为dealed_deck.hand
和dealed_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.hand
和dealed_deck.remaining_cards
指向的数据与deck
指向的数据相同,但是当我使用calloc
时,它们是空的。
我需要一种分配内存而不弄乱我之前分配的内存和数据的方法,该怎么做?
我正在使用MacOS和gcc进行编译。 谢谢。
答案 0 :(得分:2)
第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
是指向deck_t
的指针,因此(*cards)
是deck_t
,它是{{1 }}。然后char
是该数组的元素(*cards)[j]
,因此它是j
的数组。
类似地,在char
中,将print_deck
更改为*deck[i]
。
(可以更改代码,以便通过将(*deck)[i]
的类型更改为deck[i]
来使用(*deck)[i]
代替deck
。但是,您可能希望上面的更改会先发生,并在更改类型之前先了解它们。)