Apakah ada platform-agnostic dan filesystem-agnostik metode untuk mendapatkan path lengkap dari direktori dimana program ini berjalan menggunakan C/C++? Tidak menjadi bingung dengan direktori kerja saat ini. (Silakan don't sarankan perpustakaan kecuali mereka're yang standar seperti clib atau STL.)
(Jika ada's tidak ada platform/filesystem-agnostik metode, saran-saran yang bekerja di dalam Windows dan Linux untuk menemukan filesystem juga welcome.)
Berikut ini's kode untuk mendapatkan jalur penuh untuk menjalankan aplikasi:
Windows:
int bytes = GetModuleFileName(NULL, pBuf, len);
if(bytes == 0)
return -1;
else
return bytes;
Linux:
char szTmp[32];
sprintf(szTmp, "/proc/%d/exe", getpid());
int bytes = MIN(readlink(szTmp, pBuf, len), len - 1);
if(bytes >= 0)
pBuf[bytes] = '\0';
return bytes;
Jika anda mengambil direktori saat ini ketika program dijalankan pertama kali, maka anda secara efektif memiliki direktori program anda mulai dari. Menyimpan nilai ke dalam sebuah variabel dan lihat nanti dalam program anda. Ini berbeda dari direktori yang memegang saat ini program executable file. Ini isn't tentu direktori yang sama; jika seseorang menjalankan program dari command prompt, maka program ini menjadi lari command prompt's direktori kerja saat ini meskipun program file yang hidup di tempat lain.
getcwd adalah POSIX fungsi dan didukung di luar kotak oleh semua POSIX-compliant platform. Anda tidak akan harus melakukan sesuatu yang khusus (terpisah dari incliding kanan header unistd.h pada Unix dan langsung.jam di windows).
Sejak anda membuat program C akan link dengan default c waktu berjalan perpustakaan yang terkait dengan SEMUA proses dalam sistem (yang dibuat khusus pengecualian dihindari) dan itu akan mencakup fungsi ini secara default. CRT tidak pernah dianggap eksternal perpustakaan karena yang memberikan dasar sesuai standar antarmuka OS.
Pada windows getcwd fungsi telah usang dalam mendukung _getcwd. Saya pikir anda bisa menggunakannya dalam mode ini.
#include <stdio.h> /* defines FILENAME_MAX */
#ifdef WINDOWS
#include <direct.h>
#define GetCurrentDir _getcwd
#else
#include <unistd.h>
#define GetCurrentDir getcwd
#endif
char cCurrentPath[FILENAME_MAX];
if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath)))
{
return errno;
}
cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */
printf ("The current working directory is %s", cCurrentPath);
Ini adalah dari cplusplus forum
Pada windows:
#include <string>
#include <windows.h>
std::string getexepath()
{
char result[ MAX_PATH ];
return std::string( result, GetModuleFileName( NULL, result, MAX_PATH ) );
}
Di Linux:
#include <string>
#include <limits.h>
#include <unistd.h>
std::string getexepath()
{
char result[ PATH_MAX ];
ssize_t count = readlink( "/proc/self/exe", result, PATH_MAX );
return std::string( result, (count > 0) ? count : 0 );
}
Di HP-UX:
#include <string>
#include <limits.h>
#define _PSTAT64
#include <sys/pstat.h>
#include <sys/types.h>
#include <unistd.h>
std::string getexepath()
{
char result[ PATH_MAX ];
struct pst_status ps;
if (pstat_getproc( &ps, sizeof( ps ), 0, getpid() ) < 0)
return std::string();
if (pstat_getpathname( result, PATH_MAX, &ps.pst_fid_text ) < 0)
return std::string();
return std::string( result );
}
Jika anda ingin cara yang standar tanpa perpustakaan: Tidak ada. Seluruh konsep dari sebuah direktori tidak termasuk dalam standar.
Jika anda setuju bahwa beberapa (portable) ketergantungan pada dekat-standar lib baik-baik saja: Gunakan Boost's file library dan meminta initial_path().
IMHO yang's sedekat anda bisa mendapatkan, dengan karma baik (Boost lebih mapan kualitas tinggi set perpustakaan)
Filesystem TS sekarang menjadi standar ( dan didukung oleh gcc 5.3+ dan dentang 3.9+ ), sehingga anda dapat menggunakan current_path()
fungsi dari:
std::string path = std::experimental::filesystem::current_path();
Di gcc (5.3+) termasuk Filesystem yang anda butuhkan untuk menggunakan:
#include <experimental/filesystem>
dan link anda dengan kode -lstdc++fs
bendera.
Jika anda ingin menggunakan Filesystem dengan Microsoft Visual Studio, kemudian baca ini.
Aku tahu itu sangat terlambat pada hari untuk membuang jawaban yang satu ini, tapi saya menemukan bahwa tidak ada jawaban yang berguna untuk saya karena saya sendiri solusi. Cara yang sangat sederhana untuk mendapatkan path dari CWD ke folder sampah anda adalah seperti ini:
int main(int argc, char* argv[])
{
std::string argv_str(argv[0]);
std::string base = argv_str.substr(0, argv_str.find_last_of("/"));
}
Sekarang anda dapat menggunakan ini sebagai dasar untuk path relatif. Jadi misalnya saya memiliki struktur direktori ini:
main
----> test
----> src
----> bin
dan saya ingin mengkompilasi kode sumber saya untuk bin dan menulis log untuk menguji saya hanya bisa menambahkan baris ini kode saya.
std::string pathToWrite = base + "/../test/test.log";
Saya telah mencoba pendekatan ini pada Linux menggunakan full path, alias dll. dan itu bekerja dengan baik.
CATATAN:
Jika anda berada di windows anda harus menggunakan '\' sebagai file separator tidak '/'. Anda akan memiliki untuk melarikan diri ini terlalu misalnya:
std::string base = argv[0].substr(0, argv[0].find_last_of("\\"));
Saya pikir ini harus bekerja tapi belum't diuji, jadi komentar akan dihargai jika bekerja atau memperbaiki jika tidak.
Tidak ada, tidak ada's tidak ada cara standar. Saya percaya bahwa C/C++ standar don't bahkan mempertimbangkan keberadaan direktori (atau file lain sistem organisasi).
Pada Windows GetModuleFileName() akan mengembalikan path lengkap ke file eksekusi dari proses saat ini ketika hModule parameter diatur ke NULL. Saya dapat't membantu dengan Linux.
<menyerang>anda Juga harus menjelaskan apa yang anda inginkan saat ini direktori atau direktori yang program gambar/executable berada. Seperti berdiri pertanyaan anda sedikit ambigu pada titik ini.</strike>Mungkin menggabungkan direktori kerja saat ini dengan argv[0]? I'm tidak yakin apakah itu akan bekerja di Windows tetapi bekerja di linux.
Misalnya:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char **argv) {
char the_path[256];
getcwd(the_path, 255);
strcat(the_path, "/");
strcat(the_path, argv[0]);
printf("%s\n", the_path);
return 0;
}
Ketika dijalankan, itu output:
jeremy@jeremy-desktop:~/Desktop$ ./tes /home/jeremy/Desktop/./tes
Pada Windows cara paling sederhana adalah dengan menggunakan _get_pgmptr
fungsi stdlib.h
untuk mendapatkan pointer ke string yang mewakili absolute path untuk executable, termasuk executable nama.
char* path;
_get_pgmptr(&path);
printf(path); // Example output: C:/Projects/Hello/World.exe
Anda tidak dapat menggunakan argv[0]. untuk tujuan itu, biasanya tidak berisi path lengkap untuk eksekusi, tapi tidak nessesarily - proses yang bisa dibuat dengan nilai sewenang-wenang di lapangan.
Juga pikiran anda, saat ini direktori dan direktori dengan eksekusi adalah dua hal yang berbeda, jadi getcwd() tidak't membantu anda baik.
Di Windows menggunakan GetModuleFileName(), pada Linux baca /dev,/proc/procID/.. file.
Untuk sistem Windows pada konsol anda dapat menggunakan sistem(dir
) perintah. Dan konsol memberi anda informasi tentang direktori dan lain-lain. Baca tentang dir
perintah cmd
. Tapi untuk sistem Unix-like, I don't tahu... Jika perintah ini dijalankan, baca bash command. ls
tidak menampilkan direktori...
Contoh:
int main()
{
system("dir");
system("pause"); //this wait for Enter-key-press;
return 0;
}
Hanya untuk terlambat tumpukan di sini,...
tidak ada larutan standar, karena bahasa adalah agnostik yang mendasari sistem berkas, sehingga orang lain telah mengatakan, konsep dari sebuah direktori berbasis sistem file adalah di luar lingkup dari c / c++ bahasa.
di atas semua itu, anda tidak ingin saat ini bekerja direktori, direktori program ini berjalan, yang harus memperhitungkan bagaimana program harus ke mana - ie itu melahirkan sebagai proses baru melalui garpu, dll. Untuk mendapatkan direktori program ini berjalan, sebagai solusi telah menunjukkan, membutuhkan bahwa anda mendapatkan informasi tersebut dari proses kontrol struktur dari sistem operasi tersebut, yang merupakan satu-satunya otoritas pada pertanyaan ini. Dengan demikian, menurut definisi, sebuah OS tertentu solusi.
#include <windows.h>
using namespace std;
// The directory path returned by native GetCurrentDirectory() no end backslash
string getCurrentDirectoryOnWindows()
{
const unsigned long maxDir = 260;
char currentDir[maxDir];
GetCurrentDirectory(maxDir, currentDir);
return string(currentDir);
}
Linux bash command yang progname akan melaporkan sebuah jalan untuk program.
Bahkan jika seseorang bisa mengeluarkan perintah yang dari dalam program anda dan mengarahkan output ke tmp file dan program selanjutnya berbunyi bahwa tmp file, itu tidak akan memberitahu anda jika program itu adalah salah satu pelaksana. Ini hanya memberitahu anda di mana program yang mempunyai nama itu berada.
Apa yang diperlukan adalah untuk mendapatkan proses nomor id, dan untuk mengurai jalan untuk nama
Dalam program aku ingin tahu apakah program ini dijalankan dari pengguna's bin direktori atau dari yang lain di jalan atau dari /usr/bin. /usr/bin akan berisi versi yang didukung. Perasaan saya adalah bahwa di Linux ada satu solusi yang portabel.
Untuk jalur relatif, di sini's apa yang saya lakukan. Saya sadar usia dari pertanyaan ini, saya hanya ingin memberikan kontribusi yang lebih sederhana jawaban yang bekerja di sebagian besar kasus:
Katakanlah anda memiliki sebuah jalan seperti ini:
"path/to/file/folder"
Untuk beberapa alasan, Linux-membangun executable yang dibuat di eclipse bekerja dengan baik dengan ini. Namun, windows akan sangat bingung jika diberi jalan seperti ini untuk bekerja dengan!
Seperti yang dinyatakan di atas ada beberapa cara untuk mendapatkan jalan saat ini untuk eksekusi, tapi cara termudah saya menemukan karya-karya pesona dalam sebagian besar kasus adalah menambahkan ini ke DEPAN jalan anda:
"./path/to/file/folder"
Hanya menambahkan "./" harus mendapatkan anda diurutkan! :) Maka anda dapat mulai loading dari apapun direktori yang anda inginkan, asalkan dengan eksekusi itu sendiri.
EDIT: Ini tidak't bekerja jika anda mencoba untuk memulai eksekusi dari code::blocks jika itu's lingkungan pengembangan yang digunakan, karena untuk beberapa alasan, code::blocks doesn't memuat hal-hal yang benar... :D
EDIT2: Beberapa hal baru yang saya temukan adalah bahwa jika anda menentukan statis jalan seperti ini dalam kode anda (dengan Asumsi Contoh.data adalah sesuatu yang anda butuhkan untuk load):
"resources/Example.data"
Jika anda kemudian meluncurkan aplikasi anda dari direktori aktual (atau di Windows, anda membuat cara pintas, dan mengatur kerja dir untuk aplikasi anda dir) maka akan bekerja seperti itu. Menjaga ini dalam pikiran ketika debugging isu-isu yang terkait dengan sumber daya yang tidak ada/path file. (Terutama di IDEs yang mengatur salah kerja dir ketika meluncurkan membangun exe dari IDE)
Meningkatkan Filesystem's initial_path()
berperilaku seperti POSIX's getcwd()
, dan tidak melakukan apa yang anda inginkan dengan sendirinya, tetapi menambahkan argv[0]
untuk salah satu dari mereka harus melakukannya.
Anda dapat perhatikan bahwa hasilnya tidak selalu cukup-anda mungkin mendapatkan hal-hal seperti /foo/bar/../../baz/a.keluar
atau /foo/bar//baz/a.out
, tapi saya percaya bahwa itu selalu hasil dalam jalan yang sah yang nama-nama berkas yang dapat dieksekusi (perhatikan bahwa berturut-turut garis miring di jalan yang runtuh ke satu).
Sebelumnya saya menulis sebuah solusi menggunakan envp
(argumen ketiga untuk main()
yang bekerja pada Linux, tetapi didn't tampaknya bisa diterapkan pada Windows, jadi saya'm pada dasarnya merekomendasikan solusi yang sama seperti orang lain lakukan sebelumnya, tapi dengan tambahan penjelasan mengapa hal ini benar-benar benar bahkan jika hasilnya tidak cukup.
Sebagai Minok menyebutkan, tidak ada fungsi yang ditentukan ini C standar atau standar C++. Ini dianggap murni OS-fitur tertentu dan hal ini ditentukan dalam standar POSIX, misalnya.
Thorsten79 telah memberi saran yang baik, itu adalah Dorongan.Filesystem perpustakaan. Namun, hal itu mungkin tidak nyaman jika anda don't ingin memiliki link-waktu dependensi dalam bentuk biner untuk program anda.
Alternatif yang baik saya akan merekomendasikan adalah kumpulan dari 100% hanya header STLSoft C++ Libraries Matthew Wilson (penulis harus-membaca buku-buku tentang C++). Ada portable fasad PlatformSTL memberikan akses ke sistem-spesifik API: WinSTL untuk Windows dan UnixSTL pada Unix, jadi ini adalah solusi portabel. Semua sistem-unsur tertentu yang ditentukan dengan menggunakan sifat-sifat dan kebijakan, sehingga kerangka extensible. Ada filesystem perpustakaan yang disediakan, tentu saja.
Bekerja dengan mulai dari C++11, eksperimental menggunakan filesystem, dan C++14-C++17 serta menggunakan resmi filesystem.
aplikasi.h:
#pragma once
//
// https://en.cppreference.com/w/User:D41D8CD98F/feature_testing_macros
//
#ifdef __cpp_lib_filesystem
#include <Filesystem>
#else
#include <experimental/filesystem>
namespace std {
namespace filesystem = experimental::filesystem;
}
#endif
std::filesystem::path getexepath();
application.cpp:
#include "application.h"
#ifdef _WIN32
#include <windows.h> //GetModuleFileNameW
#else
#include <limits.h>
#include <unistd.h> //readlink
#endif
std::filesystem::path getexepath()
{
#ifdef _WIN32
wchar_t path[MAX_PATH] = { 0 };
GetModuleFileNameW(NULL, path, MAX_PATH);
return path;
#else
char result[PATH_MAX];
ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
return std::string(result, (count > 0) ? count : 0);
#endif
}