ChatGPT解决这个技术问题 Extra ChatGPT

How to convert an int to 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.

printf or one of its cousins should do the trick
possible duplicate of Where is the itoa function in Linux?
you may also want to see this FAQ on serialization, and maybe the following questions that relate to serialization in C: (a), (b), (c) to achieve your actual intent.
My usual pet semantic peeve here. You don't want to convert anything; you want to obtain a string containing a (base 10?) representation of the value of the int. Yeah, I know. It's a very common short cut, but it still bugs me.
possible duplicate of Converting int to string in c

D
Dave Jarvis

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))

To be sure tat ENOUGH is enough we can do it by malloc(sizeof(char)*(int)log10(num))
@Hauleth Or even +2, considering that (int)log10(42) is 1.
Or you can calculate it at compile-time: #define ENOUGH ((CHAR_BIT * sizeof(int) - 1) / 3 + 2)
@hauleth Still +2 instead of +1, even with ceil: ceil(log(100)) = 2.0, not 3. So +1 for the exact-powers-of-10, and another +1 for terminating null.
You do not consider minus sign and locale: thousands separator and grouping. Please do it this way: use int length = snprintf(NULL, 0,"%d",42); to get length, and then alloc length+1 chars for the string.
A
Alexander Galkin

EDIT: As pointed out in the comment, itoa() is not a standard, so better use sprintf() approach suggested in the rivaling answer!

You can use 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 is no 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.


itoa is not standard - see e.g. stackoverflow.com/questions/190229/…
@PaulR Now I didn't know that! Thanks for the clarification.
@PaulR Thanks, I didn't know that!
@SeanRamey This itoa() suffers the same buffer overflow potential as gets().
itoa is not available in C (C99 at least). it is more available in C++
A
APhillips

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.


#include #include
@user1821961 Thanks, it should really be mentioned that these header files need to be included.
hey, I know this is super old answer, but why "+1" in malloc? is it for the '\0' ?
Yes, +1 is for the '\0'. snprintf returns length not counting the terminating null character, but in second parameter it expects length with terminating null character, so length + 1.
a
ahogen

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;
}

Also, this is considerably faster than sprintf. Could be important when dumping large files.
@chux Yes, a compiler could optimize sprintf(str, "%d", 42); as appending two const chars, but that is theory. In practice people don't sprintf const ints and the itoa above is nearly as optimized as it gets. At least you could be 100% sure you would not get orders of magnitude downgrade of a generic sprintf. It would be nice to see whatever counterexample you have in mind, with compiler version and settings.
@Eugene Ryabtsev char str[3]; sprintf(str, "%d", 42); --> MOV #121A,W4, MOV W4,AF4, MOV #2A,W0 = 2A, MOV #0,W4, CALL 105E embedded compiler simple passes the buffer and 42 to a itoa()-like routine.
@chux If it ends in a call, it does not explain much unless we compare the called routine to the routine above (all the way down to no more calls; in assembly, if you like). If you do it as an answer with compiler version and settings, I will upvote it as useful.
It would be good to provide a way to get the output length back. I've done that here: stackoverflow.com/a/52111436/895245 + unit tests.
M
Mahonri Moriancumer

This is old but 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;
}

Works only for constants, not for variables.
Why doesn't it work if I put a macro in there...? Is it not a constant too?
c
chux - Reinstate Monica

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

Hey chux, do you know if there is any way to expose the glibc internal implementation? sourceware.org/git/?p=glibc.git;a=blob;f=stdio-common/…
@CiroSantilli新疆改造中心六四事件法轮功 I am not familiar with glibc internal implementation.
Shouln't it be '0' + x % 10 instead of '0' - x % 10 (to map a binary integer between decimal 0 and decimal 9 to binary ascii encoding)?
@étale-cohomology x%10 has the value of [-9 ... 0] as x <= 0, not 0 to 9. '0' - x % 10 is correct. Using the negative side of int avoids UB of i = -i; when i == INT_MIN, which this code never does.
@étale-cohomology UB --> Undefined behavior. Negating INT_MIN is UB.
s
sth

If you are using GCC, you can use the GNU extension asprintf function.

char* str;
asprintf (&str, "%i", 12313);
free(str);

u
user2374601

If you want to output your structure into a file there is no 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.


D
Dummy00001
/*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;
     }

b
baz

sprintf is returning the bytes and adds 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

M
Morteza Jalambadani

Use function itoa() to convert an integer to a string

For example:

char msg[30];
int num = 10;
itoa(num,msg,10);

Already answered by @AlexanderGalkin : stackoverflow.com/a/8257754/6872717