Я вижу C getcwd через: человек 3 cwd
Я подозреваю, что у С++ есть аналогичный, который может вернуть мне std::string.
Если да, то что он называется, и где я могу найти его документацию?
Спасибо!
Я вижу C getcwd через: человек 3 cwd
Я подозреваю, что у С++ есть аналогичный, который может вернуть мне std::string.
Если да, то что он называется, и где я могу найти его документацию?
Спасибо!
Хорошо, я отвечаю, хотя вы уже приняли ответ.
Еще лучше, чем обернуть вызов getcwd, будет использовать boost:: filesystem, где вы получаете объект path
из функции current_path()
. Библиотека файловой системы Boost позволяет вам делать много других полезных вещей, которые вам в противном случае понадобились бы для выполнения синтаксического анализа строк, например, проверки наличия файлов/каталогов, получения родительского пути, создания путей и т.д. Проверьте это, он также переносится, - что много кода синтаксического анализа строки, который в противном случае использовали бы, вероятно, не будет.
Обновление (2016): Файловая система была опубликована как техническая спецификация в 2015 году на основе Boost Filesystem v3. Это означает, что он может быть доступен уже с вашим компилятором (например, Visual Studio 2015). Для меня также кажется вероятным, что он станет частью будущего стандарта С++ (я бы предположил С++ 17, но я не знаю текущего состояния).
Обновление (2017): библиотека файловой системы была объединена с ISO С++ в С++ 17, для
std::filesystem::current_path();
std::string
конструктор может с уверенностью принять char*
в качестве параметра. Удивительно, что есть и версия Windows.
Изменить: на самом деле это немного сложнее:
std::string get_working_path()
{
char temp[MAXPATHLEN];
return ( getcwd(temp, MAXPATHLEN) ? std::string( temp ) : std::string("") );
}
Память не является проблемой - temp - это буфер на основе стека, а конструктор std::string выполняет копирование. Возможно, вы могли бы сделать это за один раз, но я не думаю, что этот стандарт будет гарантировать это.
О распределении памяти через POSIX:
Функция getcwd() должна указывать абсолютный путь к текущему рабочему каталогу в массиве, на который указывает buf, и возвращать buf. Путь скопирован в массив не должен содержать компонентов, которые являются символьными ссылками. Аргумент размера - это размер в байтах массива символов, на который указывает аргумент buf. Если buf является нулевым указателем, поведение getcwd() не указано.
Попробуйте переписать этот простой вызов 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());
}
}
}
Дело в том, что при обертке библиотечной функции в другой функции вы должны предположить, что все функции должны быть открыты, потому что библиотека не знает, что ее вызовет. Поэтому вам приходится обрабатывать ошибки, а не просто глотать их или надеяться, что их не произойдет.
Как правило, лучше, чтобы код клиента просто вызывал библиотечную функцию и обрабатывал ошибку в этот момент - код клиента, вероятно, не волнует, почему произошла ошибка, и поэтому он должен обрабатывать только случай прохождения/отказа, а не кодами ошибок.
Вам нужно просто написать небольшую обертку.
std::string getcwd_string( void ) {
char buff[PATH_MAX];
getcwd( buff, PATH_MAX );
std::string cwd( buff );
return cwd;
}
Все функции C также являются функциями С++. Если вам нужен std::string
, просто создайте его из char*
, который получит getcwd.
Я использовал getcwd()
в C следующим образом:
char * cwd;
cwd = (char*) malloc( FILENAME_MAX * sizeof(char) );
getcwd(cwd,FILENAME_MAX);
Требуется файл заголовка stdio.h
.
Когда я использую компилятор C, он отлично работает.
Если я компилирую точно такой же код с помощью компилятора С++, он сообщает следующее сообщение об ошибке:
identifier "getcwd" is undefined
Затем я включил unistd.h
и скомпилировал с компилятором С++.
На этот раз все работает.
Когда я переключился на компилятор C, он все равно работает!
Пока вы включаете как stdio.h
, так и unistd.h
, приведенный выше код работает для компиляторов C и С++.
Я также использовал boost:: filesystem, как указано в другом ответе выше. Я просто хотел добавить, что поскольку функция current_path() не возвращает std::string, вам необходимо ее преобразовать.
Вот что я сделал:
std::string cwd = boost::filesystem::current_path().generic_string();
Вы можете создать новую функцию, которую я бы предпочел связать с библиотекой, например boost (если вы уже не знаете).
std::string getcwd()
{
char* buff;//automatically cleaned when it exits scope
return std::string(getcwd(buff,255));
}