TinMan
TinMan

Reputation: 99

Dynamic memory allocation of an array in a struct

Working in c. I am trying to dynamically allocate an array that is within a struct. The array will hold rows of char data. I can't see any errors, any help is appreciated.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct data
{
    char **d;
}Data;

int main(void) 
{
    Data *a = malloc(10*sizeof(Data));
    int i = 0, length = 0;

    for(i = 0; i < 10; i++)
    {
        char buffer[1000] = { '\0' };
        printf("\nenter data\n");
        fgets(buffer, 1000, stdin);

        length = strlen(buffer);
        a[i].d[i] = malloc(sizeof(length+1));  //errors here, unhandled exception
        strcpy(a[i].d[i], buffer);
    }

    for (i = 0; i < 10; i++)
    {
        printf("%s", a[i].d[i]);
    }

    return 0;
}

Upvotes: 1

Views: 1129

Answers (3)

Gene
Gene

Reputation: 46960

First, the

malloc(sizeof(length+1));  

makes no sense. You mean

malloc(length+1);

malloc allocates in units of chars. The sizeof() operator returns the size in chars of the type or object that is it's argument. length+1 is not a suitable argument.

Next, you seem to mean to be reading an array of strings. The struct is not contributing much to the problem solution. Consider throwing out the structs and using just an array of pointers to characters (i.e. an array of strings of varying lengths), or else keep the structs and change the field to a char* type.

Additionally, if you don't know the number of strings in the file in advance, then you must grow the array dynamically with something like realloc().

Here is the array of strings approach:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUF_SIZE 1000

int main(void) 
{
  int i, n, n_max = 8;
  char **a = malloc(n_max * sizeof(char*));

  for(n = 0; ; ++n)
  {
    char buffer[BUF_SIZE + 1];  // zeroing buffer is a waste with fgets

    printf("\nenter data or Ctrl-Z to stop\n");
    if (!fgets(buffer, sizeof(buffer), stdin)) return;

    if (n >= n_max) {
      n_max *= 2;
      a = realloc(a, n_max * sizeof(char*));
    }
    a[n] = malloc(strlen(buffer) + 1);
    strcpy(a[n], buffer);
  }
  // n now contains number of strings actually read

  for (i = 0; i < n; i++)
  {
    printf("%s", a[i]);
  }

  return 0;
}

Upvotes: 0

Kaustav Ray
Kaustav Ray

Reputation: 754

Since char **d is a pointer to a pointer. And malloc returns void* type !

Hence,

  1. type mismatch is there.

  2. You have to first allocate the array of pointers. That is a[i].d=malloc(row*sizeof(char *);

    Then you can do a[i].d[i] = malloc((length+1)*sizoef(char));

Upvotes: 1

John Kugelman
John Kugelman

Reputation: 361546

a[i].d[i]

The double use of i here is a red flag. This should be either a[i].d or a.d[i]. It looks like you're intending to store 10 strings, one per Data object. In that case, your struct declaration should contain char * not char **.

typedef struct data {
    char *d;
} Data;

And then the lines assigning to d would become:

a[i].d = malloc(length + 1);
strcpy(a[i].d, buffer);

That gets rid of the double [i] indices. Each Data object contains one string named d. In the loop, you allocate memory for that string and then copy buffer into d. All good!

Notice also that I've gotten rid of the sizeof inside the malloc() call. You want to allocate length + 1 characters. No need for sizeof. If you want to be more explicit you could change length + 1 into (length + 1) * sizeof(char)—but you don't have to, because sizeof(char) is always 1.

Upvotes: 0

Related Questions