Question

I see C's getcwd via: man 3 cwd

I suspect C++ has a similar one, that could return me a std::string .

If so, what is it called, and where can I find it's documentation?

Thanks!

Was it helpful?

Solution

Ok, I'm answering even though you already have accepted an answer.

An even better way than to wrap the getcwd call would be to use boost::filesystem, where you get a path object from the current_path() function. The Boost filesystem library allows you to do lots of other useful stuff that you would otherwise need to do a lot of string parsing to do, like checking if files/directories exist, get parent path, make paths complete etcetera. Check it out, it is portable as well - which a lot of the string parsing code one would otherwise use likely won't be.

Update (2016): Filesystem has been published as a technical specification in 2015, based on Boost Filesystem v3. This means that it may be available with your compiler already (for instance Visual Studio 2015). To me it also seems likely that it will become part of a future C++ standard (I would assume C++17, but I am not aware of the current status).

Update (2017): The filesystem library has been merged with ISO C++ in C++17, for

std::filesystem::current_path();

OTHER TIPS

std::string's constructor can safely take a char* as a parameter. Surprisingly there's a windows version too.

Edit: actually it's a little more complicated:

std::string get_working_path()
{
   char temp[MAXPATHLEN];
   return ( getcwd(temp, sizeof(temp)) ? std::string( temp ) : std::string("") );
}

Memory is no problem -- temp is a stack based buffer, and the std::string constructor does a copy. Probably you could do it in one go, but I don't think the standard would guarantee that.

About memory allocation, via POSIX:

The getcwd() function shall place an absolute pathname of the current working directory in the array pointed to by buf, and return buf. The pathname copied to the array shall contain no components that are symbolic links. The size argument is the size in bytes of the character array pointed to by the buf argument. If buf is a null pointer, the behavior of getcwd() is unspecified.

Let's try and rewrite this simple C call as C++:

std::string get_working_path()
{
    char temp [ PATH_MAX ];

    if ( getcwd(temp, PATH_MAX) != 0) 
        return std::string ( temp );

    int error = errno;

    switch ( error ) {
        // EINVAL can't happen - size argument > 0

        // PATH_MAX includes the terminating nul, 
        // so ERANGE should not be returned

        case EACCES:
            throw std::runtime_error("Access denied");

        case ENOMEM:
            // I'm not sure whether this can happen or not 
            throw std::runtime_error("Insufficient storage");

        default: {
            std::ostringstream str;
            str << "Unrecognised error" << error;
            throw std::runtime_error(str.str());
        }
    }
}

The thing is, when wrapping a library function in another function you have to assume that all the functionality should be exposed, because a library does not know what will be calling it. So you have to handle the error cases rather than just swallowing them or hoping they won't happen.

It's usually better to let the client code just call the library function, and deal with the error at that point - the client code probably doesn't care why the error occurred, and so only has to handle the pass/fail case, rather than all the error codes.

You'll need to just write a little wrapper.

std::string getcwd_string( void ) {
   char buff[PATH_MAX];
   getcwd( buff, PATH_MAX );
   std::string cwd( buff );
   return cwd;
}

All C functions are also C++ functions. If you need a std::string, just create one from the char* that getcwd gets for you.

I used getcwd() in C in the following way:

char * cwd;
cwd = (char*) malloc( FILENAME_MAX * sizeof(char) );
getcwd(cwd,FILENAME_MAX);

The header file needed is stdio.h. When I use C compiler, it works perfect.

If I compile exactly the same code using C++ compiler, it reports the following error message:

identifier "getcwd" is undefined

Then I included unistd.h and compiled with C++ compiler. This time, everything works. When I switched back to the C compiler, it still works!

As long as you include both stdio.h and unistd.h, the above code works for C AND C++ compilers.

I also used boost::filesystem as stated in another answer above. I just wanted to add that since the current_path() function does not return a std::string, you need to convert it.

Here is what I did:

std::string cwd = boost::filesystem::current_path().generic_string();

You could create a new function, which I would prefer over linking to a library like boost(unless you already are).

 std::string getcwd()
 {
     char* buff;//automatically cleaned when it exits scope
     return std::string(getcwd(buff,255));
 }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top