不断擦除字符串会导致无限循环
Continually erasing a string leads to an infinite loop
我想做的是进入一条路径,然后逐个目录不断地擦除路径目录,随时检查它是否是符号 link。这是我拥有的:
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("[=10=]"));
} 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
,然而这是无限循环开始的地方。即使这与进入 erase
时的第一条路径格式相同,也没有任何反应。我尝试了 erase
从 here 的许多不同变体,但 none 似乎有效。我也试过 linkPath.append('[=18=]')
因为我认为最后可能是空字符的问题。
谢谢大家,这就是我最后的结果:
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("/") + 1
应该就是;
linkPath.find_last_of("/")
第一次擦除会留下尾随 /
,因此下一次擦除会尝试从字符串的末尾擦除到末尾,因此循环。擦除应包括目录分隔符 /
.
不需要linkPath.find_first_of("[=14=]")
,直接用npos
删除到字符串末尾即可。 find_first_of
的使用给出了大小类型的结果,因此使用了以下形式的擦除 basic_string& erase( size_type index = 0, size_type count = npos );
.
由于您在擦除调用中使用了 + 1
,因此您正在擦除从 /
到字符串结尾之前的字符,擦除以下字符:
/home/user/test/linktest/out/mDirs/testDir1/test[=10=]
^^^^
循环的第一次迭代将删除 test
,留下 /home/user/test/linktest/out/mDirs/testDir1/
。所有对 erase
的后续调用都不会执行任何操作,因为 /
和 [=17=]
.
之间有零个字符
您应该在擦除调用中从 linkPath.find_last_of("/") + 1
中删除 + 1
,这样结尾的斜线也会被删除。
此外,erase(size_t, size_t)
重载实际上将要擦除的部分的 长度 作为第二个参数 - find_first_of
returns 索引找到的字符,而不是它的迭代器。您的代码仅在偶然情况下起作用。使用 std::string::npos
,这将清除所有内容直到结束,而不是 [=17=]
字符的位置(如果您尚未调用 c_str()
,则该字符可能不存在于字符串中)。
我猜你在查看调试器时漏掉了结尾的斜杠。这可能会更好:
linkPath.erase (linkPath.begin()+linkPath.find_last_of("/"), linkPath.end());
另一个问题是 std::string::erase
的错误重载被调用:#1 in this list ("pos+len"), while you likely intended #3 ("range"). That happens because std::string::find_last_of returns size_t
,不是迭代器。或者,为了节省打字时间,您可以使用:
linkPath.resize(linkPath.find_last_of("/"));
我认为你的意思如下
#include <iostream>
#include <string>
int main()
{
std::string linkPath( ""
"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() );
}
程序输出为
continually-erasing-string-leads-to-infinite-loop
http://whosebug.com/questions
http://whosebug.com
http:/
http:
当然你可以随意修改代码。它演示了完成任务的方法。
至于你的代码那么这个调用
linkPath.find_first_of("[=12=]")
将永远 return 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;
}
我想做的是进入一条路径,然后逐个目录不断地擦除路径目录,随时检查它是否是符号 link。这是我拥有的:
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("[=10=]"));
} 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
,然而这是无限循环开始的地方。即使这与进入 erase
时的第一条路径格式相同,也没有任何反应。我尝试了 erase
从 here 的许多不同变体,但 none 似乎有效。我也试过 linkPath.append('[=18=]')
因为我认为最后可能是空字符的问题。
谢谢大家,这就是我最后的结果:
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("/") + 1
应该就是;
linkPath.find_last_of("/")
第一次擦除会留下尾随 /
,因此下一次擦除会尝试从字符串的末尾擦除到末尾,因此循环。擦除应包括目录分隔符 /
.
不需要linkPath.find_first_of("[=14=]")
,直接用npos
删除到字符串末尾即可。 find_first_of
的使用给出了大小类型的结果,因此使用了以下形式的擦除 basic_string& erase( size_type index = 0, size_type count = npos );
.
由于您在擦除调用中使用了 + 1
,因此您正在擦除从 /
到字符串结尾之前的字符,擦除以下字符:
/home/user/test/linktest/out/mDirs/testDir1/test[=10=]
^^^^
循环的第一次迭代将删除 test
,留下 /home/user/test/linktest/out/mDirs/testDir1/
。所有对 erase
的后续调用都不会执行任何操作,因为 /
和 [=17=]
.
您应该在擦除调用中从 linkPath.find_last_of("/") + 1
中删除 + 1
,这样结尾的斜线也会被删除。
此外,erase(size_t, size_t)
重载实际上将要擦除的部分的 长度 作为第二个参数 - find_first_of
returns 索引找到的字符,而不是它的迭代器。您的代码仅在偶然情况下起作用。使用 std::string::npos
,这将清除所有内容直到结束,而不是 [=17=]
字符的位置(如果您尚未调用 c_str()
,则该字符可能不存在于字符串中)。
我猜你在查看调试器时漏掉了结尾的斜杠。这可能会更好:
linkPath.erase (linkPath.begin()+linkPath.find_last_of("/"), linkPath.end());
另一个问题是 std::string::erase
的错误重载被调用:#1 in this list ("pos+len"), while you likely intended #3 ("range"). That happens because std::string::find_last_of returns size_t
,不是迭代器。或者,为了节省打字时间,您可以使用:
linkPath.resize(linkPath.find_last_of("/"));
我认为你的意思如下
#include <iostream>
#include <string>
int main()
{
std::string linkPath( ""
"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() );
}
程序输出为
continually-erasing-string-leads-to-infinite-loop
http://whosebug.com/questions
http://whosebug.com
http:/
http:
当然你可以随意修改代码。它演示了完成任务的方法。
至于你的代码那么这个调用
linkPath.find_first_of("[=12=]")
将永远 return 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;
}