как передавать путь к файлу?
Если программа лежит в папке «D:Proga\Bin», то надо выйти на уровень вверх:
std::string path("..\\File\\file.txt");
(Двойная косая черта нужна, так как в Си одинарная такая черта обозначает управляющий символ).
Вариант, как могла бы выглядеть ваша программа:
#include #include #include int main(int argc, char* argv[]) < if (argc >1) < std::string path(argv[1]); std::ofstream fout(path); // Тут работаем с файлом >else < std::cout return 0; >
Как получить путь к файлу c
У меня было так
#define DATA_FILE _T("C://set.ds")
Я открывал этот файл, при необходимости он создавался — и все было бы хорошо, но
#define DATA_FILE _T("C://Program Files//Internet Explorer//PLUGINS//set.ds")
И все больше файл открываться не хочет! (и не создается) Я больше ничего не менял в программе — значит виноваты эти строки. Подскажите, плиз.
03.03.06 22:54: Перенесено модератором из ‘C/C++’ — Павел Кузнецов
Re: Как правильно писать путь к файлу?
| От: | LuciferMoscow |
| Дата: | 03.03.06 10:19 |
| Оценка: |
Здравствуйте, AlexDav, Вы писали:
AD>У меня было так
AD>
AD>#define DATA_FILE _T("C://set.ds") AD>
AD>Я открывал этот файл, при необходимости он создавался — и все было бы хорошо, но
AD>Я заменил на
AD>
AD>#define DATA_FILE _T("C://Program Files//Internet Explorer//PLUGINS//set.ds") AD>
AD>И все больше файл открываться не хочет! (и не создается) Я больше ничего не менял в программе — значит виноваты эти строки. Подскажите, плиз.
Попробуй путь взять в кавычки. У тебя есть пробел в пути к файлу
const TCHAR DATA_FILE[]_T("\"C://Program Files//Internet Explorer//PLUGINS//set.ds\"");
Re: Как правильно писать путь к файлу?
| От: | HiSH | http://m0riarty.ya.ru |
| Дата: | 03.03.06 10:21 | |
| Оценка: | 2 (2) | |
Здравствуйте, AlexDav, Вы писали:
AD>
AD>#define DATA_FILE _T("C://set.ds") AD>
AD>Я открывал этот файл, при необходимости он создавался — и все было бы хорошо, но
AD>Я заменил на
AD>
AD>#define DATA_FILE _T("C://Program Files//Internet Explorer//PLUGINS//set.ds") AD>
AD>И все больше файл открываться не хочет! (и не создается) Я больше ничего не менял в программе — значит виноваты эти строки. Подскажите, плиз.
А зачем двойные слеши? Должно быть или «c:\\program files\\. «, или «c:/program files/. «
Re: Как правильно писать путь к файлу?
| От: | rg45 |
| Дата: | 03.03.06 10:24 |
| Оценка: |
Здравствуйте, AlexDav, Вы писали:
AD>У меня было так
AD>
AD>#define DATA_FILE _T("C://set.ds") AD>
AD>Я открывал этот файл, при необходимости он создавался — и все было бы хорошо, но
AD>Я заменил на
AD>
AD>#define DATA_FILE _T("C://Program Files//Internet Explorer//PLUGINS//set.ds") AD>
AD>И все больше файл открываться не хочет! (и не создается) Я больше ничего не менял в программе — значит виноваты эти строки. Подскажите, плиз.
1. Либо «C://set.ds» либо «C:/set.ds» — двойной слэш — это лишний символ в строке, хотя большинством фунций «глотается» нормально.
2. Чтобы ответить, все таки, что не так, нужно видеть, как используется эта строка.
Вполне возможно, что проблема в пробелах, которые присутствуют во втором варианте и которых нет в первом.
—
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: Как правильно писать путь к файлу?
| От: | AlexDav |
| Дата: | 03.03.06 10:27 |
| Оценка: |
Здравствуйте, HiSH, Вы писали:
HSH>А зачем двойные слеши? Должно быть или «c:\\program files\\. «, или «c:/program files/. «
Так вот зачем эти странные палочки?! И точно работает
Re[2]: Как правильно писать путь к файлу?
| От: | rg45 |
| Дата: | 03.03.06 10:27 |
| Оценка: |
R>1. Либо «C://set.ds» либо «C:/set.ds» — двойной слэш — это лишний символ в строке, хотя большинством фунций «глотается» нормально.
Написал не то, что хотел, надо было так:
—
Не можешь достичь желаемого — пожелай достигнутого.
Re: Как правильно писать путь к файлу?
| От: | RevSegment |
| Дата: | 03.03.06 10:34 |
| Оценка: |
Здравствуйте, AlexDav, Вы писали:
AD>У меня было так
AD>
AD>#define DATA_FILE _T("C://set.ds") AD>
AD>Я открывал этот файл, при необходимости он создавался — и все было бы хорошо, но
AD>Я заменил на
AD>
AD>#define DATA_FILE _T("C://Program Files//Internet Explorer//PLUGINS//set.ds") AD>
AD>И все больше файл открываться не хочет! (и не создается) Я больше ничего не менял в программе — значит виноваты эти строки. Подскажите, плиз.
А так не пробовал?
«c:\\Folder One\\Folder Two\\file.ext»
. << RSDN@Home 1.1.4 stable SR1 rev. 568>>
. опыт приходит во время боя .<>
Re[2]: Как правильно писать путь к файлу?
| От: | AlexDav |
| Дата: | 03.03.06 10:46 |
| Оценка: |
Здравствуйте, LuciferMoscow, Вы писали:
LM>Попробуй путь взять в кавычки. У тебя есть пробел в пути к файлу
LM>
LM>const TCHAR DATA_FILE[]_T("\"C://Program Files//Internet Explorer//PLUGINS//set.ds\""); LM>
я попробовал такой путь «C:/Data/set.ds» работает — т.е. ты (можно на ты?) это пробелы, но как ты написал тоже не прокатывает?? Что Делать.
Re[3]: Как правильно писать путь к файлу?
| От: | ekamaloff |
| Дата: | 03.03.06 10:50 |
| Оценка: |
Здравствуйте, AlexDav, Вы писали:
AD>я попробовал такой путь «C:/Data/set.ds» работает — т.е. ты (можно на ты?) это пробелы, но как ты написал тоже не прокатывает?? Что Делать.
Покажи где ты ее используешь и на каком варианте строки ты сейчас остановился.
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
Re[4]: Как правильно писать путь к файлу?
| От: | AlexDav |
| Дата: | 03.03.06 11:07 |
| Оценка: |
Здравствуйте, ekamaloff, Вы писали:
E>Покажи где ты ее используешь и на каком варианте строки ты сейчас остановился.
Прошу прощения за MFC
#define DATA_FILE _T("\"C:\\Program Files\\Internet Explorer\\PLUGINS\\set.ds\"") . UINT nFlags = CFile::typeBinary|CFile::modeWrite; if(_waccess(DATA_FILE,0)) // надо его создать? < nFlags |= CFile::modeCreate; bCanSave = TRUE; >else < bCanSave = CanSerialize(); // всегда TRUE :) > if(bCanSave) < CFile file; CFileException fe; if(file.Open(DATA_FILE, nFlags, &fe)) // Вот и не посредственное использование < CArchive ar(&file, CArchive::store); Serialize(ar); ar.Close(); >file.Close(); >
Re[5]: Как правильно писать путь к файлу?
| От: | AlexDav |
| Дата: | 03.03.06 13:35 |
| Оценка: |
Хотите верти — хотите нет, но
#define DATA_FILE _T("C:\\Program Files\\Internet Explorer\\PLUGINS\\set.dln")
просто начала работать и все! Зуб даю кроме этой строчки в программе ничего не менял!
Re[6]: Как правильно писать путь к файлу?
| От: | rg45 | |
| Дата: | 03.03.06 13:39 | |
| Оценка: | 4 (1) | |
Здравствуйте, AlexDav, Вы писали:
AD>Хотите верти — хотите нет, но
AD>
AD>#define DATA_FILE _T("C:\\Program Files\\Internet Explorer\\PLUGINS\\set.dln") AD>
AD>просто начала работать и все! Зуб даю кроме этой строчки в программе ничего не менял!
Впервоначальном варианте у тебя все слэши были двойные. А петерь вместо них одинарные бэк-слэши (литерал «\\» автоматически преобразуется в одинарный бэк-слэш). Значит, какая то из функций не могла вынести присутствия лишних символов в строке.
—
Не можешь достичь желаемого — пожелай достигнутого.
Re[6]: Как правильно писать путь к файлу?
| От: | i-maverick |
| Дата: | 03.03.06 13:48 |
| Оценка: |
Здравствуйте, AlexDav, Вы писали:
AD>Хотите верти — хотите нет, но
AD>
AD>#define DATA_FILE _T("C:\\Program Files\\Internet Explorer\\PLUGINS\\set.dln") AD>
AD>просто начала работать и все! Зуб даю кроме этой строчки в программе ничего не менял!
Тебе ведь так и сказали — нужно либо одинарный прямой слэш, либо двойной обратный.
Ты бы хоть разобрался, зачем тут двойной слэш, чтоб больше не путаться.
Re[7]: Как правильно писать путь к файлу?
| От: | AlexDav |
| Дата: | 03.03.06 13:54 |
| Оценка: |
Здравствуйте, i-maverick, Вы писали:
IM>Тебе ведь так и сказали — нужно либо одинарный прямой слэш, либо двойной обратный.
IM>Ты бы хоть разобрался, зачем тут двойной слэш, чтоб больше не путаться.
Ну ладно ругать то сразу — никто же не сказал что надо весь проект перекомпилить что бы подхватил эту дефайну
Спасибо — за время потраченное на меня
C++ как получить путь запущенного приложения?
использую c++17 c++20
имеется приложение, которое использует ресурсы используя относительные пути — как выяснить реальный путь в файловой системе до самого бинаря внутри кода?
апд
в общем найдено несколько способов:
1. только для систем с procfs — C++ как получить путь запущенного приложения? (комментарий)
2. по идее кроссплатформенный через sdl2 — C++ как получить путь запущенного приложения? (комментарий)
3. использовать метод нахождения используемый в which (определять является ли argv путем, если да то каким — относительным или абсолютным, если нет, то искать название бинарника по путям в env var PATH)
safocl ★★
15.01.21 01:50:13 MSK
← 1 2 3 →
я так понимаю std::filesystem не содержит такой возможности?
надо будет по подобию which делать ?
safocl ★★
( 15.01.21 02:24:46 MSK ) автор топика
Относительные относительно бинаря или таки рабочего каталога?
readlink(«/proc/self/exe», buf, bufsize)
anonymous
( 15.01.21 02:24:53 MSK )
Ответ на: комментарий от anonymous 15.01.21 02:24:53 MSK
относительные именно бинаря. — я просто юзаю файлы ресурсов — скажем бинарь может быть в /usr/bin, а ресы в /usr/share — неплоха было бы просто сделать ../share
но файл может же запускаться и просто по имени — тогда такой фокус не проходит по arcv[0].
safocl ★★
( 15.01.21 02:32:54 MSK ) автор топика
Ответ на: комментарий от anonymous 15.01.21 02:24:53 MSK
но походу да — для линукса тут будет именно readlink.
попробую в коде отвечу то или нет.
safocl ★★
( 15.01.21 02:38:53 MSK ) автор топика
Ответ на: комментарий от safocl 15.01.21 02:32:54 MSK
Если ты пишешь опенсорс и собрался складывать своё файло в /usr/bin и /usr/share, то эти пути, afaik, принято конфигурировать перед компиляцией. https://stackoverflow.com/questions/3239343/make-install-but-not-to-default-directories
anonymous
( 15.01.21 02:46:33 MSK )
Ответ на: комментарий от safocl 15.01.21 02:38:53 MSK
Это linux-специфично и непереносимо. Правильно сказали — конфигурировать пути при cборке.
slovazap ★★★★★
( 15.01.21 03:03:04 MSK )
Ответ на: комментарий от slovazap 15.01.21 03:03:04 MSK
https://en.cppreference.com/w/cpp/filesystem/read_symlink — я попробую вот енту функцию юзать — она вроде как тот сишный от unistd.h насколько я понимаю работает?
safocl ★★
( 15.01.21 03:04:57 MSK ) автор топика
Ответ на: комментарий от safocl 15.01.21 03:04:57 MSK
fs::read_symlink("/proc/self/exe")
работает именно так как я хотел
думаю можно закрывать.
для винды аналог как я понимаю енто GetModuleFileName?
safocl ★★
( 15.01.21 03:22:15 MSK ) автор топика
Ответ на: комментарий от safocl 15.01.21 03:04:57 MSK
Я не про readlink , а про /proc/self/exe — нигде кроме линукса её нет.
slovazap ★★★★★
( 15.01.21 03:35:01 MSK )
Ответ на: комментарий от slovazap 15.01.21 03:35:01 MSK
да понятно — ну в винде своя функция есть — через дефайны буду делать.
safocl ★★
( 15.01.21 03:50:42 MSK ) автор топика
Ответ на: комментарий от safocl 15.01.21 03:50:42 MSK
Кроме винды и линукса есть ещё куча операционных систем.
slovazap ★★★★★
( 15.01.21 04:14:35 MSK )
Ответ на: комментарий от slovazap 15.01.21 03:03:04 MSK

