35

関数を書きたい:

inline char separator()
{
    /* SOMETHING */
}

標準の C/C++/C++11 でシステムのファイル区切りを返す ? (システムによっては、スラッシュまたはバックスラッシュを意味します)。これを達成する方法はありますか?

4

7 に答える 7

49

ifdefs をチェックする以外の方法がわかりません

inline char separator()
{
#ifdef _WIN32
    return '\\';
#else
    return '/';
#endif
}

または(PaperBirdMasterの提案による)

const char kPathSeparator =
#ifdef _WIN32
                            '\\';
#else
                            '/';
#endif
于 2012-10-19T09:43:53.067 に答える
17

コンパイラが c++17 機能を提供している場合std::filesystem::path::preferred_separatorは、プラットフォームに応じて、優先される区切り文字を生成する which を使用できます。たとえば、Windows では通常\、Linux では/.

詳細については、これを参照してください。

于 2016-11-08T16:53:23.033 に答える
13

この質問は、もっと厄介な問題を暗示しています。

UNIX と Winodws の違いだけに関心があり、ディレクトリとファイルだけに関心がある場合は、既に見たことが (ほとんど) うまくいきますが、パス名をその構成要素につなぎ合わせるというより一般的な問題は、はるかに厄介な問題です。プラットフォームによっては、パスに次の 1 つ以上が含まれる場合があります。

  • ボリューム識別子
  • ディレクトリ一覧
  • ファイル名
  • ファイル内のサブストリーム
  • バージョンナンバー

これにはサードパーティのライブラリ (さまざまな CPAN Perl モジュール、Boost など) があり、すべての OS にはこのためのシステム関数が含まれていますが、C には何も組み込まれておらず、C++ 標準はこの機能を (組み込むことによって) 獲得しただけです。ブースト モジュール) で 2017 年に。

