473,398 Members | 2,188 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,398 software developers and data experts.

Question for a REAL expert on casting double to float...


I just noticed that my "improved" version of sscanf() doesn't assign
floating point numbers properly if the variable assigned to is declared
as a "float" rather than a "double". (This never cropped up before, since
I rarely use "float"s for anything, and hardly ever use the function for
floating-point numbers in the first place; I just was messing around
testing it for all cases and noticed a problem.)

Anyway, it is declared and I assume largely defined the same
way sscanf() is:

int scan_line(char *line,char *format,...) {
va_list var_argument;

/* loop to match up format string with argument list and assign to
pointers */
}

The problem is when I get down to the point of actually assigning
values to the pointers:

switch(*format_buf) {

case 'd' :
copy_max_length_text(number_buf,field,field_length );
*va_arg(var_argument,unsigned long *)=
strtoul(number_buf,NULL,10);
break;

case 'f' :
copy_max_length_text(number_buf,field,field_length );
*va_arg(var_argument,double *)=strtod(number_buf,NULL);
break;

case 's' :
copy_max_length_text
(va_arg(var_argument,char *),field,field_length);
break;

....

"case 'f'" is assigned as 0.0000... if the argument actually points
to a float, but works OK assigned to a double. There may be something
simple I'm missing here, but I get confused enough working with
variable argument list, because of the default promotions of var_arg(),
but I'm not sure that is even the issue here...

I'm assuming it must be possible to do this right, since sscanf()
does it right, but like I say I'm probably missing something very
simple...

---
William Ernest Reid

Jul 12 '08 #1
22 2728
>I just noticed that my "improved" version of sscanf() doesn't assign
>floating point numbers properly if the variable assigned to is declared
as a "float" rather than a "double". (This never cropped up before, since
I rarely use "float"s for anything, and hardly ever use the function for
floating-point numbers in the first place; I just was messing around
testing it for all cases and noticed a problem.)
The default argument promotions do not promote "pointer to float"
to "pointer to double". Your arguments to sscanf() should be
pointers (for the format string and those arguments matching a
conversion).

And chances are float and double are of different size (they don't
have to be but it's true on most platforms), with double being
bigger, so you'll probably have out-of-bounds memory stomping, to
say nothing of the bits not being in the same place for float and
double.
>The problem is when I get down to the point of actually assigning
values to the pointers:

switch(*format_buf) {

case 'd' :
copy_max_length_text(number_buf,field,field_length );
*va_arg(var_argument,unsigned long *)=
If it's a %d, the argument is an int *. If it's a %ld, the argument is
a long *.
strtoul(number_buf,NULL,10);
break;

case 'f' :
copy_max_length_text(number_buf,field,field_length );
*va_arg(var_argument,double *)=strtod(number_buf,NULL);
If it's %f, the argument is a float *. If it's a %lf, the argument
is a double *.
break;

case 's' :
copy_max_length_text
(va_arg(var_argument,char *),field,field_length);
break;

...
Jul 12 '08 #2
"Bill Reid" <ho********@happyhealthy.netwrites:
I just noticed that my "improved" version of sscanf() doesn't assign
floating point numbers properly if the variable assigned to is declared
as a "float" rather than a "double".
<snip>
Anyway, it is declared and I assume largely defined the same
way sscanf() is:

int scan_line(char *line,char *format,...) {
va_list var_argument;

/* loop to match up format string with argument list and assign to
pointers */
}

The problem is when I get down to the point of actually assigning
values to the pointers:

switch(*format_buf) {

case 'd' :
copy_max_length_text(number_buf,field,field_length );
*va_arg(var_argument,unsigned long *)=
strtoul(number_buf,NULL,10);
break;
I'd advice against this. Most people will expect 'd' to be for int
not unsigned long. You will get the same problem you now see with
float if this code gets to a system where ints and longs are different
sizes.
case 'f' :
copy_max_length_text(number_buf,field,field_length );
*va_arg(var_argument,double *)=strtod(number_buf,NULL);
break;
<snip>
...

"case 'f'" is assigned as 0.0000... if the argument actually points
to a float, but works OK assigned to a double. There may be something
simple I'm missing here, but I get confused enough working with
variable argument list, because of the default promotions of var_arg(),
but I'm not sure that is even the issue here...
The issue is that you can't "lie" using va_arg. If the pointer is
pointer to a float, you must convert the argument to a float pointer.
pretending, as your code does, that it points to something that is
probably of a different size will just not work.

It is the same as writing:

float f;
double *dp = (double *)&f;
*dp = 42;
I'm assuming it must be possible to do this right, since sscanf()
does it right, but like I say I'm probably missing something very
simple...
Scanf has "length modifiers" so %f expects a float *, but %lf expects
a double * (%Lf is for long double *).

--
Ben.
Jul 12 '08 #3
On Sat, 12 Jul 2008 21:17:54 GMT, "Bill Reid"
<ho********@happyhealthy.netwrote:
>
I just noticed that my "improved" version of sscanf() doesn't assign
floating point numbers properly if the variable assigned to is declared
as a "float" rather than a "double". (This never cropped up before, since
I rarely use "float"s for anything, and hardly ever use the function for
floating-point numbers in the first place; I just was messing around
testing it for all cases and noticed a problem.)
[...]
>
The problem is when I get down to the point of actually assigning
values to the pointers:

switch(*format_buf) {

case 'd' :
copy_max_length_text(number_buf,field,field_length );
*va_arg(var_argument,unsigned long *)=
strtoul(number_buf,NULL,10);
break;
Scanf actually treats "%d" as a signed integer. If you want to use a
long, you probably want to have %ld instead.
>
case 'f' :
copy_max_length_text(number_buf,field,field_length );
*va_arg(var_argument,double *)=strtod(number_buf,NULL);
break;
In this case, sscanf uses %f for a float rather than a double. If you
want it to work exactly like scanf, change the double* to float*, and
add handling for %lf.

In general, you need to add a case for 'l' and set a flag indicating
that you are dealing with a long/double instead of an int/float. If
you don't have the handling for this flag, you won't get the expected
result.
Jul 12 '08 #4

OK, I've read all the responses so far (three), I guess I've got it figured
out...I still have an outstanding question/confusion, though...

Raymond Martineau <bk***@ncf.cawrote in message
news:og********************************@4ax.com...
On Sat, 12 Jul 2008 21:17:54 GMT, "Bill Reid"
<ho********@happyhealthy.netwrote:

I just noticed that my "improved" version of sscanf() doesn't assign
floating point numbers properly if the variable assigned to is declared
as a "float" rather than a "double". (This never cropped up before,
since
I rarely use "float"s for anything, and hardly ever use the function for
floating-point numbers in the first place; I just was messing around
testing it for all cases and noticed a problem.)
[...]

The problem is when I get down to the point of actually assigning
values to the pointers:

switch(*format_buf) {

case 'd' :
copy_max_length_text(number_buf,field,field_length );
*va_arg(var_argument,unsigned long *)=
strtoul(number_buf,NULL,10);
break;

Scanf actually treats "%d" as a signed integer. If you want to use a
long, you probably want to have %ld instead.
Except it hardly matters in REAL *scanf() functions what you use
as a specifier for integer numbers, but I haven't checked my "fake"
scan_line() for this case (I just use this to assign to an "unsigned"
which has the same sizeof() as "unsigned long" on my system).

This is probably the heart of my confusion; you can kind of do
anything with integers, but floating-point numbers are "touchier"...I
have a long history of completely abusing the format specifiers
for integers (I rarely if ever get them right) in *scanf() functions
without noticeable problems, so when wrote my own scan_line()
I blew off full checking of the complete format specifier for "floats"
as well...
case 'f' :
copy_max_length_text(number_buf,field,field_length );
*va_arg(var_argument,double *)=strtod(number_buf,NULL);
break;

In this case, sscanf uses %f for a float rather than a double. If you
want it to work exactly like scanf, change the double* to float*, and
add handling for %lf.
Yeah, that works...and of course there is no other way I can see
to get it to work, and that's EXACTLY how *scanf() functions work,
so that's the answer...
In general, you need to add a case for 'l' and set a flag indicating
that you are dealing with a long/double instead of an int/float. If
you don't have the handling for this flag, you won't get the expected
result.
OK, I have spent a few minutes this afternoon re-writing the
loop to check the full format specifier (or at least my still abbreviated
version of the format specifiers) for the correct action, so it works
EXACTLY as you've said.

My REAL question NOW is: this must have something to do
with fundamental promotions/assignments, not anything to do
with *scanf() or my "fake" scan_line() per se, right? Why else
the big difference between integer types and float types? I was
also confused about exactly how the "type" argument for
va_arg() worked, I thought it HAD to be the EXACT same
type as the return value of the conversion function (strtod()).

---
William Ernest Reid

Jul 13 '08 #5
Bill Reid wrote:
>
My REAL question NOW is: this must have something to do
with fundamental promotions/assignments, not anything to do
with *scanf() or my "fake" scan_line() per se, right? Why else
the big difference between integer types and float types? I was
also confused about exactly how the "type" argument for
va_arg() worked, I thought it HAD to be the EXACT same
type as the return value of the conversion function (strtod()).
It's not a case of integer types behaving differently from floating
point types, it's a case of (on your system) int and long being the same
size where float and double differ.

If you'd been using an ILP64 (43 bit int, 64 bit long) system you would
have had problems with integer types as well.
---
This should be "-- "

--
Ian Collins.
Jul 13 '08 #6
"Bill Reid" <ho********@happyhealthy.netwrites:
OK, I've read all the responses so far (three), I guess I've got it figured
out...I still have an outstanding question/confusion, though...

Raymond Martineau <bk***@ncf.cawrote in message
news:og********************************@4ax.com...
>On Sat, 12 Jul 2008 21:17:54 GMT, "Bill Reid"
<ho********@happyhealthy.netwrote:
>
I just noticed that my "improved" version of sscanf() doesn't assign
floating point numbers properly if the variable assigned to is declared
as a "float" rather than a "double". (This never cropped up before,
since
>I rarely use "float"s for anything, and hardly ever use the function for
floating-point numbers in the first place; I just was messing around
testing it for all cases and noticed a problem.)
[...]
>
The problem is when I get down to the point of actually assigning
values to the pointers:

switch(*format_buf) {

case 'd' :
copy_max_length_text(number_buf,field,field_length );
*va_arg(var_argument,unsigned long *)=
strtoul(number_buf,NULL,10);
break;

Scanf actually treats "%d" as a signed integer. If you want to use a
long, you probably want to have %ld instead.

Except it hardly matters in REAL *scanf() functions what you use
as a specifier for integer numbers, but I haven't checked my "fake"
scan_line() for this case (I just use this to assign to an "unsigned"
which has the same sizeof() as "unsigned long" on my system).
This will lead you astray. It is just as wrong with integer types.
It works because on your current implementation the sizes and alignment
requirement of int and long and the same. Try using your scanf to
read into a short using %d.
This is probably the heart of my confusion; you can kind of do
anything with integers, but floating-point numbers are "touchier"...
Well it looks like but not quite how you see it. You can't do
anything with ints either. You just got away with whatever you've
tried so far.
I
have a long history of completely abusing the format specifiers
for integers (I rarely if ever get them right) in *scanf() functions
without noticeable problems, so when wrote my own scan_line()
I blew off full checking of the complete format specifier for "floats"
as well...
You did not try very hard. It is simple to get garbage from scanf by
supplying junk arguments. Some systems give less baffling results
(endianness kicks in a can make it look like things worked) but you
can get rubbish from scanf on any system.
case 'f' :
copy_max_length_text(number_buf,field,field_length );
*va_arg(var_argument,double *)=strtod(number_buf,NULL);
break;

In this case, sscanf uses %f for a float rather than a double. If you
want it to work exactly like scanf, change the double* to float*, and
add handling for %lf.

Yeah, that works...and of course there is no other way I can see
to get it to work, and that's EXACTLY how *scanf() functions work,
so that's the answer...
It is the only way to go.
>In general, you need to add a case for 'l' and set a flag indicating
that you are dealing with a long/double instead of an int/float. If
you don't have the handling for this flag, you won't get the expected
result.

OK, I have spent a few minutes this afternoon re-writing the
loop to check the full format specifier (or at least my still abbreviated
version of the format specifiers) for the correct action, so it works
EXACTLY as you've said.

My REAL question NOW is: this must have something to do
with fundamental promotions/assignments, not anything to do
with *scanf() or my "fake" scan_line() per se, right? Why else
the big difference between integer types and float types?
There is not difference. The code is as wrong for ints and for
floats. The undefined behaviour happens to give rise to what you
expect on the implementations you've tried. Your were unlucky.

Try %d with a short *. This is probably closer to the float/double
issue, but the bottom line is the type of pointer you turn the va_arg
into must be compatible with the argument the user passed.
I was
also confused about exactly how the "type" argument for
va_arg() worked, I thought it HAD to be the EXACT same
type as the return value of the conversion function (strtod()).
Eh? One is a pointer the other is not. If you mean the deferenced
pointer to must match what strtod() returns, then that is much less
important than the problem we've been discussing. C happily converts
values between many types, so:

*va_arg(var_argument, double *) = strtoul(number_buf, NULL, 10);

is fine if you want to implement some odd sort of "whole number"
floating point input format.

--
Ben.
Jul 13 '08 #7

Ben Bacarisse <be********@bsb.me.ukwrote in message
news:87************@bsb.me.uk...
"Bill Reid" <ho********@happyhealthy.netwrites:
OK, I've read all the responses so far (three), I guess I've got it
figured
out...I still have an outstanding question/confusion, though...

Raymond Martineau <bk***@ncf.cawrote in message
news:og********************************@4ax.com...
On Sat, 12 Jul 2008 21:17:54 GMT, "Bill Reid"
<ho********@happyhealthy.netwrote:

I just noticed that my "improved" version of sscanf() doesn't assign
floating point numbers properly if the variable assigned to is
declared
as a "float" rather than a "double". (This never cropped up before,
since
I rarely use "float"s for anything, and hardly ever use the function
for
floating-point numbers in the first place; I just was messing around
testing it for all cases and noticed a problem.)

[...]

The problem is when I get down to the point of actually assigning
values to the pointers:

switch(*format_buf) {

case 'd' :
copy_max_length_text(number_buf,field,field_length );
*va_arg(var_argument,unsigned long *)=
strtoul(number_buf,NULL,10);
break;

Scanf actually treats "%d" as a signed integer. If you want to use a
long, you probably want to have %ld instead.
Except it hardly matters in REAL *scanf() functions what you use
as a specifier for integer numbers, but I haven't checked my "fake"
scan_line() for this case (I just use this to assign to an "unsigned"
which has the same sizeof() as "unsigned long" on my system).

This will lead you astray. It is just as wrong with integer types.
It works because on your current implementation the sizes and alignment
requirement of int and long and the same. Try using your scanf to
read into a short using %d.
No thanks, I'll take your word for it (or maybe I WILL try it). In that
case, there is NO equivalent *scanf() specifier, right? So are you saying
it is impossible to *scanf() into a short? If it is, how do you do it?
This is probably the heart of my confusion; you can kind of do
anything with integers, but floating-point numbers are "touchier"...

Well it looks like but not quite how you see it. You can't do
anything with ints either. You just got away with whatever you've
tried so far.
They call me "Lucky" down at the club for multiple lottery winners...
I
have a long history of completely abusing the format specifiers
for integers (I rarely if ever get them right) in *scanf() functions
without noticeable problems, so when wrote my own scan_line()
I blew off full checking of the complete format specifier for "floats"
as well...

You did not try very hard. It is simple to get garbage from scanf by
supplying junk arguments. Some systems give less baffling results
(endianness kicks in a can make it look like things worked) but you
can get rubbish from scanf on any system.
Hey, "rubbish" would be a treat compared to what often happens
with *scanf()!!! Why do you think I "rolled my own"? (I actually have
some very specific requirements that can't be handled properly by
*scanf() at all.)
case 'f' :
copy_max_length_text(number_buf,field,field_length );
*va_arg(var_argument,double
*)=strtod(number_buf,NULL);
break;

In this case, sscanf uses %f for a float rather than a double. If you
want it to work exactly like scanf, change the double* to float*, and
add handling for %lf.
Yeah, that works...and of course there is no other way I can see
to get it to work, and that's EXACTLY how *scanf() functions work,
so that's the answer...

It is the only way to go.
In this case, yes. But what about unsigned/signed integers, or
decimal vs. integer vs. properly-formated octal and hexadecimal
numbers? Isn't stroul() going to properly convert all positive values,
and they can all be assigned properly to any properly-sized integer
variable, save the possible overflow from assigning a large unsigned
to a signed, and vice-versa?
In general, you need to add a case for 'l' and set a flag indicating
that you are dealing with a long/double instead of an int/float. If
you don't have the handling for this flag, you won't get the expected
result.
OK, I have spent a few minutes this afternoon re-writing the
loop to check the full format specifier (or at least my still
abbreviated
version of the format specifiers) for the correct action, so it works
EXACTLY as you've said.

My REAL question NOW is: this must have something to do
with fundamental promotions/assignments, not anything to do
with *scanf() or my "fake" scan_line() per se, right? Why else
the big difference between integer types and float types?

There is not difference. The code is as wrong for ints and for
floats. The undefined behaviour happens to give rise to what you
expect on the implementations you've tried. Your were unlucky.
That's not what they say at the club...
Try %d with a short *. This is probably closer to the float/double
issue, but the bottom line is the type of pointer you turn the va_arg
into must be compatible with the argument the user passed.
OK, I'm being a little more careful; remember in the following, I
don't HAVE to use ALL the EXACT *scanf() specifers, just my own
simpler "work-alikes":

if(*format_buf!='s')
copy_max_length_text(number_buf,field,field_length );

switch(*format_buf) {

case 'd' :
*va_arg(var_argument,int *)=
strtol(number_buf,NULL,10);
break;

case 'D' :
*va_arg(var_argument,long int *)=
strtol(number_buf,NULL,10);
break;

case 'i' :
*va_arg(var_argument,int *)=
strtol(number_buf,NULL,0);
break;

case 'I' :
*va_arg(var_argument,long int *)=
strtol(number_buf,NULL,0);
break;

case 'u' :
*va_arg(var_argument,unsigned *)=
strtoul(number_buf,NULL,10);
break;

case 'U' :
*va_arg(var_argument,long unsigned *)=
strtoul(number_buf,NULL,10);
break;

case 'f' :
copy_max_length_text(number_buf,field,field_length );
*va_arg(var_argument,float *)=strtod(number_buf,NULL);
break;

case 'F' :
*va_arg(var_argument,double *)=
strtod(number_buf,NULL);
break;

case 's' :
copy_max_length_text
(va_arg(var_argument,char *),field,field_length);
break;

That MORE than covers everything I use the function for now...
I was
also confused about exactly how the "type" argument for
va_arg() worked, I thought it HAD to be the EXACT same
type as the return value of the conversion function (strtod()).

Eh? One is a pointer the other is not. If you mean the deferenced
pointer to must match what strtod() returns, then that is much less
important than the problem we've been discussing. C happily converts
values between many types, so:

*va_arg(var_argument, double *) = strtoul(number_buf, NULL, 10);

is fine if you want to implement some odd sort of "whole number"
floating point input format.
Well, as a matter of fact, lacking a true "long unsigned" on this
system, I regularly use "doubles" as decimal "integer" work-alikes
giving me much bigger "integers"...

---
William Ernest Reid

Jul 13 '08 #8
Bill Reid wrote:

<snip>
No thanks, I'll take your word for it (or maybe I WILL try it). In
that case, there is NO equivalent *scanf() specifier, right? So are
you saying it is impossible to *scanf() into a short? If it is, how
do you do it?
I haven't followed this thread so I'm probably missing something, but
what's wrong with using the %hd (and variants like %hu %hx %ho)
specifier to scan a short?

Jul 13 '08 #9

"Bill Reid" <ho********@happyhealthy.netschreef in bericht
news:Yv********************@bgtnsc05-news.ops.worldnet.att.net...
>This will lead you astray. It is just as wrong with integer types.
It works because on your current implementation the sizes and alignment
requirement of int and long and the same. Try using your scanf to
read into a short using %d.

No thanks, I'll take your word for it (or maybe I WILL try it). In that
case, there is NO equivalent *scanf() specifier, right? So are you saying
it is impossible to *scanf() into a short? If it is, how do you do it?
On 32-bit windows with MSVC:

short x;
scanf("%d", &x);

"Run-time check failure - Stack around the variable 'x' was corrupted"

short x;
scanf("%hd", &x);

No problem
Jul 13 '08 #10
"Serve Lau" <ni***@qinqin.comwrites:
"Bill Reid" <ho********@happyhealthy.netschreef in bericht
news:Yv********************@bgtnsc05-news.ops.worldnet.att.net...
>>This will lead you astray. It is just as wrong with integer types.
Bill Reid did not write that (I did). That there is a missing
attribution can be deduced by counting >>s but it is much nicer you
to leave the attribution for the text you quote.

--
Ben.
Jul 13 '08 #11
"Bill Reid" <ho********@happyhealthy.netwrites:
Ben Bacarisse <be********@bsb.me.ukwrote in message
news:87************@bsb.me.uk...
>"Bill Reid" <ho********@happyhealthy.netwrites:
Except it hardly matters in REAL *scanf() functions what you use
as a specifier for integer numbers, but I haven't checked my "fake"
scan_line() for this case (I just use this to assign to an "unsigned"
which has the same sizeof() as "unsigned long" on my system).

This will lead you astray. It is just as wrong with integer types.
It works because on your current implementation the sizes and alignment
requirement of int and long and the same. Try using your scanf to
read into a short using %d.

No thanks, I'll take your word for it (or maybe I WILL try it). In that
case, there is NO equivalent *scanf() specifier, right? So are you saying
it is impossible to *scanf() into a short? If it is, how do you do
it?
Don't you have a C library manual? It is all documented. Most
systems also have extensions (and some have limitations) so you can't
avoid reading your library's documentation.
This is probably the heart of my confusion; you can kind of do
anything with integers, but floating-point numbers are "touchier"...

Well it looks like but not quite how you see it. You can't do
anything with ints either. You just got away with whatever you've
tried so far.

They call me "Lucky" down at the club for multiple lottery
winners...
But in fact this is *unlucky* (as I said below). Lucky programmers
get to see their bugs early.

<snip>

--
Ben.
Jul 13 '08 #12

Ben Bacarisse <be********@bsb.me.ukwrote in message
news:87************@bsb.me.uk...
"Bill Reid" <ho********@happyhealthy.netwrites:
Ben Bacarisse <be********@bsb.me.ukwrote in message
news:87************@bsb.me.uk...
"Bill Reid" <ho********@happyhealthy.netwrites:

Except it hardly matters in REAL *scanf() functions what you use
as a specifier for integer numbers, but I haven't checked my "fake"
scan_line() for this case (I just use this to assign to an "unsigned"
which has the same sizeof() as "unsigned long" on my system).

This will lead you astray. It is just as wrong with integer types.
It works because on your current implementation the sizes and alignment
requirement of int and long and the same. Try using your scanf to
read into a short using %d.
No thanks, I'll take your word for it (or maybe I WILL try it). In that
case, there is NO equivalent *scanf() specifier, right? So are you
saying
it is impossible to *scanf() into a short? If it is, how do you do
it?

Don't you have a C library manual? It is all documented. Most
systems also have extensions (and some have limitations) so you can't
avoid reading your library's documentation.
No, I can't avoid READING it (and the hallowed C "standard"), but
I absolutely can't MEMORIZE it, particularly when the mnemonics
are as counter-intuitive as using "h" to identify a "short" (of course
to avoid "letter-space" conflicts with the "string" specifier "s").

And of course, virtually NO "C" documentation explains the
ACTUAL ramifications of mismatched arguments and format
specifiers in clear simple language. My compiler documentation
just lists the argument "modifiers" as "optional", meaning of
course, to the "writers" of the documentation, that they aren't a
required part of the legal SYNTAX of a format specifier. Of
course, to a "normal" human being looking for information as
quickly as possible, it means you can safely ignore them...

Actually, it doesn't seem that "hh" is part of MY library's
*scanf() argument modifiers, so I may try that to see what
happens (it's possible it just isn't documented)...
This is probably the heart of my confusion; you can kind of do
anything with integers, but floating-point numbers are "touchier"...

Well it looks like but not quite how you see it. You can't do
anything with ints either. You just got away with whatever you've
tried so far.
They call me "Lucky" down at the club for multiple lottery
winners...

But in fact this is *unlucky* (as I said below). Lucky programmers
get to see their bugs early.
I guess I was lucky that I saw all those precision errors that came
from using the completely useless "float" type, so I never used it
ever again...

---
William Ernest Reid

Jul 13 '08 #13
Bill Reid wrote:
>
Ben Bacarisse <be********@bsb.me.ukwrote in message
news:87************@bsb.me.uk...
>"Bill Reid" <ho********@happyhealthy.netwrites:
Ben Bacarisse <be********@bsb.me.ukwrote in message
news:87************@bsb.me.uk...
"Bill Reid" <ho********@happyhealthy.netwrites:

Except it hardly matters in REAL *scanf() functions what you use
as a specifier for integer numbers, but I haven't checked my
"fake" scan_line() for this case (I just use this to assign to
an "unsigned" which has the same sizeof() as "unsigned long" on
my system).

This will lead you astray. It is just as wrong with integer
types. It works because on your current implementation the sizes
and alignment
requirement of int and long and the same. Try using your scanf to
read into a short using %d.

No thanks, I'll take your word for it (or maybe I WILL try it). In
that
case, there is NO equivalent *scanf() specifier, right? So are you
saying
it is impossible to *scanf() into a short? If it is, how do you do
it?

Don't you have a C library manual? It is all documented. Most
systems also have extensions (and some have limitations) so you can't
avoid reading your library's documentation.

No, I can't avoid READING it (and the hallowed C "standard"),
He was talking about the documentation that comes with your standard
library, not the Standard.
but I absolutely can't MEMORIZE it, particularly when the mnemonics
are as counter-intuitive as using "h" to identify a "short" (of course
to avoid "letter-space" conflicts with the "string" specifier "s").

And of course, virtually NO "C" documentation explains the
ACTUAL ramifications of mismatched arguments and format
specifiers in clear simple language. My compiler documentation
just lists the argument "modifiers" as "optional", meaning of
course, to the "writers" of the documentation, that they aren't a
required part of the legal SYNTAX of a format specifier. Of
course, to a "normal" human being looking for information as
quickly as possible, it means you can safely ignore them...
Well my C library documentation unambiguously states that the 'h'
modifier applies to short and 'l' to long and 'hh' to char and 'z' to
size_t and 'p' to void* and so on. Cant see what more one needs.
Actually, it doesn't seem that "hh" is part of MY library's
*scanf() argument modifiers, so I may try that to see what
happens (it's possible it just isn't documented)...
'hh' is new in C99. 'h' OTOH is part of C90. Similarly 'z' and 'j' are
also new to C99, as is 'm'.

<snip>

Jul 13 '08 #14
"Bill Reid" <ho********@happyhealthy.netwrites:
[...]
Hey, "rubbish" would be a treat compared to what often happens
with *scanf()!!! Why do you think I "rolled my own"? (I actually have
some very specific requirements that can't be handled properly by
*scanf() at all.)
[...]

Are you sure *scanf() can't handle your requirements? You didn't know
about "%hd"; perhaps there are other features you don't know about
that would solve your problem.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jul 13 '08 #15

Keith Thompson <ks***@mib.orgwrote in message
news:ln************@nuthaus.mib.org...
"Bill Reid" <ho********@happyhealthy.netwrites:
[...]
Hey, "rubbish" would be a treat compared to what often happens
with *scanf()!!! Why do you think I "rolled my own"? (I actually have
some very specific requirements that can't be handled properly by
*scanf() at all.)
[...]

Are you sure *scanf() can't handle your requirements? You didn't know
about "%hd"; perhaps there are other features you don't know about
that would solve your problem.
I sure hope not, but I'll take you up on this. The most important
thing I need for a certain amount of my file parsing is that the
*scan*() function ALWAYS increments to the next argument whether
or not the last field was actually successfully scanned. I also prefer
more of a "regular expression" type of match-up between text that
is or is not a scannable field; the next non-scannable text is NOT
delimited by a mere failure to convert, but the appearance of text
matching the next not-to-be-scanned sequence of characters.

The first absolute requirement is basically so I can be sure that
I correctly scan in empty strings (""), or any strings at all, and any
existing numbers, after the function has failed to convert one or more
scan fields; if it fails to scan fields for arguments 1, 2, and 3, I still
want it to assign arguments 4, 5, 6 correctly, from the correct
fields according to the "regular expression".

If *scanf() can actually do that, I've wasted some time, but it
would completely contradict my experience with what everybody
acknowledges are some quirky and downright dangerous functions,
and how they are explicitly documented...

---
William Ernest Reid

Jul 14 '08 #16
"Bill Reid" <ho********@happyhealthy.netwrites:
Keith Thompson <ks***@mib.orgwrote in message
news:ln************@nuthaus.mib.org...
>"Bill Reid" <ho********@happyhealthy.netwrites:
[...]
Hey, "rubbish" would be a treat compared to what often happens
with *scanf()!!! Why do you think I "rolled my own"? (I actually have
some very specific requirements that can't be handled properly by
*scanf() at all.)
[...]

Are you sure *scanf() can't handle your requirements? You didn't know
about "%hd"; perhaps there are other features you don't know about
that would solve your problem.

I sure hope not, but I'll take you up on this. The most important
thing I need for a certain amount of my file parsing is that the
*scan*() function ALWAYS increments to the next argument whether
or not the last field was actually successfully scanned.
I'm not quite sure what that means. If an argument isn't successfully
scanned, how do you even define how much text to skip to get to the
next argument?

In other words, what does a "field" look like?

You might want to handle this in two steps. First, parse the input
line into fields (perhaps delimited by white space). Then analyze
each field, perhaps using the strdo*() functions.
I also prefer
more of a "regular expression" type of match-up between text that
is or is not a scannable field; the next non-scannable text is NOT
delimited by a mere failure to convert, but the appearance of text
matching the next not-to-be-scanned sequence of characters.
There are open-source regular expression packages out there. Perhaps
using one of them would be easier than rolling your own.
The first absolute requirement is basically so I can be sure that
I correctly scan in empty strings (""), or any strings at all, and any
existing numbers, after the function has failed to convert one or more
scan fields; if it fails to scan fields for arguments 1, 2, and 3, I still
want it to assign arguments 4, 5, 6 correctly, from the correct
fields according to the "regular expression".
That's an odd requirement. Typically if I'm reading and parsing a
line of text, and there's a syntax error (scanning failure) at the
beginning, I just reject the whole line. But if those are your
requirements, that's ok.
If *scanf() can actually do that, I've wasted some time, but it
would completely contradict my experience with what everybody
acknowledges are some quirky and downright dangerous functions,
and how they are explicitly documented...
You may well be right, but I'm still don't completely understand your
requirements. A concrete example or two might help.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jul 14 '08 #17

Keith Thompson <ks***@mib.orgwrote in message
news:ln************@nuthaus.mib.org...
"Bill Reid" <ho********@happyhealthy.netwrites:
Keith Thompson <ks***@mib.orgwrote in message
news:ln************@nuthaus.mib.org...
"Bill Reid" <ho********@happyhealthy.netwrites:
[...]
Hey, "rubbish" would be a treat compared to what often happens
with *scanf()!!! Why do you think I "rolled my own"? (I actually
have
some very specific requirements that can't be handled properly by
*scanf() at all.)
[...]

Are you sure *scanf() can't handle your requirements? You didn't know
about "%hd"; perhaps there are other features you don't know about
that would solve your problem.
I sure hope not, but I'll take you up on this. The most important
thing I need for a certain amount of my file parsing is that the
*scan*() function ALWAYS increments to the next argument whether
or not the last field was actually successfully scanned.

I'm not quite sure what that means. If an argument isn't successfully
scanned, how do you even define how much text to skip to get to the
next argument?
Man, have you got a standard library "mindset"...can't comprehend
anything later than 1975 and punch-cards...

Of course, I explain it below, but you still don't seem to be able
to "get it"...
In other words, what does a "field" look like?
"don't scan%d2nd don't scan%ddon't scan%fdon't scan%s"

See the three fields to be scanned? Here, here's some precious
"whitespace" to help:

"don't scan %d 2nd don't scan %d don't scan %f don't scan %s"
You might want to handle this in two steps. First, parse the input
line into fields (perhaps delimited by white space). Then analyze
each field, perhaps using the strdo*() functions.
Are you missing the fact that I already did this years ago? Did the
fact that I posted the code for it throw you off? The scannable fields
are not delimited by anything other than the preceding (if any) and
following text, which I then use to extract a pointer to the
beginning of the scannable field and the length the field. Numeric
fields are copied to a buffer for strto*() function conversion and
assigned to their pointer arguments; string fields are
directly copied to their pointer arguments.
I also prefer
more of a "regular expression" type of match-up between text that
is or is not a scannable field; the next non-scannable text is NOT
delimited by a mere failure to convert, but the appearance of text
matching the next not-to-be-scanned sequence of characters.

There are open-source regular expression packages out there. Perhaps
using one of them would be easier than rolling your own.
Maybe I already did that too, though this is more like "regular
expression"-lite...hell, a full "regex" package came with my
compiler...stuff
like that is literally "a dime a dozen"...
The first absolute requirement is basically so I can be sure that
I correctly scan in empty strings (""), or any strings at all, and any
existing numbers, after the function has failed to convert one or more
scan fields; if it fails to scan fields for arguments 1, 2, and 3, I
still
want it to assign arguments 4, 5, 6 correctly, from the correct
fields according to the "regular expression".

That's an odd requirement. Typically if I'm reading and parsing a
line of text, and there's a syntax error (scanning failure) at the
beginning, I just reject the whole line. But if those are your
requirements, that's ok.
Actually, it's not that odd, if you could change your "mindset".
I think the way *scanf() works is pretty odd; it's kind of like fishing
while blind in a sewer, mostly you just catch CHUDs...

I don't use this to "fish" for anything; I know exactly what I want,
mostly because I wrote it there. Sometimes I don't want anything, so
that's what I write...and that's what I want when I read it back...
If *scanf() can actually do that, I've wasted some time, but it
would completely contradict my experience with what everybody
acknowledges are some quirky and downright dangerous functions,
and how they are explicitly documented...

You may well be right, but I'm still don't completely understand your
requirements. A concrete example or two might help.
Remember our format string:

"don't scan %d 2nd don't scan %d don't scan %f don't scan %s"

OK, here are some strings and how they SHOULD scan:

"don't scan 123 2nd don't scan 345 don't scan 1.23 don't scan scan"
field 1 = 123, field 2 = 345, field 3 = 1.23, field 4 = "scan"

"don't scan 2nd don't scan don't scan 1.23 don't scan "
field 1 = who cares, field 2 = who cares, field 3 = 1.23, field 4 = ""

"don't scan 2nd don't scan don't scan don't scan scan"
field 1 = who cares, field 2 = who cares, field 3 = who cares, field 4 =
"scan"

This is what I want, and what I GET, with my version of *scanf(), but
the idiotic *scanf() functions would probably put 2 into field 1
for the second two, and 1 into field 2 for the third, which isn't so
bad because I didn't care about those fields in the first place,
but write garbage into field 3 for the second, if not just crashing
completely, and definitely bomb out on field 4 for the second
two, because they would have been scanning in vain for
some digits for strtol() or strtod() to convert for field 2 or 3...as I
explained very simply, they don't advance automatically to the
next argument if a field fails to scan, instead they just look for
something to scan into the current argument, quite often with
program-ending results...

---
William Ernest Reid

Jul 14 '08 #18
On 13 Jul, 04:20, "Bill Reid" <hormelf...@happyhealthy.netwrote:
Ben Bacarisse <ben.use...@bsb.me.ukwrote in message
news:87************@bsb.me.uk...
"Bill Reid" <hormelf...@happyhealthy.netwrites:
Raymond Martineau <bk...@ncf.cawrote in message
>news:og********************************@4ax.com.. .
>On Sat, 12 Jul 2008 21:17:54 GMT, "Bill Reid"
><hormelf...@happyhealthy.netwrote:
OK, I've read all the responses so far (three), I guess I've got it
figured out...I still have an outstanding question/confusion, though....
please leave attributions at the top. I've moved some

>I just noticed that my "improved" version of sscanf() doesn't assign
>floating point numbers properly if the variable assigned to is
>declared as a "float" rather than a "double".
that's because you can't do that

void read_stuff()
{
float f;
double ff;
scanf ("%f %lf", f, ff);
}

>(This never cropped up before,
>since I rarely use "float"s for anything, and hardly ever use the function
>for floating-point numbers in the first place; I just was messing around
>testing it for all cases and noticed a problem.)
>The problem is when I get down to the point of actually assigning
>values to the pointers:
* * * * * *switch(*format_buf) {
* * * * * * * *case 'd' :
* * * * * * * *copy_max_length_text(number_buf,field,field_lengt h);
* * * * * * * **va_arg(var_argument,unsigned long *)=
* * * * * * * *strtoul(number_buf,NULL,10);
* * * * * * * *break;
>Scanf actually treats "%d" as a signed integer. If you want to use a
>long, you probably want to have %ld instead.
Except it hardly matters in REAL *scanf() functions what you use
as a specifier for integer numbers, but I haven't checked my "fake"
scan_line() for this case (I just use this to assign to an "unsigned"
which has the same sizeof() as "unsigned long" on my system).
This will lead you astray. *It is just as wrong with integer types.
It works because on your current implementation the sizes and alignment
requirement of int and long and the same. *Try using your scanf to
read into a short using %d.

No thanks, I'll take your word for it (or maybe I WILL try it). *In that
case, there is NO equivalent *scanf() specifier, right? *So are you saying
it is impossible to *scanf() into a short? *If it is, how do you do it?
"%hd"

might it be an idea to read the scanf() spec? K&R has reasonable
summary in section B1.3.
This is probably the heart of my confusion; you can kind of do
anything with integers, but floating-point numbers are "touchier"...
Well it looks like but not quite how you see it. *You can't do
anything with ints either. *You just got away with whatever you've
tried so far.

They call me "Lucky" down at the club for multiple lottery winners...
I
have a long history of completely abusing the format specifiers
for integers (I rarely if ever get them right) in *scanf() functions
without noticeable problems, so when wrote my own scan_line()
I blew off full checking of the complete format specifier for "floats"
as well...
You did not try very hard. *It is simple to get garbage from scanf by
supplying junk arguments. *Some systems give less baffling results
(endianness kicks in a can make it look like things worked) but you
can get rubbish from scanf on any system.

Hey, "rubbish" would be a treat compared to what often happens
with *scanf()!!! *Why do you think I "rolled my own"? *(I actually have
some very specific requirements that can't be handled properly by
*scanf() at all.)
what requirements? Maybe it would be better to wrapper scanf()
that way you can extend it without reinventing the wheel.

case 'q':
handle_q_format();
break;
case 'v':
handle_v_format();
break;
default:
scanf();

if it wasn't one of your special formats then call scanf()
* * * * * * * *case 'f' :
* * * * * * * *copy_max_length_text(number_buf,field,field_lengt h);
* * * * * * * **va_arg(var_argument,double

*)=strtod(number_buf,NULL);
* * * * * * * *break;
>In this case, sscanf uses %f for a float rather than a double. If you
>want it to work exactly like scanf, change the double* to float*, and
>add handling for %lf.
Yeah, that works...and of course there is no other way I can see
to get it to work, and that's EXACTLY how *scanf() functions work,
so that's the answer...
It is the only way to go.

In this case, yes. *But what about unsigned/signed integers,
use the %u format

or
decimal vs. integer vs.
??

decimal *is* integer. Or rather decimal is a representation
of integer.
properly-formated octal and hexadecima numbers?
%o and %x

>*Isn't stroul() going to properly convert all positive values,
and they can all be assigned properly to any properly-sized integer
variable, save the possible overflow from assigning a large unsigned
to a signed, and vice-versa?
what? How did we shift from scanf to strtoul()? Are you saying
strtoul() does what you want or not?... I'm confused.

>In general, you need to add a case for 'l' and set a flag indicating
>that you are dealing with a long/double instead of an int/float. *If
>you don't have the handling for this flag, you won't get the expected
>result.
OK, I have spent a few minutes this afternoon re-writing the
loop to check the full format specifier (or at least my still
abbreviated version of the format specifiers) for the correct action,
so it works EXACTLY as you've said.
My REAL question NOW is: this must have something to do
with fundamental promotions/assignments, not anything to do
with *scanf() or my "fake" scan_line() per se, right? *Why else
the big difference between integer types and float types?
There is not difference. *The code is as wrong for ints and for
floats. *The undefined behaviour happens to give rise to what you
expect on the implementations you've tried. *Your were unlucky.

That's not what they say at the club...
Try %d with a short *. *This is probably closer to the float/double
issue, but the bottom line is the type of pointer you turn the va_arg
into must be compatible with the argument the user passed.

OK, I'm being a little more careful; remember in the following, I
don't HAVE to use ALL the EXACT *scanf() specifers, just my own
simpler "work-alikes":
but *why*?

<snip>

That MORE than covers everything I use the function for now...
*I was
also confused about exactly how the "type" argument for
va_arg() worked, I thought it HAD to be the EXACT same
type as the return value of the conversion function (strtod()).
Eh? *One is a pointer the other is not. *If you mean the deferenced
pointer to must match what strtod() returns, then that is much less
important than the problem we've been discussing. *C happily converts
values between many types, so:
* **va_arg(var_argument, double *) = strtoul(number_buf, NULL, 10);
is fine if you want to implement some odd sort of "whole number"
floating point input format.

Well, as a matter of fact, lacking a true "long unsigned" on this
system, I regularly use "doubles" as decimal "integer" work-alikes
giving me much bigger "integers"...

--
Nick Keighley

Physics, as we know it, will be over in six months.
Max Born (1928)
Jul 14 '08 #19
On 13 Jul, 14:17, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
Don't you have a C library manual? *It is all documented. *Most
systems also have extensions (and some have limitations) so you can't
avoid reading your library's documentation.
actually with one compiler when we asked for the documentaion they
sent a copy of the C standard. Which was nice (I've still got it)
but not what we asked for! And their library wasn't quite complete...
--
Nick Keighley

oh, that's too simple to test...
Jul 14 '08 #20
On 14 Jul, 07:52, "Bill Reid" <hormelf...@happyhealthy.netwrote:
Keith Thompson <ks...@mib.orgwrote in message
news:ln************@nuthaus.mib.org...
"Bill Reid" <hormelf...@happyhealthy.netwrites:
Keith Thompson <ks...@mib.orgwrote in message
>news:ln************@nuthaus.mib.org...
>"Bill Reid" <hormelf...@happyhealthy.netwrites:
Hey, "rubbish" would be a treat compared to what often happens
with *scanf()!!! *Why do you think I "rolled my own"? *(I actually
have some very specific requirements that can't be handled properly by
*scanf() at all.)
>[...]
>Are you sure *scanf() can't handle your requirements? *You didn't know
>about "%hd"; perhaps there are other features you don't know about
>that would solve your problem.
I sure hope not, but I'll take you up on this. *The most important
thing I need for a certain amount of my file parsing is that the
*scan*() function ALWAYS increments to the next argument whether
or not the last field was actually successfully scanned.
I'm not quite sure what that means. *If an argument isn't successfully
scanned, how do you even define how much text to skip to get to the
next argument?

Man, have you got a standard library "mindset"...can't comprehend
anything later than 1975 and punch-cards...
a strange way to ask for help. So you've got some poorly
structured input. Is a human being typeing it in?
Of course, I explain it below, but you still don't seem to be able
to "get it"...
perhaps you're bad at explaining?

In other words, what does a "field" look like?

"don't scan%d2nd don't scan%ddon't scan%fdon't scan%s"
some sample input would help... (yes I know there's
some later).
See the three fields to be scanned? *Here, here's some precious
"whitespace" to help:

"don't scan %d 2nd don't scan %d don't scan %f don't scan %s"
no use to me
You might want to handle this in two steps. *First, parse the input
line into fields (perhaps delimited by white space). *Then analyze
each field, perhaps using the strdo*() functions.

Are you missing the fact that I already did this years ago?
are you missing the fact that we can't read minds?
What is actually wrong with this approach?

*Did the
fact that I posted the code for it throw you off? *The scannable fields
are not delimited by anything other than the preceding (if any) and
following text, which I then use to extract a pointer to the
beginning of the scannable field and the length the field. *Numeric
fields are copied to a buffer for strto*() function conversion and
assigned to their pointer arguments; string fields are
directly copied to their pointer arguments.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * I also prefer
more of a "regular expression" type of match-up between text that
is or is not a scannable field; the next non-scannable text is NOT
delimited by a mere failure to convert, but the appearance of text
matching the next not-to-be-scanned sequence of characters.
There are open-source regular expression packages out there. *Perhaps
using one of them would be easier than rolling your own.

Maybe I already did that too, though this is more like "regular
expression"-lite...hell, a full "regex" package came with my
compiler...stuff
like that is literally "a dime a dozen"...
so is it a regexp or not?
The first absolute requirement is basically so I can be sure that
I correctly scan in empty strings (""), or any strings at all, and any
existing numbers, after the function has failed to convert one or more
scan fields; if it fails to scan fields for arguments 1, 2, and 3, I
still
want it to assign arguments 4, 5, 6 correctly, from the correct
fields according to the "regular expression".
That's an odd requirement. *Typically if I'm reading and parsing a
line of text, and there's a syntax error (scanning failure) at the
beginning, I just reject the whole line. *But if those are your
requirements, that's ok.

Actually, it's not that odd, if you could change your "mindset".
I think the way *scanf() works is pretty odd; it's kind of like fishing
while blind in a sewer, mostly you just catch CHUDs...
I'm of the "the input is either correctly formatted or not" school.
"correctly formatted" can cover a lot of ground, but I still
like to know where the edge of acceptance is. If the input is really
loosely structured I'd consider a simple parser.

I don't use this to "fish" for anything; I know exactly what I want,
mostly because I wrote it there.
except sometimes you didn't...

>*Sometimes I don't want anything, so
that's what I write...and that's what I want when I read it back...
If *scanf() can actually do that, I've wasted some time,
probably not on its own. I tend to only use it on well
structured input.

but it
would completely contradict my experience with what everybody
acknowledges are some quirky and downright dangerous functions,
and how they are explicitly documented...
they are very well documented. And if you have the right mind set
not at all quirky :-)

You may well be right, but I'm still don't completely understand your
requirements. *A concrete example or two might help.

Remember our format string:

"don't scan %d 2nd don't scan %d don't scan %f don't scan %s"

OK, here are some strings and how they SHOULD scan:

"don't scan 123 2nd don't scan 345 don't scan 1.23 don't scan scan"
field 1 = 123, field 2 = 345, field 3 = 1.23, field 4 = "scan"

"don't scan 2nd don't scan don't scan 1.23 don't scan "
field 1 = who cares, field 2 = who cares, field 3 = 1.23, field 4 = ""

"don't scan 2nd don't scan don't scan don't scan scan"
field 1 = who cares, field 2 = who cares, field 3 = who cares, field 4 =
"scan"

This is what I want, and what I GET, with my version of *scanf(), but
the idiotic *scanf() functions would probably put 2 into field 1
for the second two, and 1 into field 2 for the third, which isn't so
bad because I didn't care about those fields in the first place,
but write garbage into field 3 for the second, if not just crashing
completely, and definitely bomb out on field 4 for the second
two, because they would have been scanning in vain for
some digits for strtol() or strtod() to convert for field 2 or 3...as I
explained very simply, they don't advance automatically to the
next argument if a field fails to scan, instead they just look for
something to scan into the current argument, quite often with
program-ending results...
scanf() is designed for well structured input

How about using scanf() to do the actual field parsing?
--
Nick Keighley

A lot of the c.l.c. verbiage seems to be devoted to the numerical
density of cavorting nubile seraphim upon pinheads.
CBFalconer
Jul 14 '08 #21

Nick Keighley <ni******************@hotmail.comwrote in message
news:8e**********************************@2g2000hs n.googlegroups.com...

...something that can't be automatically quoted on my newsreader since
you used the wrong "Reply" link on Google(TM) Groups, despite being told
DOZENS of times by a newsgroup regular EXACTLY how to do it...

So I'll just sum up without your unquotable text; if you really want a
specific response to each of your non-sequiturs, you might be able to
reply to your own message using the CORRECT "Reply" link, and
then I could address each non-sequitur individually...

Mr. Thompson offered what in a courtroom might be called a
"proffer", an offer of evidence to prove a fact, if I were to provide
him with a statement of my requirements. I made just such a
statement, and he reneged on his "proffer", preferring to claim
that he "didn't understand" the clearly-stated requirements.

Outside of the very specific question that I posed to initiate
this thread, I have no need of ANY "help" in writing or re-writing
the function, since I wrote it years ago and have used it probably
like a million times since then in production code. It meets all the
elements of the clearly-stated requirements, and I not once, but
TWICE posted part of the code that showed how the function was
written. Several people here need to be able to not only read
code for comprehension, but also the English language...

As part (and probably genesis) of these information communication
problems, you need to be able to make clear-cut practical logical
distinctions. You consistently conflated input that DELIBERATELY
was missing certain fields with "poorly-structured input", no
matter how many times it was explained to you, and how many
examples you were shown. You also conflate *scanf() as
"requiring structured input" when no such thing is actually
true; the way *scanf() is written it will "accept" very badly-structured
input and "silently" give you bad values for your arguments while
apparently succeeding, or not scan PERFECTLY structured
input with PERFECTLY valid scannable fields.

This is because like so much bad code, *scanf() was written
according to requirements based first and foremost on the sloth
of the programmer who wrote it, the very self-same type of
programmer that would look at a clearly-stated set of requirements
and exclaim "I DON'T GET IT?!??!! GIVE ME AN EXAMPLE...I
DON'T GET THE EXAMPLE EITHER!!!!!!! YOU JUST KEEP
EXPLAINING IT TO ME, I'LL BE OVER HERE DRINKING A
BEER!!!"

There is NO way I can use *scanf() in any rational fashion
to acheive the requirements I stated. About the only way to
do so would be to ridiculously and wastefully call *scanf()
to convert and assign a single field after I had done all the
"heavy lifting" of writing the whole argument field-scanning
variadic loop, but *scanf() essentially just calls strto*()
functions at that point, SO WHY DON'T I JUST CALL
THEM MYSELF AND ELIMINATE THE POINTLESS
MIDDLEMAN?!??!! As far as using "using *scanf() to
parse the field", GET SERIOUS, I hope nobody is so
deranged to conflate *scanf() with any type of tokenizer
or regular expression parser; it is an artless ram-shackle
piece of junk that relies almost totally on it's conversion
functions to define a "scannable" field, and can only be
TRULY safely used to scan an input string that you KNOW
to be perfectly formatted in every way (it CANNOT be SAFELY
used to determine the actual FORMAT of the string, since
it only scans as best as it can (badly), it doesn't PARSE).

---
William Ernest Reid

Jul 15 '08 #22
On 15 Jul, 02:19, "Bill Reid" <hormelf...@happyhealthy.netwrote:
Nick Keighley <nick_keighley_nos...@hotmail.comwrote in message
news:8e**********************************@2g2000hs n.googlegroups.com...
..something that can't be automatically quoted on my newsreader
other people manage. perhaps your news reader is broken.
since
you used the wrong "Reply" link on Google(TM) Groups, despite being told
DOZENS of times by a newsgroup regular EXACTLY how to do it...
I've missed these posts. I rememeber being told once (perhaps by you)
but when I asked for more information I didn't get any. Perhaps if
you explained my error I could mend my ways.

I'll snip most of your contentless ranting.

<snip>
Outside of the very specific question that I posed to initiate
this thread, I have no need of ANY "help" in writing or re-writing
the function, since I wrote it years ago and have used it probably
like a million times since then in production code.
strange I thought you asked a question at the beginning.
In fact if your code was perfected years ago why are you asking
questions about float and double?

<snip>
As part (and probably genesis) of these information communication
problems, you need to be able to make clear-cut practical logical
distinctions. *You consistently conflated input that DELIBERATELY
was missing certain fields with "poorly-structured input",
perhaps I used a poor term. Would you prefer "weakly" structured.
erm "not rigidly structured"? Flexible structured?
no
matter how many times it was explained to you, and how many
examples you were shown.
I only saw one post that had examples.
>*You also conflate *scanf() as
"requiring structured input" when no such thing is actually
true; the way *scanf() is written it will "accept" very badly-structured
input and "silently" give you bad values for your arguments while
apparently succeeding, or not scan PERFECTLY structured
input with PERFECTLY valid scannable fields.
I disagree. If scanf() is properly used it will read the
fields you specify. I agree it doesn't do what you want
but that isn't scanf()s "fault". Note all caps is like
shouting. It makes it look like you're cross or something.

This is because like so much bad code, *scanf() was written
according to requirements based first and foremost on the sloth
of the programmer who wrote it,
I disagree. scanf() can be a bit arcane. But it does a useful
job. perhaps if you'd read scanf()s documentation you would't
be reinventing wheels and trying to stuff floats into doubles.

the very self-same type of
programmer that would look at a clearly-stated set of requirements
and exclaim
obviously your idea of a clear requirment differs from mine.
If it's an input stream I like BNF or solid examples. Your
vague scanf()-like format specs didn't cut the mustard.
There are two ways a requirement can fail to be communicated.
The receiver is stupid or the message is ambiguous or
poorly structured.

<snip rant>

There is NO way I can use *scanf() in any rational fashion
to acheive the requirements I stated.
ok. I just wondered if you could smash the input string
up into tokens then use scanf() on the tokens. Just a
thought.

>*About the only way to
do so would be to ridiculously and wastefully call *scanf()
to convert and assign a single field after I had done all the
"heavy lifting" of writing the whole argument field-scanning
variadic loop, but *scanf() essentially just calls strto*()
functions at that point, SO WHY DON'T I JUST CALL
THEM MYSELF AND ELIMINATE THE POINTLESS
MIDDLEMAN?!??!!
ok... so you aren't too keen on that idea...
*As far as using "using *scanf() to
parse the field", GET SERIOUS, I hope nobody is so
deranged to conflate *scanf() with any type of tokenizer
or regular expression parser; it is an artless ram-shackle
piece of junk that relies almost totally on it's conversion
functions to define a "scannable" field, and can only be
TRULY safely used to scan an input string that you KNOW
to be perfectly formatted in every way
ooo! isn't that strongly structured input?
(it CANNOT be SAFELY
used to determine the actual FORMAT of the string, since
it only scans as best as it can (badly), it doesn't PARSE).
normally I'd plonk you at this point but you make me smile!

:-)
--
Nick Keighley

If cosmology reveals anything about God, it is that He has
an inordinate fondness for empty space and non-baryonic dark
matter.
Jul 15 '08 #23

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Pat | last post by:
Give two double-typed variable X and Y. If (X==Y) is true, then how about the following results: (float(X) > float(Y))? (float(X) < float(Y))? (float(X) >= float(Y))? ( X > float(Y) )? ( X...
5
by: lamthierry | last post by:
Are the following two similar? float a = 1.0f; float a = static_cast<float>(1.0); If they are, which one is preferrable? Thanks Thierry
7
by: ma740988 | last post by:
I've got an unpacker that unpacks a 32 bit word into 3-10 bits samples. Bits 0 and 1 are dont cares. For the purposes of perfoming an FFT and an inverse FFT, I cast the 10 bit values into doubles....
8
by: Jonathan Fielder | last post by:
Hi, I have a 32 bit integer value and I wish to find the single precision floating point value that is closest to but less than or equal to the integer. I also have a similar case where I need...
26
by: Method Man | last post by:
Say I have the following: int main(void) { char* p, q; p = (char*) malloc(sizeof(char)*10); q = (p + 100) - 99; /* legal? */ free(q - 1); /* legal? */ .... return 0; }
8
by: Quinn Kirsch | last post by:
Hi all, the following c# example baffles me. my understanding of the managed code of visual .net is that all casts like this would be safe, but this example seems to contradict this notion. if...
5
by: Thorsten | last post by:
Hi everyone, I am rather new to C# and have a problem that will probably seem trivial to most of you... but I hope you can still help me nevertheless.. Via the comport, I read the result of a...
11
by: jacob navia | last post by:
hi I am trying to use the complex data type. Consider this code, taken from the cclib library: struct complex csqrt(Cpx z) { double r; r=sqrt(z.re*z.re+z.im*z.im);...
32
by: alex.j.k2 | last post by:
Hello all, I have "PRECISION" defined in the preprocessor code and it could be int, float or double, but I do not know in the code what it is. Now if I want to assign zero to a "PRECISION"...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.