2

I am trying to pass an array of structures to a function, and then have that function process a file and fill the array of structures with values. The file is a text file containing:

Gates M 60
Jobs M 55
Jane F 45

which would fill the structure of arrays. ex. person[0] should contain Gates M 60. Currently I do not get any errors for this program but it simply does not process the file into the structure at the fscanf. Am I referencing the structure wrong?

I was also wondering if there was a way to make the for loop work for any size of array of structures-- meaning what could I replace the "2" condition in my for loop with in order for it to just continually fill an array of adequate size until it ran out of information to process?

#include <stdio.h>

struct Person
{
    char lastname[30];
    char gender;
    unsigned int age;
};

int function(struct Person array[])
{
    FILE *cfPtr;
    if((cfPtr = fopen("C:\\Users\\Nick\\Desktop\\textfile","r"))==NULL)
    {
        printf("File cannot be opened");
    }
    else
    {
        for(int i=0;i<2;i++)
        {
            fscanf(cfPtr,"%10s %c %3d",&array[i].lastname,&array[i].gender,&array[i].age);
        }
    }
}
int main(void)
{
    struct Person person[3];
    function(&person[3]);
    printf("%s %c %d\n",person[0].lastname, person[0].gender, person[0].age);
    printf("%s %c %d\n",person[1].lastname, person[1].gender, person[1].age);
    printf("%s %c %d\n",person[2].lastname, person[2].gender, person[2].age);
}
Vickel
  • 7,879
  • 6
  • 35
  • 56
yeebyeeb
  • 29
  • 3
  • Yes, this is what `realloc` is for and is how resizable vectors work in other languages (e.g. `ArrayList` in Java, `List` in .NET, `vector` in C++ STL). Use a heap-allocated array (`struct Person* people = calloc( sizeof(struct Person), 10 )` instead of an automatic array. – Dai Dec 11 '19 at 01:14
  • Tip: Use `char*` instead of fixed-length character buffers and then dynamically allocate using `calloc` or `malloc` or `strdup`. Also **use loops** and don't just spam-paste a bunch of largely identical lines. – tadman Dec 11 '19 at 01:18
  • 1
    Note you're passing in a pointer to the *fourth entry* in a three-element array. This code will crash and crash hard. You should pass in `&person[0]`. An array defined as `x[3]` has entries numbered with indexes`0`..`2`. – tadman Dec 11 '19 at 01:19

1 Answers1

1

Currently I do not get any errors for this program but it simply does not process the file into the structure at the fscanf. Am I referencing the structure wrong?

You are almost there, there are just a few things you missed:

  • for(int i=0;i<2;i++) should be for(int i=0;i<3;i++) as you will never read the third line the way it is now.
  • Drop the & when reading with scanf and storing in a string. That is, change fscanf(cfPtr,"...",&array[i].lastname,...); to fscanf(cfPtr,"...",array[i].lastname,...);. A string (i.e. char lastname[30];) is already an array and when using arrays by their names you essentially get a pointer on its first element, so there is no need for that &.
  • The call of the function (function(&person[3]);) is not correct: &person[3] means that you are getting the address of the 4th (out of bounds) element of the person array. What you need to pass is the array itself which is simply function(person). This is for the same reason as in the previous bullet.
  • Also, why do you have your function returning an int when you are not returning anything?

I was also wondering if there was a way to make the for loop work for any size of array of structures-- meaning what could I replace the "2" condition in my for loop with in order for it to just continually fill an array of adequate size until it ran out of information to process?

There is a way, namely using a dynamic array of type struct Person and allocating space to it at first with malloc and then by calling realloc in every iteration inside the function. Of course, you need to keep a counter of how many objects/lines you have read. You can find more about what you are asking by following this or this SO question, or searching and reading about dynamic arrays in C.

kyriakosSt
  • 1,754
  • 2
  • 15
  • 33
  • Wow thanks for the tips. This is all very helpful. The solution I was able to come up with last night instead of the "malloc" bit was to include an if statement: "if(feof)){break;}" after the fscanf, and simply removing the exit condition for the for loop. Is this an acceptable solution as well? What kind of disadvantages am I presenting to myself by failing to use malloc? – yeebyeeb Dec 11 '19 at 14:31
  • without malloc, or rather, realloc, you have to know in advance how many lines you will read from the file. i.e. if you declare `struct Person person[3];` but in your loop, you read 4 lines you will get an error. – kyriakosSt Dec 11 '19 at 14:42