0

I'm making phone book assignment. I have to get data from delivered file that is given in specific format. Name | Surname | Phone number I'm using code below :

    while(!feof(file)){
        int result = fscanf(file, "%19s | %39s | %d", p->name, p->last_name, &p->number);
        if (result == 3){
            p++;
            counter++;
            if (counter > size + 1){
                break;
            }
        }
    }

It works ok for simple cases like : Jim | Carrey | 123456 but it breaks when input is Louis | Gossett Jr. | 502521950 Then this function writes name Louis Surname Gossett(lacks " .Jr" and Phone number is left empty and result returns 2 which makes input invalid... How can i fix this ?

I tried to play a little bit with format specifiers [^...] but I can't really figure out if that's the correct way of thinking and how they actually works. Whenever i added something, everything broke completely. I'll add that requirement is not to use Arrays or functions allocating memory :(

Kazeyoshi
  • 49
  • 7
  • practice parsing strings without using files. add files last. add hard coded strings in your app to test the various possible data entries. Maybe scanf is not the method you should use. – john elemans Mar 24 '22 at 16:20
  • regardiing: `while(!feof(file)){` this is an error. suggest reading: [why while(eof(file)) is always wrong](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) – user3629249 Mar 25 '22 at 01:47

1 Answers1

2

Fscanf with %s format specifier will read a word and stop when it encounters a whitespace (newline, space or tab). That is why surname is not read completely. You are reading Luis and Gossett but %d can't read a string Jr.

You could use %[^|]| to read the whole string (name or surname).

Try fscanf(file, "%19[^|]|%39[^|]|%d", p->name, p->last_name, &p->number);

Something like this after fscanf call should clear the trailing spaces, but there are probably other ways to do it.

if (p->name[strlen(p->name)-1] == ' ')
   p->name[strlen(p->name)-1] = '\0';
pmatkov
  • 144
  • 1
  • 5
  • @pmatkov its almost what i need but now variables eg. with name contains extra space so instead of "Jim" i have "Jim " can i fix it with these specifiers somehow as well ? – Kazeyoshi Mar 24 '22 at 16:45
  • and im afraid surname will have extra space before and after as well : Jim | Carrey | 1234 name will be "Jim " instead of "Jim" surname will be " Carrey " instead of "Carrey" etc... :( – Kazeyoshi Mar 24 '22 at 16:53
  • @hyde added max string sizes – pmatkov Mar 24 '22 at 16:55
  • thanks again i will try this in a few mins but i'm scared of surname as the space before surname will be hard to remove this way as id have to move all other letters on array to the beginning ? – Kazeyoshi Mar 24 '22 at 17:00
  • 1
    @Dominik You can eat up whitespace with `scanf` by adding a space before `%`. And you should write some kind of a `right_trim(char *str)` function to remove trailing whitespace. Also, removing leading white space by moving characters is not "hard", even if you don't need it if you add those spaces to format string. – hyde Mar 24 '22 at 17:06