Bagaimana cara mendapatkan direktori tempat program dijalankan?

269

Apakah ada metode platform-agnostik dan filesystem-agnostik untuk mendapatkan path lengkap direktori dari tempat program berjalan menggunakan C / C ++? Jangan bingung dengan direktori kerja saat ini. (Tolong jangan menyarankan perpustakaan kecuali perpustakaan yang standar seperti clib atau STL.)

(Jika tidak ada metode platform / filesystem-agnostik, saran yang bekerja di Windows dan Linux untuk sistem file tertentu juga diterima.)

Ashwin Nanjappa
sumber
@ chakrit: Itu bagus sekali. (Meskipun masalah itu biasanya tidak muncul di bawah Windows.)
Ashwin Nanjappa
2
Jika Anda tidak dapat mengekstrak jalur dengan andal argv[0], tekniknya akan sangat bergantung pada OS.
David R Tribble
1
Hanya untuk memperjelas: 'direktori saat ini', atau, 'direktori tempat program berjalan' (dalam terminologi pertanyaan) adalah direktori tempat file gambar program (~ file .exe) berada, dan ' direktori kerja saat ini ' adalah direktori, yang dilengkapi secara otomatis jika program menggunakan jalur relatif?
colemik
3
Saat Anda #include <windows.h>, Windows secara otomatis menempatkan a char*ke jalur yang dapat dieksekusi di _pgmptr. Anda tidak perlu memanggil fungsi tambahan atau menganggap sampah jika Anda hanya bekerja pada Windows.
rsethc
1
Meskipun komentarnya dari tiga tahun yang lalu, saya ingin memperluas komentar rsethc tentang _pgmptr. Dokumentasi MSDN menyatakan bahwa variabel _pgmptrdan _wpgmptrsudah usang, dan Anda harus menggunakan fungsi _get_pgmptr(char**)atau _get_wpgmptr(wchar_t**)sebagai gantinya. MSDN
Hydranix

Jawaban:

181

Berikut kode untuk mendapatkan path lengkap ke aplikasi yang menjalankan:

Windows:

int bytes = GetModuleFileName(NULL, pBuf, len);
return bytes ? bytes : -1;

Linux:

int bytes = MIN(readlink("/proc/self/exe", pBuf, len), len - 1);
if(bytes >= 0)
    pBuf[bytes] = '\0';
return bytes;
Deduplicator
sumber
3
Saya pikir ini adalah satu-satunya jawaban di sini yang menjawab pertanyaan, dan melakukannya untuk Windows dan Linux. Pekerjaan yang baik.
Frank Szczerba
6
Boo for / proc / pid / exe - Tidak didukung pada OS X karena alasan tertentu.
Chris Lutz
24
Ketika saya melihat kode yang terlihat pada /procbagian saya mati sedikit. Seluruh dunia bukan Linux, dan bahkan pada satu platform itu /procharus dianggap dapat berubah dari versi ke versi, lengkungan ke lengkungan, dll.
asveikau
4
jika mereka meluncurkan menggunakan perintah alias di Linux adalah argv [0] "nama perintah" atau diperluas?
Andy Dent
20
Bagaimana kalau menambahkan char pBuf[256]; size_t len = sizeof(pBuf);untuk membiarkan solusi lebih jelas.
charles.cc.hsu
166

Jika Anda mengambil direktori saat ini ketika program Anda pertama kali dimulai, maka Anda secara efektif memiliki direktori tempat program Anda dimulai. Simpan nilai dalam variabel dan lihat nanti di program Anda. Ini berbeda dari direktori yang menyimpan file program yang dapat dieksekusi saat ini . Itu belum tentu direktori yang sama; jika seseorang menjalankan program dari prompt perintah, maka program sedang dijalankan dari direktori yang berfungsi prompt perintah saat ini meskipun file program tinggal di tempat lain.

getcwd adalah fungsi POSIX dan didukung di luar kotak oleh semua platform yang sesuai dengan POSIX. Anda tidak perlu melakukan sesuatu yang istimewa (selain menyertakan tajuk kanan unistd.h di Unix dan direct.h di windows).

