Wie konvertiere ich von int nach char *?

97

Ich weiß nur:

#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();
}

Aber gibt es eine Methode mit weniger Eingabe?

rsk82
quelle
8
Warum möchten Sie einen C-String anstelle eines C ++ - Strings?
KillianDS
1
benutze sprintf
Kasma

Antworten:

127
  • Verwenden Sie in C ++ 17 Folgendes std::to_chars:

    std::array<char, 10> str;
    std::to_chars(str.data(), str.data() + str.size(), 42);
  • Verwenden Sie in C ++ 11 Folgendes std::to_string:

    std::string s = std::to_string(number);
    char const *pchar = s.c_str();  //use char const* as target type
  • Und in C ++ 03 ist das, was Sie tun, in Ordnung, außer constals:

    char const* pchar = temp_str.c_str(); //dont use cast
Nawaz
quelle
1
Der erste Teil beantwortet die Frage nicht wirklich (obwohl es gute hilfreiche Informationen sind, da mir diese Funktion nicht bekannt war)
jcoder
1
Besser :) Außerdem lese ich besser noch einmal mehr über c ++ 11. Ich kenne die großen Funktionen, aber dadurch wurde mir klar, dass es wahrscheinlich mehr kleine gibt, die ich verpasst habe.
Jcoder
1
@Adambean: Warum sollte es "nicht std :: string beinhalten"? . Man sollte std::stringstandardmäßig anstelle von verwenden char*.
Nawaz
1
std :: string ist nicht immer verfügbar, insbesondere für ältere Projekte. Viele C ++ - Spiele halten sich auch immer noch von std :: string fern. Der Wechsel von int zu std :: string zu char * ist nicht dasselbe wie int zu char *.
Adambean
1
@Adambean: Wenn es C ++ ist, gehe ich davon aus std::string, dass es standardmäßig verfügbar ist, es sei denn, es ist in der Frage selbst explizit angegeben. Macht Sinn? Da die Frage selbst std::string(und std::stringstream) verwendet, haben Sie nicht viel Grund, damit nicht einverstanden zu sein.
Nawaz
11

Ich denke, Sie können einen Sprintf verwenden:

int number = 33;
char* numberstring[(((sizeof number) * CHAR_BIT) + 2)/3 + 2];
sprintf(numberstring, "%d", number);
Pierre Pellegrino Milza
quelle
1
Sie sollten char * in char ändern, im Moment ist numberstring ein Array von Zeigern
josefx
1
Außerdem benötigen Sie 12 Zeichen, um eine 32-Bit-Ganzzahl in eine nicht terminierte Basis-10-Darstellung umzuwandeln. 10 ist nicht genug für -2147483647.
Steve Jessop
11
Wie wäre es mit einer Erklärung? (((sizeof number) * CHAR_BIT) + 2)/3 + 2sieht aus wie Zauberei ...
Mike S
7

Sie können Boost verwenden

#include <boost/lexical_cast.hpp>
string s = boost::lexical_cast<string>( number );
maverik
quelle
5

Eine Lösung im C-Stil könnte die Verwendung sein itoa, aber besser ist es, diese Zahl mit sprintf/snprintf in eine Zeichenfolge zu drucken . Überprüfen Sie diese Frage: Wie konvertiere ich eine Ganzzahl portabel in eine Zeichenfolge?

Beachten Sie, dass die itoaFunktion nicht in ANSI-C definiert ist und nicht Teil von C ++ ist, sondern von einigen Compilern unterstützt wird. Es ist eine nicht standardmäßige Funktion, daher sollten Sie sie nicht verwenden. Überprüfen Sie auch diese Frage: Alternative zu itoa () zum Konvertieren von Ganzzahlen in Zeichenfolgen C ++?

Beachten Sie auch, dass das Schreiben von Code im C-Stil während des Programmierens in C ++ als schlechte Praxis angesehen wird und manchmal als "grässlicher Stil" bezeichnet wird. Möchten Sie es wirklich in eine char*Zeichenfolge im C-Stil konvertieren ? :) :)

LihO
quelle
5

Ich würde die Konstante in der letzten Zeile nicht wegschreiben, da sie aus einem bestimmten Grund vorhanden ist. Wenn Sie nicht mit einem const char * leben können, kopieren Sie das char-Array besser wie folgt:

