Floating point equivalent to strtol() in C - c

strtol converts the inputed string str to a long value of any specified base of 2 to 36. strtof() offers a similar functionality but without allowing your to specify base. Is there another function that does the same as strtof but allows you to select base?
e.g Lets say 101.101 is inputted as a string. I want to be able to do
strtof("101.101", null, 2);
and get an output of 5.625.

You can parse the string to split it in the . and convert the part before and the part after to decimal. Afterwards, you can create a float out of that string. Here is a simple function that accomplishes that.
float new_strtof(char* const ostr, char** endptr, unsigned char base)
{
char* str = (char*)malloc(strlen(ostr) + 1);
strcpy(str, ostr);
const char* dot = ".";
/* I do not validate any input here, nor do I do anything with endptr */ //Let's assume input of 101.1101, null, 2 (binary)
char *cbefore_the_dot = strtok(str, dot); //Will be 101
char *cafter_the_dot = strtok(NULL, dot); //Will be 0101
float f = (float)strtol (cbefore_the_dot, 0, base); //Base would be 2 = binary. This would be 101 in decimal which is 5
int i, sign = (str[0] == '-'? -1 : 1);
char n[2] = { 0 }; //will be just for a digit at a time
for(i = 0 ; cafter_the_dot[i] ; i++) //iterating the fraction string
{
n[0] = cafter_the_dot[i];
f += strtol(n, 0, base) * pow(base, -(i + 1)) * sign; //converting the fraction part
}
free(str);
return f;
}
One could manage this in a more efficient and less dirty way but this is just an example to show you the idea behind this. The above works well for me.
Don't forget to #include <math.h> and compile with -lm flag. An example would be gcc file.c -o file -lm.

Calculations with FP can incur accumulated round off errors and other subtleties. The below simply calculates the whole number part and the fractional part as 2 base-n integers and then, with minimally FP calculation, derives the answer.
Code also needs to cope with a negative whole number part and insure the fractional part is treated with the same sign.
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
double CC_strtod(const char *s, char **endptr, int base) {
char *end;
if (endptr == NULL) endptr = &end;
long ipart = strtol(s, endptr, base);
if ((*endptr)[0] == '.') {
(*endptr)++;
char *fpart_start = *endptr;
// Insure `strtol()` is not fooled by a space, + or -
if (!isspace((unsigned char) *fpart_start) &&
*fpart_start != '-' && *fpart_start != '+') {
long fpart = strtol(fpart_start, endptr, base);
if (ipart < 0) fpart = -fpart;
return fma(fpart, pow(base, fpart_start - *endptr), ipart);
}
}
return ipart;
}
int main() {
printf("%e\n", CC_strtod("101.101", NULL, 2));
}
Output
5.625000e+00
The above is limited in that the two parts should not exceed the range of long. Code could use wider types like intmax_t for a less restrictive function.

For comparison, here's a simple, straightforward version of atoi(), that accepts an arbitrary base to use (i.e. not necessarily 10):
#include <ctype.h>
int myatoi(const char *str, int b)
{
const char *p;
int ret = 0;
for(p = str; *p != '\0' && isspace(*p); p++)
;
for(; *p != '\0' && isdigit(*p); p++)
ret = b * ret + (*p - '0');
return ret;
}
(Note that I have left out negative number handling.)
Once you've got that, it's straightforward to detect a decimal point and handle digits to the right of it as well:
double myatof(const char *str, int b)
{
const char *p;
double ret = 0;
for(p = str; *p != '\0' && isspace(*p); p++)
;
for(; *p != '\0' && isdigit(*p); p++)
ret = b * ret + (*p - '0');
if(*p == '.')
{
double fac = b;
for(p++; *p != '\0' && isdigit(*p); p++)
{
ret += (*p - '0') / fac;
fac *= b;
}
}
return ret;
}
A slightly less obvious approach, which might be numerically better behaved, is:
double myatof2(const char *str, int b)
{
const char *p;
long int n = 0;
double denom = 1;
for(p = str; *p != '\0' && isspace(*p); p++)
;
for(; *p != '\0' && isdigit(*p); p++)
n = b * n + (*p - '0');
if(*p == '.')
{
for(p++; *p != '\0' && isdigit(*p); p++)
{
n = b * n + (*p - '0');
denom *= b;
}
}
return n / denom;
}
I tested these with
#include <stdio.h>
int main()
{
printf("%d\n", myatoi("123", 10));
printf("%d\n", myatoi("10101", 2));
printf("%f\n", myatof("123.123", 10));
printf("%f\n", myatof("101.101", 2));
printf("%f\n", myatof2("123.123", 10));
printf("%f\n", myatof2("101.101", 2));
return 0;
}
which prints
123
21
123.123000
5.625000
123.123000
5.625000
as expected.
One more note: these functions don't handle bases greater than 10.

