Sebastian Serrano
Sebastian Serrano

Reputation: 372

Dynamically increase array size in Struct "C"

My question is a simple one...I have the following structs declared:

struct Address {
   int id;
   int set;
   char *name;
   char *email;
};

struct Database {
   struct Address rows[512];
};

struct Connection {
   FILE *file;
   struct Database *db;
};

Now having that clear, I initialize my "Database" inside my "Connection" with some dummy Addresses. I later take this database and save it into the file inside my "Connection" struct with:

void Database_write(struct Connection *conn){
   rewind(conn->file);

   int rc = fwrite(conn->db, sizeof(struct Database), 1, conn->file);
      if(rc != 1){
         die("Failed to write database.\n",conn);
      }

   rc = fflush(conn->file);
      if(rc == -1){
         die("Cannot flush database.\n",conn);
      }

Everything works great when I have a predetermined number of rows inside my "Database" struct for my Addresses i.e. 512. But, what if I want to make the number of rows dynamically? As in maybe as a param passed to a function? I have tried using the following...

struct Database {
   struct Address *rows;
};

And allocating space to this pointer with:

conn->db->rows = (struct Address*) malloc(sizeof(struct Address)*max_rows);

With max_rows being a param passed to a function...But, now the problem is that when I go and try to save this to the file inside my "Connection" struct I just save the pointer "struct Address *rows;" and not the data with the space allocated to it. Any suggestions as to how to save this allocated space or have a predetermined array inside a struct and then grow it dynamically?

Thanks in advance!

Upvotes: 1

Views: 1265

Answers (1)

Gavin Shreeves
Gavin Shreeves

Reputation: 101

You are on the right track with malloc for creating a dynamic number of Addresses.

conn->db->rows = (struct Address*) malloc(sizeof(struct Address)*max_rows);

But then you have a problem writing them out to file in Database_write. This is because the dynamically-allocated structure no longer has the number of rows hardwired into it. You will have to change Database_write to

  1. Pass in how many rows to write.
  2. Adjust your fwrite line to write out all the rows.

You had:

void Database_write(struct Connection *conn)
{
    rewind(conn->file);

    int rc = fwrite(conn->db, sizeof(struct Database), 1, conn->file);
    if(rc != 1){
        die("Failed to write database.\n",conn);
    }
...

You now need something like:

void Database_write(struct Connection *conn, int num_rows)
{
    rewind(conn->file);

    int rc = fwrite(conn->db, sizeof(struct Database), num_rows, conn->file);
    if(rc != num_rows)
    {
        die("Failed to write database.\n",conn);
    }

...

You could also add the number of rows to your database struct to record how many rows are supposed to be in the file:

struct Database 
{
    int num_rows;
    struct Address *rows;
};

In which case you should fwrite the number of rows to file first, then write num_rows of struct Address.

You might also want to look up realloc for changing the number of rows on the fly. Hint - use with care, and pay close attention to the return value.

Upvotes: 3

Related Questions