1

Im trying to read a file with about 200 lines, and thereafter saving the diffrent lines into a struct. The stuct is as following:

struct person_data{
  char name[20];
  char lastname[30];
  int age;
  char country[3]
};

The lines in the file is setup as:

"Tom HALL"                            32   ENG
"Ryan SMITH"                          24   USA

So my problems is that i am not sure how i am supposed to read that file, and put the information into a struct. I how been trying a to save the file into my struct, and print it, but the result is a directory paths on my computer and a lot of weird symbols before it crashes. My code is:

int main(){
FILE *fp;
fp = fopen("person.txt", "r");
person_data *person = malloc(sizeof(struct person_info));
int i = 0;
if(fp != NULL) {
    while ( i < 200 ) {
        fscanf(fp, "%[A-Za-z] %[A-Z] %d %[A-Z]",
               person[i].name,
               person[i].lastname,
               &person[i].age,
               person[i].country);

        i++;
    }
}
else{
    perror(fp);
}
for (i = 0; i < 200; i++) {
    printf("%s %s  %d %s",
           person[i].name,
           person[i].lastname,
           person[i].age,
           person[i].country);

}
fclose(fp);
return 0;
}

I am not sure what went wrong, and would therefore like to ask if anybody knows what i did wrong and how to fix this. When i run the program it looks like this:

Output

Al0x
  • 917
  • 2
  • 13
  • 30

2 Answers2

1

If you need 200 of that struct, you need to allocate 200 times the size of the struct

#define NUMBER 200

person_data *person = malloc(NUMBER * sizeof(struct person_info));

or use calloc (initialize the allocated memory to zeroes - not necessary in your case, but is easier to read)

person_data *person = calloc(NUMBER, sizeof(struct person_info));

and also country needs to be at least 4 character (@PeterJ_01 comment) if you store 3 chars strings in it (due to trailing zero).

Déjà vu
  • 28,223
  • 6
  • 72
  • 100
  • I tried it out, but the program just printed one word and a lot of zeroes instead. Is the way i read to file and store it in my struct correct? – Frederik Christensen Nov 26 '17 at 13:18
  • Replace the `fscanf` with `fscanf(fp, "%s %s %d %s");` – Déjà vu Nov 26 '17 at 13:25
  • Thanks that helped a bit, it now prints out the first person, but after that i keeps printing out zeroes. – Frederik Christensen Nov 26 '17 at 13:35
  • Check the input file - does it fit the fscanf? Personally I prefer to use [fgets + strtok](https://stackoverflow.com/questions/12499219/using-fgets-and-strtok-to-read-in-a-file-line-by-line-in-c). – Déjà vu Nov 26 '17 at 13:42
  • I now got it to work, and it prints out all the names, but everything is unformatted, and multiple persons are on the same line. Do you know any solution to that? – Frederik Christensen Nov 26 '17 at 13:43
1

First of all look at your malloc and think what is wrong? You malloced just for one single struct. Allocating works the same for all types. If you need to allocate an array of struct person, you do that with:

struct person_data *person = malloc(number_of_elements * sizeof(struct person_data));

btw your have an typo in sizeof(sturct person_info) you don't have person_info struct

I test your code and with this statement it doesn't work fscanf(fp, "%[A-Za-z] %[A-Z] %d %[A-Z]") i can't figure out why... but i just rewrite it to fscanf(fp, "%s %s %d %s") and all work well

in perror() you pass FILE* but it expected const char *s from man:

The perror() function produces a message on standard error describing the last error encountered during a call to a system or library function.

First (if s is not NULL and *s is not a null byte ('\0')), the argument string s is printed, fol‐ lowed by a colon and a blank. Then an error message corresponding to the current value of errno and a new-line. To be of most use, the argument string should include the name of the function that incurred the error.

And also you need for + 1 in size for string because last char is '\0'; in your case country have [3] need [4];

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

struct person_data {
    char name[20];
    char lastname[30];
    int age;
   char country[4];
};


int main(){
    FILE *fp;
    fp = fopen("person.txt", "r");
    struct person_data *person = malloc(sizeof(struct person_data) * 4);
    int i = 0; 
    if(fp != NULL) {
         while ( i < 4 ) {
           fscanf(fp, "%s %s %d %s",
                person[i].name,
                person[i].lastname,
                &person[i].age,
                person[i].country);
                i++;
        }
    }
    else{
      perror("FP ERROR: ");
    }
    for (i = 0; i < 4; i++) {
        printf("%-8s %-10s  %-10d %-10s\n",
        person[i].name,
        person[i].lastname,
        person[i].age,
        person[i].country);

   }
   fclose(fp);
   return 0;
}

I try with four person in my person.txt and it work. and it print :

"Tom     HALL"       32    ENG  
"Ryan    SMITH"      24    USA  
"Hal     Al"         25    UKR  
"Peter   Peters"     99    ENG 
Nick S
  • 1,299
  • 1
  • 11
  • 23
  • Thanks for the help. You are right about perror, and i changed it. I got it to work, and it prints out all the names. But i also have the problem that for some people the lines is split up into 3 bits, from i to i+3, while the rest works fine. – Frederik Christensen Nov 26 '17 at 14:03
  • Thank you very much, i got it to work without problems now. – Frederik Christensen Nov 26 '17 at 14:21