[2 days left] What’s wrong with your cloud strategy? Learn why multicloud solutions matter with Nimble Storage.Register Now

x
?
Solved

How to use sscanf

Posted on 2004-08-31
10
Medium Priority
?
331 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
10 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
Industry Leaders: 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!

 
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

[Webinar] Lessons on Recovering from Petya

Skyport is working hard to help customers recover from recent attacks, like the Petya worm. This work has brought to light some important lessons. New malware attacks like this can take down your entire environment. Learn from others mistakes on how to prevent Petya like worms.

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…
What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. …
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
Suggested Courses

649 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