Получить CWD с учетом регистра в C

В этом коде, когда пользователь вводит 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, он возвращает то же самое. Как я могу предотвратить это?

Это связано с вашей файловой системой, а не с программированием. Если вам нужна файловая система с учетом регистра, лучше спросить на superuser.com

Stephen Newell 02.07.2024 18:04

Я использую NTFS. Проводник Windows показывает это правильно, но мой код — нет.

Hrushikesh Dharmadhikari 02.07.2024 18:14

GetCurrentDirectory ведет себя с вами так же?

Andreas Wenzel 02.07.2024 18:17

Я должен это проверить...

Hrushikesh Dharmadhikari 02.07.2024 18:18

Код станет платформозависимым.

Konstantin Makarov 02.07.2024 18:22

Да, я (надеюсь) хочу, чтобы он был портативным и кроссплатформенным.

Hrushikesh Dharmadhikari 02.07.2024 18:23

Вам, вероятно, не повезло. В вашей системе нет функциональной разницы между C;/TEMP, C:/temp, C;/TeMP и т. д. Существует ли реальная проблема с тем, что ваша программа соответствует регистру, указанному ее пользователем в команде cd?

Stephen Newell 02.07.2024 18:26

@Стивен Ньюэлл, совсем нет. FAT и NTFS нечувствительны к регистру, но сохраняют его. Вполне возможно, что каталог назван Temp, а не temp (как сказано в ОП), и можно получить это имя.

ikegami 02.07.2024 20:13
chdir и getcwd могут просто где-то хранить строку. Моей первой попыткой было бы попробовать вызвать Learn.microsoft.com/en-us/windows/win32/api/winbase/…, чтобы посмотреть, извлекает ли это имена в том виде, в каком они хранятся на диске.
Christian Stieber 02.07.2024 20:17

Попробуйте использовать функцию WinAPI getFullPathnameA().

Barmar 02.07.2024 21:29

@ikegami, это неправда, NTFS полностью совместима с POSIX и чувствительна к регистру , просто подсистема Win32 ограничена пространством имен с сохранением регистра. Но существовал ключ реестра HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\kernel\ObCaseInsensitive, созданный несколько десятилетий назад для настроек чувствительности к регистру. И теперь вы также можете иметь чувствительность к регистру для каждого каталога

phuclv 03.07.2024 02:47

@StephenNewell NTFS чувствительна к регистру, поэтому она связана с пространством имен Win32 и ее можно легко обойти с помощью префикса `` \\?\ ``

phuclv 03.07.2024 02:48

@phuclv, даже если можно изменить его на учет регистра, и даже если он был изменен на учет регистра (даже несмотря на то, что нет никаких доказательств того, что это было сделано), моя точка зрения остается в силе: он сохраняет регистр, поэтому ОП не повезло, как утверждал Стивен Ньюэлл.

ikegami 03.07.2024 03:00

Кроме того, решение в идеале должно быть кроссплатформенным.

Hrushikesh Dharmadhikari 03.07.2024 11:56

Windows Explorer, командная строка сохраняет регистр имен файлов.

Hrushikesh Dharmadhikari 03.07.2024 11:56
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
15
91
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В комментариях вы сказали, что хотите межплатформенную переносимость, но это практически невозможно:

  • 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), а не частью базовой файловой системы. Таким образом, даже если вы переключили свою файловую систему (полностью или частично) на чувствительность к регистру, это не повлияет на чувствительность к регистру букв дисков. (Соглашение ОС гласит: «все равно», хотя во многих программах их обычно представляют заглавными буквами.)

Так что ты можешь сделать?

  1. Живите с этим как есть.

  2. Напишите код, который распознает строчную букву диска в пути и меняет ее на прописную.

  3. Используйте вызовы, специфичные для платформы, чтобы заставить ОС указать каноническое имя для этого пути.

    Это сложно. Для файла вы можете открыть файл, а затем использовать GetFinalPathNameByHandle. Вы не можете открыть каталог как файл.

    Ни GetFullPathName, ни GetLongFileName тоже не делают того, что вам нужно.

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

_getcwd() ведет себя точно так же.
Hrushikesh Dharmadhikari 03.07.2024 15:30

@HrushikeshDharmadhikari: Такое же поведение, как и getcwd? Да, это так. Я не говорил иначе. Я указывал на то, что getcwd на самом деле не переносим, ​​потому что (1) это имя устарело в MSVC и (2) концепция «текущего рабочего каталога» несколько отличается в Windows от Posix, и эта разница не является существенной. запечатлено в интерфейсе getcwd.

Adrian McCarthy 03.07.2024 17:42

Ох, хорошо. Спасибо!

Hrushikesh Dharmadhikari 04.07.2024 13:59

вы можете использовать локаль UTF-8 в Windows, однако нет необходимости выполнять преобразование из/в UTF-16 во всех нужных местах

phuclv 07.07.2024 04:20

Другие вопросы по теме