如何获取标准 C/C++ 中的文件分隔符符号:/ 或 \
How to get the file separator symbol in standard C/C++ : / or ?
我想写一个函数:
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
如果您的编译器提供 c++17 功能,则可以使用std::filesystem::path::preferred_separator
根据您的平台生成首选分隔符字符。例如,在Windows上,这通常是而在Linux上,你会得到
/
。
有关详细信息,请参阅此处。
这个问题实际上暗示了一个更令人讨厌的问题。
如果你只关心UNIX与Winodws,只关心目录和文件,那么你已经看到的将(大部分)工作,但是将路径名拼接到其组件的更通用的问题是更丑陋的问题。 根据平台的不同,路径可能包括以下一项或多项:
- 卷标识符
- 目录列表
- 文件名
- 文件中的子流
- 版本号
虽然有第三方库(如各种CPAN Perl模块,Boost等),并且每个操作系统都包含用于此的系统功能,但C没有内置任何功能,C++标准仅在2017年获得了此功能(通过合并Boost模块)。
此类函数可能需要处理的一些示例包括:
- UNIX 和类 UNIX 系统使用由"/"字符分隔的字符串列表,前导"/"表示绝对路径(相对于相对路径)。 在某些上下文(如 NFS)中,可能还存在主机名前缀(带有":"分隔符) DOS
- 和DOS派生的操作系统(Windows,OS/2等)使用"\"作为目录分隔符(API也接受"/"),但路径也可以以卷信息为前缀。 它可以是驱动器号 ("C:") 或 UNC 共享名称 ("\\MYSERVER\SHARE\") 还有其他前缀来表示不同类型的服务器,后缀用于表示文件中的非默认流。
- Mac(经典Mac OS,Carbon和一些Cocoa API)使用":"作为目录分隔符,第一个术语是卷名,而不是目录名。 Mac 文件还可能包含子流("分叉"),这些子流使用专用 API 通过相同的名称进行访问。 这对于资源分叉尤其重要,资源分叉在经典 Mac 软件中广泛使用。
- Mac OS X在使用UNIX API时通常执行类UNIX系统所做的事情,但它们也可以通过在文件名后加上"."后跟fork-name来表示命名的子流("forks")。
- 最新版本的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
由可选的根名(卷标识符)、可选的根目录(用于标识绝对路径)和由目录分隔符分隔的文件名序列组成。 这涵盖了在 UNIX 平台上可能有效的所有内容以及其他平台上的大多数用例,但并不全面。 例如,它没有任何对子流的支持(依靠操作系统以某种方式将它们映射到文件名 - 这是由Mac OS X完成的,但不是经典MacOS)。 它也不包括对文件版本号的支持。
另请参阅维基百科关于 Path 和 C++17 std::filesystem::p ath 类的条目
http://en.cppreference.com/w/cpp/filesystem
我建议你看看你想用目录分隔符做什么(提取基名称,将路径分解为目录列表等)并编写一个函数来做到这一点。 如果您使用的是 C++17(并且您确定您的代码不会由 17 之前的 C++ 编译器编译),那么您可以(可能)使用标准C++库代码来编写此函数的可移植实现。 如果没有,该函数将需要对你将支持的每个平台使用特定于平台的#ifdef
,如果不满足任何条件,则使用#error
,以强制你为意外的平台添加条件。
或者使用包含所有这些功能的第三方库(如 Boost),如果可以接受的话。
可以是这样的
#if defined(WIN32) || defined(_WIN32)
#define PATH_SEPARATOR "\"
#else
#define PATH_SEPARATOR "/"
#endif
接受的答案在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
std::filesystem::path::preferred_separator
现在应该用作一个干净的C++17
库函数。
我很惊讶没有人提供以下内容。 这在某种程度上建立在其他人在这里提供的内容之上。
尽管在此示例中,我正在尝试动态获取正在运行的可执行文件的名称以供使用,但根据需要进行跳转并重新应用它并不难。
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("%snn", sepd);
printf("usage: .%s <host> nn", sepd);
while (getchar() != 'n');
}
但实际上,这是非常肮脏的,并且Windows最近包括Bash(目前尚未实现),这可能会产生意想不到或意想不到的结果。
它也不像其他人提供的那样理智和不受错误的影响,尤其是#ifdef _WIN32
.
- C++使用分隔符读取文件
- 到达分隔符时跳到文本文件的下一行
- 使用空格分隔符从文本文件将对象读入数组
- 使用任意分隔符从文件流读取
- 使用 C++ 读取具有两个连续分隔符的 csv 文件
- 通过自定义分隔符从文件中读取对象数组
- 使用不同类型的分隔符从.txt文件中读取输入
- 如何在没有分隔符的大文本文件中查找所有字典单词
- 将 OpenCV MAT 保存到 TXT 文件作为不带分隔符的十六进制值
- 如何在C++中正确解析带有多个分隔符的文本文件
- 从没有分隔符 C++ 的文件读取数字出现次数
- 生成文件,缺少分隔符错误
- 生成文件错误:缺少分隔符
- 检测 CSV 文件中的记录/行分隔符
- C++ 使用多个分隔符存储输入文件
- 用指定的分隔符按线解析文本文件
- 如何获取标准 C/C++ 中的文件分隔符符号:/ 或 \
- 在C++中搜索二进制文件分隔符时出现不正确的偏移量
- C++具有混合分隔符和数据类型的文件输入
- 我的生成文件中缺少分隔符