int'den char *'e nasıl dönüştüğü


99

Tek bildiğim yol:

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

Ancak daha az yazarak herhangi bir yöntem var mı?


8
C ++ dizesi yerine neden bir C-dizesi istiyorsun?
KillianDS

1
Kullanım sprintf
Ashish Kasma

Yanıtlar:


133
  • C ++ 17'de şu şekilde kullanın std::to_chars:

    std::array<char, 10> str;
    std::to_chars(str.data(), str.data() + str.size(), 42);
    
  • C ++ 11'de şu şekilde kullanın std::to_string:

    std::string s = std::to_string(number);
    char const *pchar = s.c_str();  //use char const* as target type
    
  • Ve C ++ 03'te, şu şekilde kullanmak dışında yaptığınız şey gayet iyi const:

    char const* pchar = temp_str.c_str(); //dont use cast
    

1
(İyi yararlı bilgiler olmasına rağmen ben bu işlev farkında değildi gibi) ilk bölümü aslında soruya cevap vermez
JCODER

1
Daha iyi :) Ayrıca gidip c ++ 11 hakkında daha fazla bilgi alsam iyi olur. Büyük özellikleri biliyorum ama bu, kaçırdığım muhtemelen daha küçük özellikler olduğunu fark etmemi sağladı.
jcoder

1
@Adambean: Neden "std :: string içermemeli"? . Bunun std::stringyerine varsayılan olarak kullanılmalıdır char*.
Nawaz

1
std :: string, özellikle eski projelerde her zaman kullanılamaz. Pek çok C ++ oyunu da std :: string'den uzak durur. İnt'ten std :: string'den char * 'a gitmek, int'ten char *' e gitmek aynı değildir.
Adambean

1
@Adambean: C ++ std::stringise, sorunun kendisinde açıkça belirtilmediği sürece varsayılan olarak kullanılabilir olduğunu varsayacağım . Mantıklı? Ayrıca, sorunun kendisi std::string(ve std::stringstream) kullandığı için , o zaman buna katılmamak için fazla nedeniniz yok.
Nawaz

12

Bir sprintf kullanabileceğinizi düşünüyorum:

int number = 33;
char* numberstring[(((sizeof number) * CHAR_BIT) + 2)/3 + 2];
sprintf(numberstring, "%d", number);

1
Şu anda işaretçiler bir dizidir NumberString, char char * değiştirmelisiniz
josefx

1
Ayrıca, 32 bitlik bir tamsayıyı sıfır sonlu taban 10 gösterimine dönüştürmek için 12 karaktere ihtiyacınız vardır. 10 için yeterli değil -2147483647.
Steve Jessop

12
Biraz açıklamaya ne dersin? (((sizeof number) * CHAR_BIT) + 2)/3 + 2büyücülük gibi görünüyor ...
Mike S

7

Boost kullanabilirsin

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

5

C tarzı çözüm kullanmak olabilir itoa, ancak daha iyi bir yol, sprintf/snprintf kullanarak bu sayıyı dizeye yazdırmaktır . Şu soruyu kontrol edin: Bir tamsayıyı taşınabilir bir şekilde dizeye nasıl dönüştürebilirim?

Bu Not itoafonksiyonu ANSI-C tanımlanmayan ve C ++ bir parçası değildir, ama bazı derleyici tarafından destekleniyor. Bu standart olmayan bir işlevdir, bu nedenle kullanmaktan kaçınmalısınız. Şu soruyu da kontrol edin: Tamsayıyı C ++ dizesine dönüştürmek için itoa () 'ya alternatif mi?

Ayrıca, C ++ ile programlama sırasında C tarzı kod yazmanın kötü bir uygulama olarak kabul edildiğini ve bazen "korkunç stil" olarak adlandırıldığını unutmayın. Onu gerçekten C tarzı char*dizeye dönüştürmek istiyor musunuz ? :)


5

Bir nedenden ötürü orada olduğu için son satırdaki const'ı yazmam. Bir const char * ile yaşayamıyorsanız, char dizisini aşağıdaki gibi kopyalamanız iyi olur:

char* char_type = new char[temp_str.length()];
strcpy(char_type, temp_str.c_str());

const char* char_type = temp_str.c_str();daha iyi mi demek istiyorsun ?
rsk82

1
Evet. c_str size dizge nesnesinin dahili arabelleğine bir işaretçi verir. Eğer const'ı atarsanız, siz veya başka bir programcı, arabelleği const olmayan değişkenle değiştirmenin uygun olduğunu düşünebilir. Ama öyle değil. Orijinal dize nesnesi bu değişiklikler hakkında hiçbir şey bilmiyor. Öte yandan, dizge hala tamponun sahibidir. Dizge nesnesi kapsam dışına çıkarsa, işaretçinin arkasındaki bellek dizi nesneleri yıkıcı tarafından silinerek sizi sarkan bir işaretçi ile bırakır. Kopyalama işlemi her iki sorunu da ortadan kaldırır.
user331471

