Question about sscanf and sprintf

B

Bumbala

Hello,

I just want to read a space delimited string of numbers into an array
of double. Is it possible with sscanf ?

Example:
double numbers[3];
char *line = "1 2.5 3.7";
sscanf(line, {format?}, numbers);

Also is the reverse possible with printf ?

sprintf(line, {format?}, numbers);

Thanks.
 
E

Eric Sosman

Bumbala said:
Hello,

I just want to read a space delimited string of numbers into an array
of double. Is it possible with sscanf ?

Example:
double numbers[3];
char *line = "1 2.5 3.7";
sscanf(line, {format?}, numbers);

Also is the reverse possible with printf ?

sprintf(line, {format?}, numbers);

There are no *printf() or *scanf() conversion specifiers
for arrays (except for string-like things), so you'll have to
convert your numbers one at a time:

sscanf(line, "%lf%lf%lf",
&numbers[0], &numbers[1], &numbers[2]);

.... and analogously for *printf(). It's inconvenient to do
this with a large (or unknown) number of things to convert,
so a loop that converts one at a time may be simpler. The
strtod() function may be easiest, but if you'd prefer to use
sscanf() you'll probably find the "%n" specifier helpful: it
tells you how many characters have already been consumed, from
which you can figure out where to start the next sscanf().
 
N

Nelu

Hello,

I just want to read a space delimited string of numbers into an array of
double. Is it possible with sscanf ?

Example:
double numbers[3];
char *line = "1 2.5 3.7";
sscanf(line, {format?}, numbers);

sscanf(line,"%lf %lf %lf",&numbers[0],&numbers[1],&numbers[2]);
Also is the reverse possible with printf ?

sprintf(line, {format?}, numbers);

sprintf(line,"%f %f %f",numbers[0], numbers[1], numbers[2]);

Make sure you can fit the numbers in the line without overflowing. You
should probably specify the desired precision.
 
K

Kaz Kylheku

Bumbala said:
Hello,

I just want to read a space delimited string of numbers into an array
of double. Is it possible with sscanf ?

Example:
double numbers[3];
char *line = "1 2.5 3.7";
sscanf(line, {format?}, numbers);

Also is the reverse possible with printf ?

sprintf(line, {format?}, numbers);

There are no *printf() or *scanf() conversion specifiers
for arrays (except for string-like things), so you'll have to
convert your numbers one at a time:

sscanf(line, "%lf%lf%lf",
&numbers[0], &numbers[1], &numbers[2]);

Hmm. Preprocessor to the partial rescue, for cases where the number of
arguments is fixed:


#define FM_1(X) X
#define FM_2(X) X X
#define FM_3(X) X X X
/* ... */
#define FM_9(X) X X X X X X X X X

#define AR(X, N, Y) X N Y

#define AR_1(X,Y) AR(X, 0, Y)
#define AR_2(X,Y) AR_1(X, Y), AR(X, 1, Y)
#define AR_3(X,Y) AR_2(X, Y), AR(X, 2, Y)
/* ... */
#define AR_9(X,Y) AR_8(X, Y), AR(X, 8, Y)

Now you can do things like:

printf(FM_3("%d"), AR_3(foo[,]))

This expands like:

printf("%d" "%d" "%d", foo[ 0 ], foo[ 1 ], foo[ 2 ])

You can visualize the comma in the AR_3 syntax not as being a macro argument
separator, but as a meta-variable which indicates where the array index will be
inserted. :)

AR stands both for argument and array.

The FM_<n> ought to be more sophisticated, or have more sophisticated
alternatives, where you can control things like material that occurs between
the format directives, but not after the last one.

#define FMS_1(X, Y) X
#define FMS_2(X, Y) X Y X
#define FMS_3(X, Y) X Y X Y X

printf(FMS_3("%02x", ":"), ...) // colon-separation, e.g. MAC

Or alternative approach: Y specifies alternative for the last conversion
specifier:

#define FMA_1(X, Y) Y
#define FMA_2(X, Y) X Y
#define FMA_3(X, Y) X X Y

printf(FMA_3("%02x:", "%02x"), ...) // colon-separation, differently

Though this can be expressed

printf(FM_2("%02x:"), "%02x", ...) // colon-separation, differently

there is still value in maintaining the encapsulation.
 
K

Keith Thompson

Eric Sosman said:
Bumbala said:
Hello,

I just want to read a space delimited string of numbers into an array
of double. Is it possible with sscanf ?

Example:
double numbers[3];
char *line = "1 2.5 3.7";
sscanf(line, {format?}, numbers);

Also is the reverse possible with printf ?

sprintf(line, {format?}, numbers);

