Как Вы выполняете итерации через каждый файл/каталог рекурсивно в стандартном C++?

Исключение нулевого указателя - это индикатор того, что вы используете объект, не инициализируя его.

Например, ниже - класс ученика, который будет использовать его в нашем коде.

public class Student {

    private int id;

    public int getId() {
        return this.id;
    }

    public setId(int newId) {
        this.id = newId;
    }
}

Приведенный ниже код дает вам исключение с нулевым указателем.

public class School {

    Student obj_Student;

    public School() {
        try {
            obj_Student.getId();
        }
        catch(Exception e) {
            System.out.println("Null Pointer ");
        }
    }
}

Поскольку вы используете Obj_Student, но вы забыли инициализировать его, как в правильном коде, показанном ниже:

public class School {

    Student obj_Student;

    public School() {
        try {
            obj_Student = new Student();
            obj_Student.setId(12);
            obj_Student.getId();
        }
        catch(Exception e) {
            System.out.println("Null Pointer ");
        }
    }
}
106
задан Peter Mortensen 9 March 2014 в 13:46
поделиться

6 ответов

В стандартном C++ технически нет никакого способа сделать это, так как стандартный C++ не имеет никакой концепции каталогов. Если Вы хотите развернуть свою сеть немного, Вы хотели бы смотреть на использование Повышение. FileSystem. Это было принято для включения в TR2, таким образом, это дает Вам лучшую возможность хранения Вашей реализации максимально близко к стандарту.

пример, взятый прямо от веб-сайта:

bool find_file( const path & dir_path,         // in this directory,
                const std::string & file_name, // search for this name,
                path & path_found )            // placing path here if found
{
  if ( !exists( dir_path ) ) return false;
  directory_iterator end_itr; // default construction yields past-the-end
  for ( directory_iterator itr( dir_path );
        itr != end_itr;
        ++itr )
  {
    if ( is_directory(itr->status()) )
    {
      if ( find_file( itr->path(), file_name, path_found ) ) return true;
    }
    else if ( itr->leaf() == file_name ) // see below
    {
      path_found = itr->path();
      return true;
    }
  }
  return false;
}
96
ответ дан 1800 INFORMATION 24 November 2019 в 03:47
поделиться

При использовании API Win32 можно использовать FindFirstFile и функции FindNextFile.

http://msdn.microsoft.com/en-us/library/aa365200 (По сравнению с 85) .aspx

Для рекурсивного обхода каталогов необходимо осмотреть каждый WIN32_FIND_DATA.dwFileAttributes, чтобы проверить, укусил ли FILE_ATTRIBUTE_DIRECTORY, установлен. Если бит установлен тогда, можно рекурсивно вызвать функцию с тем каталогом. Кроме того, можно использовать стек для обеспечения того же эффекта рекурсивного вызова, но предотвращения переполнения стека для деревьев очень длинного тракта.

#include <windows.h>
#include <string>
#include <vector>
#include <stack>
#include <iostream>

using namespace std;

bool ListFiles(wstring path, wstring mask, vector<wstring>& files) {
    HANDLE hFind = INVALID_HANDLE_VALUE;
    WIN32_FIND_DATA ffd;
    wstring spec;
    stack<wstring> directories;

    directories.push(path);
    files.clear();

    while (!directories.empty()) {
        path = directories.top();
        spec = path + L"\\" + mask;
        directories.pop();

        hFind = FindFirstFile(spec.c_str(), &ffd);
        if (hFind == INVALID_HANDLE_VALUE)  {
            return false;
        } 

        do {
            if (wcscmp(ffd.cFileName, L".") != 0 && 
                wcscmp(ffd.cFileName, L"..") != 0) {
                if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
                    directories.push(path + L"\\" + ffd.cFileName);
                }
                else {
                    files.push_back(path + L"\\" + ffd.cFileName);
                }
            }
        } while (FindNextFile(hFind, &ffd) != 0);

        if (GetLastError() != ERROR_NO_MORE_FILES) {
            FindClose(hFind);
            return false;
        }

        FindClose(hFind);
        hFind = INVALID_HANDLE_VALUE;
    }

    return true;
}

int main(int argc, char* argv[])
{
    vector<wstring> files;

    if (ListFiles(L"F:\\cvsrepos", L"*", files)) {
        for (vector<wstring>::iterator it = files.begin(); 
             it != files.end(); 
             ++it) {
            wcout << it->c_str() << endl;
        }
    }
    return 0;
}
42
ответ дан ChrisN 24 November 2019 в 03:47
поделиться

Вы не делаете. Стандарт C++ не имеет никакого понятия каталогов. Это до реализации для превращения строки в дескриптор файла. Содержание той строки и на что это отображается, зависимо от операционной системы. Следует иметь в виду, что C++ может использоваться, чтобы записать, что ОС, таким образом, это привыкает на уровне, где выяснение, как выполнить итерации через каталог, еще не определяется (потому что Вы пишете код управления каталогом).

Взгляд на Вашу документацию API ОС для того, как сделать это. Если необходимо быть портативными, у Вас должен будет быть набор #ifdef с для различных Ose.

3
ответ дан Peter Mortensen 24 November 2019 в 03:47
поделиться

Необходимо вызвать определенные для ОС функции для обхода файловой системы, как open() и readdir(). Стандарт C не определяет связанных с файловой системой функций.

2
ответ дан John Millikin 24 November 2019 в 03:47
поделиться

Вы не делаете. Стандартный C++ не подвергает понятию каталога. Конкретно это не уступает никому дорогу для списка всех файлов в каталоге.

А ужасный взлом должен был бы использовать систему () вызовы и проанализировать результаты. Самое разумное решение состояло бы в том, чтобы пользоваться некоторой межплатформенной библиотекой такой как Qt или даже POSIX.

1
ответ дан Peter Mortensen 24 November 2019 в 03:47
поделиться

В дополнение к вышеупомянутой файловой системе boost ::, вы можете изучить wxWidgets: : wxDir и Qt :: QDir .

Как wxWidgets, так и Qt являются кроссплатформенными фреймворками C ++ с открытым исходным кодом.

wxDir обеспечивает гибкий способ рекурсивного обхода файлов с использованием Traverse () или более простая функция GetAllFiles () . Также вы можете реализовать обход с помощью функций GetFirst () и GetNext () (я предполагаю, что Traverse () и GetAllFiles () являются оболочками, которые в конечном итоге используют GetFirst () и GetNext ( ) функции).

QDir обеспечивает доступ к структурам каталогов и их содержимому. Есть несколько способов перемещаться по каталогам с помощью QDir. Вы можете перебирать содержимое каталога (включая подкаталоги) с помощью QDirIterator, экземпляр которого был создан с помощью флага QDirIterator :: Subdirectories. Другой способ - использовать функцию QDir GetEntryList () и реализовать рекурсивный обход.

Вот пример кода (взятый из здесь # Пример 8-5), который показывает, как перебирать все подкаталоги.

1254]

10
ответ дан 24 November 2019 в 03:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: