Skip to content

Instantly share code, notes, and snippets.

@the-moog
Created June 20, 2022 13:24
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save the-moog/0487050449abcd9af623d09623048566 to your computer and use it in GitHub Desktop.
Save the-moog/0487050449abcd9af623d09623048566 to your computer and use it in GitHub Desktop.
Sidestepping limitation of variable length member of fixed array sizes
#include <stdio.h> // for printf
#include <string.h> // for strcmp
// Define a card
typedef struct card
{
int value; // This is an int, so it's storage size does not change
char * name; // This is a pointer, so it's storange size does not change
int rule_change;
} card_t;
// Example:
/*
card_t test = {1, "test", 0};
card_t test_ary[] = {{1, "test", 0}, {1, "test", 0}};
*/
// Define an array of card_t pointers
typedef card_t * cards_t[];
// Use a macro to save lots of typing
#define MKCARD(VAL, NAME) &(card_t){VAL, NAME, 0}
// Make the data an array of pointers to the data, the macro also adds defaults for us
#define CARD_INITIAL_VALUES { MKCARD(2, "Two"), MKCARD(3, "Three"), MKCARD(4, "Four"), MKCARD(5, "Five"), MKCARD(6, "Six"), MKCARD(7, "Seven"), \
MKCARD(8, "Eight") , MKCARD(9, "Nine") , MKCARD(10, "Ten"), MKCARD(11, "Jack"), MKCARD(12, "Queen"), MKCARD(13, "King"), MKCARD(14, "Ace") }
// Create storage - note it is not necessary that all the suits are the same!!
cards_t suit_spades = CARD_INITIAL_VALUES;
cards_t suit_clubs = CARD_INITIAL_VALUES;
cards_t suit_diamonds = CARD_INITIAL_VALUES;
cards_t suit_hearts = CARD_INITIAL_VALUES;
// Define a suit
typedef struct suit
{
char * name;
unsigned n_cards; // Information only structure does not depend on this
// card_t cards[N_CARDS] // We could say this but that would fix the number of cards in every game
card_t ** cards; // Instead pointer arrays make it more flexible and make little change to the code
} suit_t;
// Example:
/*
suit_t suit = {
.name = "Toy Cards",
.n_cards = 3,
.cards = (cards_t){ &(card_t){2, "duck"}, &(card_t){3, "goose"}, &(card_t){4,"eagle"}}
};
*/
// Instead of counting memory we are counting pointers
// That way each array of pointers can be different
#define COUNT_CARDS(SUIT) ((unsigned)(sizeof(SUIT)/sizeof(card_t *)))
suit_t mygame_deck[] = {
{
.name = "Spades",
.n_cards = COUNT_CARDS(suit_spades),
.cards = suit_spades
}, {
.name = "Clubs",
.n_cards = COUNT_CARDS(suit_clubs),
.cards = suit_clubs
}, {
.name = "Diamonds",
.n_cards = COUNT_CARDS(suit_diamonds),
.cards = suit_diamonds
}, {
.name = "Hearts",
.n_cards = COUNT_CARDS(suit_hearts),
.cards = suit_hearts
}
};
// Here we count memory as each array member is always the same size
#define N_SUITS ((unsigned)(sizeof(mygame_deck)/sizeof(typeof(0[mygame_deck]))))
// Demonstrate we are not using const so our array are not fixed
int game_rule_change(char *card, char *suit, int new_value)
{
for (unsigned isuit=0; isuit < N_SUITS; isuit++)
for (unsigned icard = 0; icard < mygame_deck[isuit].n_cards; ++icard)
if ( strcmp(mygame_deck[isuit].name, suit) == 0 &&
strcmp(mygame_deck[isuit].cards[icard]->name, card) == 0)
{
mygame_deck[isuit].cards[icard]->value = new_value;
mygame_deck[isuit].cards[icard]->rule_change = 1;
return 1;
}
return 0;
}
int main(void)
{
unsigned total_cards = 0;
for (unsigned isuit=0; isuit < N_SUITS; isuit++)total_cards += mygame_deck[isuit].n_cards;
printf("This game has %d suites\n", N_SUITS);
printf("You should have %u cards in the game\n", total_cards);
printf("\nList of cards:\n");
game_rule_change("Five", "Hearts", 200);
for (unsigned isuit=0; isuit < N_SUITS; isuit++)
{
printf(" Suit: %s (%u cards)\n", mygame_deck[isuit].name, mygame_deck[isuit].n_cards);
for (unsigned icard = 0; icard < mygame_deck[isuit].n_cards; ++icard)
{
printf(" The card \'%s of %s\' has the value of %d%s\n",
mygame_deck[isuit].cards[icard]->name,
mygame_deck[isuit].name,
mygame_deck[isuit].cards[icard]->value,
mygame_deck[isuit].cards[icard]->rule_change?" - The rules have changed!!":"");
}
printf("\n");
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment