変更されたconst char *引数であるconst char *を返す関数を書くには?

私は関数を書く必要があります(C + +)は、定義は:

const char* getFileName(const char* name);

物事を短くするために、この関数は名前を取り、いくつかの条件をチェックし、後置にそれを付加して適切なファイル名にします。例えば:

name = "someFile"、return = "someFile-hd.png"

const char* returned by this function will be immediately passed to another, which takes const char* as an argument

something->loadFile(getFileName("someFile"));

私が持っている問題は、自分の関数に const char * を作成すると、スコープが作成された関数に限定されてしまうことです。一方、コードを変更することはできませんこれは、私が使用しているサードパーティのライブラリだからです。 loadFile

私が作成した const char * を削除するために loadFile のラッパーを書くことはできますが、これは移植作業であり、簡単にするために作成したテンプレートをいくつか破棄してください。

説明したようにこの関数を書く方法はありますか?

ありがとう

編集: 小さな説明:

getFileName is a function I am trying to write, I can change the return type, but it has to fit as a parameter to loadFile function. My main problem is that const char* returned by getFileName is either lost because it's out of scope or I have to delete it explicitly, which breaks my porting template. I would like to generate the filename in one function call and do nothing else about it [in other words, in original code I have loadFile("something.png") and I want to change it to loadFile(getFileName("something")) without adding any new lines after that.

0
明確にするために、あなたの主な問題は、getFileNameによって返されたconst char *を削除することですか?
追加された 著者 Chip,
はい、私はpスレッドと一緒に作業しており、確実にスレッドセーフであることが望ましいでしょう。
追加された 著者 Krystian,
getFileNameは、私が書き込もうとしている関数ですが、戻り値の型は変更できますが、loadFile関数のパラメータとして適合する必要があります。私の主な問題は、getFileNameからのconst char *が範囲外であるために失われているか、明示的に削除する必要があることです。これは移植テンプレートを破壊します。私は1つの関数呼び出しでファイル名を生成したいと思います。それについては何もしません。つまり、元のコードではloadFile( "something.png")があり、loadFile(getFileName( "something") )その後に新しい行を追加することなく。
追加された 著者 Krystian,
返される値はいつ有効になる必要がありますか?あなたが答える必要があるのは、それが返されたもののリリースを引き起こすために検出し、使用する必要がある条件なのでです。永遠なら、それを決して解放することはできません。同じスレッドで関数の次の呼び出しまでは、その後、それを行うためにTSDを使用することができます。
追加された 著者 David Schwartz,
@フレデリックハミディリエントラントである必要がない場合でも、静的な返信は非常に悪い考えです。 something-> loadSeveralFiles(getFileName( "someFile")、getFileName( "SomeOtherFile")); を考えてみましょう。同じファイルを2回開いて、もう一方を無視しました。 静的にポインタを返さない場合は、この変数の割り当てを呼び出し元に任せます。あるいは、それがオプションの場合はstd :: stringを使用してください。
追加された 著者 Lundin,
getFileName()の戻り値の型を変更できますか?
追加された 著者 hmjd,
@ Lundin、確かに、戻ってきた統計からポップアップできる厄介な副作用がたくさんあります。私は質問者のケースがあなたの特定の例について心配しないほど単純だと思っていました。私は strtok()のような関数が過去に私に多大な影響を及ぼしていたと思います。
追加された 著者 Frédéric Hamidi,
getFileName()はスレッドセーフかリエントラントか?そうでなければ、その関数にローカルな static バッファへのポインタを返すことができます。
追加された 著者 Frédéric Hamidi,

3 答え

getFileName()の戻り値の型を std :: string に変更できる場合は、次の操作を実行できます。

std::string getFileName(const char* a_name)
{
    std::string result(a_name);
    result += ".png";

    return result;
}

// No memory management req'd
something->loadFile(getFileName("someFile").c_str());
5
追加された
@リホ:これは動作し、標準準拠ですが、それは脆いです。 Standardは、完全な式の終わりまで(つまり、; に達するまで)一時的なものが存続することを明示しているので、 getFileName の結果は loadFile が実行されましたが、それ以上は実行されませんでした。一方、誰かがそれを char const * name = getFileName( "someFile")という2つの行にリファクタリングするとしたら、c_str(); s-> loadFile(name); これは未定義の動作 - >脆い、脆い...
追加された 著者 Matthieu M.,
Damn :)文字列の使用について考えましたが、文字列を返す代わりにresult.c_str()を返し、その後に.c_str()を実行しました!どうもありがとう!これは私のテンプレートを壊すことなくそれを解決する!
追加された 著者 Krystian,
私が知る限り、この目的のために .c_str()を使用することは、 std :: string result のコピーの存在に頼ることができないため、悪い習慣とみなされます。
追加された 著者 LihO,
@マチュー:感謝、私はそれを得た。
追加された 著者 LihO,
@Liho、ありがとうございますが、表現の終わりまで一時的なオブジェクトが存続するので、私はあなたができると思っています。
追加された 著者 hmjd,

const 引数を使用する主な論理は、引数を取る関数の本体でこの引数を変更しないということです。

変更する場合は、 const を使用しないでください。

char * const char * にキャストすることについては心配しないでください。このための暗黙の変換があります。

この const char * の引数を変更する必要はありません。 std :: string オブジェクトを構築し、メモリリークの可能性を避けるために使用できます。 hmjd </html> a>。

strcat は既に存在していますが、最初の文字列の長さを再計算するので、これはメモリをリークしています。あなたのものではない)。
追加された 著者 Matthieu M.,
@LihO:それはloadFileの機能に依存します。 loadFileは「何か」のメンバーですが、getFileNameはそうではないので、loadFileが自分のクラスに属していないメモリをクリーンアップすると仮定すると変です。私はMatthieuに同意する、これはメモリをリークし、したがって悪い練習です。さらに、C ++のようにポインタを返すことには本当に意味がありません。
追加された 著者 Lundin,
それは彼がそれをどのように使う予定かによって異なります。彼が something-> loadFile(getFileName( "someFile")); を呼び出す場合、それは漏れないでしょうか?効率を上げるためには、 std :: string の構築とhjmdによるソリューションのコピーとのオーバーヘッドよりもまだ高速だと思います。
追加された 著者 LihO,
うん。今私は、hmjdによる解決策がはるかに優れていることを認識しています。君たちありがとう。私は自分の答えを編集しました。
追加された 著者 LihO,

関数からのポインタを返すことは、通常、Cでは意味をなさない(さらにC ++ではあまり意味がない)。 これはCとC ++の両方にタグを付けたので、これはCの答えです。

これを行う一般的な方法は、次のようになります。

void getFileName (const char* name, 
                  char*       complete_name, 
                  size_t      complete_name_n)
{
  ...//create a new file name in a temp buffer

  if(the new file name has a strlen() < complete_name_n)
  {
    strcpy(complete_name, the new file name);
  }
}

// caller:
char name_buf [N];

getFileName(name, name_buf, N);
something->LoadFile(name_buf);

たとえば、Windows API全体がこのように正確に関数を呼び出し、呼び出し側にパラメータを割り当てたままにして、関数がメモリ割り当てなどではなくタスクにのみ関与するようにします。

もちろん、これは呼び出し元が1つではなく複数の行を入力する必要があることを意味します。この時点で、最も重要なことを自分自身に質問する必要があります。

  • to write clean function interfaces without obscure pointer returns nor strange, needless, leaking dynamic allocations, or
  • to type as little code as possible in the caller to reduce keyboard and programmer wear-and-tear.
1
追加された