6

I am trying to learn about structs, pointers, and dynamic arrays in C. I don't understand how to create a dynamic array of structs using pointers. My code doesn't work, and I don't know what's wrong with it. I have seen several examples of dynamic arrays, but non with structs. Any help would be appreciated. Please give some explanation, not just code snippets as I do want to understand not just solve this problem.

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

struct *struct_array;
int i,m,n,p;

struct data
{
    char inputA[20];
    char inputB[20];    
};

struct data get_data()
{
    struct data thisdata;

    printf("Please enter input A\n");
    scanf("%s", thisdata.inputA);

    printf("Please enter input B\n");
    scanf("%s", thisdata.inputB);

    return thisdata;
}

void Output(struct data struct_array, int n)
{
    int index = 0;
    for(i = 0; i<n ;i++)
    {
        printf("%s ", struct_array[i].inputA);
        printf("%s ", struct_array[i].inputB);
    }   
}

void resizeArray(int n)
{
    struct_array = (int*)realloc(n*sizeof(int));
}

void mainMenu()
{
    printf("Please select from the following options:\n");
    printf("1: Add new students to database\n");
    printf("2: Display current student database contents\n");
    printf("3: exit the program\n");
    scanf("%d", &p);
    if(p == 1)
    {
        printf("Please enter the number of students to register:\n");
        scanf("%d", &n);
        resizeArray(n);
        for(i = n; i<n ;i++)
        {
            struct_array[i] = get_data();
        }
    }
    else if(p == 2)
    {
         Output(struct_array, n);
    }
    else
    {
        free(struct_array);
        exit(0);
    }        
}

int main()
{    
    struct_array = (int*)realloc(2*sizeof(int));
    mainMenu();
}
cHam
  • 2,624
  • 7
  • 26
  • 28
  • 2
    `struct data *my_data = (struct data *)malloc(sizeof(struct data) * N);` Where N is the number of elements you want in your array, this allocates memory for N elements of type `struct data` – Hunter McMillen Oct 20 '12 at 17:07
  • 1
    Global variables are bad. Your realloc-calls are incorrect, better is `struct_array=realloc(struct_array,n*sizeof*struct_array)` – user411313 Oct 20 '12 at 17:09

4 Answers4

5

Your definition

struct *struct_array;

is erroneous. You must use the name of your type, the data.

struct data *struct_array;

This way you can allocate the array

struct_array = malloc(MaxNumElements * sizeof(struct data));

and later you should free the memory

free(struct_array);

EDIT: Type definition must occur before the var declaration.

struct data ....

struct data* your_variable;

P.S. If you do not want to type struct keyword each time you use the data type, use the typedef:

typedef struct data_s
{
   char inputA[20];
   char inputB[20];    
} data;
Viktor Latypov
  • 14,289
  • 3
  • 40
  • 55
5

You have several errors in your source code:

  • struct *struct_array; (l. 5)
    What does it mean? Did you want to write struct data *struct_array?

  • printf("%s ", struct_array[i].inputA); (l.32 & l. 33)
    The argument struct_array masks the global declaration, and it is not an array. Why did you add this argument?

  • struct_array = (int *)realloc(n * sizeof(int)); (l. 39)
    You have forgotten an argument. Did you want to use malloc instead? Besides, the cast is not necessary (and incorrect!).

  • Unless you are using an hosted environnment and C99/C11, you should return a value from main.

  • Your variable index is not used. Why did you declare it?

  • for(i = n; i < n; i++) (l. 53) You won't have any iteration here...

The following code works as expected.

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

/* TODO: Avoid global variables. */
struct data *struct_array;

struct data {
    char inputA[20];
    char inputB[20];
};

/* 
 * TODO: Try to avoid passing your structure (40 bytes + padding) 
 * without pointer. 
 */
struct data get_data(void)
{
    struct data thisdata;

    printf("Please enter input A\n");

    /* TODO: Avoid using `scanf` for human inputs. */
    scanf("%s", thisdata.inputA);

    printf("Please enter input B\n");
    scanf("%s", thisdata.inputB);

    return thisdata;
}

void Output(size_t n)
{
    size_t i;
    for (i = 0; i < n; i++) {
        printf("%s ", struct_array[i].inputA);
        printf("%s ", struct_array[i].inputB);
    }
}

void resizeArray(size_t n)
{
    /* TODO: Handle reallocations errors. */
    struct_array = realloc(struct_array, n * sizeof *struct_array);
}

void mainMenu(void)
{
    size_t i, n;
    int p;

    /* TODO: Use a loop ? */
    printf("Please select from the following options:\n");
    printf("1: Add new students to database\n");
    printf("2: Display current student database contents\n");
    printf("3: exit the program\n");
    scanf("%d", &p);

    switch (p) {
    case 1:
        printf("Please enter the number of students to register:\n");
        scanf("%u", &n);
        resizeArray(n);

        for (i = 0; i < n; i++)
            struct_array[i] = get_data();
        break;
    case 2:
        Output(n);
        break;
    }
}

int main(void)
{
    struct_array = malloc(2 * sizeof(int));
    mainMenu();
    free(struct_array);
    return 0;
}
md5
  • 23,373
  • 3
  • 44
  • 93
  • I don't really understand how allocating memory to a pointer is used as/for an array. I tried creating an array and using the pointer as the length (array[pointer]) but didn't work. I really don't get it and I've read several examples that just don'e seem to help me grasp the whole concept. – cHam Oct 20 '12 at 17:17
  • I give an example in my EDIT. – md5 Oct 20 '12 at 17:24
  • 1
    You can only do one operation i the `mainMenu()`; it really needs a loop somewhere — around its call or in its body. – Jonathan Leffler Oct 20 '12 at 17:28
  • Thank you so much! Now I can compare them to see where I went wrong, that is extremely helpful. Thank you for the additional suggestions as well! – cHam Oct 20 '12 at 17:30
2

Do you know how to use typedef?

I would suggest it, makes your code easier to understand and you won't have to be typing the word struct a thousand times. Also you could treat the new type similar to the primitive types (ints, chars, etc), just don't forget to use the dot (.) to access the individual fields you might want.

You could type for instance:

    typedef struct{
      char inputA[20];
      char inputB[20];
    } data;

Now you could declare variables like this:

   data data_variable;
   data *pointer_to_data;

And to you could allocate memory as follows:

   pointer_to_data = (data*) malloc(sizeof(data)* N);

where N is the amount of struct data you want to allocate. Same works for realloc.

vmp
  • 2,370
  • 1
  • 13
  • 17
0

struct_array = (int*)realloc(2*sizeof(int));

By the above statement you are trying to assign address of an int to a pointer of type struct data.

You need to use:

struct_array = (struct data*)realloc(2*sizeof(struct data));
akaHuman
  • 1,332
  • 1
  • 14
  • 33