web-dev-qa-db-ja.com

getcwdに相当するC ++はありますか?

Cのgetcwdが表示されます:man 3 cwd

C++にもstd :: stringを返す可能性のある類似したものがあると思います。

もしそうなら、それは何と呼ばれ、どこでドキュメントを見つけることができますか?

ありがとう!

32
anon

OK、あなたはすでに答えを受け入れましたが、私は答えています。

Getcwd呼び出しをラップするよりも優れた方法は、 boost :: filesystem を使用することです。この場合、current_path()関数からpathオブジェクトを取得します。 Boostファイルシステムライブラリを使用すると、ファイル/ディレクトリが存在するかどうかを確認したり、親パスを取得したり、パスを完成させたりするなど、多くの文字列解析を行う必要がある他の多くの便利な機能を実行できます。それを調べてみてください。移植性もあります-そうでなければ使用するであろう多くの文字列解析コードはそうではないでしょう。

Update(2016):Boost Filesystem v3に基づいて、2015年にファイルシステムが 技術仕様 として公開されました。これは、コンパイラー(Visual Studio 2015など)で既に使用可能になっている可能性があることを意味します。私にとっても、将来のC++標準の一部になる可能性が高いようです(C++ 17を想定していますが、現在の状況は認識していません)。

Update(2017):filesystem library は、C++ 17のISO C++とマージされました。

std::filesystem::current_path();
25
villintehaspam

std::stringのコンストラクタは安全にchar*をパラメーターとして。驚くべきことに windows version もあります。

編集:実際には少し複雑です:

std::string get_working_path()
{
   char temp[MAXPATHLEN];
   return ( getcwd(temp, sizeof(temp)) ? std::string( temp ) : std::string("") );
}

メモリは問題ありません-tempはスタックベースのバッファであり、std :: stringコンストラクターがコピーを実行します。おそらくあなたは一度にそれを行うことができますが、私は標準がそれを保証するとは思わない。

POSIX経由のメモリ割り当てについて:

Getcwd()関数は、bufが指す配列に現在の作業ディレクトリの絶対パス名を配置し、bufを返します。配列へのパス名copiedには、シンボリックリンクであるコンポーネントは含まれません。 size引数は、buf引数が指す文字配列のバイト単位のサイズです。 bufがNULLポインターの場合、getcwd()の動作は指定されていません。

21

この簡単なC呼び出しをC++として書き直してみましょう。

std::string get_working_path()
{
    char temp [ PATH_MAX ];

    if ( getcwd(temp, PATH_MAX) != 0) 
        return std::string ( temp );

    int error = errno;

    switch ( error ) {
        // EINVAL can't happen - size argument > 0

        // PATH_MAX includes the terminating nul, 
        // so ERANGE should not be returned

        case EACCES:
            throw std::runtime_error("Access denied");

        case ENOMEM:
            // I'm not sure whether this can happen or not 
            throw std::runtime_error("Insufficient storage");

        default: {
            std::ostringstream str;
            str << "Unrecognised error" << error;
            throw std::runtime_error(str.str());
        }
    }
}

問題は、ライブラリ関数を別の関数でラップする場合、ライブラリはそれを呼び出すものを知らないため、すべての機能を公開する必要があると仮定する必要があるということです。そのため、エラーを単に飲み込んだり、発生しないことを期待するのではなく、エラーのケースを処理する必要があります。

通常、クライアントコードがライブラリ関数を呼び出すようにし、その時点でエラーを処理する方がよいでしょう。クライアントコードは、おそらくエラーが発生した理由を気にしないので、すべてのエラーコード。

12
Pete Kirkham

ちょっとしたラッパーを書くだけです。

std::string getcwd_string( void ) {
   char buff[PATH_MAX];
   getcwd( buff, PATH_MAX );
   std::string cwd( buff );
   return cwd;
}
6

すべてのC関数もC++関数です。 std::stringが必要な場合は、getcwdが取得するchar*から作成してください。

3
Rob Kennedy

次の方法でCでgetcwd()を使用しました。

char * cwd;
cwd = (char*) malloc( FILENAME_MAX * sizeof(char) );
getcwd(cwd,FILENAME_MAX);

必要なヘッダーファイルはstdio.h。 Cコンパイラを使用すると、完璧に機能します。

C++コンパイラを使用してまったく同じコードをコンパイルすると、次のエラーメッセージが報告されます。

identifier "getcwd" is undefined

次に、unistd.hおよびC++コンパイラでコンパイルされています。今回は、すべてが機能します。 Cコンパイラに切り替えたとき、まだ動作します!

両方を含める限り、stdio.hおよびunistd.h、上記のコードはCおよびC++コンパイラで機能します。

3
Zhongming Qu

上記の別の回答で述べたように、boost :: filesystemも使用しました。 current_path()関数はstd :: stringを返さないので、それを変換する必要があるので追加したいだけです。

ここに私がやったことがあります:

std::string cwd = boost::filesystem::current_path().generic_string();
1
crecre