?
Solved

How to use sscanf

Posted on 2004-08-31
10
Medium Priority
?
334 Views
Last Modified: 2008-03-06
Hi ,


I need to read in a txt file with below syntax:

  #
  # This is text file:
  #
  # color : number : exist : [OLD_STUFF]
  #
  PRODUCT: abc
  orange    : 230 : 1,4,6,8,11,44-67,88    
  purple : 127 : 3,9,22,55-77,99 : OLD_STUFF

  PRODUCT: xyz
  white    : 230 : 1,4,6,8,11,88
  black : 130 : 3,9,22,99 : OLD_STUFF
  blue    : 679 : 0-11, 100-237, 239


1. how to write sscanf to read in a file that generic enough,
   if see "#"  , no process
   no "#", further process

2.   if further process.
     how to write generic sscanf to read data from "orange    : 230 : 1,4,6,8,11,44-67,88"   and "black : 130 : 3,9,22,99 : OLD_STUFF"
0
Comment
Question by:pupuboo
7 Comments
 
LVL 11

Accepted Solution

by:
avizit earned 256 total points
ID: 11948020

1)sscanf doesn't read directly from a file , so you have to use some other funtion e.g fgets to read in a line from the file to a buffer

e.g

#include <stdio.h>
char line[LINE_MAX];

while (fgets(line, LINE_MAX, fp) != NULL) {       //careful with these constant values LINE_MAX
.............
}

now that would have put a line ( depending on constant and also the file content ) in the buffer
now you have use sscanf to read from the buffer

so within the while loop you can have a sscanf()

as in

sscanf(line, "%c%s",ch,str);

if ( ch == '#'){
.........
}else {
........
}
0
 
LVL 11

Expert Comment

by:avizit
ID: 11948025
btw are you sure  you have to use sscanf ? cos sscanf cannot read directlyfrom a file .. its reads only from a buffer .
0
 
LVL 19

Expert Comment

by:drichards
ID: 11949005
I think reading the line first and then deciding how to process is probably cleaner - certainly more flexible, but if you really want to scanf...

The following code produces this output:

Color: orange, #230, 1,4,6,8,11,44-67,88
Color: purple, #127, 3,9,22,55-77,99, OLD_STUFF
Color: white, #230, 1,4,6,8,11,88
Color: black, #130, 3,9,22,99, OLD_STUFF
Color: blue, #679, 0-11,

--------------------------------------------------
    FILE *stream = fopen(filename, "r");
    char color[32], exist[32], stuff[32];
    long number;
    int numFields = 0;
    while ( (numFields = fscanf(stream, "%s : %d : %s :%s", color, &number, exist, stuff)) > 0)
    {
        if ( numFields > 1 )
        {
            std::cout << "Color: " << color << ", #" << number << ", " << exist;
            if ( numFields > 3 ) std::cout << ", " << stuff;
            std::cout << std::endl;
        }
    }
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 19

Expert Comment

by:drichards
ID: 11949008
You should note that the fscanf is fragile.  If the input lines are not all formatted alike, it won't work.
0
 
LVL 22

Assisted Solution

by:grg99
grg99 earned 248 total points
ID: 11951086
I would start at the beginning of the string, look at each character.
If you see a digit, sscanf("%d" ) it, if not, do the right thing depending on whether it is a comma or a dash.  Keep advancing the string pointer til you get to the end of line.

0
 
LVL 14

Assisted Solution

by:wayside
wayside earned 248 total points
ID: 11954359
@drichards: your code doesn't correctly handle the blue line.

How about this:

    while ( (numFields = fscanf(stream, "%s : %d : %^[:] : %s", color, &number, exist, stuff)) > 0)

This should put everything between the second and third colons into the exist string.

In fact for maximum flexibility of input format, this should probably be done for all the strings:

    while ( (numFields = fscanf(stream, "%^[:] : %d : %^[:] : %^[\r\n]", color, &number, exist, stuff)) > 0)
0
 
LVL 19

Assisted Solution

by:drichards
drichards earned 248 total points
ID: 11955276
Yep.  Like I said, the scanf approach is very fragile.  This is a very limited set of inputs to test.  I can easily imagine others with similar seemingly minute differences that will also cause problems.

Unless I had guarantees about the exact line formats, I'd go with a more systematic approach of reading in the whole line, inspecting the first character and calling a parsing routine on lines of interest.
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

807 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question