Правильно сказали — конфигурировать пути при cборке.
Это ещё хуже. Бинарник и данные должны работать из любого места.
X512 ★★★★★
( 15.01.21 04:24:49 MSK )
Ответ на: комментарий от slovazap 15.01.21 04:14:35 MSK

Кроме винды и линукса есть ещё куча операционных систем.
Ещё один #elif __OSNAME__ дописать. Можно ещё через argv[0] путь получить, но там могут быть символьные ссылки и относительные пути.
X512 ★★★★★
( 15.01.21 04:29:01 MSK )
Ответ на: комментарий от X512 15.01.21 04:29:01 MSK
в argv[0] еще может быть ваще другое — енто же не путь запускного файла — енто команда запуска — она может состоять из вообще других слов, нежели путь к exe.
в ентом то и проблема — пока я не начал устанавливать прогу в /usr/bin все было норм — но когда поставил туда и запустил не путем а командой — тоесть просто по названию проги — перестали действовать относительные пути к ресурсам.
я просто изначально думал чо в std::filesystem реализован механизм обнаружения пути к exe — но увы — нет.
safocl ★★
( 15.01.21 05:04:06 MSK ) автор топика
Последнее исправление: safocl 15.01.21 05:07:13 MSK (всего исправлений: 2)
Ответ на: комментарий от X512 15.01.21 04:24:49 MSK
потому что данные программа должна собирать с приоритетами:
- переменная среды MY_PROG_DATA
- через сборку препроцессора, $MY_PROG_DATA
- глобальное хостовые пути xdg
- пользовательские пути xdg
anonymous
( 15.01.21 06:06:07 MSK )
Ответ на: комментарий от anonymous 15.01.21 06:06:07 MSK

