Est-il possible de convertir int en "chaîne" en C en utilisant simplement le casting? Sans fonctions telles que atoi()
ou sprintf()
?
Ce que je veux serait comme ça:
int main(int argc, char *argv[]) {
int i = 500;
char c[4];
c = (char)i;
i = 0;
i = (int)c;
}
La raison en est que je dois générer deux entiers aléatoires (0 à 500) et les envoyer sous la forme d'une chaîne dans une file d'attente de messages à un autre processus. L'autre processus reçoit le message et fait le LCM.
Je sais comment faire avec atoi()
et itoa()
. Mais mes professeurs veulent juste utiliser le casting.
Aussi, pourquoi les éléments suivants ne sont-ils pas possibles à compiler?
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;
}
Bien sûr, ce n'est pas possible, car un tableau est un objet et a besoin de storage . Les conversions résultent en valeurs , pas objets . Certains diraient que l’intérêt principal de C est que vous avez le contrôle sur le stockage et la durée de vie des objets.
La manière appropriée de générer une chaîne contenant une représentation décimale d'un entier est de créer le stockage pour elle-même et d'utiliser snprintf
:
char buf[sizeof(int)*3+2];
snprintf(buf, sizeof buf, "%d", n);
Vous devez convertir 500
en "500"
.
"500"
est le même que '5'
puis '0'
puis '0'
puis 0
. Le dernier élément 0
est le terminateur nul d'une chaîne.
500
est égal à 5 * 100 + 0 * 10 + 0 * 1
. Vous devez faire des calculs ici. En gros, vous devez utiliser l'opérateur /
.
Cela pourrait alors aussi être utile: '5'
est identique à '0' + 5
.
Le casting est une façon horrible de le faire pour des raisons d’endianisme, mais voici un exemple: il ya quelques occasions où cela est utile (les syndicats fonctionnent mieux de nos jours cependant, en raison de la gestion par ce compilateur de ce type de casting).
#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;
}
Pour un int avec une valeur <500, si l'octet le plus significatif vient en premier, alors vous obtenez un "chaîne" (pointeur sur un tableau de caractères) de "" (ou {0}), mais si endianness est d'abord LSB (x86 est un petit endian), vous obtiendrez un octet utilisable de 3 "chaîne" char * (pas nécessairement des caractères lisibles par l'homme) mais il n'y a aucune garantie qu'il y ait un octet égal à zéro dans un entier, et comme tout ce que vous avez est un pointeur sur l'adresse où le int a été stocké, si vous exécutiez des fonctions de chaîne normales sur sinon, ils iraient au-delà de la fin de l’int d'origine dans no-mans-land (dans les petits programmes de test, il s'agira souvent de variables d'environnement) ... de toute façon, pour plus de portabilité, vous pouvez utiliser l'ordre des octets du réseau (qui pour little endian est un non 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);
Ces fonctions ne font que byteswap si nécessaire pour obtenir l'ordre des octets du réseau. Sur votre x86, ils seront optimisés, vous pouvez donc aussi bien les utiliser pour la portabilité.
Sans donner de réponse codée exacte, ce que vous voudrez faire est de parcourir en boucle chaque chiffre de l'entier (en calculant son reste modulo 10 via l'opérateur%), puis d'ajouter sa valeur à la valeur ASCII de '0', en renvoyant le résultat à un caractère et en plaçant ce résultat dans une chaîne terminée par un zéro.
Un exemple prétendant que les conversions implicites n'existent pas pourrait ressembler à ceci:
char c = (char) ( ((int) '0') + 5 ); // c should now be '5'.
Vous pouvez déterminer la longueur de la chaîne résultante en calculant la base de journal 10 du nombre ou en l’allouant simplement de manière dynamique au fur et à mesure de l'utilisation de realloc ().
Juste parce qu’elle n’est pas encore listée: Voici un moyen de convertir int en tableau de caractères avec allocation de taille variable en utilisant 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 );