Оберните блок С в функции. Вопрос новичка - PullRequest
0 голосов
/ 23 мая 2011

Я нашел фрагмент C, чтобы получить текущий рабочий каталог отсюда . По сути, код:

char directory[_MAX_PATH];
getcwd(directory, sizeof(directory))

Я хочу абстрагировать это в другую функцию, в другой файл (чтобы при необходимости его можно было выгружать на разных платформах).

В настоящее время у меня есть внешний файл

void getCurrentDirectory(char *directory) {
    getcwd(directory, sizeof(directory));
}

и в основном файле

char directory[100];
getCurrentDirectory(directory);
printf("%s", *directory);

Однако при печати на экран я получаю глупости (возможно, пытаюсь распечатать ячейку памяти в виде строки?)

Я уверен, что это что-то ослепительно очевидное для новичка. Что происходит?

Редактировать: Я на Windows 7, кстати

Спасибо.

Ответы [ 8 ]

2 голосов
/ 23 мая 2011

Здесь есть несколько вещей, которые вы делаете неправильно:

void getCurrentDirectory(char *directory) 
  {
      getcwd(directory, sizeof(directory));
  }

Ошибка 1:

`sizeof(directory)` 

дает вам размер указателя, если быть точным, char *. Ваше намерение - передать размер массива, а не размер указателя.

Ошибка 2:

`printf("%s", *directory);` 

Передает первый элемент массива в printf, а не в адрес массива. Ваше намерение состоит в том, чтобы напечатать весь массив, а не только первый элемент.

Исправленное решение

Вы должны делать

void getCurrentDirectory(char *directory, size_t arrSize)  
{                                         ^^^^^^^^^^^^^^
    getcwd(directory, arrSize);
}

Размер массива передается явно, поэтому функция может просто использовать его.

В основном при печати содержимого массива:

   printf("%s", directory);
2 голосов
/ 23 мая 2011

Если это C ++, я бы посоветовал использовать boost :: filesystem , если это вообще возможно, что скрывает все детали базовой платформы и дает вам интерфейс в стиле C ++ вместо буфера склонные к переполнению функции C.

2 голосов
/ 23 мая 2011

Эта строка: printf("%s", *directory);

должно быть: printf("%s", directory);

Вы передаете первый элемент (directory [0]) в printf, а не указатель на массив char.

2 голосов
/ 23 мая 2011

Вы передаете размер символа * в getcwd вместо размера массива.

Передаете параметр размера в вашу функцию.

void getCurrentDirectory(char *directory, size_t size) {
    getcwd(directory, size);
}

и затем:

char directory[100];
getCurrentDirectory(directory, sizeof(directory));
printf("%s", *directory);

Кроме того, если вы используете Windows, вам, вероятно, следует изменить размер массива на предварительно определенный MAX_PATH, чтобы избежать потенциального переполнения буфера.getcwd занимает много времени, но я не думаю, что все файловые функции делают.

1 голос
/ 23 мая 2011

Поскольку это C ++, почему бы не сделать это:

std::string getCurrentDirectory()
{
    char directory[_MAX_PATH] = {};
    getcwd(directory, sizeof(directory));
    return directory;
}
1 голос
/ 23 мая 2011

Вы должны выделять буфер локально (где необходимо длина известна, и фактическая длина должна быть известна) и возвращение строки:

std::string
getCurrentDirectory()
{
    char results[_MAX_PATH];
    if ( getcwd( results, sizeof(results) ) == NULL )
        throw std::ios_base::failure( "Could not get current directory" );
    return std::string( results );
}

Обратите внимание, что _MAX_PATH это только предположение; фактический максимум не постоянная времени компиляции (так как это зависит от файла система). Реализация, которая принимает это во внимание, может выглядеть примерно так:

std::string
getCurrentDirectory()
{
    long length = pathconf( ".", _PC_PATH_MAX );
    if ( length == -1 )
        throw std::ios_base::failure(
                "Could not determine necessary buffer length to get current directory" );
    std::string results( length, '\0' );
    if ( getcwd( &results[0], results.size() ) == NULL )
        throw std::ios_base::failure( "Could not get current directory" );
    results.resize( strlen( results.c_str() );
    return results;
}

Это, вероятно, излишне, если программа только для использования в персональной системе без дисков NFS или SMB.

0 голосов
/ 23 мая 2011

Теперь, чтобы ответить на то, что вы спросили:

Когда getcwd по какой-то причине не работает, содержимое массива, на которое указывает directory (в вашем случае), не определено.Следовательно, с вашей ошибочной реализацией вы увидите мусор в большинстве случаев.(Кроме того, вы должны проверить возвращаемое значение из getcwd, в случае сбоя оно возвращает -1)

Теперь причиной сбоя в вашем случае является размер, который вы указываете с помощью sizeof(directory), это просторазмер указателя (который, вероятно, будет равен 4) и количество символов в имени текущего рабочего каталога, который вы пытаетесь распечатать, больше.Это будет хорошо работать для каталога размером 3 или меньше.

И, наконец, многие другие здесь уже объяснили вам, как это исправить.

0 голосов
/ 23 мая 2011

Вы не можете узнать размер блока памяти, на который указывает указатель, используя sizeof, подобный этому.Он оценивает размер самого указателя.

Измените вашу функцию на:

void getCurrentDirectory(char *directory, size_t buf_max)
{
    getcwd(directory, buf_max);
}
...