回答:
自動的には変換されません(ありがとうございます)。c_str()
C文字列バージョンを取得するには、メソッドを使用する必要があります。
std::string str = "string";
const char *cstr = str.c_str();
を返すことに注意してくださいconst char *
。によって返されるCスタイルの文字列を変更することはできませんc_str()
。処理したい場合は、最初にコピーする必要があります。
std::string str = "string";
char *cstr = new char[str.length() + 1];
strcpy(cstr, str.c_str());
// do stuff
delete [] cstr;
または最新のC ++の場合:
std::vector<char> cstr(str.c_str(), str.c_str() + str.size() + 1);
vector
動的配列のラッパーとして正確に発明されたので、それを使用しないと、せいぜい機会を逃したように見え、最悪の場合はC ++の精神に違反しています。
std::string
自動的に変換されると思います)を説明し、次に短いコードサンプルを使用して、OPの使用方法を説明します。また、この関数の使用によるいくつかの副作用についても説明します。その1つは、によって返される文字列を編集できないことですc_str()
。あなたは私の短い例を本当の問題解決コードと誤って見ていますが、そうではありません。
std::vector<char>
)。
c ++の文字列コンテンツの変更可能なrawコピーが必要な場合は、次のようにします。
std::string str = "string";
char* chr = strdup(str.c_str());
以降:
free(chr);
では、なぜstd :: vectorやnew []を他の人のようにいじらないのですか?そのため、私はCの文字列を変更し、Cのコードは(自由にものを割り当て解除コード)とのmallocで割り当て()(のstrdup用途malloc関数)を呼び出したいので、その後、文字列*私は可変Cスタイルの生の文字を必要とするとき。私はいくつかの関数Xに私の生の文字列を渡すのであればCで書かれ、それは可能性がある、それがヒープに割り当てられたことを、それの引数の制約を持っている(例えば関数は、パラメータ上のreallocを呼び出したい可能性がある場合)。しかし、(一部のユーザーが再定義した)new []で割り当てられた引数を期待することはほとんどありません。
strdup
から来たのか説明してください。
(この回答はC ++ 98にのみ適用されます。)
生は使用しないでください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ポインタを一時に割り当てずに、と言っても大丈夫ですか?
std::basic_string<>::c_str()
、string
が変更または破棄されるまで有効です。これstring
は、が変更されない限り、後続の呼び出しで同じ値を返すことも意味します。
vector
このように使用すると、速度やスペースのオーバーヘッドはありません。また、RAIIメカニズムを使用せずに例外セーフコードを作成する場合(つまり、生のポインターを使用する場合)、コードの複雑度はこの単純な1ライナーよりもはるかに高くなります。
vector
は膨大な量のオーバーヘッドと複雑さを持つ神話です。変更可能な char配列があることが要件である場合、実際にはcharのベクトルが理想的なC ++ラッパーです。要件が実際にconst-charポインターを必要c_str()
とする場合は、使用するだけで完了です。
同じコンテンツを表すCスタイルの文字列が必要な場合:
char const* ca = str.c_str();
新しい内容のCスタイルの文字列が必要な場合、1つの方法(コンパイル時に文字列のサイズがわからない場合)は動的割り当てです。
char* ca = new char[str.size()+1];
std::copy(str.begin(), str.end(), ca);
ca[str.size()] = '\0';
delete[]
後で忘れずに。
代わりに、静的に割り当てられ、長さが制限された配列が必要な場合:
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
通常、これを行う必要があるのはデザインの匂いであるという単純な理由で、これらの型に暗黙的に変換しません。あなたが本当にそれを必要とすることを確認してください。
あなたが間違いなくを必要とするならchar*
、最善の方法はおそらく:
vector<char> v(str.begin(), str.end());
char* ca = &v[0]; // pointer to start of vector
&str.front(), &str.back()
(C ++ 03には存在しないもの)ではなく、より一般的なのstr.begin()
とstr.end()
?
str.begin()
、あるいはstd::begin(str)
、イテレータのような?私はのstring
ような連続したメモリにいる義務があるとは思わないvector
か、それとも持っていますか?
&back() + 1
ではなく、誤用されました&back()
これは、boboboboの回答に対するコメントとしては優れていますが、私はその担当者がいません。それは同じことを達成しますが、より良い実践で。
他の答えは役に立ちますが、constなしで明示的に変換std::string
する必要がある場合は、あなたの友達です。char*
const_cast
std::string str = "string";
char* chr = const_cast<char*>(str.c_str());
これはデータのコピーを提供しないことに注意してください。文字列へのポインタを提供します。したがって、の要素を変更するとchr
、も変更されstr
ます。
厳密に言うと、「std :: stringをchar *またはchar []データ型に変換する」ことはできません。
他の回答が示しているように、std :: stringの内容をchar配列にコピーするか、またはstd :: stringの内容にconst char *を作成して、「Cスタイル」でそれにアクセスできるようにすることができます。 。
std :: stringの内容を変更しようとしている場合、std :: stringタイプには、実行する必要がある可能性のあることを実行するためのすべてのメソッドが含まれています。
char *を取る関数に渡そうとしている場合は、std :: string :: c_str()があります。
完全を期すために、忘れないでくださいstd::string::copy()
。
std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];
str.copy(chrs, MAX);
std::string::copy()
NULは終了しません。C文字列関数で使用するためにNULターミネータを確保する必要がある場合:
std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];
memset(chrs, '\0', MAX);
str.copy(chrs, MAX-1);
ここにもう1つの堅牢なバージョンがあります 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スタイルでの変換
converter.hpp
class StringConverter {
public: static char * strToChar(std::string str);
};
converter.cpp
char * StringConverter::strToChar(std::string str)
{
return (char*)str.c_str();
}
使用法
StringConverter::strToChar("converted string")
または、以下に示すように、ベクターを使用して書き込み可能なchar *を取得することもできます。
//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
からを取得const char *
するにstd::string
は、c_str()
メンバー関数を使用します。
std::string str = "string";
const char* chr = str.c_str();
非constを取得するには、char *
からstd::string
あなたが使用できるdata()
C ++ 17以降非constポインタを返すメンバ関数を:
std::string str = "string";
char* chr = str.data();
古いバージョンの言語の場合、範囲構築を使用して、文字列をベクターにコピーし、そこから非constポインターを取得できます。
std::string str = "string";
std::vector<char> str_copy(str.c_str(), str.c_str() + str.size() + 1);
char* chr = str_copy.data();
ただし、これではに含まれる文字列を変更できないことに注意してくださいstr
。この方法で変更できるのはコピーのデータのみです。が呼び出されるまでnullで終了することが保証されていなかったc_str()
ため、ここで使用する言語の古いバージョンでは特に重要であることに注意してください。std::string
c_str()
c_str
狂気を完全に回避する可能性が高くなります。