Karena Anda membuat program C, program itu akan ditautkan dengan pustaka c run time default yang ditautkan dengan SEMUA proses dalam sistem (pengecualian yang dibuat khusus dihindari) dan itu akan menyertakan fungsi ini secara default. CRT tidak pernah dianggap sebagai perpustakaan eksternal karena menyediakan antarmuka standar yang sesuai dengan OS.

Pada fungsi getcwd windows telah ditinggalkan demi _getcwd. Saya pikir Anda bisa menggunakannya dengan cara 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);
kehidupan komputasi
sumber
44
Jawaban yang bagus, tapi saya pikir "direktori kerja saat ini" bukan yang diinginkan.
Michael Burr
4
Anda harus menambahkan bahwa bahkan jika beberapa dokumentasi mengatakan bahwa cCurrentpath dapat menjadi nol dan akan dialokasikan oleh getcwd getcwd tampaknya tidak mengalokasikan sesuatu pada Mac OS dan dengan diam-diam crash program Anda
Janusz
4
Ada kesalahan kecil, tapi sayangnya saya belum bisa mengedit .. baris 10: cCurrentpath: harus cCurrentPath
Lipis
8
IMO di Windows fungsi-fungsi yang dinamai POSIXy (beberapa di antaranya dimulai dengan garis bawah) harus dihindari secara umum. Mereka bukan API Windows asli melainkan CRT. API Windows yang ingin Anda gunakan adalah GetCurrentDirectory (). msdn.microsoft.com/en-us/library/aa364934(VS.85).aspx
asveikau
6
Jawaban Mike benar. "Direktori saat ini" tidak selalu sama dengan direktori tempat biner dijalankan. Misalnya, jika aplikasi berjalan sebagai layanan pada Windows, direktori saat ini mungkin akan menjadi C: \ Windows \ System32, sedangkan dir biner berbeda.
Lucky Luke
42

Ini dari forum cplusplus

Di 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 );
}
Gurita
sumber
1
Solusi Windows itu tidak akan menangani karakter non-ANSI di jalur. Anda mungkin harus menggunakan GetModuleFileNameW dan mengonversinya menjadi UTF-8 secara eksplisit (berhati-hati untuk mengubahnya kembali setiap kali Anda perlu mengeluarkan perintah sistem file).
Adrian McCarthy
3
Untuk solusi Windows, saya mendapatkan kesalahan error: cannot convert 'char*' to 'LPWCH {aka wchar_t*}' for argument '2' to 'DWORD GetModuleFileNameW(HMODULE, LPWCH, DWORD)'saat kompilasi dengan MinGW.
HelloGoodbye
2
@Adrian, saya biasanya bukan seorang programmer windows, tetapi bukankah ada DEFINE atau suatu cara untuk memberitahu kompiler Anda untuk menggunakan _W () rasa fungsi secara otomatis?
Octopus
1
@Octopus: Untuk menggunakan panggilan lebar, Anda harus menggunakan WCHAR (bukan char) dan std :: wstring (bukan std :: string).
Adrian McCarthy
29

Jika Anda menginginkan cara standar tanpa pustaka: Tidak. Seluruh konsep direktori tidak termasuk dalam standar.

Jika Anda setuju bahwa beberapa ketergantungan (portabel) pada lib yang hampir standar tidak apa-apa: Gunakan pustaka sistem file Boost dan minta initial_path () .

IMHO itu sedekat yang Anda bisa dapatkan, dengan karma yang baik (Boost adalah sekumpulan perpustakaan berkualitas tinggi)

Thorsten79
sumber
8
Dari Boost docs: template <class Path> const Path & initial_path (); Pengembalian: current_path () pada saat masuk ke main (). Dan current_path () adalah 'seolah-olah oleh POSIX getcwd ()'. Ini bukan yang diminta si penanya.
Jonathan Leffler
lihat boost.org/doc/libs/1_46_1/libs/filesystem/v3/doc/… untuk peningkatan 1.46.1
moala
Seperti dikomentari, ini memberikan path dari tempat biner dipanggil, bukan path ke biner ... karena bisa dimulai dari folder yang berbeda.
jpo38
21

