comment convertir de int en char *?

98

Le seul moyen que je connaisse est:

#include <sstream>
#include <string.h>
using namespace std;

int main() {
  int number=33;
  stringstream strs;
  strs << number;
  string temp_str = strs.str();
  char* char_type = (char*) temp_str.c_str();
}

Mais existe-t-il une méthode avec moins de frappe?

rsk82
la source
8
pourquoi voulez-vous une chaîne C au lieu d'une chaîne C ++?
KillianDS
1
use sprintf
Kasma

Réponses:

128
  • Dans C ++ 17, utilisez std::to_charscomme:

    std::array<char, 10> str;
    std::to_chars(str.data(), str.data() + str.size(), 42);
  • Dans C ++ 11, utilisez std::to_stringcomme:

    std::string s = std::to_string(number);
    char const *pchar = s.c_str();  //use char const* as target type
  • Et en C ++ 03, ce que vous faites est très bien, sauf à utiliser constcomme:

    char const* pchar = temp_str.c_str(); //dont use cast
Nawaz
la source
1
La première partie ne répond pas réellement à la question (bien que ce soit une bonne information utile car je n'étais pas au courant de cette fonction)
jcoder
1
Mieux :) De plus, je ferais mieux de lire à nouveau plus sur c ++ 11. Je connais les grandes fonctionnalités, mais cela m'a fait réaliser qu'il y en a probablement d'autres petites que j'ai manquées.
jcoder
1
@Adambean: Pourquoi "ne devrait pas impliquer std :: string"? . On devrait utiliser std::stringpar défaut au lieu de char*.
Nawaz
1
std :: string n'est pas toujours disponible, en particulier pour les projets plus anciens. De nombreux jeux C ++ restent également à l'écart de std :: string. Passer de int à std :: string à char * n'est pas la même chose que int à char *.
Adambean
1
@Adambean: Si c'est C ++, alors je vais supposer qu'il std::stringest disponible par défaut, à moins qu'il ne soit explicitement spécifié dans la question elle-même. Logique? De plus, puisque la question elle-même utilise std::string(et std::stringstream), vous n'avez pas beaucoup de raisons d'être en désaccord avec elle.
Nawaz le
11

Je pense que vous pouvez utiliser un sprintf:

int number = 33;
char* numberstring[(((sizeof number) * CHAR_BIT) + 2)/3 + 2];
sprintf(numberstring, "%d", number);
Pierre Pellegrino Milza
la source
1
vous devriez changer char * en char, pour le moment numberstring est un tableau de pointeurs
josefx
1
En outre, vous avez besoin de 12 caractères pour convertir un entier 32 bits en une représentation en base 10 terminée par un nul. 10 ne suffit pas pour -2147483647.
Steve Jessop
11
Que diriez-vous d'une explication? (((sizeof number) * CHAR_BIT) + 2)/3 + 2ressemble à de la magie ...
Mike S
7

Vous pouvez utiliser boost

#include <boost/lexical_cast.hpp>
string s = boost::lexical_cast<string>( number );
Maverik
la source
5

Une solution de style C pourrait être à utiliser itoa, mais le meilleur moyen est d'imprimer ce nombre dans une chaîne en utilisant sprintf/snprintf . Vérifiez cette question: Comment convertir un entier en chaîne de manière portative?

Notez que la itoafonction n'est pas définie dans ANSI-C et ne fait pas partie de C ++, mais est prise en charge par certains compilateurs. C'est une fonction non standard, vous devriez donc éviter de l'utiliser. Vérifiez également cette question: Alternative à itoa () pour convertir un entier en chaîne C ++?

Notez également que l'écriture de code de style C pendant la programmation en C ++ est considérée comme une mauvaise pratique et parfois appelée "style horrible". Voulez-vous vraiment le convertir en char*chaîne de style C ? :)

LihO
la source
5

Je ne taperais pas le const dans la dernière ligne car il est là pour une raison. Si vous ne pouvez pas vivre avec un char const *, vous feriez mieux de copier le tableau char comme:

