2017-02-05 7 views
0

私のファイル名にはchar*が必要です。strとint ptrを連結するには

char* getFileName(int* pc1_no, char* suite) 
{ 
    int number; 
    char pCard1[80]; 
    strcpy_s(pCard1, "cards/"); 
    strcat_s(pCard1, suite); 
    number = *pc1_no; 
    cout << number << endl; 
    string str = to_string(number); 
    char const *pchar = str.c_str(); 
    strcat_s(pCard1, pchar); 
    strcat_s(pCard1, ".bmp"); 

    return pCard1; 
} 

もちろん、ゴミを返します。私は、様々なSO記事から一緒に石畳の機能を持っているcards/h11.bmp

:それはこのようなものでなければなりません。私はかなりポインタ値を取得することはありません。私はかなり私がポインタで間違ったミスを犯したと確信しています。前もって感謝します。

+1

あなたは実際に何をしようとしていますか? –

+0

整数値を格納するためにintポインタを使う以外に選択肢はありません。 "cards/h" + pc1_no + ".bmp"という2つの文字列の間に整数値を入れる必要があります。 – Randy

+1

おそらく、(おそらく 'stringstream'sを含む)文字列全体を使いやすく、実際に必要な場所にcharポインタを抽出するだけです。これは、Cスタイルの文字列を、配列や配列へのポインタとしてではなく文字列のようなオブジェクトのように扱い、ポインタをローカルメモリに返すなどの典型的なポインタミスをするという典型的なミスを回避するでしょう関数が終了するとすぐに消えます。 – Hurkyl

答えて

7

ここでは、このコードは、C++のようにどのように見えるかです値(int n)と必要に応じてコールサイトで参照解除を行います。

+0

Awww。あなたは 'suite'を' string'として渡しました。詐欺師! – user4581301

+1

@ user4581301:これは私の答えがC++のためです:...-) –

8

これは、すべてのポインタを取り除くれるすべて行うと、通過方法の全てを文字列を使用するための最良の方法:

std::string getFileName(int pc1_no, 
         const std::string & suite) 
{ 
    std::string pCard1 = "cards/" + suite + std::to_string(pc1_no) + ".bmp"; 
    return pCard1; 
} 

歳以上のC++標準に構築する場合std::to_stringは使用できません。

std::string getFileName(int pc1_no, 
         const std::string & suite) 
{ 
    std::stringstream pCard1; 
    pCard1<< "cards/" << suite << pc1_no << ".bmp"; 
    return pCard1.str(); 
} 

合理

char pCard1[80]; 

はローカル変数です。関数の終わりに消滅するので、関数は無効なメモリへのポインタを返します。結果として多くの悪いことが起こり、良いことはほとんどありません。いくつかの良いことに注意してください。彼らはストライキの最も適切な時期を待っている嘘つきです。

OPの構造を維持する最も簡単な解決策は、std::stringを使用して関数内で文字列操作を実行することです。

std::string getFileName(int* pc1_no, char* suite) 
{ 
    std::string pCard1 = "cards/"; 
    pCard1 += std::string(suite); 
    pCard1 += std::to_string(*pc1_no); 
    pCard1 += std::string(".bmp"); 
    return pCard1; 
} 

上記の恐ろしいコードが、過度に冗長で非効率的でもあるが、我々はすでにイントロで正しい方法を取り上げました。これは、その正しい方法への論理的進歩のタッチポイントにすぎません。

std::stringstreamは、外部の助けなしにCスタイルの文字列と数値を書式設定する機能を利用することがより高速で複雑です。このアプローチはおそらくstd::to_stringがC++ 11標準で利用可能になるまで最高です。

std::string getFileName(int* pc1_no, char* suite) 
{ 
    std::stringstream pCard1; 
    pCard1<< "cards/" << suite << *pc1_no << ".bmp"; 
    return pCard1.str(); 
} 

あり値によってstringを返すパフォーマンスの低下の可能性があるが、過去数十年のコンパイラが検出しopportunities to omit unnecessary copyingemploying move semantics behind the scenesを活かし得意です。

stringを値で返すことは、記憶域を動的に割り当てて、呼び出し元に解放することを期待して呼び出し元に記憶域を返すことよりもはるかにエラーが少なくなります。残っている可能性のあるパフォーマンスペナルティは、価格に見合った価値がある可能性が高いです。

はポインタがどのような方法で支援していないようにpc1_noを渡す:Profile the code to be sure.

関数呼び出しを改善します。関数内の値を変更する必要がある場合を除き、値渡しするだけです。値を変更する必要がある場合は、参照を優先してください。

std::string getFileName(int pc1_no, char* suite) 

あなたは文字列リテラルを渡すしようとした場合:例えば:

getFileName(&somenumber, "string literal"); 

文字列リテラルは、非書き込み可能なメモリでも、常にC++でconst char *ていることがあります。 const値を、値の変更を試みる可能性のある領域に渡すと、不正な形式になります。これは古いC++標準の下でのCとの下位互換性のために許されていましたが、警告を生成するかもしれませんが、C++ 11標準の後では不正です。

関数がchar配列の内容を変更する必要はありません、これがない場合、それはconstとして文字列をタグ付けし、コンパイラは関係なく、あなたのコンパイラがconstができるようにするかどうかの事故を防止できるようにするとよいでしょう非const割り当て:

std::string getFileName(int pc1_no, const char* suite) 

それは両方constと非constcharアレイから暗黙的に変換され、あなたのプログラムの残りの部分はを利用することができますよう、あなたがconst std::stringへの参照を使用する場合は、より汎用性を有することができます多くの有益者とdataを不必要に呼び出すことなく、std::stringのtsを返します。 。

#include <string> 

std::string getFileName(int* n, const std::string& suite) { 
    return "cards/" + suite + std::to_string(*n) + ".bmp"; 
} 

さらに良いことで最初のパラメータを取るために、次のようになります。

バックこの答えが入って来たところに私たちをもたらします
std::string getFileName(int pc1_no, 
         const std::string & suite) 

+0

_ "strcpy_s(pCard1、" cards/");はちょうど何でもできます。_私はそれが当てはまるとは思わない。 –

+0

'std :: toString'は存在しません –

+0

' pCard1 + = std :: string(suite); 'Wasteful; 'std :: string :: append'を使います。 –

関連する問題