Какой хороший кроссплатформенный способ объединения путей в C?

#c #path #cross-platform #concatenation

#c #путь #кроссплатформенный #объединение

Вопрос:

На данный момент у меня есть path_concat(char* path_fragment_a, char* path_fragment_b) функция, которая просто объединяет вместе path_fragment_a , PATH_DIVIDER , и path_fragment_b . (PATH_DIVIDER #определен в блоке #ifdef, поэтому он есть в Windows и / везде.)

Но я не могу не думать, что это кажется:

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

Поиск в Google только что дал много результатов о Python os.path.join (что было бы идеально, за исключением того, что это Python, а не C), поэтому мне было интересно, знает ли кто-нибудь о более чистом / более стандартном решении.

Ответ №1:

Прежде всего, вы должны использовать snprintf , а не операции конкатенации, для создания строки сразу. Это безопасный и эффективный способ. Конкатенация может быть идиоматичной в языках сценариев, но она неэффективна и вредна (подвержена опасным ошибкам) в C.

С учетом сказанного, с тех пор, как первая версия DOS, в которой были каталоги (2 или 3; я забыл, что это было), '/' была действительна в качестве разделителя путей в DOS, и она всегда была действительна и в Windows. Единственная причина, по которой он не использовался, заключается в том, что многие устаревшие программы командной строки, разработанные до DOS, поддерживали каталоги, интерпретируя '/' их как символ «switch» (опция) при синтаксическом анализе командной строки. Единственная реальная система за последние 20 лет, которая не поддерживалась '/' в качестве разделителя путей, — это macOS до OSX, и я не думаю, что это больше жизнеспособная цель, поэтому, на мой взгляд, вы должны просто всегда использовать '/' и избегать загрязнения вашего кода безвозмездной «переносимостью».

Комментарии:

1. Хотя последняя версия Windows принимает ‘/’, я почти уверен, что помню, как старые версии DOS отвергали его (по крайней мере, в интерпретаторе команд). Может быть, я неправильно помню…

2. Как я уже сказал, некоторые программы командной строки DOS сами интерпретируются '/' как символ переключения перед передачей строки вызовам доступа к файловой системе, и в этом случае вам не повезло. Но на уровне файловой системы это всегда работало.

3. Ах, хорошая мысль snprintf (и да, я больше привык к языкам сценариев). Итак, я думаю, что лучшие варианты либо в основном такие же, как у меня сейчас (но с snprintf вместо strcat ), либо предположить (вероятно, точно), что он никогда не будет работать в системе, где / не все правильно. Спасибо!

4. Если вы действительно хотите поддерживать разные разделители, вы можете разрешить определять строку формата для каждой целевой платформы (например "%s/%s/%s" , versus "%s\%s\%s" ) или использовать %c ‘s в строке формата, чтобы разрешить вставку произвольного символа разделителя.

5. В Python os.path.join есть функция, при которой, если последующие пути начинаются с / , вся предыдущая часть пути отбрасывается. Это полезно, если вы хотите добавить имя файла CWD , если оно не начинается с / , но используйте его как есть, если оно начинается с / . Простое использование snprintf не дает вам этого.

Ответ №2:

К сожалению, в стандартной библиотеке C нет такой функции для объединения путей к файлам. Вам придется делать это вручную.

Ответ №3:

По-видимому, у GLib есть некоторые функции (например g_build_path ) и макросы ( G_DIR_SEPARATOR_S и другие) для этого.