Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 不断删除字符串会导致无限循环_C++_Linux_Stdstring - Fatal编程技术网

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;
}

你有没有试过装一个去毛刺