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",
¤t_competitor.id,
current_competitor.name,
current_competitor.nationality,
current_competitor.sex,
¤t_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.