Related

Decimal to octal converter in c [duplicate]

I can use the strtol function for turning a base36 based value (saved as a string) into a long int:
long int val = strtol("ABCZX123", 0, 36);
Is there a standard function that allows the inversion of this? That is, to convert a long int val variable into a base36 string, to obtain "ABCZX123" again?
There's no standard function for this. You'll need to write your own one.
Usage example: https://godbolt.org/z/MhRcNA
const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
char *reverse(char *str)
{
char *end = str;
char *start = str;
if(!str || !*str) return str;
while(*(end + 1)) end++;
while(end > start)
{
int ch = *end;
*end-- = *start;
*start++ = ch;
}
return str;
}
char *tostring(char *buff, long long num, int base)
{
int sign = num < 0;
char *savedbuff = buff;
if(base < 2 || base >= sizeof(digits)) return NULL;
if(buff)
{
do
{
*buff++ = digits[abs(num % base)];
num /= base;
}while(num);
if(sign)
{
*buff++ = '-';
}
*buff = 0;
reverse(savedbuff);
}
return savedbuff;
}
One of the missing attributes of this "Convert long integer to base 36 string" is string management.
The below suffers from a potential buffer overflow when destination is too small.
char *long_to_string(char *destination, long num, int base);
(Assuming 32-bit long) Consider the overflow of below as the resultant string should be "-10000000000000000000000000000000", which needs 34 bytes to encode the string.
char buffer[33]; // Too small
long_to_string(buffer, LONG_MIN, 2); // Oops!
An alternative would pass in the buffer size and then provide some sort of error signaling when the buffer is too small.
char* longtostr(char *dest, size_t size, long a, int base)
Since C99, code instead could use a compound literal to provide the needed space - without calling code trying to compute the needed size nor explicitly allocate the buffer.
The returned string pointer from TO_BASE(long x, int base) is valid until the end of the block.
#include <assert.h>
#include <limits.h>
#define TO_BASE_N (sizeof(long)*CHAR_BIT + 2)
// v. compound literal .v
#define TO_BASE(x, b) my_to_base((char [TO_BASE_N]){""}, (x), (b))
char *my_to_base(char *buf, long a, int base) {
assert(base >= 2 && base <= 36);
long i = a < 0 ? a : -a; // use the negative side - this handle _MIN, _MAX nicely
char *s = &buf[TO_BASE_N - 1];
*s = '\0';
do {
s--;
*s = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[-(i % base)];
i /= base;
} while (i);
if (a < 0) {
s--;
*s = '-';
}
// Could add memmove here to move the used buffer to the beginning
return s;
}
#include <limits.h>
#include <stdio.h>
int main(void) {
long ip1 = 0x01020304;
long ip2 = 0x05060708;
long ip3 = LONG_MIN;
printf("%s %s\n", TO_BASE(ip1, 16), TO_BASE(ip2, 16), TO_BASE(ip3, 16));
printf("%s %s\n", TO_BASE(ip1, 2), TO_BASE(ip2, 2), TO_BASE(ip3, 2));
puts(TO_BASE(ip1, 8));
puts(TO_BASE(ip1, 36));
puts(TO_BASE(ip3, 10));
}
Here is another option with no need for source array of charaters, but less portable since not all character encodings have contiguous alphabetic characters, for example EBCDIC. Test HERE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>
char get_chars(long long value)
{
if (value >= 0 && value <= 9)
return value + '0';
else
return value - 10 + 'A';
}
void reverse_string(char *str)
{
int len = strlen(str);
for (int i = 0; i < len/2; i++)
{
char temp = str[i];
str[i] = str[len - i - 1];
str[len - i - 1] = temp;
}
}
char* convert_to_base(char *res, int base, long long input)
{
bool flag = 0;
int index = 0;
if(input < 0){
input = llabs(input);
flag = 1;
}
else if(input == 0){
res[index++] = '0';
res[index] = '\0';
return res;
}
while(input > 0)
{
res[index++] = get_chars(input % base);
input /= base;
}
if(flag){
res[index++] = '-';
}
res[index] = '\0';
reverse_string(res);
return res;
}
int main() {
long long input = 0;
printf("** Integer to Base-36 **\n ");
printf("Enter a valid number: ");
scanf("%lld", &input);
if(input >= LLONG_MAX && input <= LLONG_MIN){
printf("Invalid number");
return 0;
}
int base = 36;
char res[100];
printf("%lld -> %s\n", input, convert_to_base(res, base, input));
return 0;
}

