|
|
Jan Wagner schrieb:
Hi,
using gcc version 3.3.5 (Debian 1:3.3.5-13), the header stdlib.h
includes an itoa() declaration, however I can't find itoa in any
existing libraries!?
itoa() isn't really ANSI C but as it's already declared in the gcc
headers I suppose it is in some library as well.
Any ideas which one?
I'd like to do for example itoa(byte, buf, 2);
(or, a suggestion for some alternative way to do arbitrary base in
snprintf and sprintf would also be welcome! ;-))
itoa() is not a C or POSIX standard library function, so you
can run into problems when switching to another library.
Cygwin's libc, for example, does not have itoa().
As it is sufficiently easy to roll your own for bases up to a fixed
limit (say 36 for decimal digits plus upper or lower case alphabet),
I suggest you do exactly that or look for a trustworthy
implementation, ideally with a size parameter; a not entirely tested
version is included at the end.
Cheers
Michael
,-- itoa.h -
#ifdef H_ITOA_H
#define H_ITOA_H
#include <stddef.h>
void rev_str_l (char *s, size_t size);
#define rev_str(s) \
rev_str_l(s, -1);
size_t itoa (int i, int base, char *a, size_t arrsize);
#endif
`----
,-- itoa.c -
#include "itoa.h"
#include <string.h>
/****************************************************
** reverse a sequence of characters in place
**
** params:
** s .. either the address of the first character
** of a C string (size == (size_t)-1) or the
** address of the first character of an array
** of char with at least size elements.
** size .. either -1 (determine string length and
** use that) or less or equal to the size of
** the storage s points to
*/
void rev_str_l (char *s, size_t size)
{
size_t index = 0;
int temp;
if (size == (size_t)-1)
size = strlen(s);
while (index < size) {
temp = s[--size];
s[size] = s[index];
s[index++] = temp;
}
}
/****************************************************
** Calculate the number of characters necessary to
** represent "i" in base "base"; if "a" points to
** sufficiently large storage (->"arrsize"), then
** "a" contains i_(base) afterwards.
**
** Params:
** i .. number to be converted
** base .. base (between 2 and 36)
** a .. either NULL or start of an array where the
** base "base" representation of i is stored
** arrsize .. size of the storage "a" points to.
**
** Returns:
** 0 .. invalid base, or either a==0 and arrsize!=0
** or a!=0 and arrsize==0.
** n>0 .. size of an array of char that can hold
** i represented in base "base"; if
** n > arrsize, then "a" contains no valid
** number.
**
** Examples:
** 1)
** ret = itoa(42, 36, buf, bufsize);
** if (ret <= bufsize) {
** puts(a);
** }
** 2)
** size = itoa(num, base, NULL, 0);
** buf = malloc(size);
** if (buf == NULL) { /* error handling * / }
** itoa(num, base, buf, size);
** puts(buf);
** 3)
** size = 0;
** buf = NULL;
** while (somecond) {
** getNum(&num);
** newsize = itoa(num, base, buf, size);
** if (newsize > size) {
** char *tmp = realloc(buf, newsize);
** if (tmp) {
** size = newsize;
** buf = tmp;
** itoa(num, base, buf, size);
** } else {
** /* error handling * /
** break;
** }
** }
** puts(buf);
** }
*/
size_t itoa (int i, int base, char *a, size_t arrsize)
{
const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
unsigned long ui;
int minus = 0;
size_t index, size;
if ((a == NULL && arrsize != 0)
|| (arrsize == 0 && a != NULL)
|| (base <= 1 || base >= (int)sizeof digits))
return 0;
if (i < 0) {
ui = 1LU - (i + 1); /* avoid negative overflow */
minus = 1;
} else {
ui = i;
}
index = 0;
do {
if (index+minus+1 < arrsize) {
/* a can hold the next digit */
a[index] = digits[ui % base];
}
ui /= base;
++index;
} while (ui != 0);
if (index+minus >= arrsize) { /* a is too small */
size = arrsize;
++index;
if (size >= 1) {
a[size-1] = '\0';
if (minus && size >= 2) {
a[size-2] = '-';
}
if (size >= (size_t)2+minus) {
/* \\ character marks insufficient storage in a */
a[size-2-minus] = '\\';
}
}
} else { /* a is sufficiently large */
if (minus) {
a[index++] = '-';
}
a[index++] = '\0';
size = index;
}
if (a && size) {
rev_str_l(a, size-1);
}
return index;
}
`----
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
|
|