So, the correct solution, hidden in an overloaded function, would be:
--Code:std::string dirname(const std::string &fullname) { char *tmp = strdup(fullname.c_str()); std::string result(dirname(tmp)); free tmp; return result; }
Mats
So, the correct solution, hidden in an overloaded function, would be:
--Code:std::string dirname(const std::string &fullname) { char *tmp = strdup(fullname.c_str()); std::string result(dirname(tmp)); free tmp; return result; }
Mats
Last edited by matsp; 05-29-2008 at 03:22 AM. Reason: Add const correctness and reference on input.
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
No, this leaks if std::string's constructor throws. The correct solution is
Code:vector<char> tmp(fullname.c_str(), fullname.c_str() + fullname.size() + 1); return std::string(dirname(&tmp[0]));
All the buzzt!
CornedBee
"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law
Alternatively (more for my own practice, really):
But it's a bit messy.Code:std::string dirname(const std::string &fullname) { char *tmp = strdup(fullname.c_str()); try { std::string result; result = dirname(tmp); } catch(...) { free tmp; throw; } free(tmp); return result; }
--
Mats
Last edited by matsp; 05-29-2008 at 08:24 AM.
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
And your forgot to free the string in the non-error case.
All the buzzt!
CornedBee
"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law
All the buzzt!
CornedBee
"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law
I find the vector an even bigger hack, but one I'd prefer over mats's slightly longer code.
The best solution would just be to have a function that returns a buffer, char* or wchar_t* from std::string, however. But once again we are not as lucky.
I find it funny how the things in the standard library seems to be more oriented towards a C interface rather than a C++ interface (just look at the streams and how they only accept char* or wchar_t*), but with std::string, it's lacking a critical function for C compability.
Or, we can do it this way:
Despite what you may think, this is better than strdup, since strdup will do strlen first, then strcpy, where this code only does strncpy(). It may take 4 or 8KB of stack-space, but it eliminates the need to allocate dynamic memory (and thus handle problems with freeing it).Code:std::string dirname(const std::string &fullname) { char tmp[MAX_PATH+1]; strncpy(tmp, fullname.c_str(), MAX_PATH); tmp[MAX_PATH] = 0; // Make sure there is a zero somewhere! std::string result(dirname(tmp)); return result; }
--
Mats
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
And "taking 4k of stack space" in a near-leaf function such as this only means modifying the stack pointer, so yeah, that's a good way.
Of course, MAX_PATH is Windows-only. There's a PATH_MAX in limits.h on POSIX.
All the buzzt!
CornedBee
"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
What's a near-leaf function?
A leaf function is one that calls no other functions. A near-leaf function was an on-the-spot word creation meaning a function that calls only leaf functions.
All the buzzt!
CornedBee
"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law
It's a function that is near the "end" of a call-tree (main being the "root" of such a tree - at leas from the general programmers, as we don't normally consider the code that calls main() as part of the program, even if it technically is). A leaf-funciton is one that doesn't call any other functions, and a "near leaf" is one that only calls leaf-functions in itself. [Although, I suppose that the std::string::string(const char *) constructor is likely to call at least the new operator.
--
Mats
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
Here's a version that doesn't depend on strdup or the POSIX call:
Code:std::string dirname(const std::string & path) { std::string dir = path.substr(0, path.find_last_of("/")); return ((dir != path) ? dir : std::string(".")); }