1
Alternatif olarak std::vector<char> temp_vec(temp_str.begin(), temp_str.end()); temp_vec.push_back(0); char *char_type = &vec[0];,. İmleci kullanmak istediğiniz sürece vektörü canlı tutmanız gerekse de, bu size değiştirilebilir bellek sağlar.
Steve Jessop

1
Ya da sadece kullanın stringve eski, sade, eski, aptal char *C ile uğraşmayın . <Alev parçaları amaçlandı>
Griwes

@Griwes: Soru, char*"C ++ 'dan C ile yazılmış mevcut kitaplıklara çağrı yapan herhangi bir nokta var mı , yoksa bunları C ++' da yeniden uygulamalı mıyım?" ;-p
Steve Jessop


2

Pekala .. öncelikle bu sorunun sorduğu şeyi yapacak bir şeye ihtiyacım vardı, ama HIZLI ihtiyacım vardı! Ne yazık ki "daha iyi" yol yaklaşık 600 satır koddur !!! Yaptığı şeyle hiçbir ilgisi olmayan adını affedin. Uygun ad Integer64ToCharArray idi (int64_t değeri);

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

Performansı engellemeden bu kodu temizlemeyi denemekten çekinmeyin.

Giriş: Minimumdan maksimum aralığa herhangi bir işaretli 64 bit değer.

Misal:

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

Çıktı:

Test: 9223372036854775807
Test: -9223372036854775808

Orijinal Hız Testleri: ( Integer64ToCharArray (); )

En iyi durum 1 basamaklı değer.

Döngüler: 100.000.000, Harcanan Zaman: 1.381 (Milyon), Döngü Başına Süre 13 (Nano)

Daha Kötü Durum 20 Haneli Değer.

Döngüler: 100.000.000, Harcanan Zaman: 22.656 (Milyon), Döngü Başına Zaman 226 (Nano

Yeni Tasarım Hız Testleri: ( AddDynamicallyToBuffer (); )

En iyi durum 1 basamaklı değer.

Döngüler: 100.000.000, Harcanan Zaman: 427 (Milli), Döngü Başına Süre 4 (Nano)

32 Bit En Kötü Durum - 11 basamaklı Değer.

Döngüler: 100.000.000, Harcanan Zaman: 1.991 (Milyon), Döngü Başına Zaman 19 (Nano)

Negatif 1 Trilyon En Kötü Durum - 14 haneli Değer.

Döngüler: 100.000.000, Harcanan Zaman: 5.681 (Milyon), Döngü Başına Süre 56 (Nano)

64 Bit Daha Kötü Durum - 20 Haneli Değer.

Döngüler: 100.000.000, Harcanan Zaman: 13.148 (Milyon), Döngü Başına Süre 131 (Nano)

Nasıl çalışır!

Bir Divide and Conquer tekniği uyguluyoruz ve şimdi dizenin maksimum uzunluğunu belirledikten sonra her karakter değerini ayrı ayrı ayarlıyoruz. Yukarıdaki hız testlerinde gösterildiği gibi, daha büyük uzunluklar büyük performans cezaları alır, ancak yine de orijinal döngü yönteminden çok daha hızlıdır ve iki yöntem arasında gerçekte hiçbir kod değişmemiştir, diğer durumda döngü artık kullanımda değildir.

Benim kullanımımda bu nedenle, bunun yerine ofseti döndürüyorum ve bir char dizileri arabelleğini düzenlemiyorum, bunun yerine köşe verilerini güncellemeye başlıyorum ve işlevin offset için ek bir parametresi var, bu yüzden -1 olarak başlatılmamış.



0

Dökümü de kullanabilirsiniz.

misal:

string s;
int value = 3;
s.push_back((char)('0' + value));

2
Ya değer negatifse ya da rakam değilse?
Ziya ERKOC

0

Tamsayı değerimizi std :: string'e çevirerek ne kadar uzun olduğunu (ne kadar uzun rakam) anlayabiliyoruz.

Sonra +1 harf büyüklüğünde karakter dizisi oluşturuyoruz, böylece değerimizi string'e sonra da char dizisine kopyalayabiliriz.

#include <string>

char* intToStr(int data) {
    std::string strData = std::to_string(data);

    char* temp = new char[strData.length() + 1];
    strcpy(temp, strData.c_str());

   return temp;
}

1
Lütfen yanıt olarak yalnızca ham kodu göndermeyin. Her zaman kodun ne yaptığını ve nedenini açıklayın.
CodeSamurai777

Hey, cevabın için teşekkürler! Biraz açıklama yapabilir misin?
OP'ye
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.