Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

hurray for stdlib!

3 views
Skip to first unread message

luser-ex-troll

unread,
Mar 27, 2009, 12:53:06 AM3/27/09
to
Having determined what's in the string, interpreting the number
represented is almost trivial.

int grok(char *s) { /*dig?*/
if (czek(s, fsm_dec, acc_dec )) {
printf( "dec: %d\n", (int)strtol(s,NULL,10) );
return 1; }
else if (czek(s, fsm_rad, acc_rad )) {
printf( "rad: %d\n",
(int)strtol(strchr(s,'#')+1, NULL, strtol(s,NULL,10)) );
return 1; }
else if (czek(s, fsm_real,acc_real)) {
printf("real: %f\n", strtod(s,NULL));
return 1; }
/*else*/
printf("grok? %s\n", s);
return 0; }

That saves a few hundred lines (and having to type the alphabet
twice!).

--
louse wrecks trill

Jack Klein

unread,
Mar 27, 2009, 10:30:28 PM3/27/09
to
On Thu, 26 Mar 2009 21:53:06 -0700 (PDT), luser-ex-troll
<mij...@yahoo.com> wrote in comp.lang.c:

There's a potential serious problem with this, particularly on
platforms where the range of long is greater than the range of int.
This is certainly true on at least some 64-bit operating systems
today.

It is also true on all implementations where int is 16-bit, since long
always has to have at least 32 bits.

strol() can return any value in the range of LONG_MIN to LONG_MAX. In
the type of situations I mentioned above, LONG_MIN < INT_MIN, LONG_MAX
> INT_MIN, or both.

That means that strtol() can return a value outside the range that an
int can hold, resulting in implementation-defined behavior or raising
an implementation-defined signal.

You seem to think that a cast on assignment of scalar types does
something magic or prevents errors that could otherwise occur. You do
need in this case, to do the conversion to int in a variadic function
like printf() to match the "%d" conversion specifier. Just don't be
fooled into thinking the cast makes it safe from the consequences if
strol() returns a value outside the range an int can hold.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html

luserXtrog

unread,
Mar 27, 2009, 11:45:03 PM3/27/09
to
On Mar 27, 9:30 pm, Jack Klein <jackkl...@spamcop.net> wrote:
> On Thu, 26 Mar 2009 21:53:06 -0700 (PDT), luser-ex-troll
> <mijo...@yahoo.com> wrote in comp.lang.c:

>
>
>
> > Having determined what's in the string, interpreting the number
> > represented is almost trivial.
>
<snip error-prone version>

> > That saves a few hundred lines (and having to type the alphabet
> > twice!).
>
> There's a potential serious problem with this, particularly on
> platforms where the range of long is greater than the range of int.
> This is certainly true on at least some 64-bit operating systems
> today.
>
> It is also true on all implementations where int is 16-bit, since long
> always has to have at least 32 bits.
>
> strol() can return any value in the range of LONG_MIN to LONG_MAX.  In
> the type of situations I mentioned above, LONG_MIN < INT_MIN, LONG_MAX
>
> > INT_MIN, or both.
>
> That means that strtol() can return a value outside the range that an
> int can hold, resulting in implementation-defined behavior or raising
> an implementation-defined signal.
>
> You seem to think that a cast on assignment of scalar types does
> something magic or prevents errors that could otherwise occur.  You do
> need in this case, to do the conversion to int in a variadic function
> like printf() to match the "%d" conversion specifier.  Just don't be
> fooled into thinking the cast makes it safe from the consequences if
> strol() returns a value outside the range an int can hold.
>

Much appreciated. I've fixed it to check for errors from strtol and
strtod. I'll be sure to check for more restricted ranges before
storing the values into ints and floats.

int grok(char *s) { /*dig?*/
if (czek(s, fsm_dec, acc_dec )) {

long num;
num = strtol(s,NULL,10);
if((num==LONG_MAX || num==LONG_MIN) && errno==ERANGE) {
fprintf(stderr, "limitcheck\n"); return 0; }
printf( "dec: %ld\n", num );


return 1; }
else if (czek(s, fsm_rad, acc_rad )) {

long ra,num;
ra = (int)strtol(s,NULL,10);
if(ra>35 || ra<2) {
fprintf(stderr, "limitcheck\n"); return 0; }
num = strtol(strchr(s,'#')+1, NULL, ra);
if((num==LONG_MAX || num==LONG_MIN) && errno==ERANGE) {
fprintf(stderr, "limitcheck\n"); return 0; }
printf( "rad: %ld\n", num );
return 1; }
else if (czek(s, fsm_real, acc_real)) {
double num;
num = strtod(s,NULL);
if((num==HUGE_VAL || num==-HUGE_VAL) && errno==ERANGE) {
fprintf(stderr, "limitcheck\n"); return 0; }
printf("real: %f\n", num);


return 1; }
/*else*/
printf("grok? %s\n", s);
return 0; }


--
lxt

Ian Collins

unread,
Mar 28, 2009, 12:19:16 AM3/28/09
to
luserXtrog wrote:
> Much appreciated. I've fixed it to check for errors from strtol and
> strtod. I'll be sure to check for more restricted ranges before
> storing the values into ints and floats.

You really do like dense code, don't you?

> int grok(char *s) { /*dig?*/
> if (czek(s, fsm_dec, acc_dec )) {
> long num;
> num = strtol(s,NULL,10);
> if((num==LONG_MAX || num==LONG_MIN) && errno==ERANGE) {
> fprintf(stderr, "limitcheck\n"); return 0; }

What if the conversion fails and strtol() returns 0? You can just check
errno. Same for strtod.

--
Ian Collins

Jens Thoms Toerring

unread,
Mar 28, 2009, 7:49:04 AM3/28/09
to

On my implementation (Linux) errno isn't set if the conversion
fails. As far as I can see in the standard errno only must be
set (to ERANGE) on over/underflow. Using the 'endptr' argument
seems to be the only reliable way to test for this case.

Regards, Jens
--
\ Jens Thoms Toerring ___ j...@toerring.de
\__________________________ http://toerring.de

0 new messages