Passing an istream to a function

I am making a game type program similar to the Pokemon idea. We have a tournament class that keeps track of multiple teams (own class) consisting of pets (own class) with different types of pets that are subclasses of CPet.

We are trying to pass the filename to the main, from the main pass, the filename to the tournament class. In the Tournament class, we open the file with:

 14 //Construct a tournament
 15 CTournament::CTournament(const char *Filename){
 16         //opening file
 17         ifstream inFile(Filename, ios::in);
 18         if(inFile.bad()){
 19                 cout << "File error" << endl;
 20                 return ;
 21         }
 22          //get Teamlist for tournament
 23          while(!(inFile.eof())){
 24                  CTeam* temp = new CTeam;
 25                  temp->ParseTeam(inFile);
 26 
 27                  TeamList.push_back(temp);
 28          }
 29 }

      

Here we are passing inFile to CTeam.ParseTeam, which looks like this:

     30 void CTeam::ParseTeam(std::istream in){
     31   string readline;
     32   getline(in, readline);
     33   this->TeamName = readline;
     34   while(!(in.eof())&&(readline != " " || readline != "/n"))
     35   {
     36           getline(in, readline);
     37           this->Parse(readline);
     38   }
     39 }

      

and we get the error:

In file included from /usr/include/c++/4.4/ios:39,
                 from /usr/include/c++/4.4/ostream:40,
                 from /usr/include/c++/4.4/iostream:40,
                 from CTournament.h:11,
                 from CTournament.cpp:8:
/usr/include/c++/4.4/bits/ios_base.h: In copy constructor 'std::basic_ios<char, std::char_traits<char> >::basic_ios(const std::basic_ios<char, std::char_traits<char> >&)':
/usr/include/c++/4.4/bits/ios_base.h:790: error: 'std::ios_base::ios_base(const std::ios_base&)' is private
/usr/include/c++/4.4/iosfwd:47: error: within this context
/usr/include/c++/4.4/iosfwd: In copy constructor 'std::basic_istream<char, std::char_traits<char> >::basic_istream(const std::basic_istream<char, std::char_traits<char> >&)':
/usr/include/c++/4.4/iosfwd:53: note: synthesized method 'std::basic_ios<char, std::char_traits<char> >::basic_ios(const std::basic_ios<char, std::char_traits<char> >&)' first required here 
CTournament.cpp: In constructor 'CTournament::CTournament(const char*)':
CTournament.cpp:25: note: synthesized method 'std::basic_istream<char, std::char_traits<char> >::basic_istream(const std::basic_istream<char, std::char_traits<char> >&)' first required here 
CTournament.cpp:25: error:   initializing argument 1 of 'void CTeam::ParseTeam(std::istream)'

      

I know there is a similar question about this where it didn't include fstream. We have included it in both header files.

I thought that maybe it was a problem of not passing the correct type to the PraseTeam, but I couldn't find anything specific on how to pass the file to the ParseTeam to check if I was doing it correctly.

Thanks in advance.

+3


source to share


2 answers


You need to pass the stream by reference, because streams usually cannot be copied:



void CTeam::ParseTeam(std::istream &in)

      

+10


source


As @dasblinkenlight already pointed out, you need / want to stream by link.

This is just the tip of the iceberg. Your code has a number of more pernicious problems. Among them is the main code:

while(!(inFile.eof()))

      

Code like this is broken. It won't work. It never happened and never will (except for some major miracle). It is hardly possible to put a condition inside the loop (with a break statement) to exit the loop at the right time, but you didn't, and almost nobody does, and when you do, you can also turn the loop itself into while (true)

, because that there will always be other logic that exits the loop at the right time - because this loop condition cannot and will not. [I don't mean to sound harsh or disgusting, just trying to fully understand that this code is absolutely not working.]

You have the same main problem again:

 while(!(in.eof())&&(readline != " " || readline != "/n"))

      

This adds up to what I believe is another (albeit less common and much easier to fix) problem - yours "/n"

was almost certainly intended for "\n"

.

Most of the time, what you really need / need to do is read something from the stream and have a function that does the reading, return a reference to the stream. This will allow you to read the elements until the read fails (at which point the stream bitcation must be set). Once you've done that, you can condition the loop while reading. In most cases it is convenient to call this function operator>>

, so reading an object of your class uses the same syntax as reading things like ints.



For example, consider your parseTeam

:

 void CTeam::ParseTeam(std::istream in){
   string readline;
   getline(in, readline);
   this->TeamName = readline;
   while(!(in.eof())&&(readline != " " || readline != "/n"))
   {
           getline(in, readline);
           this->Parse(readline);
   }
 }

      

If it was up to me, I would write something like this:

std::istream &operator>>(std::istream &is, CTeam &t) { 
     std::getline(is, t.Teamname);
     CTeam::member member;
     while (is >> member)
         t.members.push_back(member);
     return is;
}

      

Then CTeam

will have something along this common line:

class CTeam {
    // ...
public:
    class member { 
        // ...     
        friend std::istream &operator>>(std::istream &is, member &m) { 
            // code to read one team member from is
        }
    };
};

      

I should also add that, without knowing more about the program, this organization is definitely not displayed in a specific form - for example, it is not clear if the entity that I showed as can CTeam::member

actually exist outside the command context. If possible, then you (almost certainly) want to make it an independent class outside of CTeam. For now, I'm just guessing how to organize the code based on what I can glean from the code you've posted.

Summary: Everything that is in the form while (!whatever.eof())

is irretrievably broken. You almost always want to while (read_something())

. The C ++ convention is to use >>

to read an element from a stream. Follow this convention whenever possible. Oh, yes, you almost always want to stream by reference (the exception is the odd amount of time you need to work with a pointer to a stream - unusual, but it happens over and over).

+1


source







All Articles