3 и 4 местами поменяй.
Siborgium ★★★★★
( 15.01.21 09:54:21 MSK )

Хрена вы норкоманы.
int main(int argc, char* argv[])
pon4ik ★★★★★
( 15.01.21 11:41:13 MSK )
Ответ на: комментарий от anonymous 15.01.21 06:06:07 MSK

Но в целом, глобальную проблему ТС решает именно такой подход, только и правда последние два пункта надо свапнуть.
pon4ik ★★★★★
( 15.01.21 11:48:57 MSK )
Резолвить argv[0] до абсолютного пути не помогает, если программа не была запущена по абсолютному пути:
$ cat ~/vcs/scripts/argv0.c #include int main(int argc, char ** argv) < puts(argv[0]); return 0; >$ make ~/vcs/scripts/argv0 cc argv0.c -o argv0 $ which argv0 /home/me/vcs/scripts/argv0 $ argv0 argv0
(Не говоря уже о том, что в системном вызове execve в argv[0] можно подставить любую чушь, не имеющую ничего общего с путём к исполняемому файлу.)
anonymous
( 15.01.21 11:52:27 MSK )
Ответ на: комментарий от anonymous 15.01.21 11:52:27 MSK

Лол, значит я был не прав, интересный факт, спасибки.
pon4ik ★★★★★
( 15.01.21 11:54:41 MSK )
Ответ на: комментарий от pon4ik 15.01.21 11:41:13 MSK

