-1

I am trying to parse a file in C++. My file contents are as follows:

//Comments should be ignored

FileVersion,1;
Count,5;
C:\Test\Files\Test_1.txt 0,16777216,16777552,0,0,1,0,1,1,1;

FileVersion is the first line I need to read information. All the previous lines are just comments which begin with a '//'. How do I set my cursor to line containing FileVersion? Becuase I am using fscanf to read the information from the file.

if  (  1 != fscanf( f, "FileVersion,%d;\n", &lFileVersion ))
{
     //Successfully read the file version.
}
user2495173
  • 311
  • 2
  • 5
  • 17
  • `fscanf` is a C function. If you wanted a C solution, why did you tag this as C++? – David G Mar 31 '14 at 22:19
  • 2
    @0x499602D2 it is also valid C++. But streams do generally help with I/O – clcto Mar 31 '14 at 22:20
  • I included the C tag as well. – user2495173 Mar 31 '14 at 22:20
  • So, what's wrong with your posted solution? What are you trying to improve? – Mats Petersson Mar 31 '14 at 22:24
  • When I have comments, FileVersion is not read. It fscanf returns 0. – user2495173 Mar 31 '14 at 22:25
  • @clcto I indeed assumed that he was running C code in a C++ environment. It was just that it is ambiguous as to what kind of solution he wants (C vs C++). It's now even more ambiguous now that he updated the tags. But I guess he will accept either. – David G Mar 31 '14 at 22:27
  • @0x499602D2: fscanf is a valid function in C++, http://www.cplusplus.com/reference/cstdio/fscanf/. I am looking for a solution in C++, please read the question properly. – user2495173 Mar 31 '14 at 22:29
  • consider reading http://stackoverflow.com/questions/865335/when-why-is-it-a-bad-idea-to-use-the-fscanf-function for arguments against fscanf – wonko realtime Mar 31 '14 at 22:40

3 Answers3

0

Since this is tagged C++, I will give you a C++ solution.

You can use a single call to f.ignore() to discard the first line of the stream:

f.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

Technically this skips everything up and including the newline at the end of the first line, so the stream position will be just before the newline on the second line. Formatted I/O discards leading whitespace so this will be no issue.

The above requires the use of C++ file streams since this is C++, and the use of the formatted operators operator>>() and operator<<() to perform input and output.

David G
  • 94,763
  • 41
  • 167
  • 253
0

I like to write parsers (assuming "line-based") by reading a line at a time, and then using sscanf strncmp and strcmp (or C++'s std::stringstream and std::string::substr) to check for various content.

In your example, something like:

enum Sates
{
    Version = 1,
    Count   = 2,
    ...
} state = Version;

char buffer[MAXLEN];
while(fgets(buffer, MAXLEN, f) != NULL)
{
   if (0 == strncmp("//", buffer, 2))
   {
      // Comment. Skip this line.
      continue;
   }
   switch (state) 
   {
       case Version:
          if (0 == strncmp("FileVersion,", buffer, 12))
          {
             if (1 == sscanf(buffer, "FileVersion,%d;", &version))
             {
                  state = Count;
                  break;
             }
             Error("Expected file version number...");
          }
          break;
       ... 
   }
}

There are of course oodles of other ways to do this.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
0

Not a particular C++ solution, but:

  1. read a line with fgets (oh okay, if you want, you can substitute a C++ function for that);
  2. if it starts with your 'comment' designator, skip to end of loop
  3. if the line is empty (i.e., it contains only a hard return; or, possibly, check for zero or more whitespace characters and then an end-of-line), skip to end of loop
  4. at end of loop: if you got something else, use sscanf on that string.
Jongware
  • 22,200
  • 8
  • 54
  • 100