0

I have been banging my head against this wall for so long I have been driven make my first StackOverflow post I am trying to convert a string representing any number in any base to base 10.

int* baseToDec(int base, char* value){
  //after three hours its time for a full restart :( give it up for hour 4!!!                            
  printf("%s has a length of %d\n", value, (int)strlen(value));
  int* res = (int*)malloc(1 * sizeof(int));                                           
  int p = 1;
  for(int i = strlen(value)-1; i >= 0; --i){ // moving backwards through the list                        
    int digit; // there is something I dont understand going on with the 0                               
    printf("value at i:%d %c\n",i,  value[i]);
    if(value[i] >= 48 && value[i] <= 57){
      digit = value[i] - 48;


    }
    if(value[i] >= 65 && value[i] <= 90){
      digit = value[i] - 55;
    }
    printf("%d * %d\n",digit, p);

    *res += digit * p;
    p = p * base;
  }
  return res;

from what I can tell the issues is with strings not being the length I expect (something to do with the end characters) when I run the code as is I get a lot of junk digits that make the number seem way larger than it is. All feedback is welcome I hope I did this right

when run with 33 (41 in octal) I get these results


41 has a length of 4
value at i:3 
0 * 1 //notice this 0 and the following one, where did they come from???
value at i:2 1
1 * 8
value at i:1 
1 * 64
value at i:0 4
4 * 512
2120
  • Edit the question to provide a [mre] including a `main` routine and sample input, observed output, and desired output. – Eric Postpischil Oct 09 '20 at 22:14
  • First, read this: [Don't cast malloc](https://stackoverflow.com/q/605845/6699433) – klutt Oct 09 '20 at 22:15
  • You don't need memory allocation at all. Just declare the function to return an `int` instead of a pointer. And declare `res` as an `int`. – user3386109 Oct 09 '20 at 22:18
  • Second: Don't cast the result of `strlen`. Instead, use the correct specifier `%zu`. Solving warnings by casting is a very bad habit. There's absolutely no reason to cast to an int, because you don't care about the type. You just want to print the variable, whatever type it happens to have. – klutt Oct 09 '20 at 22:19
  • I wrote a bit about casting in this answer: https://stackoverflow.com/a/62563330/6699433 – klutt Oct 09 '20 at 22:20
  • 1
    You shouldn't be using hard-coded numbers to represent character constants. 48 should be `'0'`, 57 is `'9'`, 65 is `'A'`, 90 is `'Z'`. The oddball is `- 55` which should be written as `- 'A' + 10`. – user3386109 Oct 09 '20 at 22:27
  • I think that you are accumulating the number in reverse order. If the input is "321" with `base=10`, the result will be 123. That's because `p` is initially 1. So the 3 gets multiplied by 1, the 2 gets multiplied by 10, and the 1 get multiplied by 100. The typical method of accumulating a number is `number = number * base + digit;`. That assumes that `number` was initialized to 0. – user3386109 Oct 09 '20 at 22:29
  • 1
    The cause of the strange output seems not in the function `baseToDec` but in the caller of that. Please post a [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example). – MikeCAT Oct 09 '20 at 22:41

2 Answers2

0

The buffer pointed at by res is used without initializing. Initial values of buffers allocated via malloc() is indeterminate and using the indeterminate values will invoke undefined behavior.

You should add initialization and check if allocation is successful like this:

  int* res = (int*)malloc(1 * sizeof(int));
  if (res == NULL) return NULL; /* check */
  *res = 0; /* initialization */
MikeCAT
  • 73,922
  • 11
  • 45
  • 70
0
#include <stdio.h>
#include <string.h>
#include <math.h>

int baseN_to_decimal(char *number, int from_base){
    int result = 0;
    int digit;
    int len = strlen(number);
    for(int i=len-1;i>=0;i--){
        if(number[i]>='0' && number[i]<='9'){
            digit = number[i] - '0';
        }
        if(number[i]>='A' && number[i]<='F'){
            digit = number[i] - 'A' + 10;
        }
        if(number[i]>='a' && number[i]<='f'){
            digit = number[i] - 'a' + 10;
        }
        result = result + digit * (pow(from_base,len-i-1));
    }
    return result;
}

int main()
{
    printf("%d\r\n", baseN_to_decimal("101010",2)); // Binary to decimal
    printf("%d\r\n", baseN_to_decimal("17AF",16)); // Hex to decimal
    printf("%d\r\n", baseN_to_decimal("17af",16)); // Hex to decimal
    return 0;
}
manu
  • 21
  • 5