Надо ещё символьные ссылки резолвить.
X512 ★★★★★
( 15.01.21 11:55:57 MSK )
Ответ на: комментарий от safocl 15.01.21 02:32:54 MSK
а ресы в /usr/share — неплоха было бы просто сделать ../share
Так делать глупо.
После старта бинарники:
- Он считывает переменные окружения PATH_БЛАБЛА_ДЛЯ_БЛА и т.п. Если их нет, то использует дефолт (man hier).
- Использует параметры, если их нет, то использует дефолты (man hier).
- Он читает конфиг, где определены пути. Если его нет, то использует дефолт (man hier).
- Он использует стандартные пути (man hier).
Полные пути рулят.
anonymous
( 15.01.21 12:16:07 MSK )
Ответ на: комментарий от safocl 15.01.21 05:04:06 MSK

Файловая система и твой ехе это как бы разные вещи, с чего бы рантайм лабуде быть в std::filesystem?
seiken ★★★★★
( 15.01.21 12:52:58 MSK )
Ответ на: комментарий от anonymous 15.01.21 06:06:07 MSK
safocl ★★
( 15.01.21 13:33:25 MSK ) автор топика
Ответ на: комментарий от pon4ik 15.01.21 11:41:13 MSK
чуть выше уже был коммент на счет argv[0] — енто не путь исполняемого файла — а команда запуска программы — она может быть ваще не путем, да и ваще не особо относиться к названию бинаря проги.
safocl ★★
( 15.01.21 13:35:42 MSK ) автор топика
Ответ на: комментарий от anonymous 15.01.21 12:16:07 MSK
ну в таком случае если ты портабельно собрал прогу она не найдет ресы.
safocl ★★
( 15.01.21 13:37:22 MSK ) автор топика
Ответ на: комментарий от seiken 15.01.21 12:52:58 MSK
путь там указывается.
да и текущий каталог ведь можно узнать через std::filesystem — енто тоже рантайм сущность.
safocl ★★
( 15.01.21 13:38:51 MSK ) автор топика
кстати нашел один кроссплатформенный способ — через SDL2/SDL_filesystem.h — функция SDL_GetBasePath() возвращает реальный путь нахождения проги.
safocl ★★
( 15.01.21 13:40:46 MSK ) автор топика
Последнее исправление: safocl 15.01.21 13:47:26 MSK (всего исправлений: 1)
Ответ на: комментарий от anonymous 15.01.21 02:24:53 MSK

