280

C/C++ を使用してプログラムが実行されている場所からディレクトリの完全なパスを取得するための、プラットフォームに依存しない、ファイルシステムに依存しない方法はありますか? 現在の作業ディレクトリと混同しないでください。(clib や STL などの標準的なものでない限り、ライブラリを提案しないでください。)

(プラットフォーム/ファイルシステムに依存しない方法がない場合は、Windows および Linux で特定のファイルシステムに対して機能する提案も歓迎します。)

4

25 に答える 25

192

実行中のアプリへのフルパスを取得するコードは次のとおりです。

ウィンドウズ:

char pBuf[256];
size_t len = sizeof(pBuf); 
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;
于 2008-10-13T16:01:28.090 に答える
172

プログラムの最初の起動時に現在のディレクトリをフェッチすると、プログラムが開始されたディレクトリが効果的に作成されます。値を変数に格納し、プログラムの後半で参照します。これは、現在の実行可能プログラムファイルを保持するディレクトリとは異なります。必ずしも同じディレクトリである必要はありません。誰かがコマンドプロンプトからプログラムを実行すると、プログラムファイルが別の場所にある場合でも、プログラムはコマンドプロンプトの現在の作業ディレクトリから実行されます。

getcwdはPOSIX関数であり、すべてのPOSIX準拠プラットフォームですぐにサポートされます。特別なことをする必要はありません(Unixでは正しいヘッダーunistd.hを、Windowsではdirect.hを含めることを除いて)。

Cプログラムを作成しているので、システム内のすべてのプロセスによってリンクされているデフォルトのcランタイムライブラリにリンクされ(特別に細工された例外は回避されます)、デフォルトでこの関数が含まれます。CRTは、OSに基本的な標準準拠のインターフェイスを提供するため、外部ライブラリとは見なされません。

Windowsでは、getcwd関数は廃止され、_getcwdが採用されました。このように使えそうです。

#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);
于 2008-09-28T06:04:04.923 に答える
29

ライブラリなしの標準的な方法が必要な場合:いいえ。ディレクトリの概念全体は標準に含まれていません。

標準に近いライブラリへの (移植可能な) 依存関係に問題がないことに同意する場合: Boost のファイルシステム ライブラリを使用し、initial_path()を要求します。

私見は、良いカルマを備えた、できる限り近いものです(Boostは定評のある高品質のライブラリセットです)

于 2008-09-27T07:23:51.933 に答える
10

いいえ、標準的な方法はありません。C/C++ 標準では、ディレクトリ (またはその他のファイル システム構成) の存在さえ考慮されていないと思います。

Windows では、 hModuleパラメータがNULLに設定されている場合、 GetModuleFileName()は現在のプロセスの実行可能ファイルへのフル パスを返します。Linux についてはどうすることもできません。

また、現在のディレクトリが必要か、プログラム イメージ/実行可能ファイルが存在するディレクトリが必要かを明確にする必要があります。現状では、この点に関してあなたの質問は少しあいまいです。

于 2008-09-27T07:22:03.107 に答える
8

たぶん、現在の作業ディレクトリを argv[0] と連結しますか? それがWindowsで機能するかどうかはわかりませんが、Linuxでは機能します。

例えば:

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

実行すると、次のように出力されます。

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

于 2008-09-27T07:32:09.573 に答える
7

Win32の場合、 GetCurrentDirectoryでうまくいくはずです。

于 2008-09-27T07:21:01.223 に答える
6

その目的でargv [0]を使用することはできません。通常、実行可能ファイルへのフルパスが含まれていますが、必ずしもそうではありません-フィールドに任意の値を指定してプロセスを作成できます。

また、現在のディレクトリと実行可能ファイルを含むディレクトリは2つの異なるものであるため、 getcwd() も役に立ちません。

Windows では GetModuleFileName() を使用し、Linux では /dev/proc/ procID /.. ファイルを読み取ります。

于 2008-09-27T08:17:00.387 に答える
3

dirコンソールの Windows システムでは、system( ) コマンドを使用できます。また、コンソールには、ディレクトリなどに関する情報が表示されます。dirコマンドについては、 を参照してくださいcmd。しかし、Unix ライクなシステムの場合はわかりません... このコマンドを実行する場合は、bash コマンドを読みます。lsディレクトリが表示されない...

例:

int main()
{
    system("dir");
    system("pause"); //this wait for Enter-key-press;
    return 0;
}
于 2013-06-10T16:52:50.567 に答える
3

遅ればせながらここに積み上げて、...

言語は基礎となるファイルシステムに依存しないため、標準的な解決策はありません。他の人が言ったように、ディレクトリベースのファイルシステムの概念は c / c++ 言語の範囲外です。

それに加えて、現在の作業ディレクトリではなく、プログラムが実行されているディレクトリが必要です。これは、プログラムが現在の場所に到達した方法を考慮に入れる必要があります。つまり、フォークなどを介して新しいプロセスとして生成された.ソリューションが示したように、プログラムが実行されているディレクトリを取得するには、問題のオペレーティング システムのプロセス制御構造からその情報を取得する必要があります。これは、この問題に関する唯一の権限です。したがって、定義上、これは OS 固有のソリューションです。