Filesystem TS sekarang menjadi standar (dan didukung oleh gcc 5.3+ dan clang 3.9+), sehingga Anda dapat menggunakan current_path()fungsi darinya:

std::string path = std::experimental::filesystem::current_path();

Dalam gcc (5.3+) untuk memasukkan Filesystem, Anda perlu menggunakan:

#include <experimental/filesystem>

dan tautkan kode Anda dengan -lstdc++fsbendera.

Jika Anda ingin menggunakan Filesystem dengan Microsoft Visual Studio, baca ini .

Marqin
sumber
6
Dari tautan yang 1-2) Returns the absolute path of the current working directory, obtained as if by POSIX getcwd. (2) returns path() if error occurs. direferensikan , Diturunkan, karena OP secara khusus bertanya tentang jalur saat ini yang dapat dieksekusi daripada direktori kerja saat ini.
S. Saad
20

Saya tahu sudah sangat terlambat untuk memberikan jawaban yang satu ini tetapi saya menemukan bahwa tidak ada jawaban yang berguna bagi saya sebagai solusi saya sendiri. Cara yang sangat sederhana untuk mendapatkan path dari CWD Anda ke folder bin 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("/"));
}

Anda sekarang dapat menggunakan ini sebagai basis untuk jalur relatif Anda. Jadi misalnya saya punya struktur direktori ini:

main
  ----> test
  ----> src
  ----> bin

dan saya ingin mengkompilasi kode sumber saya ke bin dan menulis log untuk menguji saya bisa menambahkan baris ini ke kode saya.

std::string pathToWrite = base + "/../test/test.log";

Saya telah mencoba pendekatan ini di Linux menggunakan path lengkap, alias dll dan berfungsi dengan baik.

CATATAN:

Jika Anda berada di windows Anda harus menggunakan '\' sebagai pemisah file bukan '/'. Anda harus menghindari ini juga misalnya:

std::string base = argv[0].substr(0, argv[0].find_last_of("\\"));

Saya pikir ini harus bekerja tetapi belum diuji, jadi komentar akan dihargai jika berhasil atau diperbaiki jika tidak.

Sam Redway
sumber
Ya, itu berfungsi pada Windows juga. Saya pikir itu adalah solusi terbaik. Sejauh yang saya tahu argv [0] selalu menjaga jalur ke executable.
Wodzu
4
argv[0]adalah ide yang sangat bagus, tetapi sayangnya apa yang saya dapatkan di Linux adalah "./my_executable_name" atau "./make/my_executable_name". Pada dasarnya apa yang saya dapatkan tergantung sepenuhnya pada bagaimana saya meluncurkannya
Xeverous
1
@Xeverous: lalu bagaimana? Jika saya memiliki beberapa file relatif terhadap executable saya yang perlu dibuka, mulai dari "./" atau "./make/" dalam kasus Anda harus bekerja. "." adalah direktori aktif saat ini, dan argv [0] akan memberi tahu Anda jalan relatif ke executable dari sana, yang persis seperti yang diinginkan OP. Bagaimanapun juga itulah yang saya butuhkan.
nilo
9

Tidak, tidak ada cara standar. Saya percaya bahwa standar C / C ++ bahkan tidak mempertimbangkan keberadaan direktori (atau organisasi sistem file lainnya).

Pada Windows, GetModuleFileName () akan mengembalikan path lengkap ke file yang dapat dieksekusi dari proses saat ini ketika parameter hModule diatur ke NULL . Saya tidak dapat membantu dengan Linux.

Anda juga harus mengklarifikasi apakah Anda ingin direktori saat ini atau direktori yang gambar program / executable berada. Saat ini, pertanyaan Anda sedikit ambigu dalam hal ini.

Michael Burr
sumber
9

Pada Windows cara paling sederhana adalah dengan menggunakan _get_pgmptrfungsi stdlib.huntuk mendapatkan pointer ke string yang mewakili jalur absolut ke executable, termasuk nama executable.

