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";
x
name__がスコープ内にあり、さらに変更されていないときに有効な文字ポインターを取得する方法
C++ 11は物事を単純化します。以下はすべて、同じ内部文字列バッファへのアクセスを許可します。
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()]
Nonconst
name__ポインター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
name__のsize()
がnot変更されます。 string
name__には、任意の数のNULを含めることができます-std::string
による特別な処理は行われません(C++ 03と同じ)。
C++ 03では、物事はかなり複雑でした(主な違いhighlighted):
x.data()
const char*
を文字列の内部バッファに返します。これは、NUL(つまり['h', 'e', 'l', 'l', 'o']
が続く可能性があります)初期化されていない値またはガベージ値によって、undefined behaviour)を持つ偶発的なアクセスがあります。x.size()
文字は安全に読み取れます。つまり、x[0]
からx[x.size() - 1]
まで&x[0]
f(const char* p, size_t n) { if (n == 0) return; ...whatever... }
を指定すると、f(&x[0], x.size());
のときにx.empty()
を呼び出してはいけません-f(x.data(), ...)
を使用するだけです。x.data()
に従いますが、const
x
name__の場合、これはnonconst
char*
ポインターを生成します。文字列コンテンツを上書きできますx.c_str()
const char*
を値のASCIIZ(NUL終了)表現に返します(つまり、['h'、 'e'、 'l'、 'l'、 'o'、 '\ 0'])。x.data()
および&x[0]
によって「露出」された潜在的に非NUL終了バッファからx.size()
+ 1文字は安全に読み取れます。どちらの方法でポインターを取得する場合でも、上記の説明で保証されている文字よりもポインターに沿ってメモリにアクセスしないでください。これを試みると、undefined behaviourが発生し、読み取りでもアプリケーションクラッシュやガベージ結果が発生する可能性が非常に高く、さらに、大量のデータ、スタック破損、書き込みのセキュリティ脆弱性があります。
string
name__を変更する、またはさらに容量を予約するstring
name__メンバー関数を呼び出す場合、上記のメソッドのいずれかによって事前に返されるポインター値はinvalidatedです。これらのメソッドを再度使用して、別のポインターを取得できます。 (ルールは、string
name__sへのイテレーターの場合と同じです)。
下記も参照してくださいx
name__がスコープを離れた後、またはさらに変更された後でも文字ポインターを有効にする方法.
C++ 11から、ASCIIZデータには.c_str()
を使用し、「バイナリ」データには.data()
を使用します(以下でさらに説明します)。
C++ 03では、.c_str()
が適切であることが確実でない限り、.data()
を使用し、空の文字列に対して安全であるため、&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()
を使用できますが、人々は時々そうしないことがあります。
.data()
を使用すると、ソースコードを読んでいる他のプログラマーに、データがASCIIZではない(むしろ、文字列を使用してデータのブロックを保存している(実際にはテキストではないこともある))か、それを渡していることを伝える「バイナリ」データのブロックとして扱う別の関数に。これは、他のプログラマーのコード変更がデータを適切に処理し続けることを保証するための重要な洞察となります。string
name__実装は、NUL終了バッファを準備するために、追加のメモリ割り当てやデータコピーを行う必要がある可能性がわずかにあります。さらにヒントとして、関数のパラメーターが(const
name__)char*
を必要とするが、x.size()
の取得を要求しない場合、関数おそらくはASCIIZ入力を必要とするため、.c_str()
が適切な選択です(関数はテキストがどこで終わるかを知る必要があるので、独立したパラメーターでない場合は、長さのプレフィックスやセンチネル、または何らかの固定長のような規則にしかなれません)。
x
name__がスコープを離れるか、さらに変更された後でも、文字ポインターを有効にする方法copystring
x
name__の内容をx
name__の外の新しいメモリ領域にコピーする必要があります。この外部バッファは、別のstring
name__や文字配列変数など、さまざまな場所に存在する可能性があります。異なるスコープ(名前空間、グローバル、静的、ヒープ、共有メモリ、メモリマップなど)にあるため、x
name__と異なるライフタイムを持つ場合とそうでない場合がありますファイル)。
テキストを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);
string
name__からchar*
またはconst char*
を生成したいその他の理由それで、上記で(const
name__)char*
を取得する方法と、元のstring
name__から独立したテキストのコピーを作成する方法を見てきましたが、それで何ができますかdo?例のランダムな散らばり...
printf("x is '%s'", x.c_str());
のように、C++のstring
name__のテキストに「C」コードのアクセス権を付与しますx
name__のテキストを関数の呼び出し元によって指定されたバッファー(strncpy(callers_buffer, callers_buffer_size, x.c_str())
など)、またはデバイスI/Oに使用される揮発性メモリー(for (const char* p = x.c_str(); *p; ++p) *p_device = *p;
など)にコピーしますx
name__のテキストを追加します(例:strcat(other_buffer, x.c_str())
)-バッファーをオーバーランしないように注意してください(多くの場合、strncat
name__を使用する必要があります)const char*
またはchar*
を返す(おそらく歴史的な理由-クライアントが既存のAPIを使用している-またはC互換性のためにstd::string
を返したくないが、呼び出し元のためにstring
name__のデータをコピーしたい) 。]string
name__変数がスコープを離れた後に、呼び出し元によって逆参照される可能性のあるポインターを返さないように注意してくださいstd::string
実装用にコンパイル/リンクされた共有オブジェクト(STLportとコンパイラネイティブなど)を使用する一部のプロジェクトでは、競合を避けるためにASCIIZとしてデータを渡すことができますconst char *
には.c_str()
メソッドを使用してください。
あなたは&mystring[0]
ポインタを得るためにchar *
を使うことができます、しかし、いくつかの落とし穴があります:あなたは必ずしもゼロで終わる文字列を得ない、そしてあなたは文字列のサイズを変更することができません。特に、文字列の末尾を超えて文字を追加しないように注意する必要があります。そうしないと、バッファオーバーラン(およびおそらくクラッシュ)が発生します。
C++ 11までは、すべての文字が同じ連続バッファーの一部になるという保証はありませんでしたが、実際には、std::string
のすべての既知の実装がいずれにせよそのように機能しました。 “&s [0]”はstd :: string内の連続した文字を指していますか? を参照してください。
多くのstring
メンバ関数は内部バッファを再割り当てし、保存したポインタを無効にすることに注意してください。直ちに使用してから廃棄するのが最善です。
C++ 17 (今後の標準)は、テンプレートbasic_string
の概要を変更し、constでないオーバーロードdata()
を追加します。
charT* data() noexcept;
戻り値:[0、size()]の各iに対してp + i ==&演算子となるようなポインタp。
CharT const *
からのstd::basic_string<CharT>
std::string const cstr = { "..." };
char const * p = cstr.data(); // or .c_str()
CharT *
からのstd::basic_string<CharT>
std::string str = { "..." };
char * p = str.data();
CharT const *
からのstd::basic_string<CharT>
std::string str = { "..." };
str.c_str();
CharT *
からのstd::basic_string<CharT>
C++ 11以降、この規格は次のように述べています。
basic_string
オブジェクト内のcharのようなオブジェクトは連続して格納されます。つまり、すべてのbasic_string
オブジェクトs
に対して、アイデンティティー&*(s.begin() + n) == &*s.begin() + n
は0 <= n < s.size()
のようにn
のすべての値に対して成り立ちます。
const_reference operator[](size_type pos) const;
reference operator[](size_type pos);
戻り値:
*(begin() + pos)
の場合はpos < size()
、それ以外の場合は値CharT()
を持つCharT
型のオブジェクトへの参照。参照された値は変更されません。
const charT* c_str() const noexcept;
const charT* data() const noexcept;
戻り値:
p + i == &operator[](i)
の各i
に対して[0,size()]
となるようなポインタp。
非const文字ポインタを取得するための切断可能な方法があります。
std::string foo{"text"};
auto p = &*foo.begin();
プロ
短所
'\0'
は変更しないでください/必ずしも非constメモリの一部ではありません。std::vector<CharT>
を使うstd::string foo{"text"};
std::vector<char> fcv(foo.data(), foo.data()+foo.size()+1u);
auto p = fcv.data();
プロ
短所
N
がコンパイル時定数である(そして十分に小さい)場合はstd::array<CharT, N>
を使用してください。std::string foo{"text"};
std::array<char, 5u> fca;
std::copy(foo.data(), foo.data()+foo.size()+1u, fca.begin());
プロ
短所
std::string foo{ "text" };
auto p = std::make_unique<char[]>(foo.size()+1u);
std::copy(foo.data(), foo.data() + foo.size() + 1u, &p[0]);
プロ
短所
std::string foo{ "text" };
char * p = nullptr;
try
{
p = new char[foo.size() + 1u];
std::copy(foo.data(), foo.data() + foo.size() + 1u, p);
// handle stuff with p
delete[] p;
}
catch (...)
{
if (p) { delete[] p; }
throw;
}
プロ
コン
私は入力としてchar*
を取得する多くの関数を持つAPIを使って作業しています。
私はこの種の問題に直面するために小さなクラスを作成しました、私はRAIIイディオムを実装しました。
class DeepString
{
DeepString(const DeepString& other);
DeepString& operator=(const DeepString& other);
char* internal_;
public:
explicit DeepString( const string& toCopy):
internal_(new char[toCopy.size()+1])
{
strcpy(internal_,toCopy.c_str());
}
~DeepString() { delete[] internal_; }
char* str() const { return internal_; }
const char* c_str() const { return internal_; }
};
そしてあなたはそれを次のように使うことができます。
void aFunctionAPI(char* input);
// other stuff
aFunctionAPI("Foo"); //this call is not safe. if the function modified the
//literal string the program will crash
std::string myFoo("Foo");
aFunctionAPI(myFoo.c_str()); //this is not compiling
aFunctionAPI(const_cast<char*>(myFoo.c_str())); //this is not safe std::string
//implement reference counting and
//it may change the value of other
//strings as well.
DeepString myDeepFoo(myFoo);
aFunctionAPI(myFoo.str()); //this is fine
既存の文字列の詳細で一意なコピーを作成しているため(DeepString
はコピーできません)、クラスDeepString
を呼び出しました。
char* result = strcpy((char*)malloc(str.length()+1), str.c_str());
これを見てください。
string str1("stackoverflow");
const char * str2 = str1.c_str();
ただし、これはconst char *
を返すことに注意してくださいchar *
の場合は、strcpy
を使用して別のchar
配列にコピーします。