Bir std :: string bir char * veya char [] veri türüne dönüştürmek istiyorum .
std::string str = "string";
char* chr = str;
Sonuçlar: “hata: 'std :: string' öğesini 'char' haline dönüştüremiyor ...” .
Bunu yapmak için hangi yöntemler var?
Bir std :: string bir char * veya char [] veri türüne dönüştürmek istiyorum .
std::string str = "string";
char* chr = str;
Sonuçlar: “hata: 'std :: string' öğesini 'char' haline dönüştüremiyor ...” .
Bunu yapmak için hangi yöntemler var?
Yanıtlar:
Otomatik olarak dönüştürülmez (şükürler olsun). c_str()
C dize sürümünü almak için yöntemi kullanmanız gerekir.
std::string str = "string";
const char *cstr = str.c_str();
Bir const char *
; tarafından döndürülen C stili dizeyi değiştirmenize izin verilmiyor c_str()
. İşlemek istiyorsanız önce kopyalamanız gerekir:
std::string str = "string";
char *cstr = new char[str.length() + 1];
strcpy(cstr, str.c_str());
// do stuff
delete [] cstr;
Veya modern C ++ ile:
std::vector<char> cstr(str.c_str(), str.c_str() + str.size() + 1);
vector
dinamik diziler için bir sargı olarak icat edildi, bu yüzden kullanmamak en iyi ihtimalle kaçırılmış bir fırsat gibi görünüyor ve en kötü ihtimalle C ++ ruhunu ihlal ediyor.
std::string
otomatik olarak dönüştüğünü düşünerek ) ve sonra ne kullanması gerektiğini kısa kod örneği ile açıklarım. İleriye dönük olarak, bu işlevin kullanımının bazı yan etkilerini de açıklarım, bunlardan biri döndürülen dizeyi düzenleyemeyeceğinizdir c_str()
. Yanlışlıkla kısa örneklerimi gerçek problem çözme kodu olarak görüyorsunuz.
std::vector<char>
).
Burada ve burada daha fazla ayrıntı ama kullanabilirsiniz
string str = "some string" ;
char *cstr = &str[0];
Bir c ++ 's dize içeriğinin değiştirilebilir bir ham kopya gerekir, o zaman bunu yapmak:
std::string str = "string";
char* chr = strdup(str.c_str());
ve sonra:
free(chr);
Öyleyse neden başka biri gibi std :: vector veya new [] ile uğraşmıyorum? Çünkü ben bir değişken C tarzı ham kömürü gerektiğinde * dize, o zaman dize değiştirir ve C kodu malloc () (strdup kullanımlar malloc) olan serbest () ve ayırır ile malzeme kaldırır C kodu aramak istiyorum çünkü . Bazı fonksiyon X'e benim ham dize geçirirseniz Yani C ile yazılmış bu olabilir o kadar yığın tahsis ettiğini 's argüman üzerinde bir sınırlama var (örneğin fonksiyon parametreye realloc aramak istersin ise). Ancak (bazı kullanıcı tarafından yeniden tanımlanmış) yeni [] ile ayrılmış bir argüman beklemesi pek olası değildir!
strdup
geldiğini açıklamalısın .
(Bu yanıt yalnızca C ++ 98 için geçerlidir.)
Lütfen, çiğ kullanmayın char*
.
std::string str = "string";
std::vector<char> chars(str.c_str(), str.c_str() + str.size() + 1u);
// use &chars[0] as a char*
vector<char>(str.c_str(), str.c_str() + str.size() + 1)
char işaretçisini geçici olarak atamadan söylemek doğru mudur?
std::basic_string<>::c_str()
edilene kadar geçerlidir string
. Bu ayrıca, string
değiştirilmediği sürece sonraki aramalarda aynı değeri döndürdüğü anlamına gelir .
vector
Bu şekilde kullanılan bir hız veya boşluk ek yükü yoktur . Ve eğer bir RAII mekanizması olmadan istisna-güvenli kod yazacak olsaydı (yani ham işaretçiler kullanarak), kod karmaşıklığı bu basit tek-kattan çok daha yüksek olurdu.
vector
Büyük miktarda ek yük ve karmaşıklığa sahip bir efsane . İhtiyacınız değişebilir bir char dizisine sahipseniz, aslında bir char vektörü hemen hemen ideal C ++ sarıcıdır. Gereksiniminiz aslında bir const-char işaretçisi gerektiriyorsa, sadece kullanın c_str()
ve işiniz bitti.
Yalnızca aynı içeriği temsil eden bir C stili dize istiyorsanız:
char const* ca = str.c_str();
Yeni içeriğe sahip bir C stili dize istiyorsanız, derleme zamanında dize boyutunu bilmediğinizden biri dinamik ayırmadır:
char* ca = new char[str.size()+1];
std::copy(str.begin(), str.end(), ca);
ca[str.size()] = '\0';
Daha delete[]
sonra unutmayın .
Bunun yerine statik olarak ayrılmış, sınırlı uzunlukta bir dizi istiyorsanız:
size_t const MAX = 80; // maximum number of chars
char ca[MAX] = {};
std::copy(str.begin(), (str.size() >= MAX ? str.begin() + MAX : str.end()), ca);
std::string
bunu yapmanın genellikle bir tasarım kokusu olmasının basit bir nedeni için örtük olarak bu türlere dönüşmez. Gerçekten emin ol ihtiyacınız .
Kesinlikle bir ihtiyacınız varsa char*
, en iyi yol muhtemelen:
vector<char> v(str.begin(), str.end());
char* ca = &v[0]; // pointer to start of vector
&str.front(), &str.back()
(C ++ 03'te mevcut değil) yerine daha yaygın str.begin()
ve str.end()
?
str.begin()
, hatta std::begin(str)
, yineleyici benzeri? Sanırım string
bitişik hafızada olmak gibi bir yükümlülüğüm vector
yok mu, öyle mi?
&back() + 1
, değil&back()
Bu, bobobobo'nun cevabına bir yorum olarak daha iyi olurdu, ancak bunun için bir temsilcim yok. Aynı şeyi daha iyi uygulamalarla başarır.
Diğer cevaplar kullanışlı olmasına rağmen hiç dönüştürmek gerekiyorsa, std::string
hiç char*
Kat olmadan açıkça, const_cast
senin arkadaşın.
std::string str = "string";
char* chr = const_cast<char*>(str.c_str());
Bu edeceği Not değil size verilerin bir kopyasını vermek; size dize için bir işaretçi verecektir. Böylece, öğesinin bir öğesini değiştirirseniz chr
, değiştirirsiniz str
.
Kesinlikle bilgiç olmak için, "std :: string'i bir char * veya char [] veri türüne dönüştüremezsiniz."
Diğer yanıtların gösterdiği gibi, std :: dizesinin içeriğini bir char dizisine kopyalayabilir veya "C stili" nden erişebilmeniz için std :: dizesinin içeriğine const char * yapabilirsiniz. .
Std :: string'in içeriğini değiştirmeye çalışıyorsanız, std :: string tipi, muhtemelen yapmanız gereken her şeyi yapmak için tüm yöntemlere sahiptir.
Char * alan bir işleve geçirmeye çalışıyorsanız, std :: string :: c_str () vardır.
İşte bir daha sağlam versiyonu Protocol Buffer
char* string_as_array(string* str)
{
return str->empty() ? NULL : &*str->begin();
}
// test codes
std::string mystr("you are here");
char* pstr = string_as_array(&mystr);
cout << pstr << endl; // you are here
if (str[str.length()-1] != 0) str.push_back(0)
OOP tarzında dönüşüm
converter.hpp
class StringConverter {
public: static char * strToChar(std::string str);
};
converter.cpp
char * StringConverter::strToChar(std::string str)
{
return (char*)str.c_str();
}
kullanım
StringConverter::strToChar("converted string")
Bütünlük uğruna unutma std::string::copy()
.
std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];
str.copy(chrs, MAX);
std::string::copy()
NUL sonlanmaz. C string işlevlerinde kullanmak için bir NUL sonlandırıcı sağlamanız gerekiyorsa:
std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];
memset(chrs, '\0', MAX);
str.copy(chrs, MAX-1);
Bir elde etmek için const char *
, bir gelen std::string
kullanımı c_str()
elemanı işlevi:
std::string str = "string";
const char* chr = str.c_str();
Olmayan bir const elde etmek için char *
bir mesafede std::string
kullanabilirsiniz data()
C ++ 17 yana const olmayan işaretçi döndürür üye işlevi:
std::string str = "string";
char* chr = str.data();
Dilin eski sürümlerinde, dizeyi sabit olmayan bir işaretçi elde edilebilecek bir vektöre kopyalamak için aralık yapısını kullanabilirsiniz:
std::string str = "string";
std::vector<char> str_copy(str.c_str(), str.c_str() + str.size() + 1);
char* chr = str_copy.data();
Ancak bunun içerdiği dizeyi değiştirmenize izin vermeyeceğine dikkat edin str
, yalnızca kopyanın verileri bu şekilde değiştirilebilir. Dilin eski sürümlerinde c_str()
burada kullanılması özellikle önemlidir, çünkü o std::string
zamana kadar çağrılıncaya kadar boş sonlandırılacağı garanti edilmemiştir c_str()
.
char* result = strcpy((char*)malloc(str.length()+1), str.c_str());
Alternatif olarak, aşağıda gösterildiği gibi yazılabilir bir karakter * elde etmek için vektörleri kullanabilirsiniz;
//this handles memory manipulations and is more convenient
string str;
vector <char> writable (str.begin (), str.end) ;
writable .push_back ('\0');
char* cstring = &writable[0] //or &*writable.begin ()
//Goodluck
Bu da işe yarayacak
std::string s;
std::cout<<"Enter the String";
std::getline(std::cin, s);
char *a=new char[s.size()+1];
a[s.size()]=0;
memcpy(a,s.c_str(),s.size());
std::cout<<a;
c_str
delilikten tamamen kaçınırdı .