char* path;
_get_pgmptr(&path);
printf(path); // Example output: C:/Projects/Hello/World.exe
Adam Yaxley
sumber
8

Mungkin merangkai direktori kerja saat ini dengan argv [0]? Saya tidak yakin apakah itu akan bekerja di Windows tetapi bekerja di linux.

Sebagai contoh:

#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;
}

Saat dijalankan, ini menghasilkan:

jeremy @ jeremy-desktop: ~ / Desktop $ ./test
/home/jeremy/Desktop/./test

Jeremy Ruten
sumber
Anda perlu pemeriksaan untuk melihat apakah path absolut diberikan dalam argv [0]. Tetapi yang lebih penting, bagaimana jika gambar tersebut terletak melalui PATH? Apakah linux mengisi path lengkap atau hanya apa yang ada di baris perintah?
Michael Burr
Seperti yang dikatakan Mike B, itu adalah solusi non-umum; itu bekerja dalam beberapa keadaan yang sangat terbatas saja. Pada dasarnya, hanya ketika Anda menjalankan perintah dengan relatif pathname - dan itu tidak semua yang elegan ketika Anda menjalankan ../../../bin/progname bukan ./test
Jonathan Leffler
Jika Anda menyelesaikan kemungkinan jalur relatif argv [0] dibandingkan dengan direktori saat ini (karena argv [0] bisa berupa "../../myprogram.exe"), itu mungkin cara paling aman untuk menjawab pertanyaan. Ini akan selalu berfungsi dan portabel (bahkan berfungsi di Android!).
jpo38
7

Untuk Win32 GetCurrentDirectory harus melakukan trik.

Torbjörn Gyllebring
sumber
Ada tangkapan besar dengan fungsi ini : Aplikasi multithreaded dan kode pustaka bersama tidak boleh menggunakan fungsi GetCurrentDirectory dan harus menghindari penggunaan nama path relatif . Jika Anda dapat bekerja dengan asumsi ini daripada itu adalah solusi terbaik.
McLeary
6

Anda tidak dapat menggunakan argv [0] untuk tujuan itu, biasanya itu berisi path lengkap ke executable, tetapi tidak perlu - proses dapat dibuat dengan nilai arbitrer di lapangan.

Ingat juga, direktori saat ini dan direktori dengan executable adalah dua hal yang berbeda, jadi getcwd () tidak akan membantu Anda juga.

Pada Windows gunakan file GetModuleFileName (), di Linux baca / dev / proc / procID / ...

eugensk
sumber
3

Hanya untuk tumpukan terlambat di sini, ...

tidak ada solusi standar, karena bahasa-bahasa tersebut agnostik dari sistem file yang mendasarinya, sehingga seperti yang dikatakan orang lain, konsep sistem file berbasis direktori berada di luar lingkup bahasa c / c ++.

di atas itu, Anda tidak ingin direktori kerja saat ini, tetapi direktori program sedang berjalan, yang harus memperhitungkan bagaimana program sampai di tempat itu - yaitu apakah itu menelurkan sebagai proses baru melalui garpu, dll. Untuk mendapatkan direktori, sebuah program sedang berjalan, seperti yang ditunjukkan oleh solusi, mengharuskan Anda mendapatkan informasi itu dari struktur kontrol proses sistem operasi yang bersangkutan, yang merupakan satu-satunya otoritas pada pertanyaan ini. Jadi, menurut definisi, ini merupakan solusi spesifik OS.

Minok
sumber
3

Untuk sistem Windows di konsol Anda dapat menggunakan dirperintah system ( ). Dan konsol memberi Anda informasi tentang direktori dan lain-lain. Baca tentang dirperintah di cmd. Tetapi untuk sistem mirip Unix, saya tidak tahu ... Jika perintah ini dijalankan, baca perintah bash. lstidak menampilkan direktori ...

Contoh:

int main()
{
    system("dir");
    system("pause"); //this wait for Enter-key-press;
    return 0;
}
Alexey1993
sumber
2
#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);
}
membeku
sumber
1

Pada platform POSIX, Anda dapat menggunakan getcwd () .

