Возврат ifstream в функции

Вот, вероятно, очень noobish вопрос для Вас: Как (если вообще возможный) я могу возвратить ifstream из функции?

В основном я должен получить имя файла базы данных от пользователя, и если база данных с тем именем файла не существует, то я должен создать тот файл для пользователя. Я знаю, как сделать это, но только путем просьбы, чтобы пользователь перезапустил программу после создания файла. Я хотел избежать, что неудобство для пользователя, если это возможно, но функция ниже не компилирует в gcc:

ifstream getFile() {
    string fileName;
    cout << "Please enter in the name of the file you'd like to open: ";
    cin >> fileName;
    ifstream first(fileName.c_str());
    if(first.fail()) {
        cout << "File " << fileName << " not found.\n";
        first.close();
        ofstream second(fileName.c_str());
        cout << "File created.\n";
        second.close();
        ifstream third(fileName.c_str());
        return third; //compiler error here
    }
    else
        return first;
}

Править: извините, забыл говорить Вам, где и какова ошибка компилятора была:

main.cpp:45: note: synthesized method ‘std::basic_ifstream<char, std::char_traits<char> >::basic_ifstream(const std::basic_ifstream<char, std::char_traits<char> >&)’ first required here 

Править: Я изменил функцию для возврата указателя вместо этого как Remus, предложенный, и изменил строку в основном () к "ifstream база данных = *getFile ()"; теперь я получаю эту ошибку снова, но на этот раз в строке в основном ():

main.cpp:27: note: synthesized method ‘std::basic_ifstream<char, std::char_traits<char> >::basic_ifstream(const std::basic_ifstream<char, std::char_traits<char> >&)’ first required here
9
задан wrongusername 8 March 2010 в 05:16
поделиться

3 ответа

bool checkFileExistence(const string& filename)
{
    ifstream f(filename.c_str());
    return f.is_open();
}

string getFileName()
{
    string filename;
    cout << "Please enter in the name of the file you'd like to open: ";
    cin >> filename;
    return filename;
}

void getFile(string filename, /*out*/ ifstream& file)
{
    const bool file_exists = checkFileExistence(filename);
    if (!file_exists) {
        cout << "File " << filename << " not found." << endl;
        filename = getFileName();  // poor style to reset input parameter though
        ofstream dummy(filename.c_str();
        if (!dummy.is_open()) {
            cerr << "Could not create file." << endl;
            return;
        }
        cout << "File created." << endl;
    }
    file.open(filename.c_str());
}

int main()
{
    // ...
    ifstream file;
    getFile("filename.ext", file);
    if (file.is_open()) {
        // do any stuff with file
    }
    // ...
}
6
ответ дан 4 December 2019 в 09:12
поделиться

Нет, не совсем. ifstream не имеет конструктора копирования, и если вы попытаетесь его вернуть, это означает копирование экземпляра в вашей функции туда, куда нужно возвращать.

Обычный обходной путь - передать ссылку на один и изменить эту ссылку в вашей функции.

Изменить: хотя это позволит вашему коду работать, это не решит основную проблему. Прямо сейчас вы смешиваете две довольно разные обязанности в одной функции: 1) получение имени файла, 2) открытие или создание этого файла.Я думаю, если вы разделите их, код будет проще и значительно упростит устранение источника проблемы, которую вы видите.

Редактировать 2: Использование такой ссылки отлично работает без оператора = . Общая идея примерно такая:

int open_file(char const *name, fstream &stream) { 
    stream.open(name);
}

Оператор присваивания в этом случае не нужен и не полезен - мы просто используем существующий fstream через ссылку. operator = был бы необходим тогда и только тогда, когда нам нужно было передать аргумент ctor. С помощью потока мы можем по умолчанию создать поток, который не подключается к файлу, а затем использовать open для подключения к файлу после этого.

14
ответ дан 4 December 2019 в 09:12
поделиться

ifstream не поддерживает семантику конструкции копирования (то, что в основном говорится в сообщении об ошибке), поэтому вы не можете вернуть ifstream. Вместо этого верните ifstream * и передайте вызывающей стороне ответственность за удаление указателя выделения.

3
ответ дан 4 December 2019 в 09:12
поделиться
Другие вопросы по тегам:

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