argv[0] ёпта, при старте приложения.
deep-purple ★★★★★
( 15.01.21 13:41:20 MSK )
Ответ на: комментарий от safocl 15.01.21 13:37:22 MSK
Разговор же идёт про обычный вариант сборки (/usr/bin, /usr/share и т.п.). С портабельной версией придётся работать через переменные окружения или ./бла-бла. Тут даже спорить не нужно.
anonymous
( 15.01.21 13:49:05 MSK )
Ответ на: комментарий от slovazap 15.01.21 03:03:04 MSK
Это linux-специфично и непереносимо.
Можно натравить which или своровать код поиска (по списку путей в PATH).
anonymous
( 15.01.21 13:50:03 MSK )
Ответ на: комментарий от anonymous 15.01.21 13:50:03 MSK
да зачем если есть /proc/self/exe симлинк ведущий к бинарю?
safocl ★★
( 15.01.21 13:53:02 MSK ) автор топика
Ответ на: комментарий от safocl 15.01.21 13:53:02 MSK
Это linux-специфично и непереносимо.
Это если надо переносимо. Решение, естественно, неточное — нужно чтобы совпали алгоритмы и данные для поиска пути у приложения и у системы.
anonymous
( 15.01.21 13:59:37 MSK )
Ответ на: комментарий от X512 15.01.21 04:24:49 MSK
Это ещё хуже. Бинарник и данные должны работать из любого места.
- Кто это сказал?
- Какие аргументы?
- В каких пределах это должно работать?
Потому что либо ты хардкодишь абсолютный путь, либо относительный. В первом случае ты можешь бинарник переносить куда угодно и он продолжит работать. Во втором можешь переносить только параллельно с данными. В разных случаях может потребоваться разное.
Претензия здесь не к одному из этих вариантов, потому что требование ровно одно — бинарник должен работать так как его установили, и ему удовлетворяют оба. Но к способу получения пути к бинарнику который непереносим, и быдлокод с /proc/self/exe просто сломается на *bsd, haiku, macos и ещё куче систем.
slovazap ★★★★★
( 15.01.21 14:53:10 MSK )
Ответ на: комментарий от slovazap 15.01.21 14:53:10 MSK
Но к способу получения пути к бинарнику который непереносим, и быдлокод с /proc/self/exe просто сломается на *bsd, haiku, macos и ещё куче систем.
ессесна — надо делать разные пути для проверки — сам способ не меняется на юникс подобных системах. — но выше же и сказано чо енто непереносимо.
safocl ★★
( 15.01.21 14:55:53 MSK ) автор топика
Ответ на: комментарий от X512 15.01.21 04:29:01 MSK
Ещё один #elif OSNAME дописать.
Это говённый код который надо допиливать под каждую новую систему чтобы запустить. Едва ли от автора можно ожидать что он знает как получить путь к бинарнику на всех существующих системах. И потом всё уткнётся в систему где этого сделать вообще нельзя и всё равно будет добавлен универсальный способ с абсолютным путём.
В итоге получаем:
- Коллекцию способов получить путь к бинарнику на несколько страниц мёртвого кода, из которого тестируется только тот что работает на системе автора
- Теряем поддержку относительной переносимости, потому что она уже не везде работает
Поэтому собственно везде и всегда используются абсолютные пути, и это единственный правильный способ.
Можно ещё через argv[0] путь получить, но там могут быть символьные ссылки и относительные пути.
Нельзя, если бинарник запущен через $PATH там вообще пути не будет. Поведение зависит от шелла и на самом деле там вообще не обязано оказаться что-либо осмысленное.
slovazap ★★★★★
( 15.01.21 15:08:17 MSK )
Ответ на: комментарий от slovazap 15.01.21 15:08:17 MSK
так а способ с применением sdl2 который я выше привел он что не везде работает где есть sdl2?
safocl ★★
( 15.01.21 15:10:12 MSK ) автор топика
Ответ на: комментарий от safocl 15.01.21 14:55:53 MSK
Какие ещё разные пути? На других системах нет никаких путей аналогичных /proc/self/exe
Как получить путь к файлу c
Доброго времени суток! Думаю где-то уже отвечали на такое но гугиль найти такое не помог. Нужно получить полный путь к файлу, переданный в качестве параметра командной строки, и использовать его для открытия файла и дальнейших манипуляций.
Вот мой кодец:
#include "stdafx.h" #include #include #include #include #include #include #include #include int _tmain(int argc, _TCHAR* argv[]) < setlocale(LC_ALL,"RUS"); SetConsoleCP(1251); SetConsoleOutputCP(1251); char *s,*s1,sc[7]; s=(char*)argv[1]; int i=0; CharToOem(argv[1],s1); while(s1[i]!=0)< printf("%c %i\n",s1[i],s1[i]); i++; >FILE *f=fopen(s1,"r"); if(f!=NULL) < fscanf(f,"s",sc); printf("%s",sc); >else < printf("NO"); >//[/преобразуем используя CharToOem] _getch(); for(int t=1;t printf("\n"); i+=2; > //[/вручную просматриваем _tchar: там четные поля-символы, нечетные, видимо, номера кодовых страниц] _getch(); return 0; >
т.е. нужно в любом случае изменять код русских символов, чтобы fopen могла их воспринимать.
ps вторую часть вывел сам; странно что CharToOem сразу не делает все хорошо;
вопщем вопрос такой: как? что? почему? можно сделать все хорошо и красиво
psps наличие или отсутствие следующих строчек на функционирование не повлияло
setlocale(LC_ALL,»RUS»);
SetConsoleCP(1251);
SetConsoleOutputCP(1251);