Di Windows, Anda dapat menggunakan _getcwd () , seperti penggunaan getcwd () telah ditinggalkan.

Untuk pustaka standar, jika Boost cukup standar untuk Anda, saya akan menyarankan Boost :: filesystem, tetapi mereka tampaknya telah menghapus normalisasi jalur dari proposal. Anda mungkin harus menunggu sampai TR2 tersedia untuk solusi standar sepenuhnya.

Fruny
sumber
10
getcwd () tidak melakukan apa yang diminta penanya.
Jonathan Leffler
bukankah jawaban yang diterima menggunakan getcwd (), atau apakah saya tidak hanya mengerti?
Sнаđошƒаӽ
Saya memilih karena Anda adalah orang yang datang dengan apa yang dianggap sebagai jawaban yang benar terlebih dahulu.
Arnaud
Jawaban ini bahkan tidak berusaha menjawab pertanyaan itu. Malu menulisnya.
HelloWorld
1

Untuk jalur relatif, inilah yang saya lakukan. Saya menyadari usia pertanyaan ini, saya hanya ingin berkontribusi jawaban yang lebih sederhana yang bekerja di sebagian besar kasus:

Katakanlah Anda memiliki jalur seperti ini:

"path/to/file/folder"

Untuk beberapa alasan, executable buatan Linux yang dibuat di eclipse berfungsi baik dengan ini. Namun, windows menjadi sangat bingung jika diberikan jalur seperti ini untuk bekerja dengannya!

Seperti yang dinyatakan di atas ada beberapa cara untuk mendapatkan jalur saat ini ke executable, tetapi cara termudah yang saya temukan bekerja pesona di sebagian besar kasus adalah menambahkan ini ke DEPAN jalur Anda:

"./path/to/file/folder"

Hanya menambahkan "./" akan membuat Anda diurutkan! :) Kemudian Anda dapat mulai memuat dari direktori apa pun yang Anda inginkan, asalkan dengan executable itu sendiri.

EDIT: Ini tidak akan berfungsi jika Anda mencoba meluncurkan executable from code :: blocks jika itu lingkungan pengembangan yang digunakan, karena beberapa alasan, code :: blocks tidak memuat barang dengan benar ...: D

EDIT2: Beberapa hal baru yang saya temukan adalah bahwa jika Anda menentukan jalur statis seperti ini dalam kode Anda (Mengasumsikan Example.data adalah sesuatu yang Anda perlu memuat):

"resources/Example.data"

Jika Anda kemudian meluncurkan aplikasi Anda dari direktori aktual (atau di Windows, Anda membuat jalan pintas, dan mengatur direktori kerja ke direktori aplikasi Anda) maka itu akan berfungsi seperti itu. Ingatlah ini ketika men-debug masalah yang terkait dengan sumber daya / jalur file yang hilang. (Terutama di IDE yang mengatur dir yang salah saat meluncurkan build exe dari IDE)

FuzzyQuills
sumber
1

Solusi perpustakaan (meskipun saya tahu ini tidak diminta). Jika Anda menggunakan Qt: QCoreApplication::applicationDirPath()

Joachim
sumber
1

Hanya dua sen saya, tetapi tidakkah kode berikut ini berfungsi baik di C ++ 17?

#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;

int main(int argc, char* argv[])
{
    std::cout << "Path is " << fs::path(argv[0]).parent_path() << '\n';
}

Tampaknya bekerja untuk saya di Linux setidaknya.

Berdasarkan ide sebelumnya, saya sekarang memiliki:

std::filesystem::path prepend_exe_path(const std::string& filename, const std::string& exe_path = "");

Dengan implementasi:

fs::path prepend_exe_path(const std::string& filename, const std::string& exe_path)
{
    static auto exe_parent_path = fs::path(exe_path).parent_path();
    return exe_parent_path / filename;
}

Dan trik inisialisasi dalam main():

(void) prepend_exe_path("", argv[0]);

Terima kasih @Sam Redway untuk ide [0] argv. Dan tentu saja, saya mengerti bahwa C ++ 17 tidak ada selama bertahun-tahun ketika OP mengajukan pertanyaan.

