jak przekonwertować z int na char *?

98

Jedyny sposób, jaki znam, to:

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

Ale czy jest jakaś metoda wymagająca mniej pisania?

rsk82
źródło
8
dlaczego chcesz, aby łańcuch C zamiast ciągu C ++?
KillianDS
1
użyj sprintf
Kasma

Odpowiedzi:

128
  • W C ++ 17 użyj std::to_charsjako:

    std::array<char, 10> str;
    std::to_chars(str.data(), str.data() + str.size(), 42);
  • W C ++ 11 użyj std::to_stringjako:

    std::string s = std::to_string(number);
    char const *pchar = s.c_str();  //use char const* as target type
  • A w C ++ 03 to, co robisz, jest w porządku, z wyjątkiem używania constjako:

    char const* pchar = temp_str.c_str(); //dont use cast
Nawaz
źródło
1
Pierwsza część właściwie nie odpowiada na pytanie (chociaż jest to dobra pomocna informacja, ponieważ nie byłem świadomy tej funkcji)
jcoder
1
Lepiej :) Plus lepiej jeszcze raz poczytać więcej o c ++ 11. Wiem o dużych funkcjach, ale to uświadomiło mi, że prawdopodobnie brakuje mi większej liczby małych.
jcoder
1
@Adambean: Dlaczego „nie powinno obejmować std :: string”? . Należy używać std::stringdomyślnie zamiast char*.
Nawaz
1
std :: string nie zawsze jest dostępne, szczególnie w starszych projektach. Wiele gier w C ++ wciąż trzyma się z dala od std :: string. Przejście z int do std :: string do char * nie jest tym samym, co int do char *.
Adambean,
1
@Adambean: Jeśli jest to C ++, założę, że std::stringjest dostępny domyślnie, chyba że jest to wyraźnie określone w samym pytaniu. Ma sens? Ponadto, ponieważ samo pytanie używa std::string(i std::stringstream), nie masz zbyt wielu powodów, aby się z nim nie zgadzać.
Nawaz
11

Myślę, że możesz użyć sprinta:

int number = 33;
char* numberstring[(((sizeof number) * CHAR_BIT) + 2)/3 + 2];
sprintf(numberstring, "%d", number);
Pierre Pellegrino Milza
źródło
1
powinieneś zmienić char * na char, w tej chwili numberstring to tablica wskaźników
josefx
1
Ponadto potrzeba 12 znaków, aby przekonwertować 32-bitową liczbę całkowitą na reprezentację dziesiętną zakończoną znakiem nul. 10 nie wystarczy -2147483647.
Steve Jessop
11
Może jakieś wyjaśnienie? (((sizeof number) * CHAR_BIT) + 2)/3 + 2wygląda jak magia ...
Mike S
7

Możesz użyć doładowania

#include <boost/lexical_cast.hpp>
string s = boost::lexical_cast<string>( number );
maverik
źródło
5

Przydałoby się rozwiązanie w stylu C itoa, ale lepszym sposobem jest wydrukowanie tej liczby w łańcuchu za pomocą sprintf/snprintf . Sprawdź to pytanie: Jak przenośnie przekonwertować liczbę całkowitą na ciąg?

Zauważ, że itoafunkcja nie jest zdefiniowana w ANSI-C i nie jest częścią C ++, ale jest obsługiwana przez niektóre kompilatory. Jest to funkcja niestandardowa, dlatego należy jej unikać. Sprawdź też to pytanie: Alternatywa dla itoa () do konwersji liczby całkowitej na łańcuch C ++?

Należy również zauważyć, że pisanie kodu w stylu C podczas programowania w C ++ jest uważane za złą praktykę i czasami nazywane jest „upiornym stylem”. Czy na pewno chcesz przekształcić go w char*napis w stylu C ? :)

LihO
źródło
5

Nie zapisałbym stałej w ostatnim wierszu, ponieważ jest tam z jakiegoś powodu. Jeśli nie możesz żyć z const char *, lepiej skopiuj tablicę char, na przykład:

