Вот, вероятно, очень 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
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
}
// ...
}
Нет, не совсем. ifstream
не имеет конструктора копирования, и если вы попытаетесь его вернуть, это означает копирование экземпляра в вашей функции туда, куда нужно возвращать.
Обычный обходной путь - передать ссылку на один и изменить эту ссылку в вашей функции.
Изменить: хотя это позволит вашему коду работать, это не решит основную проблему. Прямо сейчас вы смешиваете две довольно разные обязанности в одной функции: 1) получение имени файла, 2) открытие или создание этого файла.Я думаю, если вы разделите их, код будет проще и значительно упростит устранение источника проблемы, которую вы видите.
Редактировать 2: Использование такой ссылки отлично работает без оператора =
. Общая идея примерно такая:
int open_file(char const *name, fstream &stream) {
stream.open(name);
}
Оператор присваивания в этом случае не нужен и не полезен - мы просто используем существующий fstream через ссылку. operator =
был бы необходим тогда и только тогда, когда нам нужно было передать аргумент ctor. С помощью потока мы можем по умолчанию создать поток, который не подключается к файлу, а затем использовать open для подключения к файлу после этого.
ifstream не поддерживает семантику конструкции копирования (то, что в основном говорится в сообщении об ошибке), поэтому вы не можете вернуть ifstream. Вместо этого верните ifstream * и передайте вызывающей стороне ответственность за удаление указателя выделения.