How to use sscanf

Posted on 2004-08-31
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"
Question by:pupuboo
LVL 11

Accepted Solution

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


#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 {
LVL 11

Expert Comment

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

Expert Comment

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;
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!

LVL 19

Expert Comment

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

Assisted Solution

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.

LVL 14

Assisted Solution

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)
LVL 19

Assisted Solution

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.

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering 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

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…
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 be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

749 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