Convert a float number to char array on C

I am trying to convert a float number to a char array.
sprintf() will not work for me and neither will dtostrf.
Since I have a limit in the decimal number (it is 5) I tried this:
int num = f;
int decimales = (f-num)*10000;
Everything worked fine until I typed the number 123.050. Instead of giving me the decimal part as "0.50" it gives me a 5000, because it does not count the 0 now that my "decimal" variable is an int.
Is there any other way to convert it?
You want a quick and dirty way to produce a string with the decimal representation of your float without linking sprintf because of space constraints on an embedded system. The number of decimals is fixed. Here is a proposal:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *ftoa(char *dest, size_t size, double val, int dec) {
char *p = dest;
char *q = dest + size;
long long mul = 1;
long long num;
int i;
if (size == 0)
return NULL;
*--q = '\0';
if (size == 1)
goto fail;
if (val < 0) {
val = -val;
if (p >= q)
goto fail;
*p++ = '-';
}
for (i = 0; i < dec; i++) {
mul *= 10;
}
num = (long long)(val * mul + 0.5);
for (i = 1; i < dec + 2 || num > 0; i++) {
if (p >= q)
goto fail;
*--q = '0' + (num % 10);
num = num / 10;
if (i == dec) {
if (p >= q)
goto fail;
*--q = '.';
}
}
memmove(p, q, dest + size - q);
return dest;
fail:
return memset(dest, '*', size - 1);
}
int main(int argc, char *argv[]) {
char buf[24];
for (int i = 1; i < argc; i++) {
double d = strtod(argv[i], NULL);
int dec = 5;
if (i + 1 < argc)
dec = atoi(argv[++i]);
printf("%s\n", ftoa(buf, sizeof buf, d, dec));
}
return 0;
}
Use %04d in printf()
const int D4 = 10000;
double f = 123.050;
int i = round(f*D4);
int num = i / D4;
int decimales = i % D4;
printf("%d.%04d\n", num, decimales);
gives
123.0500
If you worry about an int overflow (since we multiply the number by 10000), use long, or long long instead...
To save decimals in a string including the leading zero(es)
char sdec[5];
sprintf(sdec, "%04d", decimales);
sdec contains the decimals, including the leading zero.
(see also Is floating point math broken? )

C int to char array [duplicate]

