std :: string to char *


335

std :: stringchar *またはchar []データ型に変換したい。

std::string str = "string";
char* chr = str;

結果:「エラー: 『文字』から『のstd :: string』を変換することはできません...」

これを行うにはどのような方法がありますか?

回答:


671

自動的には変換されません(ありがとうございます)。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);

4
@Kerrek SB:これは例であり、実際のコードでスマートポインターを使用するか、このc_str狂気を完全に回避する可能性が高くなります。
orlp

14
答えはかさばり、洗練されておらず、ローカルではなく、生の配列を使用しているため、例外の安全性に注意する必要があります。vector動的配列のラッパーとして正確に発明されたので、それを使用しないと、せいぜい機会を逃したように見え、最悪の場合はC ++の精神に違反しています。
Kerrek SB、2011

21
まず第一に、はい答えはかさばります。最初にOPのエラー(std::string自動的に変換されると思います)を説明し、次に短いコードサンプルを使用して、OPの使用方法を説明します。また、この関数の使用によるいくつかの副作用についても説明します。その1つは、によって返される文字列を編集できないことですc_str()。あなたは私の短い例を本当の問題解決コードと誤って見ていますが、そうではありません。
orlp 2011

8
私は答えに反対票を投じました。この回答は確かに役に立たず、受け入れられたという事実は最も残念です。この回答は、C ++の優れたプログラミング方法と例外の安全性を完全に無視し、はるかに優れた解決策があります。そのいくつかは、この質問の他の回答で提供されます(たとえば、を使用するildjarnによって提供される回答std::vector<char>)。
James McNellis、2011

114
それは答えていないので、@ジェームズ・mcnellisは、私が正しいものとして、この答えを選んだEXACTLY私は劣らず、より多くのために...ノー求めていたもの。私が何をすべきだと思うか、私がしていると思うことに対する別の解決策を求めなかった、良い実践を求めなかった。あなたは私が何で働いているのか、私のコードがどこに実装されるのか、そしてどのような条件下であるのかを知りません。一部の人は、質問を読み、理解し、実際に尋ねられていることに答えることを学ぶ必要があります。ここで自慢する必要はありません。

148

詳細はこちら、およびこちらですが、使用できます

string str = "some string" ;
char *cstr = &str[0];

15
FWIW、私の本では、これが実際に尋ねられた質問に対する唯一の正しい答えです。std :: stringは本質的に変更可能です。文字列の内容を変更するように聞こえるようにしている人々は、どういうわけか、悪魔の仕事にはこの事実が欠けているようです。
Jay Freeman -saurik- 2013年

2
はい、これが正解です。使用頻度を考えると、msoftのロックバッファのようにこれを行う標準的な方法がないのはばかげています。
Erik Aronesty、2015年

