whats wrong with this string to int conversion code

Programming, for all ages and all languages.
Post Reply
earlz

whats wrong with this string to int conversion code

Post by earlz »

I am trying to figure out what is wrong with this code and cannot see one problem

Code: Select all

unsigned int str2num(char *str){
   unsigned int num=0,digit=0;
   while (*str!=0){
     num=num+((*str-48)*upwr(10,digit)); //upwr is unsigned power and works
     digit++;str++;
   }
   return num;
}
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:whats wrong with this string to int conversion code

Post by Candy »

you multiply the first number with 10^0, the second with 10^1 and the third with 10^2. You convert 123 to 321.

Try:

Code: Select all

int atoi (char *str) {
  int num;
  while (*str) {
    num = num * 10 + *(str++) - 48;
  }
  return num;
}
Next time, before wondering why code doesn't work, try out the algorithm on paper first.
earlz

Re:whats wrong with this string to int conversion code

Post by earlz »

i did try working it out on paper but for some reason i was thinking i typed it different for some reason so it made it backwards
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:whats wrong with this string to int conversion code

Post by Solar »

<nitpicking mode>

The code also relies on '0' at 48 and '9' at 57. That is true for ASCII, but it is not true for EBCDIC and a couple others. You also did ignore the issue of leading spaces and signs (check the documentation on atoi()!).

Taking from my PDCLib:

Code: Select all

#include <ctype.h>

char _PDCLIB_digits[] = "0123456789";

int atoi( const char * s )
{
    int rc = 0;
    char sign = '+';
    const char * x;
    /* TODO: In other than "C" locale, additional patterns may be defined */
    while ( isspace( *s ) ) ++s;
    if ( *s == '+' ) ++s;
    else if ( *s == '-' ) sign = *(s++);
    while ( ( x = memchr( _PDCLIB_digits, *(s++), 10 ) ) != NULL )
    {
        rc = rc * 10 + ( x - _PDCLIB_digits );
    }
    return ( sign == '+' ) ? rc : -rc;
}
That should be pretty portable. As you can see from the comment, other locales may define more valid digits, but you don't have to support them.
Every good solution is obvious once you've found it.
earlz

Re:whats wrong with this string to int conversion code

Post by earlz »

wow thanks

i thought i looked at that function before and it was a return somehting_i_dont_remeber();
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:whats wrong with this string to int conversion code

Post by Solar »

Jordan3 wrote: i thought i looked at that function before and it was a return somehting_i_dont_remeber();
Correct:

Code: Select all

int atoi( const char * s )
{
    return (int) _PDCLIB_atomax( s );
}
That's a bit of trickery there. [tt]atoi()[/tt], [tt]atol()[/tt] and [tt]atoll()[/tt] basically use the very same code. Now, you could simply make [tt]atoi()[/tt] and [tt]atol()[/tt] call [tt]atoll()[/tt] and cast the result (as the standard does not require you to handle overflow correctly, as opposed to the [tt]strtol()[/tt] function family).

The problem is that [tt]atoll()[/tt] is only available since C99 - if PDCLib is compiled for C89, it is not yet available. That's why I made a function [tt]_PDCLIB_atomax()[/tt] which does the conversion to the largest type supported by the language version.

Long story short, I whittled down the complexity so I could provide you with a "simple" [tt]atoi()[/tt] here. ;-)
Every good solution is obvious once you've found it.
Post Reply