4

我正在制作一个类似于口袋妖怪想法的游戏类型程序。我们有一个锦标赛类,它跟踪几个团队(它自己的类),它由宠物(它自己的类)组成,不同种类的宠物是 CPet 的子类。

我们正在尝试将文件名传递给 main,从 main 将该文件名传递给 Tournament 类。在 Tournament 类中,我们使用以下命令打开文件:

 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 }

在这里,我们将 inFile 传递给 CTeam.ParseTeam,如下所示:

     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 }

我们得到了错误:

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)'

我知道有一个类似的问题,他没有包括 fstream。我们已经将它包含在两个头文件中。

我认为这可能是没有将正确的类型传递给 PraseTeam 的问题,但是我找不到任何关于如何将文件传递给 ParseTeam 以验证我是否正确执行的非常具体的内容。

提前致谢。

4

2 回答 2

14

您需要通过引用传递流,因为流通常不可复制:

void CTeam::ParseTeam(std::istream &in)
于 2013-01-27T15:41:21.973 回答
1

正如@dasblinkenlight 已经指出的那样,您需要/想要通过引用传递流。

但这只是冰山一角。您的代码有许多更有害的问题。其中最主要的是如下代码:

while(!(inFile.eof()))

像这样的代码被破坏了。它行不通。它从来没有,也永远不会(除非发生一些重大奇迹)。几乎不可能在循环中放置一个条件(使用 break 语句)以在正确的时间退出循环——但你还没有这样做,几乎没有其他人这样做,当你这样做时,你可能以及将循环本身变成while (true),因为它总是会在正确的时间退出循环的其他逻辑 - 因为这个循环条件不能也不会。[我的意思不是在那里听起来刺耳或讨厌,只是想完全清楚这段代码绝对不起作用 ]

您在这里再次遇到相同的基本问题:

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

这增加了我猜是另一个(虽然不太常见且更容易修复)的问题 - 你"/n"几乎肯定是打算成为"\n".

在大多数情况下,您真正​​想要/需要做的是从流中读取某些内容,并让执行读取的函数返回对流的引用。这将让您读取项目,直到读取失败(此时应设置流的故障位)。完成此操作后,您可以使循环以读取成功为条件。在大多数情况下,命名该函数很方便operator>>,因此读取类的对象使用与读取 int 之类的东西相同的语法。

例如,让我们看一下您的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);
   }
 }

如果由我决定,我会写一些更像这样的东西:

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;
}

然后,CTeam沿着这条一般路线会有一些东西:

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

我还应该补充一点,在不了解更多有关该程序的情况下,该组织绝对不是具体的——例如,尚不清楚我所展示的实体是否CTeam::member真的能够存在于团队环境之外。如果可以,那么您(几乎可以肯定)想让它成为 CTeam 之外的独立类。目前,我只是在猜测如何根据我从您发布的代码中收集到的内容来组织代码。

总结:任何形式的东西都while (!whatever.eof())被不可挽回地破坏了。你几乎总是想要while (read_something())。C++ 中的约定是用于>>从流中读取项目。尽可能/如果可能,请遵循该约定。哦,是的,您几乎总是希望通过引用传递流(例外是您需要使用指向流的指针来代替的奇怪时间 - 不寻常,但它确实会一次又一次地发生)。

于 2013-01-27T16:19:35.163 回答