#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
и другие) для этого.