Путаница с указателем - c ++ - PullRequest
3 голосов
/ 25 мая 2011

Мне было поручено внести простые изменения в приложение 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 голосов
/ 25 мая 2011

Текущий файл указывает на ту же память, что и rebuilddir, поэтому вы изменяете строку на месте. Вам нужно продублировать строку. Вы можете сделать что-то вроде:

char currentFile[MAX_PATH];
snprintf(currentFile, MAX_PATH, "%s%s", rebuildDir, ent->d.name);
3 голосов
/ 25 мая 2011

"... не сбрасывается в переменную окружения". Почему бы это "сбросить" на что-нибудь? Вы нацеливаете указатель currentFile на фактическое значение переменной среды, на которое указывает rebuildDir. И затем вы модифицируете pointee с помощью strcat, то есть вы существенно модифицируете (то есть уничтожаете) исходное значение переменной среды.

Ты не должен этого делать. Если вы хотите создать новое имя из значения переменной среды, вам нужно скопировать это значение в сторону и затем изменить копию, вместо того, чтобы пытаться уничтожить оригинал.

Например, вы можете использовать std::string, чтобы создать копию с исходным значением

const char *rebuildDir = getenv("REBUILD_DIR");
...
std::string currentFile = rebuildDir;
currentFile += ent->d_name;
ifstream raw(currentFile.c_str());
1 голос
/ 25 мая 2011
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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...