Codey Codey - 23 days ago 9
C Question

C fscanf complex format

I am trying to read this text from a file in C. Assume this is the file Input.txt

This is a description which can be up to 1024 characters long
First
Second
Thrid Option This is a description for third
Fourth


I want to read the 4 words First, Second, Third, Fourth, the rest will be discarded. I have the solution for this problem but I do not understand why it works:

char string[1024];
char words[4][256];
FILE *in = fopen("Input.txt", "r");

// Catch first line
fgets(string, 1024, in);

for(int i = 0; i < 4; i++){
fscanf(in, "%255s[^\n]\n", words[i]);
fscanf(in, "%*[^\n]\n");
}


The input file is expected in a special format.


  • The first line is a description which can be up to 1024 characters long.

  • Lines 2 to 5 are always in this format: "Word tab Option tab Description ". Word is mandatory, Option and Description are optional (see Input.txt for example)



I would be very grateful for an explanation of the different components of the format string, how they work and why this whole solution works.

(I also couldn't find any specific information about how fscanf's format works, would be happy if someone could give me a reference)

Answer Source

"and why this whole solution works" IMO, in the general case, it does not.

The 2nd '\n' in the 2 fscanf(in, ... formats makes this a weak solution. That '\n' will scan in any number of line-feeds as well as any white space. Better to continue using fgets(string, ...) and then sscanf(string, ...)

"%255s[^\n]\n" looks for a [ after the "%255s". Strange code. @John Bollinger


Instead

char string[1024+1+1];  // increase for the \n and the \0
char words[4][256]; 
FILE *in = fopen("Input.txt", "r");

// Catch first line
// fgets(string, 1024, in);
fgets(string, sizeof string, in);

// "%255s" 
// scan over yet do not save leading white-space
// scan and save up to 255 non-white-space characters.
// Append a null character to form a string
for(int i = 0; i < 4 &&  fgets(string, sizeof string, in); i++ ){
    if (sscanf(string, "%255s", words[i]) != 1) {
      words[i][0] = '\0'; // If line was all white-sapce
    }
    puts(words[i]);
}