ccase-sensitivebase-conversion

Conversion from any base to decimal and case sensitivity


I am using the following portal to verify the results of my code (again sourced from the web):

RapidTables BaseConverter

My code is as shown below:

// C program to convert a number from any base 
// to decimal 
#include <stdio.h> 
#include <string.h> 
  
// To return value of a char. For example, 2 is 
// returned for '2'.  10 is returned for 'A', 11 
// for 'B' 
int val(char c) 
{ 
    if (c >= '0' && c <= '9') 
        return (int)c - '0'; 
    else
        return (int)c - 'A' + 10; 
} 
  
// Function to convert a number from given base 'b' 
// to decimal 
int toDeci(char *str, int base) 
{ 
    int len = strlen(str); 
    int power = 1; // Initialize power of base 
    int num = 0;  // Initialize result 
    int i; 
  
    // Decimal equivalent is str[len-1]*1 + 
    // str[len-1]*base + str[len-1]*(base^2) + ... 
    for (i = len - 1; i >= 0; i--) 
    { 
        // A digit in input number must be 
        // less than number's base 
        if (val(str[i]) >= base) 
        { 
           printf("Invalid Number\n"); 
           return -1; 
        } 
  
        num += val(str[i]) * power; 
        power = power * base; 
    } 
  
    return num; 
} 
  
// Driver code 
int main() 
{ 
    char str[] = "25a"; 
    int base = 36; 
    printf("Decimal equivalent of %s in base %d is " " %d ", str, base, toDeci(str, base)); 
    return 0; 
}

As shown inside main(), if use the value "25a" for str[], I get the following output:

Invalid Number
Decimal equivalent of 25a in base 36 is  -1

But if I change the value of str[] to "25A", I get the following output:

Decimal equivalent of 25A in base 36 is  2782

Using the portal link that I have provided above for result verification, I get the last result for both values.

So my question is, how can I modify my code to make the corresponding change?

TIA

Vinod


Solution

  • If you can't or don't want to change the function signatures or use the proper library functions to perform the conversion, a simple change to the val function would allow the code to also manage the lower cases.

    int val(char c) 
    { 
        if ( '0' <= c  &&  c <= '9') 
            return c - '0'; 
        else if ( 'A' <= c  &&  c <= 'Z' )
            return c - 'A' + 10;
        else if ( 'a' <= c  &&  c <= 'z' )
            return c - 'a' + 10;
        else
            return -1;
    } 
    

    A little change to the other function (using the Horner method to evaluate the polynomial) and we can also avoid a call to strlen.

    int toDeci(char *str, int base) 
    { 
        unsigned long long int num = 0;
        
        while( *str != '\0' )
        {
            int digit = val(*str);
            if ( digit == -1  ||  digit >= base )
            {
                printf("Invalid digit.\n");
                return -1;
            }
            unsigned long long int n = num * base + digit;
            if ( n < num )
            {
                printf("The number is too big.\n");
                return -1;
            }
            num = n;
            ++str;
        }
        if ( num > INT_MAX )  // You'll have to include <limits.h>
        {
            printf("The number is too big to fit into an int.\n");
            return -1;
        }
        return num; 
    }
    

    Note that this code still can't process negative numbers or prefixes like 0 for octals and 0x for hexadecimal numbers. The error checking also follows OP's choice (returning -1 when something goes wrong) and needs to be rethinked.