I want to implement atoi function which converts string to an integer.
So I did this :
int atoi(char str[])
{
int i, num;
for( num = 0, i = 0 ; isdigit(str[i]) ; i++)
num = num * 10 + str[i] - '0' ;
return num;
}
Here I wnat to know is there any way to tell user if num goes out of
range of int ?
I mean we can't check num after overflow as it will be UB so is there
a way to check if str[] contains large integer ?
|
|
0
|
|
|
|
Reply
|
hppymittal (23)
|
1/21/2010 4:16:21 PM |
|
On Jan 21, 11:16=A0am, happy <hppymit...@yahoo.com> wrote:
> I want to implement atoi function which converts string to an integer.
> So I did this :
>
> int atoi(char str[])
> {
> =A0 int i, num;
> =A0 for( num =3D 0, i =3D 0 ; isdigit(str[i]) ; i++)
> =A0 =A0 =A0 num =3D num * 10 + str[i] - '0' ;
> =A0 return num;
>
> }
>
> Here I wnat to know is there any way to tell user if num goes out of
> range of int ?
> I mean we can't check num after overflow as it will be UB so is there
> a way to check if str[] contains large integer ?
The usual way would be to check to ensure that num < (num * 10 +
value). I don't think that's 100% portable but for all practical
purposes it's just fine.
Tom
|
|
0
|
|
|
|
Reply
|
Tom
|
1/21/2010 4:32:27 PM
|
|
On 1/21/2010 11:32 AM, Tom St Denis wrote:
> On Jan 21, 11:16 am, happy<hppymit...@yahoo.com> wrote:
>> I want to implement atoi function which converts string to an integer.
>> So I did this :
>>
>> int atoi(char str[])
>> {
>> int i, num;
>> for( num = 0, i = 0 ; isdigit(str[i]) ; i++)
>> num = num * 10 + str[i] - '0' ;
>> return num;
>>
>> }
>>
>> Here I wnat to know is there any way to tell user if num goes out of
>> range of int ?
>> I mean we can't check num after overflow as it will be UB so is there
>> a way to check if str[] contains large integer ?
>
> The usual way would be to check to ensure that num< (num * 10 +
> value). I don't think that's 100% portable but for all practical
> purposes it's just fine.
>
> Tom
Except that that doesn't work. Take for example (assuming 32-bit ints)
num = 0x40000000. Then num*10 = 0x80000000 after the overflow, which is
still bigger than num.
The best I can come up with is to compare num with ((num * 10 + value) -
value)/10. If they are equal then the inner paranthetical expression
didn't overflow. If not then it did. To be explicit:
int atoi(char str[])
{
int i, num, numtemp;
for( num = 0, i = 0 ; isdigit(str[i]) ; i++)
{
numtemp = num
num = num * 10 + str[i] - '0' ;
if(numtemp != ((num - str[i]) + '0')/10)
{
/* Overflow */
}
}
return num;
}
--
Dan Giaimo
|
|
0
|
|
|
|
Reply
|
news
|
1/21/2010 4:49:10 PM
|
|
happy <hppymittal@yahoo.com> wrote:
> I want to implement atoi function which converts string to an integer.
> So I did this :
> int atoi(char str[])
> {
> int i, num;
> for( num = 0, i = 0 ; isdigit(str[i]) ; i++)
> num = num * 10 + str[i] - '0' ;
> return num;
> }
> Here I wnat to know is there any way to tell user if num goes out of
> range of int ?
> I mean we can't check num after overflow as it will be UB so is there
> a way to check if str[] contains large integer ?
You could check if num is larger than INT_MAX / 10 before you
multiply it by 10. If that isn't the case and num has been mul-
tiplied by 10 you then have to check if INT_MAX minus the new
digit is not smaller than 'num'. Another way would be to do a
string comparison on 'str' (but only the part that contains
numbers!) to a stringified version of INT_MAX, obtained defi-
ning the macros
#define _STRFY( x ) #x
#define STRFY( x ) _STRFY( x )
and using something like
if ( strlen( str ) > strlen( STRFY( INT_MAX ) )
|| strcmp( str, STRFY( INT_MAX ) ) > 0 )
puts( "overflow" );
Reporting an overflow back to the user could be done in the same
way strtol() does it, i.e. passing back INT_MAX and setting errno
to ERANGE.
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
|
|
0
|
|
|
|
Reply
|
jt
|
1/21/2010 4:52:21 PM
|
|
On 1/21/2010 11:49 AM, news.telesweet.net wrote:
> On 1/21/2010 11:32 AM, Tom St Denis wrote:
>> On Jan 21, 11:16 am, happy<hppymit...@yahoo.com> wrote:
>>> I want to implement atoi function which converts string to an integer.
>>> So I did this :
>>>
>>> int atoi(char str[])
>>> {
>>> int i, num;
>>> for( num = 0, i = 0 ; isdigit(str[i]) ; i++)
>>> num = num * 10 + str[i] - '0' ;
>>> return num;
>>>
>>> }
>>>
>>> Here I wnat to know is there any way to tell user if num goes out of
>>> range of int ?
>>> I mean we can't check num after overflow as it will be UB so is there
>>> a way to check if str[] contains large integer ?
>>
>> The usual way would be to check to ensure that num< (num * 10 +
>> value). I don't think that's 100% portable but for all practical
>> purposes it's just fine.
>>
>> Tom
>
> Except that that doesn't work. Take for example (assuming 32-bit ints)
> num = 0x40000000. Then num*10 = 0x80000000 after the overflow, which is
> still bigger than num.
>
> The best I can come up with is to compare num with ((num * 10 + value) -
> value)/10. If they are equal then the inner paranthetical expression
> didn't overflow. If not then it did. To be explicit:
>
> int atoi(char str[])
> {
> int i, num, numtemp;
> for( num = 0, i = 0 ; isdigit(str[i]) ; i++)
> {
> numtemp = num
> num = num * 10 + str[i] - '0' ;
> if(numtemp != ((num - str[i]) + '0')/10)
> {
> /* Overflow */
> }
> }
> return num;
> }
>
> --
> Dan Giaimo
I must be exhausted. The example above only works for unsigned ints.
For signed ints try num = 0x20000000. Then num*10 = 0x40000000 after
the overflow and the same considerations apply.
--
Dan G
|
|
0
|
|
|
|
Reply
|
news
|
1/21/2010 4:56:05 PM
|
|
"Tom St Denis" <tom@iahu.ca> wrote in message
news:0a169ba1-0bb4-436a-acd7-8034567aface@k35g2000yqb.googlegroups.com...
> On Jan 21, 11:16 am, happy <hppymit...@yahoo.com> wrote:
> > I want to implement atoi function which converts string to an integer.
> > So I did this :
> >
> > int atoi(char str[])
> > {
> > int i, num;
> > for( num = 0, i = 0 ; isdigit(str[i]) ; i++)
> > num = num * 10 + str[i] - '0' ;
> > return num;
> >
> > }
> >
> > Here I wnat to know is there any way to tell user if num goes out of
> > range of int ?
> > I mean we can't check num after overflow as it will be UB so is there
> > a way to check if str[] contains large integer ?
>
> The usual way would be to check to ensure that num < (num * 10 +
> value). I don't think that's 100% portable but for all practical
> purposes it's just fine.
Yes, it's just fine, other than the fact that it doesn't work. For example,
assume a platform with 32 bit two's complement int's, and which does
overflow handling by discarding the high order bits. Then, on the last
iteration of computing:
atoi( "5000000000" )
num will initially be 500000000, and then num*10+value will be 705032704;
because 705032704>500000000, overflow will not be detected.
Instead, in this particular case, I would suggest making the test:
if (num > INT_MAX/10 || (num == INT_MAX/10 && value > INT_MAX%10))
handle_overflow();
(I'd also suggest making num an unsigned int, but that's not strictly
speaking necesssary)
--
poncho
|
|
0
|
|
|
|
Reply
|
Scott
|
1/21/2010 5:00:59 PM
|
|
"Tom St Denis" <tom@iahu.ca> wrote in message
news:0a169ba1-0bb4-436a-acd7-8034567aface@k35g2000yqb.googlegroups.com...
> On Jan 21, 11:16 am, happy <hppymit...@yahoo.com> wrote:
> > I want to implement atoi function which converts string to an integer.
> > So I did this :
> >
> > int atoi(char str[])
> > {
> > int i, num;
> > for( num = 0, i = 0 ; isdigit(str[i]) ; i++)
> > num = num * 10 + str[i] - '0' ;
> > return num;
> >
> > }
> >
> > Here I wnat to know is there any way to tell user if num goes out of
> > range of int ?
> > I mean we can't check num after overflow as it will be UB so is there
> > a way to check if str[] contains large integer ?
>
> The usual way would be to check to ensure that num < (num * 10 +
> value). I don't think that's 100% portable but for all practical
> purposes it's just fine.
Yes, it's just fine, other than the fact that it doesn't work. For example,
assume a platform with 32 bit two's complement int's, and which does
overflow handling by discarding the high order bits. Then, on the last
iteration of computing:
atoi( "5000000000" )
num will initially be 500000000, and then num*10+value will be 705032704;
because 705032704>500000000, overflow will not be detected.
Instead, in this particular case, I would suggest making the test:
if (num > INT_MAX/10 || (num == INT_MAX/10 && value > INT_MAX%10))
handle_overflow();
(I'd also suggest making num an unsigned int, but that's not strictly
speaking necesssary)
--
poncho
|
|
0
|
|
|
|
Reply
|
Scott
|
1/21/2010 5:00:59 PM
|
|
On Jan 21, 11:49=A0am, "news.telesweet.net" <dgia...@gmail.com> wrote:
> On 1/21/2010 11:32 AM, Tom St Denis wrote:
>
>
>
> > On Jan 21, 11:16 am, happy<hppymit...@yahoo.com> =A0wrote:
> >> I want to implement atoi function which converts string to an integer.
> >> So I did this :
>
> >> int atoi(char str[])
> >> {
> >> =A0 =A0int i, num;
> >> =A0 =A0for( num =3D 0, i =3D 0 ; isdigit(str[i]) ; i++)
> >> =A0 =A0 =A0 =A0num =3D num * 10 + str[i] - '0' ;
> >> =A0 =A0return num;
>
> >> }
>
> >> Here I wnat to know is there any way to tell user if num goes out of
> >> range of int ?
> >> I mean we can't check num after overflow as it will be UB so is there
> >> a way to check if str[] contains large integer ?
>
> > The usual way would be to check to ensure that num< =A0(num * 10 +
> > value). =A0I don't think that's 100% portable but for all practical
> > purposes it's just fine.
>
> > Tom
>
> Except that that doesn't work. =A0Take for example (assuming 32-bit ints)
> num =3D 0x40000000. =A0Then num*10 =3D 0x80000000 after the overflow, whi=
ch is
> still bigger than num.
Except it does work...
tstdenis@photon:~$ cat test.c
#include<stdio.h>
#include<limits.h>
int main (void)
{
int a;
a =3D INT_MAX/10;
printf("%d %d %d\n", a < (a * 10), a, a*10);
++a;
printf("%d %d %d\n", a < (a * 10), a, a*10);
return 0;
}
tstdenis@photon:~$ ./test
1 214748364 2147483640
0 214748365 -2147483646
The second case fails since a is not less than a*10 which means an
overflow occurred.
Tom
|
|
0
|
|
|
|
Reply
|
Tom
|
1/21/2010 5:08:37 PM
|
|
On Jan 21, 12:00=A0pm, "Scott Fluhrer" <sfluh...@ix.netcom.com> wrote:
> "Tom St Denis" <t...@iahu.ca> wrote in messagenews:0a169ba1-0bb4-436a-acd=
7-8034567aface@k35g2000yqb.googlegroups.com...
>
>
>
> > On Jan 21, 11:16 am, happy <hppymit...@yahoo.com> wrote:
> > > I want to implement atoi function which converts string to an integer=
..
> > > So I did this :
>
> > > int atoi(char str[])
> > > {
> > > int i, num;
> > > for( num =3D 0, i =3D 0 ; isdigit(str[i]) ; i++)
> > > num =3D num * 10 + str[i] - '0' ;
> > > return num;
>
> > > }
>
> > > Here I wnat to know is there any way to tell user if num goes out of
> > > range of int ?
> > > I mean we can't check num after overflow as it will be UB so is there
> > > a way to check if str[] contains large integer ?
>
> > The usual way would be to check to ensure that num < (num * 10 +
> > value). =A0I don't think that's 100% portable but for all practical
> > purposes it's just fine.
>
> Yes, it's just fine, other than the fact that it doesn't work. =A0For exa=
mple,
> assume a platform with 32 bit two's complement int's, and which does
> overflow handling by discarding the high order bits. =A0Then, on the last
> iteration of computing:
>
> =A0 =A0atoi( "5000000000" )
>
> num will initially be 500000000, and then num*10+value will be 705032704;
> because 705032704>500000000, overflow will not be detected.
Am I missing something here? neither of 0x1DCD6500 or 0x2A05F200 are
too big for a 32-bit int. Why would there be an overflow?
tstdenis@photon:~$ cat test.c
#include<stdio.h>
#include<limits.h>
int main (void)
{
int a;
a =3D 500000000; INT_MAX/10;
printf("%d %d %d\n", a < (a * 10), a, a*10);
++a;
printf("%d %d %d\n", a < (a * 10), a, a*10);
return 0;
}
tstdenis@photon:~$ ./test
1 500000000 705032704
1 500000001 705032714
Which is exactly what I would expect happen... They're both in range
and return true for the test a < (a*10 + v).
Tom
|
|
0
|
|
|
|
Reply
|
Tom
|
1/21/2010 5:15:49 PM
|
|
On Jan 21, 12:15=A0pm, Tom St Denis <t...@iahu.ca> wrote:
> On Jan 21, 12:00=A0pm, "Scott Fluhrer" <sfluh...@ix.netcom.com> wrote:
>
>
>
> > "Tom St Denis" <t...@iahu.ca> wrote in messagenews:0a169ba1-0bb4-436a-a=
cd7-8034567aface@k35g2000yqb.googlegroups.com...
>
> > > On Jan 21, 11:16 am, happy <hppymit...@yahoo.com> wrote:
> > > > I want to implement atoi function which converts string to an integ=
er.
> > > > So I did this :
>
> > > > int atoi(char str[])
> > > > {
> > > > int i, num;
> > > > for( num =3D 0, i =3D 0 ; isdigit(str[i]) ; i++)
> > > > num =3D num * 10 + str[i] - '0' ;
> > > > return num;
>
> > > > }
>
> > > > Here I wnat to know is there any way to tell user if num goes out o=
f
> > > > range of int ?
> > > > I mean we can't check num after overflow as it will be UB so is the=
re
> > > > a way to check if str[] contains large integer ?
>
> > > The usual way would be to check to ensure that num < (num * 10 +
> > > value). =A0I don't think that's 100% portable but for all practical
> > > purposes it's just fine.
>
> > Yes, it's just fine, other than the fact that it doesn't work. =A0For e=
xample,
> > assume a platform with 32 bit two's complement int's, and which does
> > overflow handling by discarding the high order bits. =A0Then, on the la=
st
> > iteration of computing:
>
> > =A0 =A0atoi( "5000000000" )
>
> > num will initially be 500000000, and then num*10+value will be 70503270=
4;
> > because 705032704>500000000, overflow will not be detected.
>
> Am I missing something here? =A0neither of =A00x1DCD6500 or 0x2A05F200 ar=
e
> too big for a 32-bit int. =A0Why would there be an overflow?
>
> tstdenis@photon:~$ cat test.c
> #include<stdio.h>
> #include<limits.h>
> int main (void)
> {
> int a;
> a =3D 500000000; INT_MAX/10;
> printf("%d %d %d\n", a < (a * 10), a, a*10);
> ++a;
> printf("%d %d %d\n", a < (a * 10), a, a*10);
> return 0;}
>
> tstdenis@photon:~$ ./test
> 1 500000000 705032704
> 1 500000001 705032714
>
> Which is exactly what I would expect happen... =A0They're both in range
> and return true for the test a < (a*10 + v).
Here is the algorithm "not working" ... (ignore the use of sprintf, I
wasn't thinking and/or I'm busy at work ya ... that's it)
tstdenis@photon:~$ cat test.c
#include<stdio.h>
#include<limits.h>
int t_atoi(char *s)
{
int tmp, num =3D 0;
while (*s) {
tmp =3D num; num =3D num * 10 + *s++ - '0';
if (tmp > num) { printf("OVERFLOW\n"); }
}
return num;
}
int main(void)
{
char buf[64];
sprintf(buf, "%lu", (unsigned long)INT_MAX);
printf("%d\n", t_atoi(buf));
sprintf(buf, "%lu", (unsigned long)INT_MAX + 1);
printf("%d\n", t_atoi(buf));
return 0;
}
tstdenis@photon:~$ ./test
2147483647
OVERFLOW
-2147483648
Tom
|
|
0
|
|
|
|
Reply
|
Tom
|
1/21/2010 5:22:23 PM
|
|
happy wrote:
> I want to implement atoi function which converts string to an integer.
> So I did this :
>
> int atoi(char str[])
> {
> int i, num;
> for( num = 0, i = 0 ; isdigit(str[i]) ; i++)
> num = num * 10 + str[i] - '0' ;
> return num;
> }
>
> Here I wnat to know is there any way to tell user if num goes out of
> range of int ?
The maximum value num can legally have is INT_MAX.
The maximum value str[i] can have (within the loop) is '9', so str[i] -
'0' is at most 9. Therefore, the result of num * 10 can't exceed INT_MAX
- 9, so num mustn't exceed (INT_MAX - 9) / 10.
#include <limits.h>
int my_atoi(char str[])
{
int i = 0;
int num = 0;
int max = (INT_MAX - 9) / 10;
while(isdigit(str[i] && num < max)
{
num = num * 10 + str[i++] - '0';
}
return num;
}
Question: having discovered that overflow would occur, what will you do?
Alert the user? Or simply stop processing digits, documenting that the
function processes as many characters as it legally can (as shown above)?
Another question: have you considered the possibility of a sign? e.g.
atoi("-42");
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within
|
|
0
|
|
|
|
Reply
|
Richard
|
1/21/2010 5:30:34 PM
|
|
Tom St Denis wrote:
<snip>
>>>> On Jan 21, 11:16 am, happy <hppymit...@yahoo.com> wrote:
<snip>
>>>>> Here I wnat to know is there any way to tell user if num goes out of
>>>>> range of int ?
>>>>> I mean we can't check num after overflow as it will be UB so is there
>>>>> a way to check if str[] contains large integer ?
<snip>
>
> int t_atoi(char *s)
> {
> int tmp, num = 0;
> while (*s) {
> tmp = num; num = num * 10 + *s++ - '0';
> if (tmp > num) { printf("OVERFLOW\n"); }
By the time you've detected overflow, you're too late - the behaviour is
undefined. The OP (see above) clearly knows this already.
<snip>
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within
|
|
0
|
|
|
|
Reply
|
Richard
|
1/21/2010 5:32:22 PM
|
|
Richard Heathfield wrote:
) The maximum value num can legally have is INT_MAX.
)
) The maximum value str[i] can have (within the loop) is '9', so str[i] -
) '0' is at most 9. Therefore, the result of num * 10 can't exceed INT_MAX
) - 9, so num mustn't exceed (INT_MAX - 9) / 10.
And what if a user enters a number that's (almost) exactly INT_MAX ?
You're trading simplicity for a slightly shorter range.
Perhaps you could precalculate two sentinels, and if you're inbetween
do the exact calculation.
SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
|
|
0
|
|
|
|
Reply
|
Willem
|
1/21/2010 5:37:07 PM
|
|
On Jan 21, 12:15=A0pm, Tom St Denis <t...@iahu.ca> wrote:
> On Jan 21, 12:00=A0pm, "Scott Fluhrer" <sfluh...@ix.netcom.com> wrote:
>
>
>
> > "Tom St Denis" <t...@iahu.ca> wrote in messagenews:0a169ba1-0bb4-436a-a=
cd7-8034567aface@k35g2000yqb.googlegroups.com...
>
> > > On Jan 21, 11:16 am, happy <hppymit...@yahoo.com> wrote:
> > > > I want to implement atoi function which converts string to an integ=
er.
> > > > So I did this :
>
> > > > int atoi(char str[])
> > > > {
> > > > int i, num;
> > > > for( num =3D 0, i =3D 0 ; isdigit(str[i]) ; i++)
> > > > num =3D num * 10 + str[i] - '0' ;
> > > > return num;
>
> > > > }
>
> > > > Here I wnat to know is there any way to tell user if num goes out o=
f
> > > > range of int ?
> > > > I mean we can't check num after overflow as it will be UB so is the=
re
> > > > a way to check if str[] contains large integer ?
>
> > > The usual way would be to check to ensure that num < (num * 10 +
> > > value). =A0I don't think that's 100% portable but for all practical
> > > purposes it's just fine.
>
> > Yes, it's just fine, other than the fact that it doesn't work. =A0For e=
xample,
> > assume a platform with 32 bit two's complement int's, and which does
> > overflow handling by discarding the high order bits. =A0Then, on the la=
st
> > iteration of computing:
>
> > =A0 =A0atoi( "5000000000" )
>
> > num will initially be 500000000, and then num*10+value will be 70503270=
4;
> > because 705032704>500000000, overflow will not be detected.
>
> Am I missing something here? =A0neither of =A00x1DCD6500 or 0x2A05F200 ar=
e
> too big for a 32-bit int. =A0Why would there be an overflow?
>
> tstdenis@photon:~$ cat test.c
> #include<stdio.h>
> #include<limits.h>
> int main (void)
> {
> int a;
> a =3D 500000000; INT_MAX/10;
> printf("%d %d %d\n", a < (a * 10), a, a*10);
> ++a;
> printf("%d %d %d\n", a < (a * 10), a, a*10);
> return 0;}
>
> tstdenis@photon:~$ ./test
> 1 500000000 705032704
> 1 500000001 705032714
>
> Which is exactly what I would expect happen... =A0They're both in range
> and return true for the test a < (a*10 + v).
>
> Tom
Look very carefully at what _you_ just wrote:
For a =3D 500000000:
(1) a < (a * 10) evaluated to 1
(2) a evaluated to 500000000
(3) a * 10 evaluated to 705032714
Last time I checked 500000000 * 10 =3D 5000000000, not 705032714.
Therefore
you overflowed. However, your test (see line (1)) would imply that no
overflow occurred. I don't think I can make this any simpler.
--
Dan Giaimo
|
|
0
|
|
|
|
Reply
|
dgiaimo
|
1/21/2010 5:42:33 PM
|
|
Willem wrote:
> Richard Heathfield wrote:
> ) The maximum value num can legally have is INT_MAX.
> )
> ) The maximum value str[i] can have (within the loop) is '9', so str[i] -
> ) '0' is at most 9. Therefore, the result of num * 10 can't exceed INT_MAX
> ) - 9, so num mustn't exceed (INT_MAX - 9) / 10.
>
> And what if a user enters a number that's (almost) exactly INT_MAX ?
I'm trading simplicity for a slightly shorter range.
> You're trading simplicity for a slightly shorter range.
Right. :-)
> Perhaps you could precalculate two sentinels, and if you're inbetween
> do the exact calculation.
Or just use strtol, as $deity intended.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within
|
|
0
|
|
|
|
Reply
|
Richard
|
1/21/2010 5:43:36 PM
|
|
"Tom St Denis" <tom@iahu.ca> wrote in message
news:dfa958f6-d0b8-45e8-a24f-10f42dcda174@g23g2000vbl.googlegroups.com...
On Jan 21, 12:00 pm, "Scott Fluhrer" <sfluh...@ix.netcom.com> wrote:
> > Yes, it's just fine, other than the fact that it doesn't work. For
> > example,
> > assume a platform with 32 bit two's complement int's, and which does
> > overflow handling by discarding the high order bits. Then, on the last
> > iteration of computing:
> >
> > atoi( "5000000000" )
> >
> > num will initially be 500000000, and then num*10+value will be
> > 705032704;
> > because 705032704>500000000, overflow will not be detected.
>
> Am I missing something here? neither of 0x1DCD6500 or 0x2A05F200 are
> too big for a 32-bit int. Why would there be an overflow?
0x1DCD6500 == 5000000000 fits into a 32-bit int, however 10*5000000000+0 ==
0x12A05F200 does not. The CPU handles the overflow by discarding the high
order bits, giving 0x2A05F200 == 705032704. So, in this specific case, an
overflow happens that is not detected by your test.
> tstdenis@photon:~$ cat test.c
> #include<stdio.h>
> #include<limits.h>
> int main (void)
> {
> int a;
> a = 500000000; INT_MAX/10;
> printf("%d %d %d\n", a < (a * 10), a, a*10);
> ++a;
> printf("%d %d %d\n", a < (a * 10), a, a*10);
> return 0;
> }
> tstdenis@photon:~$ ./test
> 1 500000000 705032704
> 1 500000001 705032714
>
> Which is exactly what I would expect happen... They're both in range
> and return true for the test a < (a*10 + v).
Are you assuming that "a < (a*10 + v)" indicates an overflow? That's also
true in the nonoverflow case (unless a=v=0)
--
poncho
|
|
0
|
|
|
|
Reply
|
Scott
|
1/21/2010 5:44:47 PM
|
|
On Jan 21, 12:44=A0pm, "Scott Fluhrer" <sfluh...@ix.netcom.com> wrote:
> 0x1DCD6500 =3D=3D 5000000000 fits into a 32-bit int, however 10*500000000=
0+0 =3D=3D
> 0x12A05F200 does not. =A0The CPU handles the overflow by discarding the h=
igh
> order bits, giving 0x2A05F200 =3D=3D 705032704. =A0So, in this specific c=
ase, an
> overflow happens that is not detected by your test.
The real problem [other than I shouldn't be posting to usenet over
lunch] is gcalc betrayed me and truncated the result.
:-)
Tom
|
|
0
|
|
|
|
Reply
|
Tom
|
1/21/2010 5:51:07 PM
|
|
The result according to the C Standard:
1. Ignore leading white space, convert the optional sign ('+' or '-')
plus all digits to a number.
2. If the result does not fit into the range from LONG_MIN to LONG_MAX
then replace it with LONG_MIN or LONG_MAX.
3. Convert the result to type int.
So it's a lot easier to implement long atol (const char* str) first,
and make atoi
int atoi(const char* str)
{
return (int) atol (str);
}
In the implementation of atol, first ignore white space characters
using isspace (). Process a plus or minus character. Then process the
digits. When each digit is processed, there are three cases:
1. Result so far is less than LONG_MAX / 10: Times 10, plus next
digit.
2. Result so far is greater than LONG_MAX / 10, or there is another
digit: Return LONG_MAX or LONG_MIN, depending on the sign.
3. Result so far is equal to LONG_MAX / 10: Check whether the digit
will cause on overflow. The maximum value is (LONG_MAX % 10) if the
sign is positive, or (10 - LONG_MIN) % 10 if the sign is negative.
Return LONG_MAX or LONG_MIN if the next digit is too large. Otherwise,
return the value, being careful that an input of LONG_MIN will be
returned without any stupid overflows.
|
|
0
|
|
|
|
Reply
|
christian
|
1/21/2010 6:41:30 PM
|
|
happy wrote:
> I want to implement atoi function which converts string to an integer.
> So I did this :
>
> int atoi(char str[])
> {
> int i, num;
> for( num = 0, i = 0 ; isdigit(str[i]) ; i++)
> num = num * 10 + str[i] - '0' ;
> return num;
> }
>
> Here I wnat to know is there any way to tell user if num goes out of
> range of int ?
> I mean we can't check num after overflow as it will be UB so is there
> a way to check if str[] contains large integer ?
If you really are implementing a function
that does exactly what atoi does,
then you don't have to check if num goes out of range.
The standard library function (atoi), doesn't do that.
--
pete
|
|
0
|
|
|
|
Reply
|
pete
|
1/21/2010 6:52:39 PM
|
|
happy wrote:
> I want to implement atoi function which converts string to an integer.
> So I did this :
>
> int atoi(char str[])
> {
> int i, num;
> for( num = 0, i = 0 ; isdigit(str[i]) ; i++)
> num = num * 10 + str[i] - '0' ;
> return num;
> }
>
> Here I wnat to know is there any way to tell user if num goes out of
> range of int ?
> I mean we can't check num after overflow as it will be UB so is there
> a way to check if str[] contains large integer ?
If you want to report an error, don't implement atoi (which doesn't
indicate failure), implement strtol, which does.
--
Ian Collins
|
|
0
|
|
|
|
Reply
|
Ian
|
1/21/2010 7:07:04 PM
|
|
christian.bau wrote:
> The result according to the C Standard:
>
> 1. Ignore leading white space, convert the optional sign ('+' or '-')
> plus all digits to a number.
> 2. If the result does not fit into the range from LONG_MIN to LONG_MAX
> then replace it with LONG_MIN or LONG_MAX.
You just made that up.
ISO/IEC 9899:1999 (E)
7.20.1 Numeric conversion functions
1 The functions atof, atoi, atol, and atoll
need not affect the value of the integer
expression errno on an error.
If the value of the result cannot be represented,
the behavior is undefined.
> 3. Convert the result to type int.
>
> So it's a lot easier to implement long atol (const char* str) first,
> and make atoi
>
> int atoi(const char* str)
> {
> return (int) atol (str);
> }
--
pete
|
|
0
|
|
|
|
Reply
|
pete
|
1/21/2010 7:17:42 PM
|
|
jt@toerring.de (Jens Thoms Toerring) writes:
> happy <hppymittal@yahoo.com> wrote:
>> I want to implement atoi function which converts string to an integer.
>> So I did this :
>
>> int atoi(char str[])
>> {
>> int i, num;
>> for( num = 0, i = 0 ; isdigit(str[i]) ; i++)
>> num = num * 10 + str[i] - '0' ;
>> return num;
>> }
>
>> Here I wnat to know is there any way to tell user if num goes out of
>> range of int ?
>> I mean we can't check num after overflow as it will be UB so is there
>> a way to check if str[] contains large integer ?
>
> You could check if num is larger than INT_MAX / 10 before you
> multiply it by 10. If that isn't the case and num has been mul-
> tiplied by 10 you then have to check if INT_MAX minus the new
> digit is not smaller than 'num'. Another way would be to do a
> string comparison on 'str' (but only the part that contains
> numbers!) to a stringified version of INT_MAX, obtained defi-
> ning the macros
>
> #define _STRFY( x ) #x
> #define STRFY( x ) _STRFY( x )
>
> and using something like
>
> if ( strlen( str ) > strlen( STRFY( INT_MAX ) )
> || strcmp( str, STRFY( INT_MAX ) ) > 0 )
> puts( "overflow" );
>
> Reporting an overflow back to the user could be done in the same
> way strtol() does it, i.e. passing back INT_MAX and setting errno
> to ERANGE.
The string comparison trick only works if INT_MAX is defined as a
decimal constant. It merely has to be a constant expression of type
int. For example, <limits.h> could plausibly have:
#define INT_MAX 0x7fffffff
--
Keith Thompson (The_Other_Keith) kst-u@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"
|
|
0
|
|
|
|
Reply
|
Keith
|
1/21/2010 8:37:13 PM
|
|
happy <hppymittal@yahoo.com> writes:
> I want to implement atoi function which converts string to an integer.
> So I did this :
>
> int atoi(char str[])
> {
> int i, num;
> for( num = 0, i = 0 ; isdigit(str[i]) ; i++)
> num = num * 10 + str[i] - '0' ;
> return num;
> }
>
> Here I wnat to know is there any way to tell user if num goes out of
> range of int ?
> I mean we can't check num after overflow as it will be UB so is there
> a way to check if str[] contains large integer ?
Apart from the other comments you've gotten, the identifier "atoi"
is always reserved for use as an external identifier. If you write
your own function with that name (unless you declare it static),
the behavior is undefined. For example, a call might quietly call
the system's atoi() function rather than yours.
If you're writing your own atoi() function as an exercise, pick a
different name (unless you're implementing the C standard library).
strtol(), also in the standard, is much better in terms of error
handling, though it's a little complicated to use. A friendlier
wrapper around strtol() might be a nice thing to have.
--
Keith Thompson (The_Other_Keith) kst-u@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"
|
|
0
|
|
|
|
Reply
|
Keith
|
1/21/2010 8:42:23 PM
|
|
Keith Thompson <kst-u@mib.org> wrote:
> jt@toerring.de (Jens Thoms Toerring) writes:
> > ... Another way would be to do a
> > string comparison on 'str' (but only the part that contains
> > numbers!) to a stringified version of INT_MAX, obtained defi-
> > ning the macros
> >
> > #define _STRFY( x ) #x
> > #define STRFY( x ) _STRFY( x )
> >
> > and using something like
> >
> > if ( strlen( str ) > strlen( STRFY( INT_MAX ) )
> > || strcmp( str, STRFY( INT_MAX ) ) > 0 )
> > puts( "overflow" );
> The string comparison trick only works if INT_MAX is defined as a
> decimal constant. It merely has to be a constant expression of type
> int. For example, <limits.h> could plausibly have:
> #define INT_MAX 0x7fffffff
Right, what a pity;-) But with a bit more of effort I guess it
can still be made to work:
char im[ ( CHAR_BIT * sizeof( int ) ) / 3 + 1 ];
sprintf( im, "%d\n", INT_MAX );
if ( strlen( str ) > strlen( im ) || strcmp( str, im ) > 0 )
puts( "overflow" );
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
|
|
0
|
|
|
|
Reply
|
jt
|
1/21/2010 9:23:58 PM
|
|
pete <pfiland@mindspring.com> writes:
> christian.bau wrote:
>> The result according to the C Standard:
>>
>> 1. Ignore leading white space, convert the optional sign ('+' or '-')
>> plus all digits to a number.
>> 2. If the result does not fit into the range from LONG_MIN to LONG_MAX
>> then replace it with LONG_MIN or LONG_MAX.
>
> You just made that up.
No he didn't. He plucked it mostly from the standard. OK,
from the bit of the standard that describes the behaviour of
strtol rather than ato[il].
Phil
--
Any true emperor never needs to wear clothes. -- Devany on r.a.s.f1
|
|
0
|
|
|
|
Reply
|
Phil
|
1/21/2010 9:37:33 PM
|
|
happy a �crit :
> I want to implement atoi function which converts string to an integer.
> So I did this :
>
> int atoi(char str[])
> {
> int i, num;
> for( num = 0, i = 0 ; isdigit(str[i]) ; i++)
> num = num * 10 + str[i] - '0' ;
> return num;
> }
>
> Here I wnat to know is there any way to tell user if num goes out of
> range of int ?
> I mean we can't check num after overflow as it will be UB so is there
> a way to check if str[] contains large integer ?
Use a double for comparing num*10 against INT_MAX:
double d = num;
if (d*10 > INT_MAX)
etc
jacob
|
|
0
|
|
|
|
Reply
|
jacob
|
1/21/2010 10:22:28 PM
|
|
happy <hppymittal@yahoo.com> writes:
> int atoi(char str[])
> {
> int i, num;
> for( num = 0, i = 0 ; isdigit(str[i]) ; i++)
> num = num * 10 + str[i] - '0' ;
> return num;
> }
>
> Here I wnat to know is there any way to tell user if num goes out of
> range of int ?
if (num > INT_MAX / 10) {
...handle overflow...
}
--
"Some people *are* arrogant, and others read the FAQ."
--Chris Dollin
|
|
0
|
|
|
|
Reply
|
Ben
|
1/21/2010 10:43:20 PM
|
|
jacob navia <jacob@nospam.org> writes:
> happy a écrit :
>> I want to implement atoi function which converts string to an integer.
>> So I did this :
>>
>> int atoi(char str[])
>> {
>> int i, num;
>> for( num = 0, i = 0 ; isdigit(str[i]) ; i++)
>> num = num * 10 + str[i] - '0' ;
>> return num;
>> }
>>
>> Here I wnat to know is there any way to tell user if num goes out of
>> range of int ?
>> I mean we can't check num after overflow as it will be UB so is there
>> a way to check if str[] contains large integer ?
>
> Use a double for comparing num*10 against INT_MAX:
>
> double d = num;
> if (d*10 > INT_MAX)
> etc
That can fail if double has fewer value bits than int does (e.g., if
int and double are both 64 bits).
Aside from that, I'd write the above as:
if (num * 10.0 > INT_MAX) /* ... */
--
Keith Thompson (The_Other_Keith) kst-u@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"
|
|
0
|
|
|
|
Reply
|
Keith
|
1/21/2010 10:59:48 PM
|
|
"Jens Thoms Toerring" <jt@toerring.de> wrote in message
news:7rruveFe2aU1@mid.uni-berlin.de...
> Keith Thompson <kst-u@mib.org> wrote:
>> jt@toerring.de (Jens Thoms Toerring) writes:
>> > ... Another way would be to do a
>> > string comparison on 'str' (but only the part that contains
>> > numbers!) to a stringified version of INT_MAX, obtained defi-
>> > ning the macros
>> >
>> > #define _STRFY( x ) #x
>> > #define STRFY( x ) _STRFY( x )
>> >
>> > and using something like
>> >
>> > if ( strlen( str ) > strlen( STRFY( INT_MAX ) )
>> > || strcmp( str, STRFY( INT_MAX ) ) > 0 )
>> > puts( "overflow" );
>
>> The string comparison trick only works if INT_MAX is defined as a
>> decimal constant. It merely has to be a constant expression of type
>> int. For example, <limits.h> could plausibly have:
>
>> #define INT_MAX 0x7fffffff
>
> Right, what a pity;-) But with a bit more of effort I guess it
> can still be made to work:
>
> char im[ ( CHAR_BIT * sizeof( int ) ) / 3 + 1 ];
> sprintf( im, "%d\n", INT_MAX );
> if ( strlen( str ) > strlen( im ) || strcmp( str, im ) > 0 )
> puts( "overflow" );
I use a similar technique in a real application. But I only do the strcmp()
test when both strings are the same length, otherwise it goes wrong I think.
--
bartc
|
|
0
|
|
|
|
Reply
|
bartc
|
1/21/2010 11:05:00 PM
|
|
"Ben Pfaff" <blp@cs.stanford.edu> wrote in message
news:871vhjrsdg.fsf@blp.benpfaff.org...
> happy <hppymittal@yahoo.com> writes:
>
>> int atoi(char str[])
>> {
>> int i, num;
>> for( num = 0, i = 0 ; isdigit(str[i]) ; i++)
>> num = num * 10 + str[i] - '0' ;
>> return num;
>> }
>>
>> Here I wnat to know is there any way to tell user if num goes out of
>> range of int ?
>
> if (num > INT_MAX / 10) {
> ...handle overflow...
Let's say INT_MAX is 2147483647 for example. So you're doing:
if (num>214748364) ... overflow.
However this might not detect overflows for inputs of "2147483648" and
"2147483649" (assuming you're doing the test with at least one more digit in
hand).
--
Bartc
|
|
0
|
|
|
|
Reply
|
bartc
|
1/21/2010 11:11:46 PM
|
|
"bartc" <bartc@freeuk.com> writes:
> "Ben Pfaff" <blp@cs.stanford.edu> wrote in message
> news:871vhjrsdg.fsf@blp.benpfaff.org...
>> happy <hppymittal@yahoo.com> writes:
>>
>>> int atoi(char str[])
>>> {
>>> int i, num;
>>> for( num = 0, i = 0 ; isdigit(str[i]) ; i++)
>>> num = num * 10 + str[i] - '0' ;
>>> return num;
>>> }
>>>
>>> Here I wnat to know is there any way to tell user if num goes out of
>>> range of int ?
>>
>> if (num > INT_MAX / 10) {
>> ...handle overflow...
>
> Let's say INT_MAX is 2147483647 for example. So you're doing:
>
> if (num>214748364) ... overflow.
>
> However this might not detect overflows for inputs of "2147483648" and
> "2147483649" (assuming you're doing the test with at least one more digit in
> hand).
Telling whether you can add a digit between 0 and 9 is the easy
and obvious part :-)
--
"I don't have C&V for that handy, but I've got Dan Pop."
--E. Gibbons
|
|
0
|
|
|
|
Reply
|
Ben
|
1/21/2010 11:14:56 PM
|
|
On 1/21/2010 6:05 PM, bartc wrote:
> "Jens Thoms Toerring" <jt@toerring.de> wrote
>> [...]
>> char im[ ( CHAR_BIT * sizeof( int ) ) / 3 + 1 ];
>> sprintf( im, "%d\n", INT_MAX );
>> if ( strlen( str ) > strlen( im ) || strcmp( str, im ) > 0 )
>> puts( "overflow" );
>
> I use a similar technique in a real application. But I only do the
> strcmp() test when both strings are the same length, otherwise it goes
> wrong I think.
So if im[] holds "2147483647" and str is "11111111111111111"
you'll conclude that all's well?
--
Eric Sosman
esosman@ieee-dot-org.invalid
|
|
0
|
|
|
|
Reply
|
Eric
|
1/21/2010 11:46:50 PM
|
|
"Eric Sosman" <esosman@ieee-dot-org.invalid> wrote in message
news:hjap17$5r7$1@news.eternal-september.org...
> On 1/21/2010 6:05 PM, bartc wrote:
>> "Jens Thoms Toerring" <jt@toerring.de> wrote
>>> [...]
>>> char im[ ( CHAR_BIT * sizeof( int ) ) / 3 + 1 ];
>>> sprintf( im, "%d\n", INT_MAX );
>>> if ( strlen( str ) > strlen( im ) || strcmp( str, im ) > 0 )
>>> puts( "overflow" );
>>
>> I use a similar technique in a real application. But I only do the
>> strcmp() test when both strings are the same length, otherwise it goes
>> wrong I think.
>
> So if im[] holds "2147483647" and str is "11111111111111111"
> you'll conclude that all's well?
I didn't say I'd leave out the strlen(str)>strlen(im) part. Only that I
would then test for strlen(str)==strlen(im) before calling strcmp().
--
Bartc
|
|
0
|
|
|
|
Reply
|
bartc
|
1/21/2010 11:58:58 PM
|
|
Eric Sosman <esosman@ieee-dot-org.invalid> wrote:
> On 1/21/2010 6:05 PM, bartc wrote:
> > "Jens Thoms Toerring" <jt@toerring.de> wrote
> >> [...]
> >> char im[ ( CHAR_BIT * sizeof( int ) ) / 3 + 1 ];
> >> sprintf( im, "%d\n", INT_MAX );
> >> if ( strlen( str ) > strlen( im ) || strcmp( str, im ) > 0 )
> >> puts( "overflow" );
> >
> > I use a similar technique in a real application. But I only do the
> > strcmp() test when both strings are the same length, otherwise it goes
> > wrong I think.
> So if im[] holds "2147483647" and str is "11111111111111111"
> you'll conclude that all's well?
I guess that bartc meant that when the length isn't equal you
actually don't have to do anymore checks since then the question
is already answered (but then, as I just realized, there is ano-
ther point that needs to be taken care about: what about strings
that start with one or more '0'?). Just the concern about the string
being shorter than a "stringified" version of INT_MAX is something I
don't get since strcmp() will return -1 if 'str' is shorter than 'im'.
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
|
|
0
|
|
|
|
Reply
|
jt
|
1/22/2010 12:01:56 AM
|
|
Phil Carmody wrote:
> pete <pfiland@mindspring.com> writes:
>> christian.bau wrote:
>>> The result according to the C Standard:
>>>
>>> 1. Ignore leading white space, convert the optional sign ('+' or '-')
>>> plus all digits to a number.
>>> 2. If the result does not fit into the range from LONG_MIN to LONG_MAX
>>> then replace it with LONG_MIN or LONG_MAX.
>> You just made that up.
>
> No he didn't. He plucked it mostly from the standard. OK,
> from the bit of the standard that describes the behaviour of
> strtol rather than ato[il].
Yes, the bit of the standard that describes
the behavior of strtol which is different from atoi.
--
pete
|
|
0
|
|
|
|
Reply
|
pete
|
1/22/2010 12:08:02 AM
|
|
"Jens Thoms Toerring" <jt@toerring.de> wrote in message
news:7rs87kFt7qU1@mid.uni-berlin.de...
> Eric Sosman <esosman@ieee-dot-org.invalid> wrote:
>> On 1/21/2010 6:05 PM, bartc wrote:
>> > "Jens Thoms Toerring" <jt@toerring.de> wrote
>> >> [...]
>> >> char im[ ( CHAR_BIT * sizeof( int ) ) / 3 + 1 ];
>> >> sprintf( im, "%d\n", INT_MAX );
>> >> if ( strlen( str ) > strlen( im ) || strcmp( str, im ) > 0 )
>> >> puts( "overflow" );
>> >
>> > I use a similar technique in a real application. But I only do the
>> > strcmp() test when both strings are the same length, otherwise it goes
>> > wrong I think.
>
>> So if im[] holds "2147483647" and str is "11111111111111111"
>> you'll conclude that all's well?
>
> I guess that bartc meant that when the length isn't equal you
> actually don't have to do anymore checks since then the question
> is already answered (but then, as I just realized, there is ano-
> ther point that needs to be taken care about: what about strings
> that start with one or more '0'?). Just the concern about the string
> being shorter than a "stringified" version of INT_MAX is something I
> don't get since strcmp() will return -1 if 'str' is shorter than 'im'.
My strcmp() behaves differently from yours then:
printf("%d\n", strcmp("9","214748647"));
outputs 1 on my machine.
--
Bartc
|
|
0
|
|
|
|
Reply
|
bartc
|
1/22/2010 12:08:09 AM
|
|
On Jan 22, 12:08=A0am, pete <pfil...@mindspring.com> wrote:
> Yes, the bit of the standard that describes
> the behavior of strtol which is different from atoi.
Since this is about _implementing_ a library function or a function
that is compatible with the definition of a library function, anything
in the standard that says where the use of that library function
invokes undefined behaviour can be ignored.
If the standard says "Except in the case of errors, where behaviour is
undefined, the behaviour is like this..."
then we can implement "The behaviour is like this..."
|
|
0
|
|
|
|
Reply
|
christian
|
1/22/2010 12:19:31 AM
|
|
pete <pfiland@mindspring.com> writes:
> Phil Carmody wrote:
>> pete <pfiland@mindspring.com> writes:
>>> christian.bau wrote:
>>>> The result according to the C Standard:
>>>>
>>>> 1. Ignore leading white space, convert the optional sign ('+' or '-')
>>>> plus all digits to a number.
>>>> 2. If the result does not fit into the range from LONG_MIN to LONG_MAX
>>>> then replace it with LONG_MIN or LONG_MAX.
>>> You just made that up.
>>
>> No he didn't. He plucked it mostly from the standard. OK, from the
>> bit of the standard that describes the behaviour of strtol rather
>> than ato[il].
>
> Yes, the bit of the standard that describes
> the behavior of strtol which is different from atoi.
Erm, I think that's what I said. Is you a bit fick?
--
Any true emperor never needs to wear clothes. -- Devany on r.a.s.f1
|
|
0
|
|
|
|
Reply
|
Phil
|
1/22/2010 6:50:50 PM
|
|
On Jan 21, 10:16=A0am, happy <hppymit...@yahoo.com> wrote:
> [...]
> Here I wnat to know is there any way to tell user if num goes out of
> range of int ?
> [...]
Richard Heathfield wrote:
The maximum value str[i] can have (within the loop) is '9', so
str[i] - '0' is at most 9. Therefore, the result of num * 10 can't
exceed INT_MAX - 9, so num mustn't exceed (INT_MAX - 9) / 10.
Willem wrote:
And what if a user enters a number that's (almost) exactly INT_MAX?
You're trading simplicity for a slightly shorter range.
Jens wrote:
You could check if num is larger than INT_MAX/10 before you multiply
it by 10. If that isn't the case and num has been multiplied by 10
you then have to check if INT_MAX minus the new digit is not smaller
than 'num'.
----------------------------------------------------------------------
Putting the ideas above together, and noting ((INT_MAX/10)-1) gives
the same result as (INT_MAX-9)/10, you can get the complete range
with:
If num <=3D ((INT_MAX/10)-1) there can't be an overflow. For 32 bit
signed int this is 214,748,363 and the maximum result is 2,147,483,639
Else if num =3D (INT_MAX/10) =3D 214,748,364 and (str[i]-'0') < 8 you are
OK - this gives numbers from 2,147,483,640 to 2,147,483,647
Else overflow is certain if you continue.
----------------------------------------------------------------------
Note:
As long as the bitlength of the integer is a power of 2, the magic
number 8 in the 'Else if' line works for signed integers:
2^7 =3D 128 (bitlength =3D 8, INT_MAX =3D 127)
2^15 =3D 32768 (bitlength =3D 16, etc.)
2^31 =3D 2147483648
2^63 =3D 9223372036854775808
All numbers =3D 2^((2^n)-1) where n > 1 end in '8' (See Note)
If you go to an unsigned int, all numbers =3D 2^(2^n) where n > 1
end in '6', and you need to change INT_MAX to UNSIGNED_INT_MAX (I'm
guessing about that, it might be U_INT_MAX or whatever) and change
'8' to '6' in the 'Else If' line.
2^8 =3D 256 (UNSIGNED_INT_MAX =3D 255, bitlength =3D 8)
2^16 =3D 65536 (etc.)
2^32 =3D 4294967296
2^64 =3D 18446744073709551616
If you aren't trusting enough to just believe my statements about
2^(2^n) and 2^((2^n)-1), consider that the numbers 2^(2^n) are
generated by squaring the previous number in the series. The
square of any number in '6' also ends in '6':
x =3D 10*y + 6 (x, y integers)
x^2 =3D 100y^2 + 6*2*10y + 36
Since (100y^2 + 6*2*10y) is a multiple of 10, ending in '0', the sum
with 36 ends in '6'.
Dividing the numbers 2^(2^n) by 2 gives the second series 2^((2^n)-1),
and the result of dividing a number ending in '6' can only end in '3'
or '8'. Since 3 is odd and the powers of 2 are even (VERY even) the
result must end in '8'.
Finally, if you subtract 9 from a number ending in '0' through '8'
you need to borrow from the second integer from the right. Integer
division by 10 then gives you the same result as (number/10)-1,
which does the 'borrow' after the division.
I hope this is clear and correct, I've been looking at it too long.
Gil
|
|
0
|
|
|
|
Reply
|
gil_johnson
|
1/23/2010 4:48:04 AM
|
|
Keith Thompson wrote:
> jacob navia <jacob@nospam.org> writes:
>> happy a écrit :
>>> I want to implement atoi function which converts string to an integer.
>>> So I did this :
>>>
>>> int atoi(char str[])
>>> {
>>> int i, num;
>>> for( num = 0, i = 0 ; isdigit(str[i]) ; i++)
>>> num = num * 10 + str[i] - '0' ;
>>> return num;
>>> }
>>>
>>> Here I wnat to know is there any way to tell user if num goes out of
>>> range of int ?
>>> I mean we can't check num after overflow as it will be UB so is there
>>> a way to check if str[] contains large integer ?
>> Use a double for comparing num*10 against INT_MAX:
>>
>> double d = num;
>> if (d*10 > INT_MAX)
>> etc
>
> That can fail if double has fewer value bits than int does (e.g., if
> int and double are both 64 bits).
>
> Aside from that, I'd write the above as:
>
> if (num * 10.0 > INT_MAX) /* ... */
For using double I would do the same thing. However, if writing the
function for real I would simple pre-calculate INT_MAX/10 and INT_MAX%10
so I can do a couple of quick integer comparisons...
if ((num > 0 &&
num < IMAX_DIV_10 ||
num == IMAX_DIV_10 && dig <= IMAX_MOD_10) ||
(num < 0 &&
num > IMIN_DIV_10 ||
num == IMIN_DIV_10 && dig <= IMIN_MOD_10))
/* all OK */
Obviously on pre-calculating you need to ensure you use round towards 0,
where I believe C90 allows round towards -inf, so you need a little
care. It should also allow the common case to fall out fast (if you need
the efficiency), and depending on how you handle negative numbers in
your atoi implementation you could move the sign check else where.
--
Flash Gordon
|
|
0
|
|
|
|
Reply
|
Flash
|
1/23/2010 11:19:26 AM
|
|
bartc <bartc@freeuk.com> wrote:
> "Jens Thoms Toerring" <jt@toerring.de> wrote in message
> news:7rs87kFt7qU1@mid.uni-berlin.de...
> > Eric Sosman <esosman@ieee-dot-org.invalid> wrote:
> >> On 1/21/2010 6:05 PM, bartc wrote:
> >> > "Jens Thoms Toerring" <jt@toerring.de> wrote
> >> >> [...]
> >> >> char im[ ( CHAR_BIT * sizeof( int ) ) / 3 + 1 ];
> >> >> sprintf( im, "%d\n", INT_MAX );
> >> >> if ( strlen( str ) > strlen( im ) || strcmp( str, im ) > 0 )
> >> >> puts( "overflow" );
> >> >
> >> > I use a similar technique in a real application. But I only do the
> >> > strcmp() test when both strings are the same length, otherwise it goes
> >> > wrong I think.
> >
> >> So if im[] holds "2147483647" and str is "11111111111111111"
> >> you'll conclude that all's well?
> >
> > I guess that bartc meant that when the length isn't equal you
> > actually don't have to do anymore checks since then the question
> > is already answered (but then, as I just realized, there is ano-
> > ther point that needs to be taken care about: what about strings
> > that start with one or more '0'?). Just the concern about the string
> > being shorter than a "stringified" version of INT_MAX is something I
> > don't get since strcmp() will return -1 if 'str' is shorter than 'im'.
> My strcmp() behaves differently from yours then:
> printf("%d\n", strcmp("9","214748647"));
> outputs 1 on my machine.
Ooops, no, your strcmp() doesn't work differently from mine;-)
- I just considered cases like strcmp("1", "123") only, stupid
me.... So, yes, a correct version will need to compare strings
only of they have exactly the same lengths (and avoiding an un-
necessary strcmp() is better anyway when the result can already
be derived from the lengths).
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
|
|
0
|
|
|
|
Reply
|
jt
|
1/23/2010 10:30:50 PM
|
|
|
40 Replies
1053 Views
(page loaded in 0.337 seconds)
Similiar Articles: integer overflow in atoi - comp.lang.cI want to implement atoi function which converts string to an integer. So I did this : int atoi(char str[]) { int i, num; for( num = 0, i =... implementation of atoi - comp.lang.cRounded integer division - comp.lang.asm.x86 integer overflow in atoi - comp.lang.c Integer division by 10 then gives you the ... by (2^n)) and rounding to the nearest ... Compare strings as integers - comp.unix.solarisinteger overflow in atoi - comp.lang.c I want to implement atoi function which converts string to an integer. So I did this ... So, yes, a correct version will need to ... How can I add string to an integer matrix ?? - comp.soft-sys ...integer overflow in atoi - comp.lang.c Telling whether you can add a digit between 0 and 9 is the easy ... int atoi ( const char * string ); atoi() converts a string to an ... strcmp usage - comp.soft-sys.matlabinteger overflow in atoi - comp.lang.c strcmp usage - comp.soft-sys.matlab integer overflow in atoi - comp.lang.c... BIT * sizeof( int ) ) / 3 + 1 ]; > sprintf( im, "%d\n ... 16 bit two's complement - comp.soft-sys.matlabinteger overflow in atoi - comp.lang.c 16 bit two's complement - comp.soft-sys.matlab 128 bit integer - comp.lang.c Convert signed integer to a 16-bit hex number - comp ... reading a .csv file with a space after negative sign - comp.soft ...integer overflow in atoi - comp.lang.c Ignore leading white space, convert the optional sign ... 10 - LONG_MIN) % 10 if the sign is negative ... know in general a way to ... Detect integer/arithmetic overflow? - comp.emacsIs it possible to detect integer overflow, when entering large numbers such as ... Still ... not with some libraries. First, write your own atoi using ordinary integer ... Converting number to std::string ("itoa()" ) - comp.lang.c++ ...If atoi can be explained in terms of sscanf, then itoa ... string type but please do not try to special case integer ... worm, which propagated by exploiting buffer overflow in a ... 64 bit integer - comp.lang.c++.moderated----- So, if the value 9999999999999999999 cannot be represented as a long int, then the behavior is undefined > (or is an integer > overflow in a literal integer undefined ... itoa() in Linux - comp.unix.programmerinteger overflow in atoi - comp.lang.c itoa() in Linux - comp.unix.programmer But I could find atoi as part of the library. Does ... char number[32]; snprintf(number, 32 ... Large numbers, floating point number questions - comp.lang.c ...Then you won't get the overflow problems so early. ... A0 =A0 return 1; > > =A0 } > > > =A0 s =3D atoi ... An integer type is preferable. I don't think there is ... integer overflow in atoi - comp.lang.c | Computer GroupI want to implement atoi function which converts string to an integer. So I did this : int atoi(char str[]) { int i, num; for( num = 0, i =... c - convert string to integer sscanf or atoi - Stack Overflowgcc 4.4.4 c89. What is better to convert a string to an integer value. I have tried 2 different methods atoi and sscanf. Both work as expected. char digits[3] = "34 ... 7/24/2012 10:14:20 AM
|