0

For a class assignment I have an array that I need to define in main() but allocate memory and load the data in a sperate function load(). Right now autos[] doesn't get populated with the data from the file. Any help is appreciated.

The struct has 4 fields: name, floatNum, intNum, color, that the data needs to be written to. size and autos[] are both defined in main and size refers to the number of elements in autos[].

Load function

void load(int size, struct data autos[]) {
    
    autos = malloc(size * sizeof(struct data));
   
    FILE *data;
    data = fopen("./hw3.data", "r");
    int i;
    for (i = 0; i < size; i++) {
        fscanf(data, "%s %f %d %s", autos[i].name, &autos[i].floatNum, &autos[i].intNum, autos[i].color);
    }
}
FunkyMunky
  • 21
  • 5
  • 1
    If you pass the array into the function, the allocation problem is for the calling code, not the function shown. If you want to allocate the array in the function, it is usually best to return the pointer to the allocated data, either directly as the return value or via a pointer to pointer argument that you assign to. That means either `struct data *load(int size);` or `int load(int size, struct data **p_autos)` where your calling code has `struct data *autos;` and you pass `&autos` to the function. If the memory allocation fails (or the file open fails), you should return a null pointer. – Jonathan Leffler Sep 16 '22 at 16:35
  • Do you mean something like this? (Sorry for the awful formating) void load(int size, struct data *(*autos)) { *autos = (struct data*)malloc(size * sizeof(struct data)); FILE* data; data = fopen("./hw3.data", "r"); int i; for (i = 0; i < size; i++) { fscanf(data, "%s %f %d %s", autos[i]->name, &autos[i]->floatNum, &autos[i]->intNum, autos[i]->color); } } – FunkyMunky Sep 16 '22 at 17:24
  • No. I used `struct autos **p_autos` and it seems that you're using `struct autos (*autos)` — there's a major difference (and the relevant difference isn't the redundant parentheses)! But maybe the problem is SO's use of MarkDown. Use back quotes around code fragments in comments to avoid `*` being interpreted as formatting — start/stop italic/bold etc. So, type `\`void load(int size, struct data *(*autos)) …\`` to get the code formatted better, if that's what you meant. – Jonathan Leffler Sep 16 '22 at 17:43
  • You certainly want to check that `fopen` succeeds and that each call to `fscanf` returns 4. You also want to limit the scans with eg `fscanf(data, "%31s %f %d %31s" ...)` (assuming the size of each field is not less than 32). You may also want a width modifier on the %f and %d to avoid undefined behavior for inputs that overflow the type, but that's probably overkill at this point. Checking the values returned by `fopen` and `fscanf` is essential, however. – William Pursell Sep 16 '22 at 17:50
  • I just did an answer: [Creation of Dynamic Array of Strings in C](https://stackoverflow.com/a/73737192/5382650) that shows how to have a dynamic array struct and I used it to allocate an array of structs that was populated by reading in the struct data from a file. – Craig Estey Sep 16 '22 at 18:27
  • Craig, I'm having some trouble understanding how you are returning the array, is it a pointer or are you just returning the data in the array. Jonathan, you are correct I meant to type `void load(int size, struct data *(*autos)) {` but the formatting was messing it up. – FunkyMunky Sep 16 '22 at 19:01
  • Everything is a pointer. `arrnew` returns a pointer to the array control struct. `arrappend` returns a pointer to the target type of the data in the "array". For you, it would be: `arr_t *arr = arrnew(sizeof(struct data)); while (1) { struct data *cur = arrappend(arr); if (fscanf(data, "%s %f %d %s", cur->name, &cur->floatNum, &cur->intNum, cur->color)) != 4) { arr->arr_count -= 1; break; } } arrtrim(arr); do_stuff(arr); arrfree(arr);` – Craig Estey Sep 16 '22 at 19:27
  • You will also need to `fclose()` the file stream that you opened, assuming it was opened successfully. – Jonathan Leffler Sep 16 '22 at 21:38

1 Answers1

0

I figured it out. Thank you Craig and Johnathan for giving me some pointers. It takes the size of the array needed (from a different function) and creates one and scans through the data file putting data into each element.

struct data* load(int size){
    
    struct data* autos = malloc(size * sizeof(struct data));  

    FILE* data;
    data = fopen("./hw3.data", "r");

    int i = 0;
    for (i = 0; i < size; i++) {
        fscanf(data, "%20s %f %d %20s", autos[i].name, &autos[i].floatNum, &autos[i].intNum, autos[i].color);
    }

    fclose(data);

    return autos;
}
FunkyMunky
  • 21
  • 5