1

I am aware that strtol(hexstring, NULL, 16) will convert my string hexstring, which is hexadecimal, to a decimal. Likewise this would be the case in binary in strtol(binstring, NULL, 2). Is there a function that will do this in general? From one base to the next? If not, can someone propose the most line-efficient way?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Jerry West
  • 151
  • 5
  • 1
    `int`s aren't in "decimal" on the machine; they're in binary, but usually printed in decimal. `itoa` can convert an integer to a string with arbitrary base. – Colonel Thirty Two Mar 26 '16 at 16:40
  • Thanks a bunch, I will look into this! – Jerry West Mar 26 '16 at 16:42
  • However, `itoa` is not a standard C function. BTW, you could code one quite easily. – Basile Starynkevitch Mar 26 '16 at 16:43
  • 2
    Unless you need bases outside the range 2-36 (or non-standard encodings for bases), the `strtol()` family of functions serves to convert from string to internal (binary, non-string) format. You then need a separate function to convert from the internal format to a string format in an arbitrary base. Standard C doesn't provide such a function — you have to look elsewhere. – Jonathan Leffler Mar 26 '16 at 16:43
  • You can use this link http://stackoverflow.com/questions/24916666/recursive-function-to-convert-between-number-bases-fails-at-certain-numbers. You will understand. – Shiv Mar 26 '16 at 16:43
  • @Shiv: You've linked to a curious (interesting) question — it certainly isn't a general answer to this one, though the subject matter is related. – Jonathan Leffler Mar 26 '16 at 16:48
  • What do you mean by 'line-efficient', Jerry? Number of lines of code in the calling code base, or number of lines of code in the function doing the conversion? Or did you have something else in mind? – Jonathan Leffler Mar 26 '16 at 16:51
  • both, what you proposed.. – Bozidar Vulicevic Mar 26 '16 at 16:56

2 Answers2

3

This is one proposition of a C99 base_convert :

#include <stdlib.h>
#include <string.h>

static char *base_convert(const char * str, const int base_in, const int base_out) {
    static const char *alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    size_t a, b, c = 1, d;
    char *s = malloc(c + 1);
    strcpy(s, "0");
    for (; *str; ++str) {
        for (a = (char*)memchr(alphabet, *str, base_out) - alphabet, b = c; b;) {
            d = ((char *) memchr(alphabet, s[--b], base_out) - alphabet) * base_in + a;
            s[b] = alphabet[d % base_out];
            a = d / base_out;
        }
        for (; a; s = realloc(s, ++c + 1), memmove(s + 1, s, c), *s = alphabet[a % base_out], a /= base_out);
    }
    return s;
}

Example usage :

#include <stdio.h>

int main() {
    const char a[] = "10000000000000000000000000000000000000000000000000000000"
                     "00000000000000000000000000000000000000000000000000000000"
                     "00000000000000000000000000000000000000000000000000000000"
                     "00000000000000000000000000000000000000000000000000000000";
    char *b = base_convert(a, 2, 10);
    puts(b);
    free(b);
}

It's magic, example output :

13479973333575319897333507543509815336818572211270286240551805124608
Michel
  • 259
  • 2
  • 3
2

OP all ready knows how to convert a string s representing base digits into an integer. Sample usage:

char *endptr;
errno = 0;
unsigned long y = strtoul(s, &endptr, base);
if (endptr == s) No_conversion();
if (errno) Handle_Overflow();
if (*endptr) Handle_TrailingText();

An easy away to convert an unsigned integer uses a compound literal for memory allocation.

How to use compound literals to fprintf() multiple formatted numbers with arbitrary bases?

If you need other methods, search on 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ.

Community
  • 1
  • 1
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256