std::stringを
charや
const char` に変換するにはどうしたらいいですか?
もし、std::string`をconst char*
を必要とする関数に渡したいだけなら、次のようにします。
std::string str;
const char * c = str.c_str();
char *` のような書き込み可能なコピーを取得したい場合は、これでできます。
std::string str;
char * writable = new char[str.size() + 1];
std::copy(str.begin(), str.end(), writable);
writable[str.size()] = '\0'; // don't forget the terminating 0
// don't forget to free the string after finished using it
delete[] writable;
編集。上記は例外セーフではないことに注意してください。newの呼び出しと
deleteの呼び出しの間で何かがスローされた場合、何も自動的に
delete`を呼び出してくれないので、メモリをリークしてしまいます。これを解決するには2つの方法があります。
boost::scoped_array
は、スコープ外に出たときに、あなたに代わってメモリを削除します。
std::string str;
boost::scoped_array<char> writable(new char[str.size() + 1]);
std::copy(str.begin(), str.end(), writable.get());
writable[str.size()] = '\0'; // don't forget the terminating 0
// get the char* using writable.get()
// memory is automatically freed if the smart pointer goes
// out of scope
これは標準的な方法です(外部ライブラリを必要としません)。メモリを完全に管理してくれる std::vector` を使用します。
std::string str;
std::vector<char> writable(str.begin(), str.end());
writable.push_back('\0');
// get the char* using &writable[0] or &*writable.begin()
与えられた言葉は...
std::string x = "hello";
const char* p_c_str = x.c_str();
const char* p_data = x.data();
char* p_writable_data = x.data(); // for non-const x from C++17
const char* p_x0 = &x[0];
char* p_x0_rw = &x[0]; // compiles iff x is not const...
上記のすべてのポインタは、バッファ内の最初の文字のアドレスという 同じ値 を保持します。 C++11 では、明示的に割り当てられた文字列内容の後に、常に余分な NUL/0 終端文字を保持することが保証されているため、空の文字列であっても「バッファ内の最初の文字」が存在します(例えば、std::string("this\0that", 9)
は、"this\0that\0"
を保持するバッファを持ちます)。
上記のポインターのいずれかが与えられると
char c = p[n]; // valid for n <= x.size()
// i.e. you can safely read the NUL at p[x.size()]
非const
のポインタ p_writable_data
に対してのみ,&x[0]
から。
p_writable_data[n] = c;
p_x0_rw[n] = c; // valid for n <= x.size() - 1
// i.e. don't overwrite the implementation maintained NUL
文字列内の他の場所に NUL を書いても,string
の size()
は変化しません.string
には NUL をいくつでも含めることができますが,std::string
では特別な扱いはされません(C++03 でも同様).
C++03では、かなり複雑でした(主な相違点 **強調)。
x.データ()
const char*
を返します。このバッファは、規格では NUL で終わることが要求されていませんでした** (つまり、['h', 'e', 'l', 'l', 'o']
の後に、初期化されていない値やゴミのような値が続く可能性があり、それに誤ってアクセスすると 未定義の動作* になります)。の文字は読んでも安全です。つまり、
x[0]から
x[x.size() - 1]`までです。&x[0]
f(const char* p, size_t n) { if (n == 0) return; ...whatever...が与えられた場合。例えば、
f(const char* p, size_t n { if (n == 0) return; ... whatever... }が与えられた場合、
x.empty()のときに
f(&x[0], x.size());` を呼んではいけません。x.data()
と同じですが。の
xに対しては,非const
の char*
ポインタが生成されます; 文字列コンテンツを上書きできます。x.c_str()
const char*
を ASCIIZ (NUL-terated) で表現した値 (例: ['h', 'e', 'l', 'o', '0']) を返します。x.data()
および &x[0]
によって「公開された」潜在的な非 NUL 終端バッファから、区別された NUL 終端バッファ を オンザフライ で作成できるようになっています。を変更したり、さらに容量を確保するような
文字列メンバ関数を呼び出した場合、上記のいずれかのメソッドによって事前に返されたポインタの値は*無効*になります。 これらのメソッドを再度使用して、別のポインタを得ることができます。 (ルールは
stringへのイテレータと同じです)。) .... 以下の *How to get a character pointer valid even after
x` leaves scope or is modified further も参照してください。
では、どちらを使うのが 良い* のでしょうか?C++11 以降では、ASCIIZ データには .c_str()
を、「バイナリ」データには .data()
を使用してください(以下で詳しく説明します)。
C++03では、.data()
が適切であると確信できる場合を除き、.c_str()
を使用し、空の文字列に対して安全であるため、&x[0]
よりも.data()
を優先します。....
...適切なときにdata()
を使えるように、プログラムを十分に理解するようにしてください、さもなければ、おそらく他の間違いを犯すでしょう...。
.c_str()で保証されているASCIIのNUL '0'文字は、多くの関数で、関連する安全なデータの終わりを示すセンチネル値として使用されています。 これは、
fstream::fstream(const char* filename, ...)のような C++ のみの関数にも、
strchr()や
printf()のような C++ と共有する関数にも当てはまります。 C++03 の
.c_str()の戻り値のバッファに関する保証は
.data()のスーパーセットであるため、常に
.c_str()` を安全に使用することができますが、そうしない人もいます。
string
の実装では、NUL 終端のバッファを準備するために、余分なメモリ割り当てやデータコピーが必要になる可能性があります。
さらにヒントとして、関数のパラメータが(const
) char*
を必要としていて、x.size()
を得ることにこだわらない場合、その関数はおそらく* ASCIIZの入力を必要としているので、.c_str()
が良い選択となります(関数はテキストの終端を何らかの方法で知る必要があるので、独立したパラメータでない場合は、長さのプレフィックスやセンチネルなどの規則や、期待される固定長にするしかありません)。
x` がスコープから外れたり、さらに変更された後でも、文字ポインタを有効にする方法文字列 x
の内容を x
の外側の新しいメモリ領域に コピー する必要があります。 この外部バッファは、別の string
や文字配列変数など、さまざまな場所にある可能性があります。また、異なるスコープ (名前空間、グローバル、スタティック、ヒープ、共有メモリ、メモリマップドファイルなど) にあるため、x
とは異なるライフタイムを持つ場合もありますし、持たない場合もあります。
テキストを std::string x
から独立した文字配列にコピーするには、以下のようにします。
// USING ANOTHER STRING - AUTO MEMORY MANAGEMENT, EXCEPTION SAFE
std::string old_x = x;
// - old_x will not be affected by subsequent modifications to x...
// - you can use `&old_x[0]` to get a writable char* to old_x's textual content
// - you can use resize() to reduce/expand the string
// - resizing isn't possible from within a function passed only the char* address
std::string old_x = x.c_str(); // old_x will terminate early if x embeds NUL
// Copies ASCIIZ data but could be less efficient as it needs to scan memory to
// find the NUL terminator indicating string length before allocating that amount
// of memory to copy into, or more efficient if it ends up allocating/copying a
// lot less content.
// Example, x == "ab\0cd" -> old_x == "ab".
// USING A VECTOR OF CHAR - AUTO, EXCEPTION SAFE, HINTS AT BINARY CONTENT, GUARANTEED CONTIGUOUS EVEN IN C++03
std::vector<char> old_x(x.data(), x.data() + x.size()); // without the NUL
std::vector<char> old_x(x.c_str(), x.c_str() + x.size() + 1); // with the NUL
// USING STACK WHERE MAXIMUM SIZE OF x IS KNOWN TO BE COMPILE-TIME CONSTANT "N"
// (a bit dangerous, as "known" things are sometimes wrong and often become wrong)
char y[N + 1];
strcpy(y, x.c_str());
// USING STACK WHERE UNEXPECTEDLY LONG x IS TRUNCATED (e.g. Hello\0->Hel\0)
char y[N + 1];
strncpy(y, x.c_str(), N); // copy at most N, zero-padding if shorter
y[N] = '\0'; // ensure NUL terminated
// USING THE STACK TO HANDLE x OF UNKNOWN (BUT SANE) LENGTH
char* y = alloca(x.size() + 1);
strcpy(y, x.c_str());
// USING THE STACK TO HANDLE x OF UNKNOWN LENGTH (NON-STANDARD GCC EXTENSION)
char y[x.size() + 1];
strcpy(y, x.c_str());
// USING new/delete HEAP MEMORY, MANUAL DEALLOC, NO INHERENT EXCEPTION SAFETY
char* y = new char[x.size() + 1];
strcpy(y, x.c_str());
// or as a one-liner: char* y = strcpy(new char[x.size() + 1], x.c_str());
// use y...
delete[] y; // make sure no break, return, throw or branching bypasses this
// USING new/delete HEAP MEMORY, SMART POINTER DEALLOCATION, EXCEPTION SAFE
// see boost shared_array usage in Johannes Schaub's answer
// USING malloc/free HEAP MEMORY, MANUAL DEALLOC, NO INHERENT EXCEPTION SAFETY
char* y = strdup(x.c_str());
// use y...
free(y);
から
charや
const char`を生成したいと思うその他の理由以上、(const
) char*
を取得する方法と、元の string
から独立したテキストのコピーを作成する方法を見てきましたが、それを使って何ができるのでしょうか。 適当な例を挙げてみると...
string
のテキストへのアクセスを与える。のテキストを、関数の呼び出し元が指定したバッファ(例:
strncpy(callers_buffer, callers_buffer_size, x.c_str()))や、デバイスの I/O に使われる揮発性メモリ(例:
for (const char p = x.c_str(); p; ++p) p_device = p;`)にコピーします。のテキストを、既に ASCIIZ テキストが格納されている文字配列に追加します (例 :
strcat(other_buffer, x.c_str())) - バッファをオーバーランしないように注意してください (多くの状況で
strncat` を使用する必要があるでしょう)。const char*
または char*
を返す (クライアントが既存の API を使用しているという歴史的な理由や、C 言語との互換性のために std::string
を返したくないが、呼び出し元のために string
のデータをどこかにコピーしておきたいという理由があるかもしれません)。string
変数がスコープから外れた後に、呼び出し元がそれを参照しないように注意してください。std::string
実装 (STLport や compiler-native など) でコンパイル/リンクされた共有オブジェクトを持つプロジェクトでは、衝突を避けるためにデータを ASCIIZ として渡すことがあります。const char *には
.c_str()` メソッドを使用します。
char *のポインタを取得するために
&mystring[0]` を使用することができますが、いくつかの問題があります: 必ずしもゼロ終端の文字列を取得できるわけではないことと、文字列のサイズを変更できないことです。また、文字列のサイズを変更することはできません。特に、文字列の最後に文字を追加しないように注意しなければなりません。そうしないと、バッファオーバーラン(およびクラッシュの可能性)が生じます。
C++11 までは、すべての文字が同じ連続したバッファの一部であるという保証はありませんでしたが、実際には、すべての既知の std::string
の実装がそのように動作しました。Does "&s[0]" point to contiguous characters in a std::string?を参照してください。
多くの string
メンバ関数は、内部バッファを再割り当てし、保存していたポインタを無効にすることに注意してください。すぐに使用してから破棄するのがベストです。