char* char_type = new char[temp_str.length()];
strcpy(char_type, temp_str.c_str());
user331471
źródło
masz na myśli const char* char_type = temp_str.c_str();lepsze?
rsk82
1
Tak. c_str daje wskaźnik do wewnętrznego bufora obiektu ciągu. Jeśli odrzucisz stałą, Ty lub inny programista możecie pomyśleć, że można zmienić bufor za pomocą zmiennej innej niż stała. Ale to nie jest. Oryginalny obiekt string nie wie nic o tych zmianach. Z drugiej strony łańcuch nadal jest właścicielem bufora. Jeśli obiekt ciągu znaków znajdzie się poza zakresem, pamięć za wskaźnikiem jest usuwana przez destruktor obiektów łańcuchowych, pozostawiając wiszący wskaźnik. Operacja kopiowania usuwa oba problemy.
user331471
1
Alternatywnie std::vector<char> temp_vec(temp_str.begin(), temp_str.end()); temp_vec.push_back(0); char *char_type = &vec[0];. Daje to zmienną pamięć, chociaż oczywiście nadal musisz utrzymywać wektor przy życiu tak długo, jak chcesz używać wskaźnika.
Steve Jessop
1
Lub po prostu użyj stringi nie przejmuj się starym, prostym, głupim char *ze starego, zwykłego C. <zamierzone kawałki ognia>
Griwes
@Griwes: pytanie brzmi, jak się do tego dostać char*, a nie „czy jest jakiś sens wywoływać z C ++ do istniejących bibliotek napisanych w C, czy powinienem ponownie zaimplementować je w C ++?” ;-p
Steve Jessop
2

W porządku… po pierwsze potrzebowałem czegoś, co spełniło to pytanie, ale potrzebowałem tego SZYBKO! Niestety „lepszym” sposobem jest prawie 600 linii kodu !!! Wybaczcie nazwę tego, która nie ma nic wspólnego z tym, co robi. Właściwa nazwa to Integer64ToCharArray (wartość int64_t);

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

Możesz spróbować wyczyścić ten kod bez obniżania wydajności.

Wejście: Dowolna wartość 64-bitowa ze znakiem od minimalnego do maksymalnego zakresu.

Przykład:

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

Wynik:

Test: 9223372036854775807
Test: -9223372036854775808

Oryginalne testy prędkości: ( Integer64ToCharArray (); )

Wartość jednocyfrowa w najlepszym przypadku.

Pętle: 100 000 000, spędzony czas: 1381 (mili), czas na pętlę 13 (Nano)

Gorsza 20-cyfrowa wartość przypadku.

Pętle: 100 000 000, spędzony czas: 22 656 (mili), czas na pętlę 226 (Nano

Nowe testy szybkości projektowania: ( AddDynamicallyToBuffer (); )

Wartość jednocyfrowa w najlepszym przypadku.

Pętle: 100 000 000, spędzony czas: 427 (mili), czas na pętlę 4 (Nano)

Najgorszy przypadek 32-bitowy - 11-cyfrowa wartość.

Pętle: 100 000 000, spędzony czas: 1 991 (mili), czas na pętlę 19 (Nano)

Ujemny 1 bilion Najgorszy przypadek - 14-cyfrowa wartość.

Pętle: 100 000 000, spędzony czas: 5681 (mili), czas na pętlę 56 (nano)

64-bitowy gorszy przypadek - wartość 20 cyfr.

Pętle: 100 000 000, spędzony czas: 13 148 (mili), czas na pętlę 131 (Nano)

Jak to działa!

Wykonujemy technikę dzielenia i zwyciężania i po ustaleniu maksymalnej długości ciągu po prostu ustawiamy każdą wartość znaku indywidualnie. Jak pokazano w powyższych testach szybkości, większe długości powodują duże kary za wydajność, ale nadal jest znacznie szybsza niż oryginalna metoda pętli i żaden kod nie zmienił się między tymi dwiema metodami, a pętla nie jest już używana.

W moim użyciu stąd nazwa, zamiast tego zwracam przesunięcie i nie edytuję buforu tablic char, raczej zaczynam aktualizować dane wierzchołków, a funkcja ma dodatkowy parametr przesunięcia, więc nie jest zainicjowana na -1.

Jeremy Trifilo
źródło
0

Możesz także użyć przesyłania.

przykład:

string s;
int value = 3;
s.push_back((char)('0' + value));
elmaystro
źródło
2
Co się stanie, jeśli wartość jest ujemna lub nie jest cyfrą?
Ziya ERKOC