Search code examples
cdata-structuresinitializationnew-operator

Is there a substitute for Java's new() in C?


I am trying to create a simple poker game in C and am having difficulty with getting my card structures inside of an array using a loop so that I do not have to individually create each card object and then put them inside of the array manually one by one. I am more familiar with Java and know that I could use the "new className(class parameters)" method for inputting new objects inside of an array without naming and initializing them one by one. This is essentially what I would be doing in Java, and am wondering if there is a way to do this using C.

    for(int i = 0; i < 14; i++){
        table_deck.deck[i] = new card("diamonds", i);
    }

screenshot of my C attempt thus far

I tried doing the attached photo but will not pass compilation. I was hoping that there is some way for me to do this without manually initializing 52 cards individually and them inserting them inside of my array 52 individually.


Solution

  • This OP-linked code seems to want to assign a struct value to an array element:

    for (int i = 0; i < 14; i++) {
        table_deck.deck[i] = struct card {"diamonds", i};
    }
    

    The above code isn't legal in C, but you could use a compound literal to accomplish this:

    for (int i = 0; i < 14; i++) {
        table_deck.deck[i] = (struct card){"diamonds", i};
    }
    

    A compound literal creates an unnamed object, and if it occurs outside of any function that object has static storage duration. Otherwise the unnamed object has automatic storage duration which ends when the block in which the compound literal occurs is exited.

    In general you have to be careful with the lifetimes of objects created through compound literals. The compound literals in the above code occur in a for loop body, and their storage is restricted to that block. The assignment table_deck.deck[i] = (struct card){"diamonds", i}; copies the contents of the unnamed structs into the indexed structs table_deck.deck[i].

    Using a compound literal here is just a convenience. Another way to accomplish the same thing would be to simply assign directly to the relevant fields. You could modify the suit field of the card struct to accept a pointer to char, or perhaps better a pointer to const char. Then a string literal (which decays to a pointer to char in static memory) can be assigned to the pointer:

    struct card {
        const char *suit;
        int value;
    };
    
    /* ... */
    int main(void) {
        /* ... */
        for (int i = 0; i < 14; i++) {
            table_deck.deck[i].suit = "diamonds";
            table_deck.deck[i].value = i;
        }
        /* ... */
    }
    

    Or you could leave the card struct as it is and copy characters into the suit field:

    #include <stdio.h>
    #include <string.h>
    
    struct card {
        char suit[9];
        int value;
    };
    
    /* ... */
    int main(void) {
        /* ... */
        for (int i = 0; i < 14; i++) {
            strcpy(table_deck.deck[i].suit, "diamonds");
            table_deck.deck[i].value = i;
        }
        /* ... */
    }
    

    If you elect to try a solution like this you must be certain that any strings you attempt to copy into a suit field will fit (including the \0 terminator). You might want to use strncpy instead, but this brings its own issues since strncpy can leave its target arrays without null termination.