そのような関数が処理する必要があるもののいくつかの例は次のとおりです。

  • UNIX および UNIX ライクなシステムでは、"/" 文字で区切られた文字列のリストを使用し、先頭に "/" を付けて絶対パス (相対パス) を示します。一部のコンテキスト (NFS など) では、ホスト名のプレフィックス (":" 区切り文字を使用) もある場合があります。
  • DOS および DOS 由来の OS (Windows、OS/2 など) は、ディレクトリ区切りとして "\" を使用します (API も "/" を受け入れます) が、パスにはボリューム情報がプレフィックスとして付けられることもあります。ドライブ文字 (「C:」) または UNC 共有名 (「\\MYSERVER\SHARE\」) の可能性があります。さまざまな種類のサーバーを表す追加のプレフィックスと、ファイル内の既定以外のストリームを表すサフィックスがあります。
  • Mac (Classic Mac OS、Carbon、および一部の Cocoa API) は、ディレクトリの区切り文字として ":" を使用します。最初の用語は、ディレクトリ名ではなくボリューム名です。Mac ファイルには、専用 API を使用して同じ名前でアクセスされるサブストリーム (「フォーク」) が含まれている場合もあります。これは、従来の Mac ソフトウェアで広く使用されているリソース フォークにとって特に重要です。
  • Mac OS X で UNIX API を使用する場合、通常は UNIX ライクなシステムと同じように動作しますが、「.」をサフィックスとして名前付きサブストリーム (「フォーク」) を表すこともできます。ファイル名へのフォーク名が続きます。
  • Cocoa の最新バージョン (Mac OS X、iOS など) では、この問題がますます複雑になるため、URL ベースの API を使用してファイルを表現することを推奨しています。クラウドベースのドキュメントやその他の複雑なネットワーク ファイル システムなどについて考えてみてください。
  • VMS はかなり複雑 ( https://web.archive.org/web/20160324205714/http://www.djesys.com/vms/freevms/mentor/vms_path.html ) ですが、ボリューム、ディレクトリを表すコンポーネントがあります。 -パス、ファイル、およびファイル リビジョン。

他にもたくさんあります。

C++17 ファイルシステム ライブラリは、これらの可能性のすべてをカバーしていないことに注意してください。はstd::filesystem::path、オプションのroot-name (ボリューム識別子)、オプションのroot-directory (絶対パスを識別するため)、およびディレクトリ セパレータで区切られた一連のファイル名で構成されます。これは、UNIX プラットフォームで有効である可能性が高いすべてのものと、他のプラットフォームのユースケースの大部分をカバーしていますが、包括的ではありません。たとえば、サブストリームのサポートはありません (OS に依存してファイル名にマップします。これは Mac OS X で行われますが、従来の MacOS では行われません)。また、ファイルのバージョン番号のサポートも含まれていません。

Pathおよび C++17 std::filesystem::pathクラスに関するウィキペディアのエントリも参照してください。

http://en.cppreference.com/w/cpp/filesystem

ディレクトリセパレーターで何をしたいのかを調べて(ベース名を抽出する、パスをディレクトリのリストに分割するなど)、それを行う関数を書くことをお勧めします。C++17 を使用している場合 (そして、コードが 17 より前の C++ コンパイラでコンパイルされないことが確実である場合)、(おそらく) 標準の C++ ライブラリ コードを使用して、この関数の移植可能な実装を作成できます。#ifdefそうでない場合、その関数は、サポートする予定の各プラットフォームにプラットフォーム固有の を使用する必要があります。どの#error条件も満たされない場合は、予期しないプラットフォームの条件を強制的に追加する必要があります。

または、許容できる場合は、これらすべての機能を含むサードパーティのライブラリ (Boost など) を使用します。

于 2015-05-15T13:54:30.150 に答える
12

それはこのようなものになることができます

#if defined(WIN32) || defined(_WIN32) 
#define PATH_SEPARATOR "\\" 
#else 
#define PATH_SEPARATOR "/" 
#endif 
于 2012-10-19T10:09:17.790 に答える
7

受け入れられた回答は、Cygwin では機能しません。Windows で実行されている Cygwin コンパイル済みプログラムは、Windows スタイルの '\' セパレーターを使用できますが、_WIN32 などは定義しません。Cygwin で動作する修正されたソリューション:

inline char separator()
{
#if defined _WIN32 || defined __CYGWIN__
    return '\\';
#else
    return '/';
#endif
}

また

const char kPathSeparator =
#if defined _WIN32 || defined __CYGWIN__
    '\\';
#else
    '/';
#endif
于 2015-09-07T12:59:32.640 に答える
2

誰も以下を提供していないことに驚いています。これは、他の人がここで提供しているものに少し基づいています。

この例では、使用のために実行されている実行可能ファイルの名前を動的に取得しようとしていますが、必要に応じてジャンプしてこれを再適用するのはそれほど難しくありません。

Windows では、スラッシュを使用して引数を示します。argv[0]したがって、実行中のプログラムの名前を含む最初の引数で最初にそれを確認できます。

次の結果は、最後のスラッシュの前のパス名を削除sepdし、プログラムのファイル名のままにすることに注意してください。

#include <string.h>
#include <stdio.h>

int main(int argc, char *argv[]){
//int a = 1
//int this = (a == 1) ? 20 : 30;  //ternary operator
//is a==1 ? If yes then 'this' = 20, or else 'this' = 30
    char *sepd = (strrchr(argv[0], '\/') != NULL) ? 
        strrchr(argv[0], '\/') : 
        strrchr(argv[0], '\\');
    printf("%s\n\n", sepd);
    printf("usage: .%s <host> \n\n", sepd);
    while (getchar() != '\n');
}

しかし、実際には、これは非常に汚いものであり、Bash を組み込むという Windows の最新の動き (現時点ではまだ実装されていません) により、予期しない、または予期しない結果が生じる可能性があります。

また、特に#ifdef _WIN32.

于 2016-07-05T19:12:37.830 に答える