User6996
User6996

Reputation: 3013

Return filename from path

What did I do wrong here?

call

printf(filename(exename));

my function should return filename

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
}

Upvotes: 1

Views: 4789

Answers (2)

Mr.C64
Mr.C64

Reputation: 43044

str.substr(found+1) returns a temporary std::string. You call c_str() method on that temporary std::string, and assign the returned pointer to path. When the temporary is destroyed (at the ;), your path is pointing to garbage.

Make yourself a favor and use C++ (not C mixed with C++), using robust string classes like std::string to store strings (instead of raw potentially-dangling char* pointers):

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;
}

Note also that your use of path variable name is confusing, since the function seems to return the file name (not the path).

A simpler rewrite (without the path variable):

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());

...or just use cout (which plays well with std::string and doesn't require c_str() method call to get a raw C string pointer like in C printf() function):

std::cout << ExtractFileName("c:\\some\\dir\\hello.exe");

Upvotes: 6

antlersoft
antlersoft

Reputation: 14751

You are returning a pointer to memory that is held by a temporary (str.substr(found+1)).c_str(). When the temporary goes out of scope, the memory could be overwritten at any time.

str.substr(found+1) is an expression that returns a string. This object is a temporary value which will go away at the end of the execution of the expression that contains it. With .c_str(), you are getting a pointer to memory controlled by this object. After the object's lifetime, this pointer is no longer valid.

Try declaring path as a string, and having your function return a string instead of a pointer.

In general, you should avoid working with raw char * when you are also working with the std::string class. That means you should also avoid using printf; use the std::iostream classes instead.

Upvotes: 5

Related Questions