I was wondering if my implementation of an "itoa" function is correct. Maybe you can help me getting it a bit more "correct", I'm pretty sure I'm missing something. (Maybe there is already a library doing the conversion the way I want it to do, but... couldn't find any)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
char * itoa(int i) {
char * res = malloc(8*sizeof(int));
sprintf(res, "%d", i);
return res;
}
int main(int argc, char *argv[]) {
...
This should work:
If you don't want to have to use the math/floating point functions (and have to link in the math libraries) you should be able to find non-floating point versions of log10 by searching the Web and do:
size_t len = my_log10( abs(x) ) + 1;
That might give you 1 more byte than you needed, but you'd have enough.
I think you are allocating perhaps too much memory.
malloc(8*sizeof(int))
will give you 32 bytes on most machines, which is probably excessive for a text representation of an int.You should use a function in the
printf
family for this purpose. If you'll be writing the result tostdout
or a file, useprintf
/fprintf
. Otherwise, usesnprintf
with a buffer big enough to hold3*sizeof(type)+2
bytes or more.The only actual error is that you don't check the return value of
malloc
for null.The name
itoa
is kind of already taken for a function that's non-standard, but not that uncommon. It doesn't allocate memory, rather it writes to a buffer provided by the caller:If you don't want to rely on your platform having that, I would still advise following the pattern. String-handling functions which return newly allocated memory in C are generally more trouble than they're worth in the long run, because most of the time you end up doing further manipulation, and so you have to free lots of intermediate results. For example, compare:
vs.
If you had reason to be especially concerned about performance (for instance if you're implementing a stdlib-style library including
itoa
), or if you were implementing bases thatsprintf
doesn't support, then you might consider not callingsprintf
. But if you want a base 10 string, then your first instinct was right. There's absolutely nothing "incorrect" about the%d
format specifier.Here's a possible implementation of
itoa
, for base 10 only:Here's one which incorporates the snprintf-style approach to buffer lengths:
sprintf is quite slow, if performance matters it is probably not the best solution.
if the base argument is a power of 2 the conversion can be done with a shift and masking, and one can avoid reversing the string by recording the digits from the highest positions. For instance, something like this for base=16
const char digits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
For decimals there is a nice idea to use a static array big enough to record the numbers in the reversed order, see here