There are no *printf() or *scanf() conversion specifiers
for arrays (except for string-like things), so you'll have to
convert your numbers one at a time:

sscanf(line, "%lf%lf%lf",
&numbers[0], &numbers[1], &numbers[2]);

... and analogously for *printf(). It's inconvenient to do
this with a large (or unknown) number of things to convert,
so a loop that converts one at a time may be simpler. The
strtod() function may be easiest, but if you'd prefer to use
sscanf() you'll probably find the "%n" specifier helpful: it
tells you how many characters have already been consumed, from
which you can figure out where to start the next sscanf().

Note that if the converted value won't fit in the target type, the
behavior is undefined. For example, if the input line starts with
"1.0e999999 ", anything could happen; there's no portable way to
recover from the overflow. strtod() is a bit more work, but it's
safer.
 
K

Kaz Kylheku

On 2009-02-07 said:
Note that if the converted value won't fit in the target type, the
behavior is undefined. For example, if the input line starts with
"1.0e999999 ", anything could happen; there's no portable way to
recover from the overflow. strtod() is a bit more work, but it's
safer.

This really should be fixed in the scanf spec (and implementations). The
function certainly the means of reporting the error. If a conversion would
overflow, it can simply report that as a case of failed conversion: not
make the conversion, and return the number of conversions that were
successfully made, or -1 if none. Moreover, to distinguish that situation from
a syntax error, errno can be set to ERANGE.
 
J

James Kuyper

Malcolm said:
The problem is that this puts all the burden on the caller. It might be
very unlikely that an input file would contain an overflow real value
without also being corrupt in other ways, and it is not easy to know
what to do if this occurs.
Allowing the system to make the decision aka "undefined beahviour" might
actually be better.

I can't imagine how. I can see how the undefined behavior might, by
sheer accident, be equally useful as carefully selected behavior, but I
can't see how it could be better.
 
K

Keith Thompson

Malcolm McLean said:
"Undefined behaviour" means "the C standard places no restrictions on
the behaviour of this construct", not "the program exists in some
mystical state of undefinedness".
Right.

So say a compiler writer decides to define that any illegal access to
an array will produce the message "segmentation fault" and terminate
the program. This is superior in most cases to silently suppressing
the write and continuing the program.

So say a compiler writer (or, in the case of sscanf(), a runtime
library writer) decides to define it in some other manner -- or
doesn't bother to define it at all, so something random happens. (Not
truly random, of course, just arbitrarily bad.)
Now in this case, we probably haven't thought what to do if our input
files contain numbers out of the range of a double.

I suggest that thinking about that is a programmer's job. Now if
you've thought about it and decided that the risk is acceptable, and
the effort to avoid the risk is not, then you can go ahead and act on
that decision.

Then somebody analyzes the actual behavior of your program in the
presence of bad input, and manages to use it as an avenue to take over
your system and spread malware.
 
J

James Kuyper

Malcolm said:
"Undefined behaviour" means "the C standard places no restrictions on
the behaviour of this construct", not "the program exists in some
mystical state of undefinedness".

I didn't intend to suggest that it did. It just means that the
consequences could be arbitrarily bad (reality imposes some limits on
undefined behavior that the C standard itself does not, but those limits
are not strict enough to be useful). When undefined behavior can include
causing your program to malfunction in ways too subtle to be detected
until after they've caused a huge amount of damage, it's not very
comforting to imagine someone thinking that they might be "better" than
the alternative.
So say a compiler writer decides to define that any illegal access to an
array will produce the message "segmentation fault" and terminate the
program. This is superior in most cases to silently suppressing the
write and continuing the program.

True. But the discussion was about using strtod() in preference to
scanf(), with the implicit suggestion that you actually pay attention to
the error indications returned by strtod(). There's a great many forms
of undefined behavior that are far worse than having the user choose
what to do in response to an error indication returned by strtod().
Now in this case, we probably haven't thought what to do if our input
files contain numbers out of the range of a double. ...

Why not? That's something that should be routinely thought about when
writing such code.
> ... Note that we need the
code every time we call the scanf() family of functions with a real
conversion specifier, rendering the functions effectively useless.

Correct; that's a good reason for using the strto*() family rather than
scanf().
 
B

Bumbala

Hello,

I just want to read a space delimited string of numbers into an array
of double. Is it possible with sscanf ?

Example:
double numbers[3];
char *line = "1 2.5 3.7";
sscanf(line, {format?}, numbers);

Also is the reverse possible with printf ?

sprintf(line, {format?}, numbers);

Thanks.

Thanks for the suggestions! Looks like strtod did the job :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,480
Members
44,900
Latest member
Nell636132

Latest Threads

Top