2

I read an ascii file with an fstream. A line contains at least two repetitions of the following patern (and at most 128) :

 %d %llu %d %d %llu %d %d %llu

For each line i need the max of the third %d of each pattern in the line

i can't find a way to do it properly with sscanf.

myFstreams->getline (buffer, MAX_BUFF-1);
while( ... ){
    sscanf (buffer," %*d %*llu %*d %d %*llu %*d %*d %*llu",&number);
    if(number>max) max=number;
    //modify buffer ???
}

any help would be greatly appreciated.

Lance Richardson
  • 4,610
  • 23
  • 30
Tony Morris
  • 435
  • 4
  • 15

3 Answers3

5

Your approach looks good, kudos for using %* to suppress assignment.

You need to add code to check the return value of sscanf(), and loop until it fails (i.e. it doesn't return 1). In the loop, maintain the maximum by comparing each converted value to the largest you've seen so far.

UPDATE: I realized I didn't account for the repeating pattern in the same line aspect. D'oh. I think one solution would be to use the %n specifier at the end of the pattern. This will write (through and int * argument) the number of characters processed, and thus allow you to step forward in the line for the next call to sscanf().

unwind
  • 391,730
  • 64
  • 469
  • 606
  • 1
    I think he meant that this pattern repeats in one line, so he is wondering how to modify `buffer` so the next `sscanf` will check the next 8 numbers and not the same ones. – Pawel Zubrycki Sep 10 '12 at 13:10
  • Use `n` type - it gives you the number of characters read. Then offset buffer by that many bytes. – Agent_L Sep 10 '12 at 13:19
  • @PawelZubrycki, @Agent_L good points, and I must claim I edited in the recommendation to use `%n` before fully reading Agent_L's comment. Thanks, both. – unwind Sep 10 '12 at 14:00
1

How about something of the sort: (code untested)

#include <limits>
#include <sstream>
...

std::string line;
while(std::getline(input_stream,line))//delimit by /n
{
    auto line_ss = std::stringstream(line);
    std::string token;
    int number = std::numeric_limits<int>::min();
    int k=0;
    while(std::getline(line_ss,token,' '))//delimit by space
    {
        if(k == 3) // 3rd number
        {
            int i3;
            std::stringstream(token) >> i3; 
            number = std::max(number,i3)
        }

        k = k == 7 ? 0: k+1; //8 numbers in the set
    }
}
Indy9000
  • 8,651
  • 2
  • 32
  • 37
1

There's one "secret" type used by scanf and not by printf, that's why it's often forgotten: %n

while( ... )
{
    //%n gives number of bytes read so far
    int bytesRead =0;
    sscanf (buffer," %*d %*llu %*d %d %*llu %*d %*d %*llu%n",&number, &bytesRead);
    if(number>max)
        max=number;
    buffer +=bytesRead;//be cautious here if using UTF-8 or other MCBS
}
Agent_L
  • 4,960
  • 28
  • 30