char* char_type = new char[temp_str.length()];
strcpy(char_type, temp_str.c_str());
user331471
la source
tu veux dire que const char* char_type = temp_str.c_str();c'est mieux?
rsk82
1
Oui. c_str vous donne un pointeur vers le tampon interne de l'objet string. Si vous rejetez le const, vous ou un autre programmeur pourriez penser qu'il est correct de changer le tampon via la variable non-const. Mais ce n'est pas. L'objet chaîne d'origine ne sait rien de ces modifications. D'un autre côté, la chaîne possède toujours le tampon. Si l'objet chaîne est hors de portée, la mémoire derrière le pointeur est supprimée par le destructeur d'objets chaîne, vous laissant avec un pointeur suspendu. L'opération de copie supprime les deux problèmes.
user331471
1
Vous pouvez également std::vector<char> temp_vec(temp_str.begin(), temp_str.end()); temp_vec.push_back(0); char *char_type = &vec[0];. Cela vous donne une mémoire modifiable, bien que vous deviez bien sûr garder le vecteur en vie aussi longtemps que vous souhaitez utiliser le pointeur.
Steve Jessop
1
Ou utilisez simplement stringet ne vous embêtez pas avec de vieux, simples, stupides char *de vieux, simples C. <bits de flamme prévus>
Griwes
@Griwes: la question est de savoir comment y arriver char*, et non "y a-t-il un intérêt à appeler de C ++ dans des bibliothèques existantes écrites en C, ou dois-je les réimplémenter en C ++?" ;-p
Steve Jessop
2

Très bien .. d'abord j'avais besoin de quelque chose qui fasse ce que cette question demande, mais j'en avais besoin RAPIDEMENT! Malheureusement, la "meilleure" façon est de près de 600 lignes de code !!! Pardonnez-lui le nom qui n'a rien à voir avec ce qu'il fait. Le nom propre était Integer64ToCharArray (valeur int64_t);

https://github.com/JeremyDX/All-Language-Testing-Code/blob/master/C%2B%2B%20Examples/IntegerToCharArrayTesting.cpp

N'hésitez pas à essayer de nettoyer ce code sans nuire aux performances.

Entrée: toute valeur 64 bits signée de la plage minimale à la plage maximale.

Exemple:

std::cout << "Test: " << AddDynamicallyToBuffer(LLONG_MAX) << '\n';
std::cout << "Test: " << AddDynamicallyToBuffer(LLONG_MIN) << '\n';

Production:

Test: 9223372036854775807
Test: -9223372036854775808

Tests de vitesse d'origine: ( Integer64ToCharArray (); )

Meilleur cas, valeur à 1 chiffre.

Boucles: 100000000, temps passé: 1381 (milli), temps par boucle 13 (nano)

Dans le pire des cas, valeur à 20 chiffres.

Boucles: 100 000 000, temps passé: 22 656 (milli), temps par boucle 226 (nano

Nouveaux tests de vitesse de conception: ( AddDynamicallyToBuffer (); )

Meilleur cas, valeur à 1 chiffre.

Boucles: 100 000 000, temps passé: 427 (milli), temps par boucle 4 (nano)

Pire cas 32 bits - Valeur à 11 chiffres.

Boucles: 100000000, temps passé: 1991 (milli), temps par boucle 19 (nano)

Pire cas négatif de 1 billion de dollars - Valeur à 14 chiffres.

Boucles: 100000000, temps passé: 5681 (milli), temps par boucle 56 (nano)

Cas pire de 64 bits - Valeur de 20 chiffres.

Boucles: 100 000 000, temps passé: 13 148 (milli), temps par boucle 131 (nano)

Comment ça fonctionne!

Nous effectuons une technique Divide and Conquer et une fois que nous avons maintenant la longueur maximale de la chaîne, nous définissons simplement chaque valeur de caractère individuellement. Comme indiqué dans les tests de vitesse ci-dessus, les plus grandes longueurs entraînent de lourdes pénalités de performances, mais c'est toujours beaucoup plus rapide que la méthode de boucle d'origine et aucun code n'a réellement changé entre les deux méthodes, à part la boucle n'est plus utilisée.

Dans mon utilisation, d'où le nom, je renvoie le décalage à la place et je ne modifie pas un tampon de tableaux de caractères plutôt que je commence à mettre à jour les données de sommet et la fonction a un paramètre supplémentaire pour le décalage afin qu'il ne soit pas initialisé à -1.

Jérémy Trifilo
la source
0

Vous pouvez également utiliser la diffusion.

exemple:

string s;
int value = 3;
s.push_back((char)('0' + value));
elmaystro
la source
2
Et si la valeur est négative ou pas un chiffre?
Ziya ERKOC