char* char_type = new char[temp_str.length()];
strcpy(char_type, temp_str.c_str());
user331471
quelle
du meinst const char* char_type = temp_str.c_str();ist besser
rsk82
1
Ja. c_str gibt Ihnen einen Zeiger auf den internen Puffer des String-Objekts. Wenn Sie die Konstante wegwerfen, könnten Sie oder ein anderer Programmierer denken, dass es in Ordnung ist, den Puffer über die Variable ohne Konstante zu ändern. Aber es ist nicht. Das ursprüngliche Zeichenfolgenobjekt weiß nichts über diese Änderungen. Andererseits besitzt der String immer noch den Puffer. Wenn das Zeichenfolgenobjekt den Gültigkeitsbereich verlässt, wird der Speicher hinter dem Zeiger durch den Destruktor der Zeichenfolgenobjekte gelöscht, sodass Sie einen baumelnden Zeiger erhalten. Der Kopiervorgang behebt beide Probleme.
user331471
1
Alternativ std::vector<char> temp_vec(temp_str.begin(), temp_str.end()); temp_vec.push_back(0); char *char_type = &vec[0];. Dies gibt Ihnen veränderlichen Speicher, obwohl Sie den Vektor natürlich noch so lange am Leben halten müssen, wie Sie den Zeiger verwenden möchten.
Steve Jessop
1
Oder verwenden Sie einfach stringund char *
kümmern
@Griwes: Die Frage ist, wie man dahin kommt char*, nicht "gibt es irgendeinen Grund , von C ++ in vorhandene Bibliotheken aufzurufen, die in C geschrieben sind, oder sollte ich sie in C ++ erneut implementieren?" ;-p
Steve Jessop
2

Okay ... zuerst brauchte ich etwas, das das tat, was diese Frage stellt, aber ich brauchte es SCHNELL! Leider ist der "bessere" Weg fast 600 Codezeilen !!! Verzeihen Sie den Namen, der nichts mit dem zu tun hat, was er tut. Der richtige Name war Integer64ToCharArray (int64_t-Wert);

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

Versuchen Sie, diesen Code zu bereinigen, ohne die Leistung zu beeinträchtigen.

Eingabe: Beliebiger vorzeichenbehafteter 64-Bit-Wert vom Min- bis Max-Bereich.

Beispiel:

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

Ausgabe:

Test: 9223372036854775807
Test: -9223372036854775808

Ursprüngliche Geschwindigkeitstests: ( Integer64ToCharArray (); )

Bester Fall 1-stelliger Wert.

Schleifen: 100.000.000, Zeitaufwand: 1.381 (Milli), Zeit pro Schleife 13 (Nano)

Schlimmer Fall 20-stelliger Wert.

Schleifen: 100.000.000, Zeitaufwand: 22.656 (Milli), Zeit pro Schleife 226 (Nano

Neue Entwurfsgeschwindigkeitstests: ( AddDynamicallyToBuffer (); )

Bester Fall 1-stelliger Wert.

Schleifen: 100.000.000, Zeitaufwand: 427 (Milli), Zeit pro Schleife 4 (Nano)

32 Bit Worst Case - 11-stelliger Wert.

Schleifen: 100.000.000, Zeitaufwand: 1.991 (Milli), Zeit pro Schleife 19 (Nano)

Negativ 1 Billion Worst Case - 14-stelliger Wert.

Schleifen: 100.000.000, Zeitaufwand: 5.681 (Milli), Zeit pro Schleife 56 (Nano)

64-Bit-Worse-Case - 20-stelliger Wert.

Schleifen: 100.000.000, Zeitaufwand: 13.148 (Milli), Zeit pro Schleife 131 (Nano)

Wie es funktioniert!

Wir führen eine Divide and Conquer-Technik durch und sobald wir nun die maximale Länge der Zeichenfolge erreicht haben, setzen wir einfach jeden Zeichenwert einzeln. Wie in den obigen Geschwindigkeitstests gezeigt, erhalten die größeren Längen große Leistungseinbußen, aber es ist immer noch viel schneller als die ursprüngliche Schleifenmethode, und zwischen den beiden Methoden hat sich kein Code geändert, außer dass die Schleife nicht mehr verwendet wird.

In meiner Verwendung, daher der Name, gebe ich stattdessen den Offset zurück und bearbeite keinen Puffer mit Zeichenarrays. Stattdessen beginne ich mit der Aktualisierung der Scheitelpunktdaten. Die Funktion verfügt über einen zusätzlichen Parameter für den Offset, sodass dieser nicht auf -1 initialisiert wird.

Jeremy Trifilo
quelle
0

Sie können auch Casting verwenden.

Beispiel:

string s;
int value = 3;
s.push_back((char)('0' + value));
elmaystro
quelle
1
Was ist, wenn der Wert negativ ist oder keine Ziffer?
Ziya ERKOC