1

I am new to C and had a question about dynamic arrays.

I am building a game so that when the user enters 6 numbers so that it matches the 6 random numbers that the code generates, the user wins.

I am trying to create a dynamic array to store the user's guesses until the user gets the answer correctly. However, I am unsure of how that would work. Would I create a function so that whenever the user gets an answer wrong, I call the function to create a new dynamic array to store the user's guesses?

6
  • 1
    For some examples of dynamic arrays, see my answers: C Programming: Reading data from a file, dynamically allocating memory, placing contents in struct array and Creation of Dynamic Array of Strings in C Commented Feb 21, 2024 at 0:55
  • Do you mean "dynamically allocated" arrays? C does not have a built-in extensible array type. Commented Feb 21, 2024 at 1:05
  • It's always worth asking yourself if there is an upper bound on the number of elements you wish to store. Sometimes it's not worth the hassle of using a dynamic, growable data structure. Commented Feb 21, 2024 at 1:47
  • Write singly/doubly linked-list according to your need Commented Feb 21, 2024 at 3:16
  • Why do you need dynamic memory? This sounds like a solid case for a fixed maximum number of tries. Or will the game run for all eternity until they guess the right numbers? Commented Feb 21, 2024 at 9:35

1 Answer 1

0

What does a "vector" that can dynamically grow need to keep track of?

  • A current size.
  • An allocated memory size.
  • A (pointer to a) chunk of dynamically allocated memory, which can be reallocated when the vector needs to grow in size.

One that can store int values.

typedef struct int_vec {
    size_t sz;
    size_t allocated_sz;
    int *data;
} int_vec_t;

When you want to allocate a vector you can use malloc to allocate the vector struct, but also the array that the data member will point to.

int_vec_t *make_int_vec(size_t starting_capacity) {
    int_vec_t *vec = malloc(sizeof(*vec));
    if (!vec) return NULL;

    vec->data = malloc(sizeof(int) * starting_capacity);
    if (!vec->data) {
        free(vec);
        return NULL;
    }

    vec->sz = 0;
    vec->allocated_sz = starting_capacity;

    return vec;
}

When you want a vector to grow it's best to do this by a factor other than +1. For simplicity, let's use x2. You'd use realloc to accomplish this, but in case realloc fails, we use a pointer other than vec->data to test it so we don't leave the original pointer dangling. Once we know it succeeded we can assign it to vec->data.

int_vec_t *grow_int_vec(int_vec_t *vec) {
    if (!vec) return NULL;

    int *new_data = realloc(vec->data, sizeof(int) * vec->allocated_sz * 2);
    if (!new_data) return NULL;

    vec->data = new_data;
    vec->allocated_size *= 2;

    return vec;
}

Remember on freeing such a structure you need to free the internal array as well. Two malloc calls were made to bring this struct into existence, so two free calls are needed to destroy it.

void free_int_vec(int_vec_t *vec) {
    if (vec) free(vec->data);

    free(vec);
}

If we wanted to write a push_onto_int_vec function, it might look like the following. A return value of NULL indicating that the element was not added, otherwise returning the vector.

int_vec_t *push_onto_int_vec(int_vec_t *vec, int val) {
    if (!vec) return NULL;

    if (vec->sz == vec->allocated_sz && !grow_int_vec(vec)) 
        return NULL;
    
    vec->data[vec->sz++] = val;
    return vec;
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.