How do you convert an int (integer) to a string?
I'm trying to make a function that converts the data of a struct into a string to save it in a file.
You can use sprintf to do it, or maybe snprintf if you have it:
char str[ENOUGH];
sprintf(str, "%d", 42);
Where the number of characters (plus terminating char) in the str can be calculated using:
(int)((ceil(log10(num))+1)*sizeof(char))
As pointed out in a comment, itoa() is not a standard, so better use the sprintf() approach suggested in the rival answer!
You can use the itoa() function to convert your integer value to a string.
Here is an example:
int num = 321;
char snum[5];
// Convert 123 to string [buf]
itoa(num, snum, 10);
// Print our string
printf("%s\n", snum);
If you want to output your structure into a file there isn't any need to convert any value beforehand. You can just use the printf format specification to indicate how to output your values and use any of the operators from printf family to output your data.
The short answer is:
snprintf( str, size, "%d", x );
The longer is: first you need to find out sufficient size. snprintf tells you length if you call it with NULL, 0 as first parameters:
snprintf( NULL, 0, "%d", x );
Allocate one character more for null-terminator.
#include <stdio.h>
#include <stdlib.h>
int x = -42;
int length = snprintf( NULL, 0, "%d", x );
char* str = malloc( length + 1 );
snprintf( str, length + 1, "%d", x );
...
free(str);
If works for every format string, so you can convert float or double to string by using "%g", you can convert int to hex using "%x", and so on.
After having looked at various versions of itoa for gcc, the most flexible version I have found that is capable of handling conversions to binary, decimal and hexadecimal, both positive and negative is the fourth version found at http://www.strudel.org.uk/itoa/. While sprintf/snprintf have advantages, they will not handle negative numbers for anything other than decimal conversion. Since the link above is either off-line or no longer active, I've included their 4th version below:
/**
* C++ version 0.4 char* style "itoa":
* Written by Lukás Chmela
* Released under GPLv3.
*/
char* itoa(int value, char* result, int base) {
// check that the base if valid
if (base < 2 || base > 36) { *result = '\0'; return result; }
char* ptr = result, *ptr1 = result, tmp_char;
int tmp_value;
do {
tmp_value = value;
value /= base;
*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
} while ( value );
// Apply negative sign
if (tmp_value < 0) *ptr++ = '-';
*ptr-- = '\0';
while(ptr1 < ptr) {
tmp_char = *ptr;
*ptr--= *ptr1;
*ptr1++ = tmp_char;
}
return result;
}
Here's another way.
#include <stdio.h>
#define atoa(x) #x
int main(int argc, char *argv[])
{
char *string = atoa(1234567890);
printf("%s\n", string);
return 0;
}
Converting anything to a string should either 1) allocate the resultant string or 2) pass in a char * destination and size. Sample code below:
Both work for all int including INT_MIN. They provide a consistent output unlike snprintf() which depends on the current locale.
Method 1: Returns NULL on out-of-memory.
#define INT_DECIMAL_STRING_SIZE(int_type) ((CHAR_BIT*sizeof(int_type)-1)*10/33+3)
char *int_to_string_alloc(int x) {
int i = x;
char buf[INT_DECIMAL_STRING_SIZE(int)];
char *p = &buf[sizeof buf] - 1;
*p = '\0';
if (i >= 0) {
i = -i;
}
do {
p--;
*p = (char) ('0' - i % 10);
i /= 10;
} while (i);
if (x < 0) {
p--;
*p = '-';
}
size_t len = (size_t) (&buf[sizeof buf] - p);
char *s = malloc(len);
if (s) {
memcpy(s, p, len);
}
return s;
}
Method 2: It returns NULL if the buffer was too small.
static char *int_to_string_helper(char *dest, size_t n, int x) {
if (n == 0) {
return NULL;
}
if (x <= -10) {
dest = int_to_string_helper(dest, n - 1, x / 10);
if (dest == NULL) return NULL;
}
*dest = (char) ('0' - x % 10);
return dest + 1;
}
char *int_to_string(char *dest, size_t n, int x) {
char *p = dest;
if (n == 0) {
return NULL;
}
n--;
if (x < 0) {
if (n == 0) return NULL;
n--;
*p++ = '-';
} else {
x = -x;
}
p = int_to_string_helper(p, n, x);
if (p == NULL) return NULL;
*p = 0;
return dest;
}
[Edit] as request by #Alter Mann
(CHAR_BIT*sizeof(int_type)-1)*10/33+3 is at least the maximum number of char needed to encode the some signed integer type as a string consisting of an optional negative sign, digits, and a null character..
The number of non-sign bits in a signed integer is no more than CHAR_BIT*sizeof(int_type)-1. A base-10 representation of a n-bit binary number takes up to n*log10(2) + 1 digits. 10/33 is slightly more than log10(2). +1 for the sign char and +1 for the null character. Other fractions could be used like 28/93.
Method 3: If one wants to live on the edge and buffer overflow is not a concern, a simple C99 or later solution follows which handles all int.
#include <limits.h>
#include <stdio.h>
static char *itoa_simple_helper(char *dest, int i) {
if (i <= -10) {
dest = itoa_simple_helper(dest, i/10);
}
*dest++ = '0' - i%10;
return dest;
}
char *itoa_simple(char *dest, int i) {
char *s = dest;
if (i < 0) {
*s++ = '-';
} else {
i = -i;
}
*itoa_simple_helper(s, i) = '\0';
return dest;
}
int main() {
char s[100];
puts(itoa_simple(s, 0));
puts(itoa_simple(s, 1));
puts(itoa_simple(s, -1));
puts(itoa_simple(s, 12345));
puts(itoa_simple(s, INT_MAX-1));
puts(itoa_simple(s, INT_MAX));
puts(itoa_simple(s, INT_MIN+1));
puts(itoa_simple(s, INT_MIN));
}
Sample output
0
1
-1
12345
2147483646
2147483647
-2147483647
-2147483648
If you are using GCC, you can use the GNU extension asprintf function.
char* str;
asprintf(&str, "%i", 12313);
free(str);
sprintf is returning the bytes and adds a null byte as well:
# include <stdio.h>
# include <string.h>
int main() {
char buf[1024];
int n = sprintf( buf, "%d", 2415);
printf("%s %d\n", buf, n);
}
Output:
2415 4
/* Function return size of string and convert signed *
* integer to ascii value and store them in array of *
* character with NULL at the end of the array */
int itoa(int value, char *ptr)
{
int count = 0, temp;
if(ptr == NULL)
return 0;
if(value == 0)
{
*ptr = '0';
return 1;
}
if(value < 0)
{
value* = (-1);
*ptr++ = '-';
count++;
}
for(temp=value; temp>0; temp/=10, ptr++);
*ptr = '\0';
for(temp=value; temp>0; temp/=10)
{
*--ptr = temp%10 + '0';
count++;
}
return count;
}
Use function itoa() to convert an integer to a string
For example:
char msg[30];
int num = 10;
itoa(num,msg,10);

