0

Good day everyone I have a quick question..

How do I make fscanf read the whole entire file?

Let's say I have the files settings.txt

setting1 = 1
setting2 = 2
setting3 = 3

How do I parse those into C programming Variables?

int setting1, setting2,setting3;

I tried by simple doing this:

fscanf(fp, "setting2 = %d\n", &setting2);

but it isn't able to take thw value from file, while this works:

fscanf(fp, "setting1 = %d\n", &setting1);

Is there a proper way of reading the whole file?

Jomar Sevillejo
  • 1,648
  • 2
  • 21
  • 33

5 Answers5

3

What about reading each line with fgets() and parsing their content with sscanf() like in this example: https://stackoverflow.com/a/861822/1150918 ? :)

Also, personally for such kind of configs i'd prefer Lua or something tiny and simple like that. Built-in syntax check, C API and small interpreter size.

Community
  • 1
  • 1
Kamiccolo
  • 7,758
  • 3
  • 34
  • 47
  • Thanks, but the problem with fgets is you have to specify the size for the variable that contains it, and I don't know how big it'll be.. the settings about could be really long numbers. – Jomar Sevillejo Aug 19 '13 at 23:37
2

First of all there is nothing wrong with fscanf(). The first thing you should know is that fscanf treats new line characters as white space. Thus, even though you look at the file as individual lines, fscanf sees it as:

  setting1 = 1  setting2 = 2  setting3 = 3

This is NOT a problem, but it does affect how you might write fscanf code to read this text string. This next simple approach is much too simple?!

  fscanf(fp, " setting1 = %d", &setting1);
  fscanf(fp, " setting2 = %d", &setting2);
  fscanf(fp, " setting3 = %d", &setting3);

Note. There is a leading space on the formats for fscanf. This is so that the scanner can find none, one, or many white space characters. If the lines of the text file have leading spaces then a match will NOT be found unless that leading space is in the format. This makes perfect sense because the start of a line might have a few spaces.

Opening a file with read and append also works, when fscanf is coded correctly.

Get this to work. Now, is there more to the file than three settings? If so, then your fscanf code might have to be more complex, but maybe not. Remember the idea is to read data, if your code reads the data, then you're done.

Just for fun, I tried the following fscanfs:

fscanf(fp, " setting1 = %i ", &setting1);
fscanf(fp, "setting2 = %i ", &setting2);
fscanf(fp, "setting3 = %i", &setting3); 

Notice that the "oddly placed spaces in the format definition allow for one or more white spaces between each of the keywords.

And one last comment. Your code should consider that a keyword might be misspelled by the user, in which case fscanf fails. Thus, always store or test the returned value from fscanf:

   int x;

   x = fscanf(fp, " setting1 = %d", &setting1);

   if (x == 0) { // keyword setting1 was misspelled...

And for the trivia of the day:

  x = fscanf(fp, " s e t t i n g 1 = %d", &setting1);  // also works
JackCColeman
  • 3,777
  • 1
  • 15
  • 21
  • I thought this would have solved it, but still it's reading the first line only.. I even tried siplier test, Scanned "Jake123" with "Jake%d" and was able to get "123". Then, I added "asd" to the previous line "Jake" was in. (That makes "Jake" in the second line). when I ran, it's not abled tofind it anymore. :\ – Jomar Sevillejo Aug 19 '13 at 23:49
  • I did another test with a string. I have "JakeSold" in settings.txt (first line and only one line) then scanned it with "Jake%s" it's able to get "Sold" but when I added space between "Jake" and "Sold", Which makes it "Jake Sold". It doesn't read "Sold" anymore. How do I make it include spaces? as fscanf stops on spaces, which I do not understand why.. – Jomar Sevillejo Aug 19 '13 at 23:54
  • I am currently opening the file with the "a+" fopen flag. in read and append mode.. Does that matter? – Jomar Sevillejo Aug 19 '13 at 23:56
  • @user2128576, fundamentally, I think it would. Append mode places the file ptr at the end of the file. Try it as just read and let me know. – JackCColeman Aug 20 '13 at 02:56
1

You want something like this:

int setting[3], i;
for(i = 0; i < 3; ++i)
    fscanf(fp, "setting%*d = %d\n", &setting[i]);
Paul Evans
  • 27,315
  • 3
  • 37
  • 54
1
char line[1024];
int setting[N],i = 0;
while(fgets(fp,line,1024) != NULL)
{
     fscanf(line,"setting%*d = %d",&setting[i++]);
} 
Lidong Guo
  • 2,817
  • 2
  • 19
  • 31
1

The best approach is to separate file I/O from parsing and handle their individual potential errors. IOWs: avoid fscanf().

void Parse(FILE *fp, int NN) {
  char buf[100];
  int setting[NN];
  int i;
  for (i = 0; i < NN; i++) {
    if (fgets(buf, sizeof(buf), fp) == NULL ) {
      ;  // Handle unexpected I/O error
    }
    int n, count;
    unsigned u;
    count = sscanf(buf, "setting%u = %d", &u, &n);
    // Qualify the parse
    if ((count != 2) && (u <= 0) && (u > NN)) {
      ;  // Handle parse I/O error
    }
    setting[u - 1] = n;
  }
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256