2016-04-22 14 views
11

私が期待どおりに動作this codeを持っている:const char *をchar *に格納する方法は?

#define MAX_PARAM_NAME_LEN 32 

const char* GetName() 
{ 
    return "Test text"; 
} 

int main() 
{ 
    char name[MAX_PARAM_NAME_LEN]; 
    strcpy(name, GetName());  

    cout << "result: " << name << endl; 
} 

(私はフレームワーク内の一部の機能のみchar *入力として使用することを使用しているので)私はstrcpyを使用せずにchar *に結果を保存したい場合(コードの実用性と読みやすさ、そして学習するために)、どうすればいいですか?

const char* name; 
name = GetName(); 

を私はまだconstを持っている:constに維持する、これはうまく動作します。

だけchar*を使用しようとすると:

char* name; 
name = GetName(); 

私はinvalid conversion from 'const char*' to 'char*'を取得します。このような変換のための最良の習慣は何ですか?

Cで
+5

あなたは何をしたいですか?文字列を変更したくない場合、最初のイディオムがあなたにサービスを提供し、余分なメモリを使用しません。文字列を変更したい場合は、他の場所でその内容をコピーする必要があります(strcpyなどが必要です)。 – SJuan76

答えて

9

読み取り専用ストリングリテラルへのポインタを返します。

あなたが入力としてchar*を取る関数を使用している場合、あなたはconst char*(例えばリテラルの読み取り専用文字列として)、その後、あなたはそのconst char*で始まる文字列の深いコピーを供給するべきである持っていますそのような機能に。

また、関数が読み取り専用文字列を変更しようとすると、実行時に未定義の動作が発生する危険性があります。

あなたの現在のものは十分です。 std::stringで作業できないと仮定します。 (あなたがstd::stringすべてのフレームワークの機能を持つ仕事はconst char*入力を取ることができ場合、私はあなたがstd::stringを使用するようにコードをリファクタリングを提案し、あなたのフレームワークにその文字列クラスのc_str()メソッドの出力を渡したいです機能。最後に)

、あなたのフレームワークの機能のいくつかは、あなたは常に自分自身に小さなアダプタクラスを構築することができchar*が必要な場合:

class Adapter 
{ 
public: 
    Adapter(const& Adapter) = delete; /*don't try to copy me please*/ 
    Adapter& operator=(const Adapter&) = delete; /*don't try to copy me please*/ 
    Adapter(const char* s) : m_s(::strdup(s)) 
    { 
    } 
    ~Adapter() /*free memory on destruction*/ 
    { 
     ::free(m_s); /*use free to release strdup memory*/ 
    } 
    operator char*() /*implicit cast to char* */ 
    { 
     return m_s; 
    } 
private: 
    char* m_s; 
}; 

は次に機能void foo(char* c)のために、あなたはfoo(Adapter("Hello"/*or any const char* */));を呼び出すことができますし、fooはそれとして行うことができます匿名の暫定版に組み込まれているchar*で満足しています!このクラスを拡張して、コンストラクタをchar*にすることもできます。その場合、ポインタの浅いコピーのみが使用されます(デストラクタはメモリを削除しません)。

+0

'const char *'の内容を 'char *'に "コピー"したいのですが(固定サイズを指定せずに)?私はそのchar *のサイズを知りません、後で私は他のcharを連結するでしょうから。 – markzzz

+0

ああ待ってください。私は 'char * name;'と 'strcpy(name、GetName()); 'も使うことができます。基本的に、私は長さが決められていない文字列を持っています。これは私の仕事に役立ちます。それは正しいのでしょうか? – markzzz

+1

@paizzaいいえ 'std :: string name = GetName();'のようなものを使って、 'const char *'を期待するフレームワーク関数に 'name.c_str()'を渡します。 – Andrew

-1

++、「constをドロップ」する典型的な方法は、const_cast<>を使用することです:

char *name = const_cast<char*>(GetName()); 

これは、もちろん、それはGetName()ポインタを返すことは本当に可能なので、眉をひそめ醜いと潜在的に危険なのを変更しないでください。、そして次にあなたはそれを変更する許可を与えます。その場合、バグを見つけるのは非常に難しくなります。

一時的な保持領域としてstd::stringを使用することで回避できます。それは、文字列のコピーを意味しますが、それは許容できる性能面であるかもしれない:sがスコープの外に出るときnameが周りに保持されていない場合にのみ動作これはもちろん

std::string s(GetName()); 
char *name = s.c_str(); 

。その場合は、永続的なストリング・ストレージ・レイヤーを使用することになります。

return "Test text";
+3

'const char *'未定義の動作からconstを削除していませんか? – Default

+1

私が尋ねることができるのであれば、他の提案をしなくても、何が欲しかったのか、なぜ示唆していますか? – Default

+0

@Defaultそれはポスターがどうやってやりたいのかと思っていたので、問題の状況でそれが悪いことを確かに知ることはできませんでした。 – unwind

15

この種の変換のベストな習慣は、コード全体でstd::stringを使用することです。使用しているフレームワークは、その入力としてconst char*がかかるため、あなたは常にあなたのstd::stringにそれをc_str()呼び出しの結果を渡すことができます。

std::string GetName() { 
    return "Test text"; 
} 

int main() { 
    std::string name = GetName(); 
    int res = external_framework_function(name.c_str()); 
    cout << "result: " << res << " for " << name << endl; 
} 

を遠くのコード内でconst char*を使用している次善:

const char* name = GetName(); 

あなたが使用しているフレームワークはconst char*なので、ここでもうまくいきます。

非constポインタが必要な場合は、文字列をコピーする方法がありません。あなたはあなたのためにそれを行う関数を作ることができますが、あなたはそれから入手コピーを解放する責任残る:

char* copy(const char* orig) { 
    char *res = new char[strlen(orig)+1]; 
    strcpy(res, orig); 
    return res; 
} 
... 
char *name = copy(GetName()); 
... 
delete[] name; 
-2

あなたが明示的にキャストすることができます。 (char*) getName()。しかし、おそらくあなたはすべきではありません。 constビットは「それを変更しないことを約束する」のような意味を持つためです。だから私は関数を持っている場合void foo(const char* string)私はsaiyingです: "私に文字列へのポインタを与える。私はそれを変更しません。 変数を宣言した場合const char* string = "hello";この文字列は変更しないでください。この約束を守ることで、コンパイラーはコンパイラーを認識し、コードをより効率的にすることができます。あなたのコンパイラはあなたがaまたはbので、それは彼らが同じアドレスを指しますので、それが唯一の"hello"文字列を格納する必要がありますを変更することはありません知っている

const char* a = "hello"; 
const char* b = "hello"; 
(a==b); //is probably true 

:理由です。 aの変更については、bも変更されています。これはあなたが望むものではありません。

ストーリーが短いので、あなたの呼び出しが文字列を変更しないことを確信しているなら、明示的にキャストすることができます。 (それ以上の場合は、機能を(const char*)に変更してください)。
不明な点がある場合は、コピーを作成する必要があります。 (あなたがすでにstrcpy()でやっているように)。

+2

なぜあなたはポットを提案していますか?本当に危険なキャスト? C++文字列リテラルから非const C文字列を取得する唯一の正しい方法は、それをコピーすることです。非constキャストバージョンを変更しようとする試みはすべてUBです。行の中でプログラムの動作を診断するのが難しい(ほとんど確実に)方法を提案しないでください。 – Andrew

関連する問題