This is a school assignment. I have to write a function in my program that opens a file stream and returns a heaped value to the main function. I believe the file opening function works but after it passes the ifstream pointer to the main function, I'm having trouble dereferencing it.

#include <iostream>
#include <fstream>
#include <string>
#include <vector>

using namespace std;

char getOption();
ifstream * openInputFile();

int main()
{
    char userOption;
    ifstream * currentFile;
    ifstream fileInUse;

    do //calls the getOption function until user inputs 'q' or 'Q'
    {
        userOption = getOption();

        if ((userOption == 'i') || (userOption == 'I'))
        {
            currentFile = openInputFile();

            fileInUse = * currentFile;
        }
    }
    while ((userOption != 'q') && (userOption != 'Q'));

    return 0;
}

char getOption() //prompts user for input and sends it back to main function
{
    //Edited out for simplicity
}

ifstream * openInputFile() //opens a file stream and returns it to main function as a heaped value
{
    string fileName;
    ifstream * sendFile;

    cout << "Please enter a valid file name: ";
    cin >> fileName;
    cout << "\n\n";

    ifstream newFile(fileName);

    sendFile = & newFile;

    return sendFile;
}

The function names are required to be like that. When I try to compile, I get the following error:

1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\istream(860): error C2249: 'std::basic_ios<_Elem,_Traits>::operator =' : no accessible path to private member declared in virtual base 'std::basic_ios<_Elem,_Traits>'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\ios(177) : see declaration of 'std::basic_ios<_Elem,_Traits>::operator ='
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>
1>          ]
1>          This diagnostic occurred in the compiler generated function 'std::basic_istream<_Elem,_Traits> &std::basic_istream<_Elem,_Traits>::operator =(const std::basic_istream<_Elem,_Traits> &)'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>
1>          ]

In proper socratic fashion I'll ask you this: what happens to an ifstream object when it goes out of scope?

Thanks for the reply. I've declared the ifstream on the heap so it doesn't go out of scope when the function exits. However, I'm still not quite sure how to work with the ifstream when it's returned to the main function. For example, reading the file stream.

The program compiles if I exclude the do loop in the main function.

ifstream * openInputFile()
{
    string fileName;
    ifstream * openFile = new ifstream;

    cout << "Please enter a valid file name: ";
    cin >> fileName;

    * openFile = ifstream(fileName);

    return openFile;
}

ifstream doesn't have a copy constructor. Rather, it's declared private prior to C++11 and declared deleted in C++11. Either way, you can't copy stream objects in any generally useful manner, so it's truly awkward to use them as a return value. I was pushing you toward a different solution entirely, specifically using an output parameter:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

char getOption();

bool openInputFile(ifstream& strm)
{
    string fileName;

    cout << "Please enter a valid file name: ";
    cin >> fileName;

    strm.open(fileName);

    return strm;
}

int main()
{
    char userOption;
    ifstream fileInUse;

    do
    {
        userOption = getOption();

        if ((userOption == 'i') || (userOption == 'I'))
        {
            if (!openInputFile(fileInUse))
            {
                cerr << "Error opening file\n";
            }
        }
    }
    while ((userOption != 'q') && (userOption != 'Q'));
}

Thanks a lot for the reply, deceptikon. I would have found a different way of doing it if it weren't in my professor's explicit instructions. As per his instructions:

ifstream * openInputFile() - Prompt the user for a valid input file name, and return an open file stream connected to the input file. Called as needed to open an input file, and the return value must be heaped.

So that's where I'm at right now. I've seen examples where it's possible to pass an ifstream reference from the main function to another function, but am unsure how that could apply to returning an ifstream reference back to the main function.

Thanks again for the reply. I'm gonna keep trying to work this.

@dyl_ham, your last try was really close. Just move some things around.
#include <iostream>
#include <fstream>
#include <cstdio>
#include <cerrno>
using namespace std;

ifstream * openInputFile() {
    string fileName;
    cout << "Please enter a valid file name: ";
    cin >> fileName;
    //---------------------------------------------------
    // You have the file name, just use it
    ifstream *openFile(new ifstream(fileName.c_str()));

    //---------------------------------------------------
    // Do some error checking
    if ( !openFile->is_open()){
      cerr << "Error:  " << fileName << " -> " << strerror(errno) << endl;
      delete openFile;
      //---------------------------------------------------
      // Set to null if bad file
      openFile = 0;
    }
    return openFile;
}

int main(){
 ifstream *file(openInputFile());
 if ( file ){
   // Do something
   cout << "Doing something" << endl;
   file->close();
   delete file;
 } else {
   cout << "Bad file!" << endl;
 }
 return 1;
}

histrungalot, I see what you're doing there. Thanks a lot! I'll give it a try now and see what I can come up with.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.