Рекурсивный CreateDirectory

Я нашел много примеров рекурсивного использования MakingDirectory, но не тот, который искал.

вот спецификация

Учитывая ввод

  1. \\сервер\доля\аа\бб\куб
  2. c:\aa\bb\cc

ИСПОЛЬЗОВАНИЕ вспомогательного API

 CreateDirectory (char * path)
 returns true, if successful
 else
 FALSE

Условие: не должно быть никакого синтаксического анализа, чтобы определить, является ли путь локальным или общим ресурсом сервера.

Напишите подпрограмму на C или C++


person jacob    schedule 04.10.2009    source источник
comment
Это вопрос домашнего задания? (это не проблема, если это так)   -  person John Carter    schedule 05.10.2009
comment
В случае сбоя, не хотели бы вы узнать (и сообщить вызывающему абоненту), почему это не удалось? Причины сбоя включают: no permission, file with same name already exists, no space on disk.   -  person pmg    schedule 05.10.2009
comment
Дубликат stackoverflow.com/q/1530760/103167, за исключением того, что прямо не сказано, что CreateDirectory означает функцию Win32 (хотя большинство ответов предположил, что да)   -  person Ben Voigt    schedule 23.04.2015


Ответы (8)


Я думаю, что это намного проще... вот версия, которая работает во всех версиях Windows:

unsigned int pos = 0;
do
{
    pos = path.find_first_of("\\/", pos + 1);
    CreateDirectory(path.substr(0, pos).c_str(), NULL);
} while (pos != std::string::npos);

Юникод:

pos = path.find_first_of(L"\\/", pos + 1);

С уважением,

person Didac Perez Parera    schedule 05.10.2012
comment
Примечание: pos должен быть целым числом со знаком, а не целым числом без знака, иначе результат npos переполнится, и вы застрянете в бесконечном цикле. - person Liam Potter; 07.11.2017
comment
pos должен быть size_t. - person Gediminas; 26.05.2018

Это может быть именно то, что вы хотите. Он не пытается выполнить синтаксический анализ, чтобы определить, является ли путь локальным или общим ресурсом сервера.

bool TryCreateDirectory(char *path){
    char *p;
    bool b;

    if(
        !(b=CreateDirectory(path))
        &&
        !(b=NULL==(p=strrchr(path, '\\')))
        ){
        size_t i;

        (p=strncpy((char *)malloc(1+i), path, i=p-path))[i]='\0';
        b=TryCreateDirectory(p);
        free(p);
        b=b?CreateDirectory(path):false;
    }

    return b;
}

Алгоритм довольно прост, просто рекурсивно передайте строку каталога более высокого уровня, в то время как создание каталога текущего уровня завершается ошибкой до тех пор, пока не будет достигнут один успех или не будет более высокого уровня. Когда внутренний вызов возвращается с успехом, создайте текущий. Этот метод не анализирует сам локальный или серверный файл, он соответствует CreateDirectory. В WINAPI CreateDirectory никогда не позволит вам создать «c:» или «\», когда путь достигает этого уровня, метод вскоре сваливается на вызов самого себя с путем = «», и это тоже терпит неудачу. Это причина, по которой Microsoft определяет такое правило именования файлов для совместимости с правилом пути DOS и упрощает кодирование.

person Ken Kin    schedule 03.09.2011
comment
+1 за алгоритм, но ваш стиль кодирования ужасен. Кстати, с MinGW (=gcc) вы должны вычислить i вне вызова strncpy. - person Seki; 21.02.2012

Совершенно хакерский и небезопасный, и ничего такого, что вы когда-либо хотели бы делать в производственном коде, но...

Внимание: здесь будет код, который был набран в браузере:

int createDirectory(const char * path) {
  char * buffer = malloc((strlen(path) + 10) * sizeof(char));
  sprintf(buffer, "mkdir -p %s", path);
  int result = system(buffer);
  free(buffer);
  return result;
}
person Dave DeLong    schedule 04.10.2009
comment
Есть худшие способы сделать это. Когда-то, несколько десятилетий назад, это было бы необходимо: в версии 7 Unix mkdir была корневой программой SUID, и не было системного вызова mkdir() (но не было и опции -p для mkdir). - person Jonathan Leffler; 05.10.2009

Как насчет использования MakeSureDirectoryPathExists()?

person Stefan    schedule 05.10.2009
comment
Эта функция не поддерживает строки Unicode. Чтобы указать путь в формате Unicode, используйте функцию SHCreateDirectoryEx. - person Cody Gray; 14.07.2016

Просто пройдитесь по каждому уровню каталога по пути, начиная с корня, пытаясь создать следующий уровень.

Если какой-либо из вызовов CreateDirectory завершится ошибкой, вы можете выйти раньше, вы добились успеха, если дошли до конца пути без сбоя.

Предполагается, что вызов CreateDirectory по уже существующему пути не имеет негативных последствий.

person John Carter    schedule 04.10.2009
comment
Единственное, на что следует обратить внимание, — это разные ошибки «отсутствие разрешения» и «каталог уже существует». Попытка создать существующий каталог просто потерпит неудачу (если вы не используете устаревшую версию NFS, когда могут произойти всевозможные странности). - person Jonathan Leffler; 05.10.2009

Требование не анализировать имя пути для имен серверов интересно, так как кажется, что требуется анализ для /.

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

Если это домашняя работа, я могу выдать алгоритм, который вы должны были придумать, но мне приходит в голову, что один из способов выполнить эти требования — начать попытки с попытки mkdir полного имени пути. Если это не удается, отрежьте последний каталог и повторите попытку, если это не удастся, отрежьте другой и повторите попытку... В конце концов вы должны добраться до корневого каталога без необходимости понимать синтаксис сервера, а затем вам нужно будет начать добавлять компоненты пути обратно и создавать подкаталоги один за другим.

person DigitalRoss    schedule 05.10.2009

person    schedule
comment
Нет необходимости в рекурсии. ПРИМЕЧАНИЕ. «C:\mydir\mydir.txt\mydir.pdf\here» — допустимый путь. - person jasnmoore; 18.11.2011

person    schedule
comment
Не могли бы вы добавить текст, объясняющий ваш ответ? - person Kmeixner; 14.04.2016
comment
createFloders(a/b/c/d/e,'/'); - person Awais Rafique; 15.04.2016