1

ここで何が間違っていましたか?

電話

printf(filename(exename));

私の関数はファイル名を返す必要があります

const char* filename(const string& str)
{
  const char* path;
  size_t found;
  found=str.find_last_of("/\\");
  path = (str.substr(found+1)).c_str();

  cout << str.substr(found+1); // ------------> is name ok 

  printf("\n\n");
  printf(path); // ------------> is name not ok random numbers
  printf("\n\n");
  return  path; // ------------> is not ok random numbers
}
4

2 に答える 2

6

str.substr(found+1)一時的な を返しますstd::stringその一時的なc_str()でメソッドを呼び出し、返されたポインターを に割り当てます。テンポラリーが (で) 破棄されると、パスはガベージを指しています。 std::stringpath;

C++ (C++と混合した C ではありません) を使用して、文字列std::stringを保存するような堅牢な文字列クラスを使用します (未加工の潜在的にぶら下がっているchar*ポインターの代わりに):

std::string FileName(const std::string& str)
{
  size_t found = str.find_last_of("/\\");
  std::string path = str.substr(found+1); // check that is OK
  return path;
}

pathまた、関数はパスではなくファイル名を返すように見えるため、変数名の使用は混乱を招くことに注意してください。

より単純な書き直し (path変数なし):

std::string ExtractFileName(const std::string& fullPath)
{
  const size_t lastSlashIndex = fullPath.find_last_of("/\\");
  return fullPath.substr(lastSlashIndex + 1);
}


printf("Filename = %s\n", ExtractFileName("c:\\some\\dir\\hello.exe").c_str());

...または単に使用しますcout(これは、C関数のように生のC文字列ポインターを取得するためにメソッド呼び出しでうまく機能しstd::string、必要としません):c_str()printf()

std::cout << ExtractFileName("c:\\some\\dir\\hello.exe");
于 2013-01-03T17:41:01.443 に答える
5

一時的に保持されているメモリへのポインターを返しています(str.substr(found+1)).c_str()。一時が範囲外になると、メモリはいつでも上書きされる可能性があります。

str.substr(found+1)を返す式ですstring。このオブジェクトは、それを含む式の実行が終了すると消える一時的な値です。では.c_str()、このオブジェクトによって制御されるメモリへのポインタを取得しています。オブジェクトの有効期間が過ぎると、このポインターは無効になります。

pathとして宣言し、関数がポインタでstringはなく を返すようにしてください。string

一般に、クラスchar *も操作している場合は、raw を操作することは避ける必要があります。std::stringつまりprintf、 ; の使用も避ける必要があります。std::iostream代わりにクラスを使用してください。

于 2013-01-03T17:19:43.890 に答える