How to convert literal char hex value into the hex value itself?

I'm having the literal value that should be stored on an unsigned char[64] array. How can I convert such values to it's hex equivalent?
int main() {
unsigned char arry[1] = { 0xaa }
char* str = "fe"; //I want to store 0xfe on arry[0]
arry[0] = 0xfe; // this works, but I have to type it
arry[0] = 0x + str; //obviously fails
return 0;
}
Any pointers?
arr[0] = strtol(str,NULL,16); // If one entry is big enough to hold it.
For each character c, the value is:
if ('0' <= c && c <= '9') return c - '0';
if ('a' <= c && c <= 'f') return c - 'a' + 10;
if ('A' <= c && c <= 'F') return c - 'A' + 10;
// else error, invalid digit character
Now just iterate over the string from left to right, adding up the digit values, and multiplying the result by 16 each time.
(This is implemented for you by the standard library in the strto*l functions with base 16.)
Use function strtol() to convert a string to a long in a specific base: http://www.cplusplus.com/reference/cstdlib/strtol/
"Parses the C-string str interpreting its content as an integral number of the specified base, which is returned as a long int value. If endptr is not a null pointer, the function also sets the value of endptr to point to the first character after the number."
Example:
#include <stdio.h> /* printf */
#include <stdlib.h> /* strtol */
int main ()
{
char szNumbers[] = "2001 60c0c0 -1101110100110100100000 0x6fffff";
char * pEnd;
long int li1, li2, li3, li4;
li1 = strtol (szNumbers,&pEnd,10);
li2 = strtol (pEnd,&pEnd,16);
li3 = strtol (pEnd,&pEnd,2);
li4 = strtol (pEnd,NULL,0);
printf ("The decimal equivalents are: %ld, %ld, %ld and %ld.\n", li1, li2, li3, li4);
return 0;
}
Put together an arbitrary length solution to and from.
Sadly the String to X is verbose: pesky dealing with non hex string, odd length, too big, etc.
#include <string.h>
#include <stdio.h>
// S assumed to be long enough.
// X is little endian
void BigXToString(const unsigned char *X, size_t Length, char *S) {
size_t i;
for (i = Length; i-- > 0; ) {
sprintf(S, "%02X", X[i]);
S += 2;
}
}
int BigStringToX(const char *S, unsigned char X[], size_t Length) {
size_t i;
size_t ls = strlen(S);
if (ls > (Length * 2)) {
return 1; //fail, too big
}
int flag = ls & 1;
size_t Unused = Length - (ls/2) - flag;
memset(&X[Length - Unused], 0, Unused); // 0 fill unused
char little[3];
little[2] = '\0';
for (i = Length - Unused; i-- > 0;) {
little[0] = *S++;
little[1] = flag ? '\0' : *S++;
flag = 0;
char *endptr;
X[i] = (unsigned char) strtol(little, &endptr, 16);
if (*endptr) return 1; // non-hex found
if (*S == '\0') break;
}
return 0;
}
int main() {
unsigned char X[64];
char S[64 * 2 + 2];
char T[64 * 2 + 2];
strcpy(S, "12345");
BigStringToX(S, X, sizeof(X));
BigXToString(X, sizeof(X), T);
printf("'%s'\n", T);
return 0;
}