于 2010-01-27T23:50:14.493 に答える
3
#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);
}
于 2014-02-19T17:15:35.623 に答える
1

相対パスについては、これが私がしたことです。私はこの質問の年齢を認識しています。ほとんどの場合に機能するより簡単な回答を提供したいだけです。

次のようなパスがあるとします。

"path/to/file/folder"

何らかの理由で、Eclipse で作成された Linux ビルドの実行可能ファイルはこれで問題なく動作します。ただし、このようなパスを指定すると、Windows は非常に混乱します。

上記のように、実行可能ファイルへの現在のパスを取得する方法はいくつかありますが、ほとんどの場合、これをパスの FRONT に追加するのが最も簡単な方法です。

"./path/to/file/folder"

「./」を追加するだけでソートされます。:) 次に、実行可能ファイル自体がある限り、任意のディレクトリからロードを開始できます。

編集: code::blocks から実行可能ファイルを起動しようとしても、それが使用されている開発環境である場合、これは機能しません。何らかの理由で、code::blocks は正しくロードされません... :D

EDIT2:私が見つけたいくつかの新しいことは、コードでこのような静的パスを指定した場合です(Example.dataがロードする必要があると仮定します):

"resources/Example.data"

次に、実際のディレクトリからアプリを起動すると (または Windows では、ショートカットを作成し、作業ディレクトリをアプリ ディレクトリに設定します)、そのように動作します。リソース/ファイル パスの欠落に関連する問題をデバッグするときは、この点に注意してください。(特に、IDE からビルド exe を起動するときに間違った作業ディレクトリを設定する IDE で)

于 2015-04-21T05:21:19.423 に答える
0

Boost Filesysteminitial_path()はPOSIXのように動作し、どちらもそれ自体では必要なことを実行しませんが、どちらかにgetcwd()追加することで実行できます。argv[0]

結果が常にきれいであるとは限らないことに気付くかもしれません-/foo/bar/../../baz/a.outまたは/foo/bar//baz/a.outのようなものが得られるかもしれませんが、実行可能ファイルを指定する有効なパスが常に得られると思います(パス内の連続するスラッシュは1つに折りたたまれていることに注意してください)。

私は以前に( Linuxでは機能したがWindowsでは機能しなかったように見えるenvp3番目の引数を使用してソリューションを作成しました。したがって、他の誰かが以前に行ったのと同じソリューションを基本的にお勧めしますが、実際に正しい理由の追加の説明がありますmain()結果がきれいでなくても。

于 2008-09-28T04:28:35.823 に答える
0

progname がプログラムへのパスを報告するLinux bash コマンド 。

プログラム内から which コマンドを発行して出力を tmp ファイルに送信し、その後プログラムがその tmp ファイルを読み取ったとしても、そのプログラムが実行中のプログラムであるかどうかはわかりません。その名前のプログラムがどこにあるかを示すだけです。

必要なのは、プロセスID番号を取得し、名前へのパスを解析することです

私のプログラムでは、プログラムがユーザーの bin ディレクトリから実行されたのか、パス内の別のディレクトリから実行されたのか、/usr/bin から実行されたのかを知りたいです。/usr/bin には、サポートされているバージョンが含まれます。私の感じでは、Linux には移植可能なソリューションが 1 つあります。

于 2016-08-22T15:46:54.233 に答える
0

POSIX プラットフォームでは、 getcwd()を使用できます。

Windows では、getcwd()の使用が推奨されていないため、 _getcwd()を使用できます。

標準ライブラリの場合、Boost が十分に標準的である場合、Boost::filesystem を提案しましたが、提案からパスの正規化が削除されたようです。TR2 が完全に標準的なソリューションとしてすぐに利用できるようになるまで待つ必要がある場合があります。

于 2008-09-27T07:31:38.717 に答える
0

Minokが述べたように、C標準またはC++標準で指定されたそのような機能はありません。これは純粋に OS 固有の機能と見なされ、たとえば POSIX 標準で指定されています。

Thorsten79は良い提案をしてくれました。Boost.Filesystem ライブラリです。ただし、プログラムにバイナリ形式のリンク時の依存関係を持たせたくない場合は、不便な場合があります。

私がお勧めする良い代替案は、100% ヘッダーのみのSTLSoft C++ ライブラリのコレクションです 。Matthew Wilson (C++ に関する必読本の著者)。移植可能なファサード PlatformSTL は、システム固有の API (Windows の場合は WinSTL、Unix の場合は UnixSTL) へのアクセスを提供するため、移植可能なソリューションです。すべてのシステム固有の要素は、特性とポリシーを使用して指定されるため、拡張可能なフレームワークです。もちろん、ファイルシステムライブラリが提供されています。

于 2010-01-28T00:26:18.837 に答える