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
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
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
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
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