我正在寻找一种方法来检查 2 个字符串在文件系统路径(目录)方面是否相同。例如,此集合中的所有字符串在文件系统路径方面都是相同的:{/x
,\x
,//x
,/x/
},但是这两个 - /x
和 /y
不是,即使 /y
是符号链接(symbolic link)到 /x
。我要编写的程序应该既适用于 Linux 也适用于 Windows,因此我正在寻找可移植的解决方案。
编辑:
我只使用 boost 的仅 header 库,所以 boost::filesystem
的解决方案对我来说不合适。我知道在 windows API 中有 UrlCompare
,在 linux 中有类似的东西吗?
最佳答案
任何非 Boost 解决方案都将涉及系统相关代码(即
如果您使用 Boost,则隐藏在 Boost 中)。你必须准确定义
你所说的“匹配”是什么意思:应该"./MyFile.xxx"
和 "MyFile.xxx"
比较相等?怎么样"aaa/.../MyFile.xxx"
和 "MyFile.xxx"
?
我处理这个问题的方法是定义一个有两个数据成员的类,
一个std::string
带有“前缀”(总是
在 Unix 中为空)和一个 std::vector<std::string>
与所有的路径
元素。这门课会被必要的比较所淹没
功能,并将使用系统相关代码来实现
构造器;构造函数本身将在源文件中,而
源文件将包含一个机器相关的头文件(通常通过使用
每个变体的单独目录,并通过方式选择标题
的 -I
或 /I
指定要使用的目录)。那种东西
这可能会进入标题:
inline bool
isPathSeparator( char ch )
{
return ch == '/';
}
std::string
getHeader( std::string const& fullPathName )
{
return "";
}
bool
charCompare( char lhs, char rhs )
{
return lhs < rhs;
}
bool
charMatch( char lhs, char rhs )
{
return lhs == rhs;
}
对于 Unix,具有:
inline bool
isPathSeparator( char ch )
{
return ch == '/' || ch == '\\';
}
std::string
getHeader( std::string const& fullPathName )
{
return fullPathName.size() > 2 && fullPathName[1] == ':'
? fullPathName.substr( 0, 2 )
: std::string();
}
bool
charCompare( char lhs, char rhs )
{
return tolower( (unsigned char)lhs) < tolower( (unsigned char)rhs );
}
bool
charMatch( char lhs, char rhs )
{
return tolower( (unsigned char)lhs ) == tolower( (unsigned char)rhs );
}
适用于 Windows。
然后构造函数将使用 getHeader
初始化标题,和
遍历 input.begin() + header.size()
和 input.end()
, 打破
把字符串向上分解成元素。如果遇到"."
的元素,
忽略它,对于 ".."
之一, 使用 pop_back()
删除顶部
路径的元素,前提是路径不为空。之后,就是
只是定义要使用的比较器的问题 charCompare
和
charMatch
对于 char
, 和 std::lexicographical_compare
要么
std::equal
(在验证大小相等之后)与
std::string
的比较器(可能还有你的新
类(class))。像这样的东西:
struct FileNameCompare
{
bool operator()( char lhs, char rhs ) const
{
return charCompare( lhs, rhs );
}
bool operator()( std::string const& lhs, std::string const& rhs ) const
{
return std::lexicographical_compare(
lhs.begin(), lhs.end(),
rhs.begin(), rhs.end(),
*this );
}
bool operator()( FileName const& lhs, FileName const& rhs ) const
{
return (*this)( lhs.prefix, rhs.prefix )
|| ( !(*this)( rhs.prefix, lhs.prefix )
&& std::lexicographical_compare(
lhs.elements.begin(), lhs.elements.end(),
rhs.elements.begin(), rhs.elements.end(),
*this ) );
}
};
struct FileNameMatch
{
bool operator()( char lhs, char rhs ) const
{
return charMatch( lhs, rhs );
}
bool operator()( std::string const& lhs, std::string const& rhs ) const
{
return lhs.size() == rhs.size()
&& std::equal( lhs.begin(), lhs.end(), rhs.begin(), *this );
}
bool operator()( FileName const& lhs, FileName const& rhs ) const
{
return (*this)( lhs.prefix, rhs.prefix )
&& lhs.elements.size() == rhs.elements.size()
&& std::equal( lhs.elements.begin(), lhs.elements.end(),
rhs.elements.begin(),
*this );
}
};
应该可以解决问题。 (请记住 operator()( char, char )
const
必须在源文件中;您不能将它们内联到标题中,
其中不包括定义的系统相关 header
charCompare
和 charMatch
.)
关于c++ - 如何在 C++ 中比较(目录)路径?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8504571/