tags:

views:

218

answers:

6

I am trying to convert from any base to base 10. For an input of 010111 base 2 it gives me 1, and for 35 base 9 it gives me 18 which should be 38. Any suggestions?

#include<stdio.h>
#include<math.h>
#include<string.h>

#define LENGTH 6

double pow( double x, double power );

int main()
{
    char input[LENGTH+1] ;
    int base;
    unsigned decValue ;
    char values[] = "0123456789ABCDEFG";
    int i;

    puts( "Enter a value, and its base: " );
    scanf( "%s", &input );
    scanf( "%i", &base );

    for( i = LENGTH-1 ; i >= 0; i-- )
    {  
     int index = strchr(values, input[ i ] ) - values;

     decValue += index * pow( base , i - LENGTH + 1 );
    }

    printf( "%s (base-%u) equals %u \n", input, base, decValue );


    return 0;
}
+1  A: 

You're adding to decValue before you ever assign anything to it. I didn't look too closely at your logic but that stood out immediately. Depending on platform that may cause you issues.

phoebus
I have tried setting that to 0 but it didnt have any effect
Josh Curren
I suggest initializing it to zero anyway if you're going to be adding to it.
phoebus
+3  A: 

Since i < LENGTH, i - LENGTH + 1 is negative and the pow is therefore 0.

So, you should use pow( base , LENGTH - i - 1 ) -- that one's the biggie. Other big bugs: you should use strlen(input) wherever you're using LENGTH; and you should initialize decValue to 0. There may be others, I stopped looking after the first three (this IS after all California, land of the "Three Strikes, You're Out" law;-).

Alex Martelli
Considering the errors that have been pointed out thus far, I'd say he's lost a few innings already.
Chris Lutz
+1  A: 

A few comments:

  1. As written, your code doesn't support "any base", only bases up to 17 (an odd place to stop).
  2. strchr() can return NULL. You should never assume that it won't, especially when you're feeding it direct user input.
  3. Lowercase letters are nice, and you should support them. Simply convert the relevant character to uppercase with toupper(), and then you can recognize both a and A as hexidecimal 10.
  4. In the interest of coding practices, I would suggest creating a function to perform the relevant conversion, rather than doing all the dirty work in main().

If you're doing this as a learning exercise, ignore this paragraph, but you appear to essentially be rewriting the standard library function strtol(), which converts a string to a long for arbitrary bases. It's pretty nice, actually, and has some functionality that you could incorporate into your code if you wanted.

Chris Lutz
+2  A: 

The thing that troubles me here the most is the mixture of floating point arithmetic into your code. Not only is it less efficient, but when the result is converted back to an int, there's the possibility it might get rounded down or something silly. Hypothetical example:

double n = pow(2,3); //becomes 7.99999999999999999999999 for some silly reason
int in = n; //rounds down to 7

Although this might not even be happening in your case, be wary of integer <-> floating point conversions, and avoid them when they are unnecessary.

A better solution is to build up the power incrementally. If I were you, I'd iterate from beginning to end of the number. Pseudocode:

let s be the input string's digits;
let r be the radix;
let n be the resulting number;
n=0;
for (i=0; i<s.size(); i++) {
    n *= radix;
    n += s[i];
}

The concept is that you are picking up digits and shifting them into the number. E.g. 123 in decimal:

1
(shift 1 left, then add 2)
12
(shift 12 left, then add 3)
123

Shifting left, in the context of integers in a given base, is simply multiplying by the radix.

Joey Adams
A: 

Couple things: don't take the address of input (input, an array, already degrades to the pointer you want; taking a pointer of it will result in a pointer to an array, not what you want); and you need to make sure not to overflow the input buffer when reading into it.

If this is not homework, you should just use strtol():

#include <stdlib.h>
#include <stdio.h>

#define Str(x) #x
#define Xstr(x) Str(x)

int main()
{
    char input[LENGTH+1] ;
    int base;
    long decValue;
    char *endptr;

    puts( "Enter a value, and its base: " );
    scanf( "%" Xstr(LENGTH) "s", input ); /* reads at most LENGTH characters */
    scanf( "%i", &base );

    decValue = strtol( input, &endptr, base );
    assert( *endptr == '\0' ); /* if there are any characters left, then string contained invalid characters */

    printf( "%s (base-%u) equals %ld\n", input, base, decValue );

    return 0;
}
newacct
+3  A: 

My suggestion: Dont reinvent the wheel.

See strtoul function:

#include <stdlib.h>                                                             
#include <stdio.h>
int main(){

        /* first arg: number in base n to convert to base 10
         * third arg: base n
         */
        long int b10= strtoul("111",NULL,2);
        printf("%ld\n",b10);
        return 0;

}
Tom