There are several things going on here:
- First an uninitialised local pointer has an indeterminate value; it doesn't point anywhere in particular. The
NULL
pointer doesn't point anywhere either, but at least you can test for a NULL
pointer easily. Make a habit of initalising a pointer to make it point to valid memory or to make it explicitly null.
- The pointer is supposed to point to a char buffer. The way your function looks like, you must allocate memory for that buffer on the heap with
malloc
. (You can't use local storage, because that would be invalidated immediately.)
- Don't make base 10 a special case. (You're even doing it wrong by printing base 10 numbers as hex.)
- Your method of printing is okay, but you print the number backwards. So determine the required klength first and then decrement the position you print at.
- Here, you deal with the raw characters. Use
res[i]
rather than do complicated things with the standard library functions. In particular, don't build strings by concatenating or printing strings to themselves. That's very likely undefined behaviour.
A possible implementation of your function could look like:
int ndigits(int num, int base)
{
int n = 0;
while (num) {
n++;
num /= base;
}
if (n == 0) n++;
return n;
}
char* baseConverter(int num, int base)
{
if (num >= 0 && base > 1 && base <= 36) {
int n = ndigits(num, base);
char *res = malloc(n + 1);
int i = n;
res[n] = '\0';
if (num == 0) res[--i] = '0';
while (num) {
res[--i] = digits[num % base];
num /= base;
}
return res;
}
return NULL;
}
Note how an auxiliary function is used to determine the length of the string. The string is then filled backwards, staring with the null terminator. Also note how invalid cases are handled by returning NULL
.
Your calling code must explicitly free the string after using it:
int n = rand() % 100000 + 1;
int m = rand() % 10 + 2;
char *p = baseConverter(n, m);
if (p) printf("%d#%d == %s\n", n, m, p);
free(p);
C has manual memory management and keeping track of allocated stuff is tedious. You can't, for example, call baseConverter
from inside printf
, because you'd lose the handle to the allocated string.
Another popular variant is to have the calling code allocate the memory and then pas a buffer and its size to the function to fill it. A prototype could then look like this:
void sbase(char buf, size_t buflen, int num, int base);
It would then be called like this:
char buf[33]; // Maximum, when base 2 is printed
sbase(buf, sizeof(buf), 5000, 13);
puts(buf);
Because buf
is an automatic variable, no free
ing is to be done. (How to implement thins and how to properly enforce that the buffer size isn't exceeded is left as an exercise. :)
)