hurray for stdlib!

L

luser-ex-troll

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!).
 
L

luserXtrog

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


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; }
 
I

Ian Collins

luserXtrog said:
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.
 
J

Jens Thoms Toerring

You really do like dense code, don't you?
What if the conversion fails and strtol() returns 0? You can just check
errno. Same for strtod.

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
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top