我想写一个函数:
inline char separator()
{
/* SOMETHING */
}
返回标准C / C ++ / C ++ 11中系统的文件分隔符? (我的意思是斜杠或反斜杠取决于系统)。有没有办法实现这个目标?
答案 0 :(得分:34)
除了检查ifdefs
之外,我不知道该怎么做inline char separator()
{
#ifdef _WIN32
return '\\';
#else
return '/';
#endif
}
或(由PaperBirdMaster建议)
const char kPathSeparator =
#ifdef _WIN32
'\\';
#else
'/';
#endif
答案 1 :(得分:11)
这个问题确实暗示了一个更糟糕的问题。
如果您只关心UNIX与Winodws并且您只关心目录和文件,那么您已经看到的(大多数)将会工作,但是将路径名拼接到其组件中的更通用的问题是更丑陋的问题。根据平台,路径可能包括以下一个或多个:
虽然有第三方库(比如各种CPAN Perl模块,Boost等),并且每个操作系统都包含用于此的系统功能,但是C没有为此内置任何内容,C ++标准仅获得此功能(通过纳入Boost模块),2017年。
这种功能可能需要处理的一些例子是:
还有很多其他的。
值得注意的是,C ++ 17文件系统库并未涵盖所有这些可能性。 std::filesystem::path
由可选的根名称(卷标识符),可选的根目录(用于标识绝对路径)和一系列文件名组成由目录分隔符分隔。这涵盖了在UNIX平台上可能有效的所有内容以及其他平台的大多数用例,但并不全面。例如,它没有任何子流支持(依靠操作系统以某种方式将它们映射到文件名 - 这是由Mac OS X完成的,但不是经典的MacOS)。它也不包括对文件版本号的支持。
另请参阅Wikipedia's entry on Path和C ++ 17 std::filesystem::path类
http://en.cppreference.com/w/cpp/filesystem
我建议您查看您要对目录分隔符执行的操作(提取基本名称,将路径分解为目录列表等)并编写一个函数来执行此操作。如果您正在使用C ++ 17(并且您确定您的代码不会被17之前的C ++编译器编译),那么您可以(可能)使用标准C ++库代码来编写此函数的可移植实现。如果没有,该功能将需要为您将支持的每个平台使用特定于平台的#ifdef
,如果没有满足任何条件,则使用#error
强制您为意外添加条件平台。
或者使用包含所有这些功能的第三方库(如Boost),如果可以接受的话。
答案 2 :(得分:10)
可能是这样的
#if defined(WIN32) || defined(_WIN32)
#define PATH_SEPARATOR "\\"
#else
#define PATH_SEPARATOR "/"
#endif
答案 3 :(得分:6)
接受的答案在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
答案 4 :(得分:6)
如果您的编译器已经提供了c ++ 17功能,那么您可以使用std::experimental::filesystem::path::preferred_separator
,它应该返回/
或\
,具体取决于您的平台。
有关详细信息,请参阅this。
答案 5 :(得分:0)
我很惊讶没有人提供以下内容。这构建了其他人在这里提供的东西。
虽然在这个例子中,我试图动态获取正在运行的可执行文件的名称,但是根本不需要跳转并重新应用它。
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');
}
但是在所有现实中,这都非常糟糕,并且使用Windows&#39;最近采取措施包括Bash(此时尚未实施),这可能会产生意外或意外的结果。
它也不像其他人所提供的那样理智和不受错误的影响,特别是#ifdef _WIN32
。
答案 6 :(得分:0)
现在使用C ++ 17可以使用std::filesystem::path::preferred_separator
(see):
#include <filesystem>
#include <iostream>
int main() {
std::cout << "This OS separator: " << std::filesystem::path::preferred_separator;
}
答案 7 :(得分:0)
std::filesystem::path::preferred_separator
现在应该作为一个干净的 C++17
库函数使用。