指针混淆 - c++

3

我被分配任务对C++应用程序进行简单更改。不幸的是,我来自Java背景,我在一些指针问题上遇到了困难。

有关的代码从给定目录(使用环境变量设置)读取文件列表,并对每个文件执行某些操作。

char * rebuildDir = getenv("REBUILD_DIR");
char * currentFile;
DIR *asciiDir;
struct dirent *ent;

asciiDir = opendir(rebuildDir);
if (asciiDir != NULL)
{
    while ((ent = readdir(asciiDir)) != NULL)
    {
        std::cout << "rebuild sensor, rebuild dir is " << getenv("REBUILD_DIR") << std::endl;
        currentFile = rebuildDir;
        strcat(currentFile, ent->d_name);
        ifstream raw(currentFile);
        while(raw)
        {
            ...snip...
        }
        raw.close();
    }

    closedir(asciiDir);
}

正如您所看到的,意图是将环境变量存储一次,然后将其复制到currentFile,然后将当前文件名连接到currentFile中,以便传递给ifstream。

问题在于

currentFile = rebuildDir;

该变量未重置为环境变量,因此strcat一直使用旧的文件名并继续追加,所以:

/home/file1
/home/file2
/home/file3

将执行为

/home/file1
/home/file1/home/file2
/home/file1/home/file2/home/file3

在循环中出现了问题。我猜测我的指针有一个初学者的错误,但我一直没有找到它。

感谢任何帮助,并对这个琐碎的问题表示歉意。

PS - 如果有更好的方法来完成我的任务,请随时指出 :)

3个回答

5

当前文件指向与rebuilddir相同的内存,因此您需要在原地修改字符串。您需要复制该字符串。您可以执行以下操作:

char currentFile[MAX_PATH];
snprintf(currentFile, MAX_PATH, "%s%s", rebuildDir, ent->d.name);

1
如果可能的话,请使用snprintf(即使MAX_PATH“相当大”)。 - aschepler
好的观点。我必须更努力地打破 sprintf 的习惯。 - Laurion Burchall
我必须更加努力地打破使用 sprintf 的习惯。实际上,你最好努力打破使用 [v][sf][n]printf 的习惯,而是使用 std::stringstd::string currentFile(rebuildDir); currentFile += ent->d.name; - Serge Dundich

3
"...不会重置到环境变量"。为什么要“重置”到任何东西?你的指针currentFile指向由rebuildDir指向的实际环境变量值。然后,你通过strcat修改了指针所指向的内容,也就是说,你实际上修改了(即破坏了)原始环境变量的值。
你不应该这样做。如果你想从环境变量的值中构建新名称,你必须将该值复制到一边,然后修改副本,而不是试图破坏原始值。
例如,你可以使用std::string来创建原始值的副本。
const char *rebuildDir = getenv("REBUILD_DIR");
...
std::string currentFile = rebuildDir;
currentFile += ent->d_name;
ifstream raw(currentFile.c_str());

1
int main(int argc, char *argv[])
{
    char* pDir = getenv("REBUILD_DIR");

    if (! pDir)
    {
        cerr << "did not find ENV var\n";
        exit(1);
    }

    string rebuildDir(pDir);

    DIR* asciiDir;

    if ((asciiDir = opendir(rebuildDir.c_str())) != NULL)
    {
        std::cout << "rebuild sensor, rebuild dir is " << rebuildDir << std::endl;

        struct dirent *ent;

        while ((ent = readdir(asciiDir)) != NULL)
        {
            string currentFile(rebuildDir);

            currentFile += '/' + string(ent->d_name);

            //probably want to skip "." and ".." entries...

            /*
            ifstream raw(currentFile);

            while(raw)
            {
                ...snip...
            }

            raw.close();
            */
        }

        closedir(asciiDir);
    }
    else
    {
        cerr << "coult not open dir\n";
        exit(1);
    }

    return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接