9

Is is possible to convert int to "string" in C just using casting? Without any functions like atoi() or sprintf()?

What I want would be like this:

int main(int argc, char *argv[]) {
    int i = 500;
    char c[4];

    c = (char)i;
    i = 0;
    i = (int)c;
}

The reason is that I need to generate two random ints (0 to 500) and send both as one string in a message queue to another process. The other process receives the message and do the LCM.

I know how to do with atoi() and itoa(). But my teachers wants just using cast.

Also, why isn't the following possible to compile?

typedef struct
{
    int x;
    int y;
} int_t;

typedef struct
{
    char x[sizeof(int)];
    char y[sizeof(int)];
} char_t;

int main(int argc, char *argv[])
{
    int_t rand_int;
    char_t rand_char;

    rand_int.x = (rand() % 501);
    rand_int.y = (rand() % 501);

    rand_char = (char_t)rand_int;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Bodosko
  • 139
  • 1
  • 1
  • 5
  • 9
    key phrase being 'my teachers want` which means everything after that is for you to figure out, not for us to show you. ~smile~ – K Scott Piel May 07 '13 at 22:37
  • You cant imagine the amount of effort, time and research I wasted trying to do that. Everything is working fine, just the cast doesnt work. – Bodosko May 07 '13 at 22:40
  • 6
    I would counter that you have wasted not one second... you've done exactly what the teachers intended... you've spent a lot of time figuring out how not to do it. And that's incredibly valuable as a programmer. – K Scott Piel May 07 '13 at 22:42
  • Can you share the function signature for placing it on the message queue? That sounds like the crux of the problem. – Kaiged May 07 '13 at 22:43
  • I understand K Scott Piel. So I can tell you I achieved everything but casting int to char array. Can you please help me? :) – Bodosko May 07 '13 at 22:47
  • Also, why the second code I posted isnt compiling? – Bodosko May 07 '13 at 23:11
  • possible duplicate of [Convert integer to string without access to libraries](http://stackoverflow.com/questions/3982320/convert-integer-to-string-without-access-to-libraries). This is the #4 hit for itoa on SO. Surprised you missed it. – Raymond Chen May 07 '13 at 23:24

6 Answers6

11

Of course it's not possible, because an array is an object and needs storage. Casts result in values, not objects. Some would say the whole point/power of C is that you have control over the storage and lifetime of objects.

The proper way to generate a string containing a decimal representation of an integer is to create storage for it yourself and use snprintf:

char buf[sizeof(int)*3+2];
snprintf(buf, sizeof buf, "%d", n);
R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
5

You have to convert 500 to "500".

"500" is the same as '5' then '0' then '0' then 0. The last element 0 is the null terminator of a string.

500 is equal to 5 * 100 + 0 * 10 + 0 * 1. You have to do some math here. Basically you have to use the / operator.

Then this could be also useful: '5' is the same as '0' + 5.

ouah
  • 142,963
  • 15
  • 272
  • 331
  • 1
    But that way I wouldnt use casting. I can imagine many ways of doing what I need, but any of them involves casting, and I have no idea even if its possible. – Bodosko May 07 '13 at 23:01
  • 1
    The requirement that you use casting is not practical. It's like telling somebody they have to solve a problem with a calculator when they already did it in their head. Just solve it without casting. (Stick a dummy cast if you must. Like typing 1+1= into the calculator.) – Raymond Chen May 07 '13 at 23:35
2

Without giving away an exact coded answer, what you'll want to do is loop through each digit of the integer (by computing its remainder modulo 10 via the % operator), and then add its value to the ASCII value of '0', casting the result back to a char, and placing that result in a null-terminated string.

An example which pretends like implicit casts don't exist might look like this:

char c = (char) ( ((int) '0') + 5 ); // c should now be '5'.

You can determine the length of the resulting string by computing the log base 10 of the number, or by simply allocating it dynamically as you go using realloc().

CmdrMoozy
  • 3,870
  • 3
  • 19
  • 31
2

Casting is a horrible way to do this due to endianness, but here is an example anyhow - there are some occasions where it is useful (unions work better these days though, due to compiler handling of these types of casts).

#include <stdio.h> //for printf 
#define INT(x) ((int*)(x)) //these are not endian-safe methods
#define CHAR(x) ((char*)(x))
int main(void)
{
    int *x=INT(&"HI !");
    printf("%X\n",*x); //look up the ascii and note the order
    printf("%s\n",CHAR(x));
    return 0;
}

For an int with a value <500, if the most significant byte comes first, then you get a "string" (pointer to a char array) of "" (or {0}) but if the endianness is LSB first (x86 is little endian) then you would get a usable 3 byte "string" char* (not necessarily human readable characters) but there is no guarantee that there will be a zero byte in an integer and since all you have is a pointer to the address where the int was stored, if you were to run normal string functions on it, they would go past the end of the original int into no-mans-land (in small test programs it will often be environment variables) ... anyhow for more portability you can use network byte order (which for little endian is a no-op):

#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

These functions just byteswap as necessary to get network byte order. On your x86 they will be optimized away, so you might as well use them for portability.

technosaurus
  • 7,676
  • 1
  • 30
  • 52
1

Just because it is not listed yet: Here a way to convert int to char array with variable size allocation by using snprintf:

int value = 5

// this will just output the length which is to expect
int length = snprintf( NULL, 0, "%d", value );

char* valueAsString = malloc( length + 1 );// one more for 0-terminator
snprintf( valueAsString, length + 1, "%d", value );
Alex
  • 1,602
  • 20
  • 33
0

get the number of divisions then add one by one to your buffer

char *int2str(int nb) {
    int i = 0;
    int div = 1;
    int cmp = nb;
    char *nbr = malloc(sizeof(char) * 12);

    if (!nbr)
        return (NULL);
    if (nb < 0)
        nbr[i++] = '-';
    while ((cmp /= 10) != 0)
        div = div * 10;
    while (div > 0) {
        nbr[i++] = abs(nb / div) + 48;
        nb = nb % div;
        div /= 10;
    }
    nbr[i] = '\0';
    return (nbr);
}

Even more compact:

char *lotaa(long long nb) {
    int size = (nb ? floor(log10(llabs(nb))) : 0) + (nb >= 0 ? 1 : 2);
    char *str = malloc(size + 1);

    str[0] = '-';
    str[size] = 0;
    for(nb = llabs(nb); nb > 0 || (size > 0 && str[1] == 0); nb /= 10)
        str[--size] = '0' + nb % 10;
    return (str);
}
Locoder
  • 22
  • 1
  • 4