1
0を0uに変更しました。一部のコンパイラ/ライブラリは、警告が&str [0]構文に対してオンになっていると、あいまいさについて文句を言うでしょう(信じられない
かもしれ

strが削除されると、char cstrがnullになるとは思いません。したがって、ここでは文字列のポインタのみがcharポインタに割り当てられていると思います。したがって、文字列から文字への変換は文字通り完全ではありません。文字列はchar *のみを指していますが、その値は変換されません。私は正しいですか???
Samitha Chathuranga

5
これはC ++ 11のみであることに注意してください。以前のバージョンでは、継続的なストレージを持っていない可能性がありますまたは終端のNULL不足している
Flamefire

40

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から来たのか説明してください。
LF

22

(この回答は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*

1
今日は、このようなものが必要だった。vector<char>(str.c_str(), str.c_str() + str.size() + 1)charポインタを一時に割り当てずに、と言っても大丈夫ですか?
Kerrek SB、2011

1
@Kerrek:はい、の戻り値はstd::basic_string<>::c_str()stringが変更または破棄されるまで有効です。これstringは、が変更されない限り、後続の呼び出しで同じ値を返すことも意味します。
ildjarn、2011

2
@friendzis:vectorこのように使用すると、速度やスペースのオーバーヘッドはありません。また、RAIIメカニズムを使用せずに例外セーフコードを作成する場合(つまり、生のポインターを使用する場合)、コードの複雑度はこの単純な1ライナーよりもはるかに高くなります。
ildjarn、2011

7
それvectorは膨大な量のオーバーヘッドと複雑さを持つ神話です。変更可能な char配列があることが要件である場合、実際にはcharのベクトルが理想的なC ++ラッパーです。要件が実際にconst-charポインターを必要c_str()とする場合は、使用するだけで完了です。
Kerrek SB、2011


15
  • 同じコンテンツを表す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

1
なぜ&str.front(), &str.back()(C ++ 03には存在しないもの)ではなく、より一般的なのstr.begin()str.end()
Armen Tsirunyan、2011

1
どの程度str.begin()、あるいはstd::begin(str)、イテレータのような?私はのstringような連続したメモリにいる義務があるとは思わないvectorか、それとも持っていますか?
xtofl

1
@xtofl:私はすでにそれらを編集しました。そしてはい、C ++ 11の時点で義務があります。これはC ++ 03では暗黙的でした。
オービットの軽さのレース

@xtofl:C ++ 03にはありません。C ++ 11では、front()関数とback()関数に加えて、元の回答で誤用されていた保証があります
Armen Tsirunyan

1
@Tomalak:彼らはあなたが必要とするの&back() + 1ではなく、誤用されました&back()
Armen Tsirunyan

12

これは、boboboboの回答に対するコメントとしては優れていますが、私はその担当者がいません。それは同じことを達成しますが、より良い実践で。

他の答えは役に立ちますが、constなしで明示的に変換std::stringする必要がある場合は、あなたの友達です。char*const_cast

std::string str = "string";
char* chr = const_cast<char*>(str.c_str());

これはデータのコピーを提供しないことに注意してください。文字列へのポインタを提供します。したがって、の要素を変更するとchr、も変更されstrます。


7

入力として渡すには、Cスタイルの文字列だけが必要だと仮定します。

std::string str = "string";
const char* chr = str.c_str();

5

厳密に言うと、「std :: stringをchar *またはchar []データ型に変換する」ことはできません。

他の回答が示しているように、std :: stringの内容をchar配列にコピーするか、またはstd :: stringの内容にconst char *を作成して、「Cスタイル」でそれにアクセスできるようにすることができます。 。

std :: stringの内容を変更しようとしている場合、std :: stringタイプには、実行する必要がある可能性のあることを実行するためのすべてのメソッドが含まれています。

char *を取る関数に渡そうとしている場合は、std :: string :: c_str()があります。


4

完全を期すために、忘れないでください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);

4

ここにもう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

+1は、文字列が空であることを確認します。私はまた、文字列が終了ゼロされていることを確認するためのチェックを追加します。 if (str[str.length()-1] != 0) str.push_back(0)
GaspardP

4

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 *へのキャストがc_strの出力からconstを排除する方法が好きです。c_strがconst char *を返す理由は、読み取り専用バージョンを提供することにより、潜在的なメモリアクセスの問題を排除するためです。OPはchar *を必要としていますが、c_strのconst char *出力がより安全であり、char *をとる関数は通常const char *も取ると思います(関数が入力の変更など、一般的にはすべきでないことを行います)。
フェリペバルデス


3

または、以下に示すように、ベクターを使用して書き込み可能な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  

これにより、ベクターに新しいメモリが割り当てられ、各文字がコピーされます。std :: stringは既にコンテナーです。文字列にpush_back(0)を実行して&str [0]を実行することもできます
GaspardP

3

イテレータを使用して作成できます。

std::string str = "string";
std::string::iterator p=str.begin();
char* chr = &(*p);

幸運を。


3

unique_ptrを使用したorlpのchar *応答の安全なバージョン:

std::string str = "string";
auto cstr = std::make_unique<char[]>(str.length() + 1);
strcpy(cstr.get(), str.c_str());

3

からを取得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::stringc_str()


2

これも機能します

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;  
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.