nilo
sumber
0

Tingkatkan Filesystem initial_path()berperilaku seperti POSIX getcwd(), dan tidak juga melakukan apa yang Anda inginkan dengan sendirinya, tetapi menambahkannya argv[0]ke salah satu dari mereka harus melakukannya.

Anda mungkin mencatat bahwa hasilnya tidak selalu cantik - Anda mungkin mendapatkan hal-hal seperti /foo/bar/../../baz/a.outatau /foo/bar//baz/a.out, tetapi saya percaya bahwa itu selalu menghasilkan jalur yang valid yang menamai executable (perhatikan bahwa garis miring berturut-turut di jalan diciutkan menjadi satu).

Saya sebelumnya menulis solusi menggunakan envp(argumen ketiga main()yang bekerja di Linux tetapi tampaknya tidak bisa diterapkan pada Windows, jadi saya pada dasarnya merekomendasikan solusi yang sama seperti yang dilakukan orang lain sebelumnya, tetapi dengan penjelasan tambahan mengapa itu sebenarnya benar bahkan jika hasilnya tidak cantik.

John Zwinck
sumber
0

Sebagai Minok disebutkan , tidak ada fungsi yang ditentukan dalam standar C atau standar C ++ ini. Ini dianggap murni fitur OS-spesifik dan ditentukan dalam standar POSIX, misalnya.

Thorsten79 telah memberikan saran yang baik, itu adalah perpustakaan Boost.Filesystem. Namun, mungkin tidak nyaman jika Anda tidak ingin memiliki dependensi waktu tautan dalam bentuk biner untuk program Anda.

Alternatif yang baik yang saya sarankan adalah koleksi 100% header-only STLSoft C ++ Libraries Matthew Wilson (penulis buku yang harus dibaca tentang C ++). Ada fasad portabel PlatformSTL memberikan akses ke API khusus sistem: WinSTL untuk Windows dan UnixSTL di Unix, jadi ini adalah solusi portabel. Semua elemen khusus sistem ditentukan dengan penggunaan sifat dan kebijakan, sehingga merupakan kerangka yang dapat diperluas. Ada perpustakaan filesystem yang disediakan, tentu saja.

mloskot
sumber
0

Perintah linux bash yang progname akan melaporkan path ke program.

Bahkan jika seseorang dapat mengeluarkan perintah yang mana dari dalam program Anda dan mengarahkan output ke file tmp dan program selanjutnya membaca file tmp itu, ia tidak akan memberi tahu Anda apakah program itu yang menjalankan. Ini hanya memberi tahu Anda di mana program yang memiliki nama itu berada.

Apa yang diperlukan adalah untuk mendapatkan nomor id proses Anda, dan untuk mem-parsing path ke nama

Dalam program saya, saya ingin tahu apakah program itu dijalankan dari direktori bin pengguna atau dari yang lain di path atau dari / usr / bin. / usr / bin akan berisi versi yang didukung. Perasaan saya adalah bahwa di Linux ada satu solusi yang portabel.

Leslie Satenstein
sumber
0

Gunakan realpath()di stdlib.hseperti ini:

char *working_dir_path = realpath(".", NULL);
Manabu Nakazawa
sumber
0

Bekerja dengan mulai dari C ++ 11, menggunakan filesystem eksperimental, dan C ++ 14-C ++ 17 juga menggunakan filesystem resmi.

application.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
}
TarmoPikaro
sumber
Jawaban yang bagus, tetapi tidak didefinisikan perilaku untuk menambahkan deklarasi atau definisi ke namespacestd . Untuk menghindari ini, Anda bisa menambahkan ruang nama std::filesystemdan std::experimental::filesystemruang nama ketiga pilihan Anda, atau gunakan saja using std::filesystem::path, jika Anda tidak keberatan menambahkan deklarasi pathke ruang nama global.
Cássio Renan
Saya kira setelah C ++ 14 eksperimental :: filesystem tidak digunakan lagi, jadi Anda bisa melupakan ini? (masuk ke cabang
#jika