Printing an int array from a structure in C

advertisements

I am trying to read in a struct from a file and then display (and sort) and array. I am having trouble though which I think is to do with me not accessing the correct memory. When I print the array it comes up as loads of random numbers.

struct details
{
    int numberOfPresents;
    int numberOfBuildings;
    int buildings[];
};

void print_int_array(const int *array)
{
    for(int i=0; i<200; i++)
        printf("%d | ", array[i]);

    putchar('\n');
} 

void sort(int buildings[], int count)
{
    int i, j, temp;
    do {
        j = 0;
        for (i = 0;i<count-1;i++)
        {
            if (buildings[i] < buildings[i+1])
            {
                j = 1;
                temp = buildings[i];
                buildings[i] = buildings[i+1];
                buildings[i+1] = temp;
            }
        }
    } while (j == 1);
}

int main()
{
    FILE *fp;
    fp = fopen("buildings.out", "r");
    struct details data1;
    size_t structSize = sizeof(struct details);
    //size_t arraySize = sizeof(int)*sizeof(buildings);
    fread(&data1, structSize, 1, fp);
    for(int i=0; i<200; i++)
        printf("%d | ", data1.buildings[i]);

    //sort(data1.buildings );
    //print_int_array(data1.buildings, arraySize);
    //printf("Number of Houses: %d\n",numberOfHouses(data1.numberOfPresents, data1.buildings));
    fclose(fp);
    return 0;
}


You've got two issues working against you printing the data.

  • Enough room is not allocated for the records.
  • Enough data is not read for the records.

The line struct details data1 only allocates enough room on the stack for one copy of the struct. You need enough for 200 of them. I'd immediately suggest an array.

struct details data1[200];

When you perform the read, fread(&data1, structSize, 1, fp), you're only reading in one record of size structSize. Now that you have enough memory allocated to read in 200 records, you can bump up the number of records you're reading to 200 as well.

fread(data1, structSize, 200, fp);

(Notice we dropped the & because we're dealing with an array now. Arrays automatically return their base address if you just reference them by name.)

Now, what if your file doesn't have 200 records in it? You probably need to capture the return value of fread() to determine how many records you actually read.

int intNumberOfRecords = fread(&data1, structSize, 200, fp);
for(int i=0; i<intNumberOfRecords ; i++)
  [...]

Now that we have that working, we can look a little closer at the srtuct itself. We've got a challenge with the definition that we can't easily overcome.

struct details{
    int numberOfPresents;
    int numberOfBuildings;
    int buildings[];
};

The last member, buildings[], is not going to read correctly from a file. This is because it's only a 32-bit integer at best in a 32-bit memory model. In other words, what you'll be reading from the disk is just a 32-bit number that points to somewhere in memory. What you won't end up with is an array that contains the buildings. If you try to access it (i.e. in your sort routine) you'll more than likely seg-fault and your program will never work. Trying to post a general solution for this is a little out of the scope of my answer. Suffice it to say, you'll either have to go with a fixed size array or dynamically write variable size arrays to disk (variable length records). The fixed size array would be a lot easier. If we change your definition to the following, we'd load up some data from the disk.

struct details{
    int numberOfPresents;
    int numberOfBuildings;
    int buildings[16];
};

We'd also avoid seg-faulting, which is a nice plus. However, I don't know what your input file looks like so I don't know if this will work given your data.