2

I'm trying to change a string of chars into a number. For example the string '5','3','9' into 539. what I did is:

for (j = 0; j < len_of_str; j++)
     num = num + ((str[j] - 48) * (10 ^ (len_of_str - j)))    
printf("%d", num);

num is the number which would contain the number as a int the minus 48 is to change the value in ASCII to a number who's like the real number. and the (10 ^ (len_of_str - j)) is the change the values to hundreds, thousands, etc...

myaut
  • 11,174
  • 2
  • 30
  • 62
Roy Ancri
  • 119
  • 2
  • 14
  • 6
    `^` doesn't do what you think it does. – Retired Ninja Apr 23 '15 at 20:11
  • 1
    Unless it's the `^` next to good comments. – nhgrif Apr 23 '15 at 20:11
  • 1
    I suggest using `'0'`, it's much more readable than 48. And unless you're trying to read the number backwards, using `num = num*10 + str[j] - '0'` is much more better. But do you know what's even better? [atoi](http://linux.die.net/man/3/atoi) – holgac Apr 23 '15 at 20:14
  • atoi isn't in every library oddly. It probably should be, but it is not. – DAhrens Apr 23 '15 at 20:27

3 Answers3

3

Several issues:

First, ^ is not an exponentiation operator in C - it's a bitwise exclusive-OR operator. Instead of getting 10N, you'll get 10 XOR N, which is not what you want. C does not have an exponentiation operator (ironic for a language that defines eleventy billion operators, but there you go) - you'll need to use the library function pow instead. Or you can avoid the whole issue and do this instead:

num = 0;
for ( j = 0; j < len_of_str; j++ )
{
  num *= 10;
  num += str[j] - 48;
}

Second, str[j]-48 assumes ASCII encoding. To make that a bit more generic, use str[j] - '0' instead (in most encodings digit characters are sequential, so '9' - '0' should equal 9).

Finally, is there a reason you're not using one of the built-in library functions such as atoi or strtol?

num = (int) strtol( str, NULL, 0 );
printf( "num = %d\n", num );
John Bode
  • 119,563
  • 19
  • 122
  • 198
  • 1
    The spec states that, *"In both the source and execution basic character sets, the value of each character after '0' in the [...] list of decimal digits shall be one greater than the value of the previous."* In other words, you should always use `str[j] - '0'` and it's guaranteed to work. – user3386109 Apr 23 '15 at 20:57
0

As pointed out by the comments above, ^ does not actually calculate a power, but instead does a bit-wise XOR (see wikipedia). For instance for 0101 ^ 0111 == 0010, as XOR will only set the bits to one for which the inputs differ in that bit.

To calculate 10 to the power something in c, use pow(double x, double y) from <math.h>. See this post for more information.

Community
  • 1
  • 1
MrHug
  • 1,315
  • 10
  • 27
0

Convert a sequence of digits into an integer is a special case of the more general case of parsing a number (integer or real) into a binary integer or double value.

One approach is to describe the number using a pattern, which you can either describe iteratively, or recursively as follows,

An integer_string is composed of:
    and optional '+' or '-' (sign)
    follwed by a digit_sequence
a digit_sequence is composed of:
    digit ('0', '1', '2', '3', ..., '9')
    followed by an optional (recursive) digit_sequence

This can be written using Backus-Naur formalism as,

integer_string := { '+' | '-' } digit_sequence
digit_sequence := digit { digit_sequence }
digit := [ '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' ]

Should you desire, you can extend the above to recognize a real number,

real_number := integer_string { '.' { digit_sequence } }
               { [ 'e' | 'E' ] integer_string }

Although the above is not quite correct, as it forces a digit before the decimal (fix is left as an exercise for the reader).

Once you have the Backus-Naur formalism, it is easy to recognize the symbols that comprise the pattern, and the semantic action of the actual conversion to integer

long int
atol_self(char* str)
{
    if(!str) return(0);
    //accumulator for value
    long int accum=0; //nothing yet
    //index through the string
    int ndx=0;
    //handle the optional sign
    int sign=1;
    if ( str[ndx=0] == '+' ) { sign=1; ndx+=1; }
    else if ( str[ndx=0] == '+' ) { sign=1; ndx+=1; }
    for( ; str[ndx] && isdigit(str[ndx]); ) {
        int digval = str[ndx] - '0';
        accum = accum*10 + digval;
        ++ndx;
    }
    return(accum*sign);
}
ChuckCottrill
  • 4,360
  • 2
  • 24
  • 42