関数を書きたい:
inline char separator()
{
/* SOMETHING */
}
標準のC/C++/C++ 11でシステムのファイル区切りを返す(システムに応じて、スラッシュまたはバックスラッシュを意味します)。これを達成する方法はありますか?
Ifdefsを確認する以外に、どうすればよいかわかりません
inline char separator()
{
#ifdef _WIN32
return '\\';
#else
return '/';
#endif
}
または(PaperBirdMasterの提案どおり)
const char kPathSeparator =
#ifdef _WIN32
'\\';
#else
'/';
#endif
この質問は、非常に厄介な問題をほのめかしています。
UNIXとWinodwsだけに関心があり、ディレクトリとファイルのみに関心がある場合、すでに見たものは(ほとんど)機能しますが、パス名をそのコンポーネントにスプライスするというより一般的な問題は、はるかに醜い問題です。プラットフォームに応じて、パスには次の1つ以上が含まれる場合があります。
これにはサードパーティのライブラリ(さまざまなCPAN Perlモジュール、Boostなど)があり、すべてのOSにはこのためのシステム関数が含まれていますが、Cに組み込まれているものはなく、C++標準はこの機能のみを組み込みました(組み込むことにより)ブーストモジュール)2017年に。
そのような関数が処理する必要があるかもしれないもののいくつかの例は:
他にもたくさんあります。
C++ 17ファイルシステムライブラリがこれらの可能性のすべてをカバーしているわけではないことは注目に値します。 std::filesystem::path
は、オプションのroot-name(ボリューム識別子)、オプションのroot- directory(絶対パスを識別するため)、およびディレクトリ区切り文字で区切られたファイル名のシーケンス。これは、UNIXプラットフォームで有効である可能性が高いすべてと他のプラットフォームの大部分のユースケースをカバーしますが、包括的ではありません。たとえば、サブストリームはサポートされていません(OSを何らかの方法でファイル名にマッピングしているため、Mac OS Xでは実行されますが、クラシックMacOSでは実行されません)。また、ファイルバージョン番号のサポートも含まれていません。
Wikipediaのパスに関するエントリ およびC++ 17 std :: filesystem :: path クラスも参照してください
http://en.cppreference.com/w/cpp/filesystem
ディレクトリセパレーターで何をしたいか(ベース名を抽出し、パスをディレクトリのリストに分割するなど)を確認し、それを行う関数を作成することをお勧めします。 C++ 17を使用している場合(かつ、コードが17より前のC++コンパイラーによってコンパイルされないことが確実である場合)、(おそらく)標準のC++ライブラリコードを使用して、この関数の移植可能な実装を作成できます。そうでない場合、その関数は、サポートするプラットフォームごとにプラットフォーム固有の#ifdef
sを使用する必要があります。条件が満たされない場合は#error
を使用して、予期しないプラットフォームの条件を追加するように強制します。 。
または、それが許容できる場合は、これらすべての機能を含むサードパーティライブラリ(Boostなど)を使用します。
それはこのようなものにすることができます
#if defined(WIN32) || defined(_WIN32)
#define PATH_SEPARATOR "\\"
#else
#define PATH_SEPARATOR "/"
#endif
コンパイラがすでにc ++ 17機能を提供している場合は、std::experimental::filesystem::path::preferred_separator
を使用できます。これにより、プラットフォームに応じて/
または\
が返されます。
詳細は this を参照してください。
受け入れられた回答は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
C++ 17ではstd::filesystem::path::preferred_separator
を使用できるようになりました( see ):
#include <filesystem>
#include <iostream>
int main() {
std::cout << "This OS separator: " << std::filesystem::path::preferred_separator;
}
誰もが以下を提供していないことに驚いています。これは、他の人がここで提供しているものに少し基づいています。
この例では、実行のために実行されている実行可能ファイルの名前を動的に取得しようとしていますが、必要に応じてジャンプして再適用することはそれほど難しくありません。
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
。