0

I have a following problem. I want to convert a string like "10 15 30" to an int array with ints 10, 15, 30. I searched in google a lot, but usually solutions included vectors (which I am not familiar with) or other more complex solutions. I found a code like this:

#include <cstdio>
void foo ( char *line ) {
    int num, i = 0, len;
    while ( sscanf( line, "%d%n", &num, &len) == 1 ) {
        printf( "Number %d is %d; ", i, num );
        line += len;    
        i++;            
    }
}
int main ( ) {
    char test[] = "12 45 6 23 100";
    foo( test );
    return 0;
}

It works and extracts numbers from string in a way I wanted, but I don't understand part with:

line += len;

Can someone explain how it works? Why are we adding len (which is int) to the string?

2
  • line isn't really a string, it's a pointer to a position of the string. when you enter the first time in the loop it points to the first position of your string, every time line += len; is called this pointer is incremented by the number of characters that were read by sscanf. (if I'm understanding the behavior of %n). So the next time you call sscanf the pointer line points to the the position of next number in the string. Commented Jun 21, 2015 at 15:50
  • 1
    but usually solutions included vectors (which I am not familiar with) You should start getting familiar with it. Might as well start now. And how was this code "simpler" than the answer given by @zenith? Your code is not really intuitive, not typesafe, and even an experienced programmer has to read the docs or look twice (or more times) at it to figure out what it is doing. Commented Jun 21, 2015 at 16:17

6 Answers 6

2

Solution for C++:

#include <iostream>
#include <sstream>
#include <vector>

std::vector< int > foo ( char *c_str ) {
    std::istringstream line( c_str );
    std::vector< int > numbers;
    for ( int n; line >> n; )
        numbers.push_back( n );
    return numbers;
}

int main ( ) {
    char test[] = "12 45 6 23 100";
    std::vector< int > numbers = foo( test );
    for ( int n : numbers )
        std::cout << n << ' ';
    return 0;
}

Output:

12 45 6 23 100
Sign up to request clarification or add additional context in comments.

3 Comments

You need to fix your return type, and the loop can be a simple int n; while (line >> n)
@PaulMcKenzie Fixed. IMO both while and for are equally simple.
But I prefer for because it reduces the scope of n.
0

%n specifies the number of characters accessed by sscanf in its one execution and saved it in variable len. so line + =len; is incrementing variable line, with number of characters accessed by sscanf

line + =len; is nothing but line =line+ len;

Comments

0

line += len; is equivalent to line = line + len;

line is a char pointer, thus the code increases the pointer by len, so that the pointer points to the next number, every time the loop is executed. Note than len is updated by the call to sscanf().

Comments

0

The "string" is a pointer to a character buffer. You are performing pointer arithmetic to increment the sscanf to parse the next int characters from the buffer. So, in your example:

char test[] = "12 45 6 23 100";

say *line points to test, and has some pointer value, we don't care what the value is per-se, so let's say it is 1000. After the 1st call to sscanf, you read "12" in. That is two characters, so len should return 2. line then gets set to 1002, and is now "pointing" to the next set of characters in the buffer. sscanf reads that, and this continues until no more characters in the buffer.

Comments

0

Look at sscanf docs. It receive format and additional params.

In params you have "%d%n" which you explain using format table from docs.

d or u

Decimal integer

Any number of decimal digits (0-9), optionally preceded by a sign (+ or -). d is for a signed argument, and u for an unsigned.

n

Count

No input is consumed. The number of characters read so far from stdin is stored in the pointed location.

So you read integer from string and number of chars this integer consist from.

After reading part of string you move pointer into number of read chars.

Comments

0

sscanf( line, "%d%n", &num, &len)

This line reads a number from line, and put the digit into num and number of characters read into len.

We need len to move pointer to unread portion of the string.

Does it make sense ?

Useful links: scanf sscanf

3 Comments

Does it read a digit or a number? A number is one or more digits. I think the OP wants a number extracted.
d or u Decimal integer Any number of decimal digits (0-9), optionally preceded by a sign (+ or -). d is for a signed argument, and u for an unsigned. extract from scanf documentation
But your answer says "This line reads a digit from line...". My understanding is if the string contains "147", you are saying that it reads the "1" only from the line. The term a means one.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.