В этом коде, когда пользователь вводит c:\\temp, getcwd() возвращает "c:\temp".
Фактический путь — C:\Temp.
if (chdir(fullpath))
{
perror("cd");
return 1;
}
if (!getcwd(path, sizeof(path))
{
perror("getcwd error");
getchar();
exit(1);
}
Я ожидал, что оно вернется "C:\\Temp". Есть ли способ получить текущий рабочий каталог с учетом регистра в C? Где бы я ни искал, был только getcwd().
Обновлено: Кроме того, если пользователь вводит c:\tEMp, он возвращает то же самое. Как я могу предотвратить это?
Я использую NTFS. Проводник Windows показывает это правильно, но мой код — нет.
GetCurrentDirectory ведет себя с вами так же?
Я должен это проверить...
Код станет платформозависимым.
Да, я (надеюсь) хочу, чтобы он был портативным и кроссплатформенным.
Вам, вероятно, не повезло. В вашей системе нет функциональной разницы между C;/TEMP, C:/temp, C;/TeMP и т. д. Существует ли реальная проблема с тем, что ваша программа соответствует регистру, указанному ее пользователем в команде cd?
@Стивен Ньюэлл, совсем нет. FAT и NTFS нечувствительны к регистру, но сохраняют его. Вполне возможно, что каталог назван Temp, а не temp (как сказано в ОП), и можно получить это имя.
chdir и getcwd могут просто где-то хранить строку. Моей первой попыткой было бы попробовать вызвать Learn.microsoft.com/en-us/windows/win32/api/winbase/…, чтобы посмотреть, извлекает ли это имена в том виде, в каком они хранятся на диске.
Попробуйте использовать функцию WinAPI getFullPathnameA().
@ikegami, это неправда, NTFS полностью совместима с POSIX и чувствительна к регистру , просто подсистема Win32 ограничена пространством имен с сохранением регистра. Но существовал ключ реестра HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\kernel\ObCaseInsensitive, созданный несколько десятилетий назад для настроек чувствительности к регистру. И теперь вы также можете иметь чувствительность к регистру для каждого каталога
@StephenNewell NTFS чувствительна к регистру, поэтому она связана с пространством имен Win32 и ее можно легко обойти с помощью префикса `` \\?\ ``
@phuclv, даже если можно изменить его на учет регистра, и даже если он был изменен на учет регистра (даже несмотря на то, что нет никаких доказательств того, что это было сделано), моя точка зрения остается в силе: он сохраняет регистр, поэтому ОП не повезло, как утверждал Стивен Ньюэлл.
Кроме того, решение в идеале должно быть кроссплатформенным.
Windows Explorer, командная строка сохраняет регистр имен файлов.





В комментариях вы сказали, что хотите межплатформенную переносимость, но это практически невозможно:
getcwd — это функция Posix, а не часть стандартной библиотеки времени выполнения C.
В системах Posix различие между средой выполнения C и системными библиотеками обычно нечеткое. Microsoft старается не стирать границы, но они это делали в прошлом, поэтому в среде выполнения C остаются некоторые определения, подобные Posix. В Windows с библиотеками, поставляемыми с MSVC, getcwd на самом деле является макросом или оболочкой, которая делегирует _getcwd. Кажется маловероятным, что Microsoft когда-либо удалит его, но они устарели getcwd.
Даже если вы были готовы пойти на компромисс в отношении кросс-платформенной переносимости, вызвав _getcwd или даже GetCurrentDirectoryA, вполне вероятно, что в конечном итоге вы споткнетесь о пути, который невозможно представить ни в какой действующей кодовой странице. Таким образом, вам, вероятно, следует называть «широкие» версии этих API с поддержкой Unicode, но теперь ваш подражательный кроссплатформенный код использует строки char на некоторых платформах и строки WCHAR на других (и/или выполняет дополнительную работу в Windows для преобразования в UTF -8 и принудительно поставить кодовую страницу CP_UTF8 во всех нужных местах).
В Posix для процесса существует единственный рабочий каталог. В Windows процесс может иметь один рабочий каталог на каждую букву диска. В Windows такие функции, как _getcwd, возвращают текущий рабочий каталог.
Некоторые утверждают, что буква рабочего каталога на диске является соглашением оболочки или CMD и поэтому не имеет значения. Я хочу сказать, что вы не можете предсказать, как вызов ОС, например CreateFileW, разрешит неабсолютный путь, например D:foo.txt, если вы не знаете текущий рабочий каталог процесса для диска D:, для чего требуется непереносимый код, специфичный для платформы.
Проводник Windows использует WinAPI и свои собственные правила для обработки и представления путей к файловой системе. Простой пример: в зависимости от настроек пользователя Проводник может скрывать расширения для некоторых файлов. Для соответствия этому поведению требуется код, специфичный для платформы.
Буквы дисков в Windows являются соглашением операционной системы (унаследованным от CP/M через DOS), а не частью базовой файловой системы. Таким образом, даже если вы переключили свою файловую систему (полностью или частично) на чувствительность к регистру, это не повлияет на чувствительность к регистру букв дисков. (Соглашение ОС гласит: «все равно», хотя во многих программах их обычно представляют заглавными буквами.)
Так что ты можешь сделать?
Живите с этим как есть.
Напишите код, который распознает строчную букву диска в пути и меняет ее на прописную.
Используйте вызовы, специфичные для платформы, чтобы заставить ОС указать каноническое имя для этого пути.
Это сложно. Для файла вы можете открыть файл, а затем использовать GetFinalPathNameByHandle. Вы не можете открыть каталог как файл.
Ни GetFullPathName, ни GetLongFileName тоже не делают того, что вам нужно.
Я думаю, вам придется использовать FindFirstFile, чтобы получить официальное название последнего сегмента пути. Затем отрежьте этот сегмент и повторите поиск, чтобы получить официальное имя его родителя. Повторяйте, пока не дойдете до корня.
_getcwd() ведет себя точно так же.
@HrushikeshDharmadhikari: Такое же поведение, как и getcwd? Да, это так. Я не говорил иначе. Я указывал на то, что getcwd на самом деле не переносим, потому что (1) это имя устарело в MSVC и (2) концепция «текущего рабочего каталога» несколько отличается в Windows от Posix, и эта разница не является существенной. запечатлено в интерфейсе getcwd.
Ох, хорошо. Спасибо!
вы можете использовать локаль UTF-8 в Windows, однако нет необходимости выполнять преобразование из/в UTF-16 во всех нужных местах
Это связано с вашей файловой системой, а не с программированием. Если вам нужна файловая система с учетом регистра, лучше спросить на superuser.com