Home > Enterprise >  Why am I getting segmentation fault in my while loop?
Why am I getting segmentation fault in my while loop?

Time:12-01

My program will read the datas from a txt into my structure.

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

typedef struct competitor
{
    int id;
    char* name;
    char* nationality;
    char* sex;
    double weight;
    char* event;
}competitor;

int sportolok_beolvas(char* filename, competitor* array)
{
    FILE* file = fopen(filename, "r"); 
    int n = 0; 

    while(fscanf(file, "%d %s %s %s %lf %s", &array[n].id, array[n].name, array[n].nationality, array[n].sex, &array[n].weight, array[n].event) == 6)
    {
          n;
    }
    fclose(file);

    return n;
}

int main()
{
    competitor* array;
    int i = sportolok_beolvas("sportolok.txt", array);
    printf("%d", i);
    return 0;
}

I did this function based on my previous project, which uses almost the same function. Read in the file to my struct. I don't understand what's wrong with it.

CodePudding user response:

A string is really an array of characters with a null-terminator at the end.

You can create a string using plain arrays, like

char str[] = "foo";

Or you can use pointers and allocate memory dynamically, like

char *str = malloc(4);
strcpy(str, "foo");

Both those examples are almost equivalent (there are some important differences between arrays and pointers, but lets put those aside for now). Both those examples creates a string with three characters (plus the null-terminator).

However, if you have

char *str;
strcpy(str, "foo");

then you have undefined behavior because the pointer str doesn't point anywhere.


Going back to your code, the simplest solution for the strings are simply to change them from pointers to arrays:

#define NAME_SIZE        20
#define NATIONALITY_SIZE 20
#define SEX_SIZE         10
#define EVENT_SIZE       20

typedef struct competitor
{
    int id;
    char name[NAME_SIZE];
    char nationality[NATIONALITY_SIZE];
    char sex[SEX_SIZE];
    double weight;
    char event[EVENT_SIZE];
}competitor;

As for the array of competitor structures, I recommend you create it dynamically as needed inside the loop, reallocating as needed.

Read into a single defined competitor structure object, and copy it to the current array element.

Once done return the pointer to the first element of the array.

Perhaps something like this:

// Out dynamic "array", pointer to its first element
competitor *competitors = NULL;

// Current size of the competitor array
size_t current_size = 0;

// A structure object to store the data we read from the input
competitor current_competitor;

// Now the loop to read the data
while(fscanf(file, "%d %s %s %s %lf %s",
             &current_competitor.id,
             current_competitor.name,
             current_competitor.nationality,
             current_competitor.sex,
             &current_competitor.weight,
             current_competitor.event) == 6)
{
    // Reallocate the array, adding one new element ( 1)
    // If the array doesn't exist, when competitors is NULL, create
    // an array with a single element
    competitor *new_array = realloc(competitors, sizeof *new_array * current_size   1);

    // Check if the allocation succeeded or failed
    if (new_array == NULL)
    {
        // TODO: Report it
        exit(EXIT_FAILURE);
    }

    // Make the new array our actual array
    competitors = new_array;

    // Copy the the structure object we just have read, into the array
    competitors[current_size] = current_competitor;

    // And finally increase the size
      current_size;
}

After this, the `competitors` pointer will point to the first element of an array of `current_size` elements.

Exactly how to return these values (*both* needs to be returned) is left as an exercise for the reader.
  • Related