Solved

How to use sscanf

Posted on 2004-08-31
10
324 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
10 Comments
 
LVL 11

Accepted Solution

by:
avizit earned 64 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
Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

 
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 62 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 62 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 62 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

Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

Question has a verified solution.

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

Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

813 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

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now