C++ 不断删除字符串会导致无限循环
我正在尝试做的是获取一个路径,然后逐个目录不断地擦除路径目录,检查它在任何点是否是符号链接。以下是我所拥有的:C++ 不断删除字符串会导致无限循环,c++,linux,stdstring,C++,Linux,Stdstring,我正在尝试做的是获取一个路径,然后逐个目录不断地擦除路径目录,检查它在任何点是否是符号链接。以下是我所拥有的: static bool isLinkDirInSymLink (std::string linkPath) { DIR *baseDir; struct dirent *currentDir; do { baseDir = opendir(linkPath.c_str()); if (baseDir)
static bool isLinkDirInSymLink (std::string linkPath)
{
DIR *baseDir;
struct dirent *currentDir;
do
{
baseDir = opendir(linkPath.c_str());
if (baseDir)
{
currentDir = readdir(baseDir);
if (currentDir->d_type == DT_LNK)
return true;
}
linkPath.erase (linkPath.find_last_of("/") + 1, linkPath.find_first_of("\0"));
} while (strcmp(linkPath.c_str(), "") != 0);
return false;
}
这会陷入无限循环。当我在gdb
中运行程序时,我会发送一个linkPath
的/home/user/test/linktest/out/mDirs/testDir1/test
,当它成功擦除时,剩下的是/home/user/test/linktest/out/mDirs/testDir1
,然而这就是无限循环开始的地方。即使这与进入擦除
时的第一条路径的格式相同,也不会发生任何事情。我尝试了许多不同的擦除
变体,但似乎都不起作用。我还尝试了linkPath.append('\0')
,因为我认为可能是结尾的空字符有问题
谢谢大家,这就是我的结局:
char realPath[MAX_FILELENGTH];
do
{
if (realpath (linkPath.c_str(), realPath) != NULL)
if (strcmp(linkPath.c_str(), realPath) != 0)
return true;
size_t eraseFrom = linkPath.rfind('/');
if (std::string::npos != eraseFrom)
linkPath.erase(eraseFrom);
} while ( !linkPath.empty() );
return false;
应该是,
linkPath.find_last_of("/")
第一次擦除会留下一个尾随的/
,因此下一次擦除会尝试从字符串的结尾到结尾进行擦除,从而产生循环。擦除操作应包括目录分隔符/
不需要(“\0”)的linkPath.find\u first\u,您可以使用npos
删除到字符串末尾。使用
的find\u first\u会得到一个大小类型的结果,因此使用以下形式的擦除basic\u string&erase(大小类型索引=0,大小类型计数=npos)代码>
应该是,
linkPath.find_last_of("/")
第一次擦除会留下一个尾随的/
,因此下一次擦除会尝试从字符串的结尾到结尾进行擦除,从而产生循环。擦除操作应包括目录分隔符/
不需要(“\0”)
的linkPath.find\u first\u,您可以使用npos
删除到字符串末尾。使用
的find\u first\u会得到一个大小类型的结果,因此使用以下形式的擦除basic\u string&erase(大小类型索引=0,大小类型计数=npos)
由于擦除调用中的+1
,您正在擦除从/
到字符串末尾之前的字符,擦除以下字符:
/home/user/test/linktest/out/mDirs/testDir1/test\0
^^^^
循环的第一次迭代将删除test
,留下/home/user/test/linktest/out/mDirs/testDir1/
。所有后续调用erase
都将无效,因为/
和\0
之间没有字符
您应该从链接路径中删除+1
。在擦除调用中找到(“/”+1
中的最后一个,以便同时删除尾部斜杠
此外,erase(size\u t,size\u t)
重载实际上将要擦除的部分的长度作为第二个参数-find\u first\u of
返回找到的字符的索引,而不是迭代器。你的代码只是偶然的。使用std::string::npos
,它将擦除所有内容直到结束,而不是\0
字符的位置(如果您尚未调用c_str()
,则该字符可能不会出现在字符串中)。因为擦除调用中的+1
,您正在擦除从/
前面的字符到字符串末尾之前的字符,并擦除以下字符:
/home/user/test/linktest/out/mDirs/testDir1/test\0
^^^^
循环的第一次迭代将删除test
,留下/home/user/test/linktest/out/mDirs/testDir1/
。所有后续调用erase
都将无效,因为/
和\0
之间没有字符
您应该从链接路径中删除+1
。在擦除调用中找到(“/”+1
中的最后一个,以便同时删除尾部斜杠
此外,erase(size\u t,size\u t)
重载实际上将要擦除的部分的长度作为第二个参数-find\u first\u of
返回找到的字符的索引,而不是迭代器。你的代码只是偶然的。使用std::string::npos
,它将擦除所有内容直到结束,而不是\0
字符的位置(如果您尚未调用c_str()
,字符串中可能不存在该字符)。我猜您在调试器中查找时遗漏了尾随斜杠。这可能更好:
linkPath.erase (linkPath.begin()+linkPath.find_last_of("/"), linkPath.end());
还有一个问题是调用了错误的std::string::erase
重载:#1 in(“pos+len”),而您可能希望使用#3(“range”)。这是因为返回的是size\u t
,而不是迭代器。或者,要保存键入内容,您可以使用以下命令:
linkPath.resize(linkPath.find_last_of("/"));
我猜您在调试器中查找时错过了尾随斜杠。这可能更好:
linkPath.erase (linkPath.begin()+linkPath.find_last_of("/"), linkPath.end());
还有一个问题是调用了错误的std::string::erase
重载:#1 in(“pos+len”),而您可能希望使用#3(“range”)。这是因为返回的是size\u t
,而不是迭代器。或者,要保存键入内容,您可以使用以下命令:
linkPath.resize(linkPath.find_last_of("/"));
我想你的意思如下
#include <iostream>
#include <string>
int main()
{
std::string linkPath( "http://stackoverflow.com/questions/31590945/"
"continually-erasing-string-leads-to-infinite-loop" );
do
{
std::cout << linkPath << std::endl;
auto n = linkPath.rfind( '/' );
n = n == std::string::npos ? 0 : n;
linkPath.erase( n );
} while ( !linkPath.empty() );
}
当然,您可以根据需要修改代码。它展示了一种完成任务的方法
至于你的代码,那么这个电话
linkPath.find_first_of("\0")
将始终返回std::string::npos
。所以这不是男性的感觉。
使用这个表达式
linkPath.find_last_of("/") + 1
将始终保留字符串中找到的第一个字符“/”。我认为您的意思如下
#include <iostream>
#include <string>
int main()
{
std::string linkPath( "http://stackoverflow.com/questions/31590945/"
"continually-erasing-string-leads-to-infinite-loop" );
do
{
std::cout << linkPath << std::endl;
auto n = linkPath.rfind( '/' );
n = n == std::string::npos ? 0 : n;
linkPath.erase( n );
} while ( !linkPath.empty() );
}
当然,您可以根据需要修改代码。它展示了一种完成任务的方法
至于你的代码,那么这个电话
linkPath.find_first_of("\0")
将始终返回std::string::npos
。所以这不是男性的感觉。
使用这个表达式
linkPath.find_last_of("/") + 1
将始终保留字符串中找到的第一个字符“/”。更正确、更简化的实现
static bool isLinkDirInSymLink(std::string linkPath) {
DIR * baseDir;
struct dirent * currentDir;
do {
baseDir = opendir(linkPath.c_str());
if (baseDir) {
currentDir = readdir(baseDir);
if (currentDir->d_type == DT_LNK) return true;
}
std::string::size_type it = linkPath.rfind('/');
if (it != std::string::npos) linkPath.erase(it);
} while (!linkPath.empty());
return false;
}
更正确和简化的实现
static bool isLinkDirInSymLink(std::string linkPath) {
DIR * baseDir;
struct dirent * currentDir;
do {
baseDir = opendir(linkPath.c_str());
if (baseDir) {
currentDir = readdir(baseDir);
if (currentDir->d_type == DT_LNK) return true;
}
std::string::size_type it = linkPath.rfind('/');
if (it != std::string::npos) linkPath.erase(it);
} while (!linkPath.empty());
return false;
}
你有没有试过装一个去毛刺