How can I convert an int to a string in C?

How do you convert an int (integer) to a string?
I'm trying to make a function that converts the data of a struct into a string to save it in a file.
You can use sprintf to do it, or maybe snprintf if you have it:
char str[ENOUGH];
sprintf(str, "%d", 42);
Where the number of characters (plus terminating char) in the str can be calculated using:
(int)((ceil(log10(num))+1)*sizeof(char))
As pointed out in a comment, itoa() is not a standard, so better use the sprintf() approach suggested in the rival answer!
You can use the itoa() function to convert your integer value to a string.
Here is an example:
int num = 321;
char snum[5];
// Convert 123 to string [buf]
itoa(num, snum, 10);
// Print our string
printf("%s\n", snum);
If you want to output your structure into a file there isn't any need to convert any value beforehand. You can just use the printf format specification to indicate how to output your values and use any of the operators from printf family to output your data.
The short answer is:
snprintf( str, size, "%d", x );
The longer is: first you need to find out sufficient size. snprintf tells you length if you call it with NULL, 0 as first parameters:
snprintf( NULL, 0, "%d", x );
Allocate one character more for null-terminator.
#include <stdio.h>
#include <stdlib.h>
int x = -42;
int length = snprintf( NULL, 0, "%d", x );
char* str = malloc( length + 1 );
snprintf( str, length + 1, "%d", x );
...
free(str);
If works for every format string, so you can convert float or double to string by using "%g", you can convert int to hex using "%x", and so on.
After having looked at various versions of itoa for gcc, the most flexible version I have found that is capable of handling conversions to binary, decimal and hexadecimal, both positive and negative is the fourth version found at http://www.strudel.org.uk/itoa/. While sprintf/snprintf have advantages, they will not handle negative numbers for anything other than decimal conversion. Since the link above is either off-line or no longer active, I've included their 4th version below:
/**
* C++ version 0.4 char* style "itoa":
* Written by Lukás Chmela
* Released under GPLv3.
*/
char* itoa(int value, char* result, int base) {
// check that the base if valid
if (base < 2 || base > 36) { *result = '\0'; return result; }
char* ptr = result, *ptr1 = result, tmp_char;
int tmp_value;
do {
tmp_value = value;
value /= base;
*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
} while ( value );
// Apply negative sign
if (tmp_value < 0) *ptr++ = '-';
*ptr-- = '\0';
while(ptr1 < ptr) {
tmp_char = *ptr;
*ptr--= *ptr1;
*ptr1++ = tmp_char;
}
return result;
}
Here's another way.
#include <stdio.h>
#define atoa(x) #x
int main(int argc, char *argv[])
{
char *string = atoa(1234567890);
printf("%s\n", string);
return 0;
}
Converting anything to a string should either 1) allocate the resultant string or 2) pass in a char * destination and size. Sample code below:
Both work for all int including INT_MIN. They provide a consistent output unlike snprintf() which depends on the current locale.
Method 1: Returns NULL on out-of-memory.
#define INT_DECIMAL_STRING_SIZE(int_type) ((CHAR_BIT*sizeof(int_type)-1)*10/33+3)
char *int_to_string_alloc(int x) {
int i = x;
char buf[INT_DECIMAL_STRING_SIZE(int)];
char *p = &buf[sizeof buf] - 1;
*p = '\0';
if (i >= 0) {
i = -i;
}
do {
p--;
*p = (char) ('0' - i % 10);
i /= 10;
} while (i);
if (x < 0) {
p--;
*p = '-';
}
size_t len = (size_t) (&buf[sizeof buf] - p);
char *s = malloc(len);
if (s) {
memcpy(s, p, len);
}
return s;
}
Method 2: It returns NULL if the buffer was too small.
static char *int_to_string_helper(char *dest, size_t n, int x) {
if (n == 0) {
return NULL;
}
if (x <= -10) {
dest = int_to_string_helper(dest, n - 1, x / 10);
if (dest == NULL) return NULL;
}
*dest = (char) ('0' - x % 10);
return dest + 1;
}
char *int_to_string(char *dest, size_t n, int x) {
char *p = dest;
if (n == 0) {
return NULL;
}
n--;
if (x < 0) {
if (n == 0) return NULL;
n--;
*p++ = '-';
} else {
x = -x;
}
p = int_to_string_helper(p, n, x);
if (p == NULL) return NULL;
*p = 0;
return dest;
}
[Edit] as request by #Alter Mann
(CHAR_BIT*sizeof(int_type)-1)*10/33+3 is at least the maximum number of char needed to encode the some signed integer type as a string consisting of an optional negative sign, digits, and a null character..
The number of non-sign bits in a signed integer is no more than CHAR_BIT*sizeof(int_type)-1. A base-10 representation of a n-bit binary number takes up to n*log10(2) + 1 digits. 10/33 is slightly more than log10(2). +1 for the sign char and +1 for the null character. Other fractions could be used like 28/93.
Method 3: If one wants to live on the edge and buffer overflow is not a concern, a simple C99 or later solution follows which handles all int.
#include <limits.h>
#include <stdio.h>
static char *itoa_simple_helper(char *dest, int i) {
if (i <= -10) {
dest = itoa_simple_helper(dest, i/10);
}
*dest++ = '0' - i%10;
return dest;
}
char *itoa_simple(char *dest, int i) {
char *s = dest;
if (i < 0) {
*s++ = '-';
} else {
i = -i;
}
*itoa_simple_helper(s, i) = '\0';
return dest;
}
int main() {
char s[100];
puts(itoa_simple(s, 0));
puts(itoa_simple(s, 1));
puts(itoa_simple(s, -1));
puts(itoa_simple(s, 12345));
puts(itoa_simple(s, INT_MAX-1));
puts(itoa_simple(s, INT_MAX));
puts(itoa_simple(s, INT_MIN+1));
puts(itoa_simple(s, INT_MIN));
}
Sample output
0
1
-1
12345
2147483646
2147483647
-2147483647
-2147483648
If you are using GCC, you can use the GNU extension asprintf function.
char* str;
asprintf(&str, "%i", 12313);
free(str);
sprintf is returning the bytes and adds a null byte as well:
# include <stdio.h>
# include <string.h>
int main() {
char buf[1024];
int n = sprintf( buf, "%d", 2415);
printf("%s %d\n", buf, n);
}
Output:
2415 4
/* Function return size of string and convert signed *
* integer to ascii value and store them in array of *
* character with NULL at the end of the array */
int itoa(int value, char *ptr)
{
int count = 0, temp;
if(ptr == NULL)
return 0;
if(value == 0)
{
*ptr = '0';
return 1;
}
if(value < 0)
{
value* = (-1);
*ptr++ = '-';
count++;
}
for(temp=value; temp>0; temp/=10, ptr++);
*ptr = '\0';
for(temp=value; temp>0; temp/=10)
{
*--ptr = temp%10 + '0';
count++;
}
return count;
}
Use function itoa() to convert an integer to a string
For example:
char msg[30];
int num = 10;
itoa(num,msg,10);

Resources