?
Solved

How to use sscanf

Posted on 2004-08-31
10
Medium Priority
?
330 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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
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

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [s…
C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

762 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