C++ 将文件读取到istream替换类变量

C++ 将文件读取到istream替换类变量,c++,istream,C++,Istream,我知道如何实现重载的ostream操作符,但对于重载的istream操作符我有点困惑。所有联机示例只显示了一个简短的演示(即is>>val;),它对我的类变量和方法的上下文没有帮助。在我的主要工作中,我试图读入一个文件,并用文件内容替换指针内容。我已经有了一个工厂方法和读取方法,但是我正在尝试重载我的istream操作符来做同样的事情然而,尽管指针内容被替换,我仍然收到下面的cerr消息。我是否应该在我的>>函数中将某些内容传递给ifs? 这是我的主要任务 int main() { //

我知道如何实现重载的ostream操作符,但对于重载的istream操作符我有点困惑。所有联机示例只显示了一个简短的演示(即is>>val;),它对我的类变量和方法的上下文没有帮助。在我的主要工作中,我试图读入一个文件,并用文件内容替换指针内容。我已经有了一个工厂方法和读取方法,但是我正在尝试重载我的istream操作符来做同样的事情然而,尽管指针内容被替换,我仍然收到下面的cerr消息。我是否应该在我的>>函数中将某些内容传递给ifs?

这是我的主要任务

int main() {

  // factory method instantiates all class variables
  Base *aa = Base::create(file);     // it works

  ifstream in(file2);
  if((in >> *aa).fail())             // Read file contents
    cerr << "Read failed" << '\n'; 

  cout << *aa;                       // prints vector contents
}
intmain(){
//工厂方法实例化所有类变量
Base*aa=Base::create(file);//有效
ifstream-in(文件2);
if((在>>*aa.fail()中)//读取文件内容
cerr>val.image;ifs>>val.height;等等。但我得到的只是编译器错误)。我应该传递什么到istream(在上面的函数中),这样上面(main下面)的错误就不会显示

.h文件以供参考

class Base 
{
  protected:
    std::vector<std::vector<int> > vec;
    std::string filetype;
    int width, height, max;
    Base() = default;
    Base &operator=(const Base &) = default;
  public:
    static Base* create(std::string filename);
    virtual ~Base();
    // read by derived class
    virtual void read(std::string filename) = 0;
    friend std::istream &operator>>(std::istream &, Base &);
    friend std::ostream &operator<<(std::ostream &, const Image &);
};
类基
{
受保护的:
std::vec;
std::字符串文件类型;
整数宽度、高度、最大值;
Base()=默认值;
基本运算符=(常量基本运算符=)=默认值;
公众:
静态基*创建(标准::字符串文件名);
虚拟~Base();
//按派生类读取
虚拟无效读取(std::string filename)=0;
friend std::istream&operator>>(std::istream&,Base&);
friend std::ostream&operator使用

只有当文件中没有可读取的内容或读取文件内容时出错,该循环才会中断。当该循环退出时,
ifs.fail()
将始终为真

您应该将
if
语句替换为:

in >> *aa;
如果您需要执行任何错误检查并打印适当的错误消息,则必须在
operator>>(std::istream&,Base&)
内部完成

更新,回应OP的评论 确保
istream
不会到达
ifs.fail()
始终为
true
的点的一种方法是提前知道预期的内容

如果文件中预期的行数是第一个输入,则可以读取所有数据并从函数返回,从而使
ifs.fail()
false

样本输入:

type1
3.
111
222
333
然后,可以将
oprator>
功能定义为:

std::stream& operator>>(std::istream& ifs, Base& val) 
{
   std::string line;
   if ( !getline(ifs, line) ) // type of file
   {
      // Problem reading. No point trying to read more.
      return ifs;
   }

   if(line == "type1") 
      val.filetype = "type1";
   if(line == "type2")
      val.filetype = "type2";

   // read remaining contents

   int numLines = 0;
   if ( !(ifs >> numLines) )
   {
      // Problem reading. No point trying to read more.
      return ifs;
   }

   val.vec.clear();    // clear old vector
   vector<int> inner;  // inner vec to push onto main vec

   for ( int n = 0; n < numLines; ++n )
   {
      if ( !getline(ifs, line))
      {
         // Problem reading. No point trying to read more.
         return ifs;
      }

      for(size_t i = 0; i < line.length(); i++) 
      {
         inner.push_back(line[i]);
      }

      val.vec.push_back(inner);
      inner.clear();
   }

   val.height = val.vec.size();
   val.width = val.vec[0].size();
   val.max = val.vec[height-1][width-1];

   return ifs;
}
std::stream和operator>>(std::istream和ifs、Base和val)
{
std::字符串行;
if(!getline(ifs,line))//文件类型
{
//阅读有问题。尝试阅读更多没有意义。
返回ifs;
}
如果(行==“类型1”)
val.filetype=“type1”;
如果(行==“类型2”)
val.filetype=“type2”;
//阅读剩余内容
int numLines=0;
如果(!(ifs>>numLines))
{
//阅读有问题。尝试阅读更多没有意义。
返回ifs;
}
val.vec.clear();//清除旧向量
向量内部;//要推到主向量上的内部向量
对于(int n=0;n
Base*aa=Base::create(文件)
-不要这样做-不需要使用指针。作为一个真正完整的示例,我们还需要您的输入文件。我添加了它。它位于main下面。是否有方法修复我的运算符>>函数中的逻辑,使其不会失败?in>*aa;可以正常工作,但我需要使用您在响应中突出显示的if语句。是的。完整的我脑子里的海绵太长了,几个小时内我都做不到。
if((in >> *aa).fail())             // Read file contents
   cerr << "Read failed" << '\n';
while(getline(ifs, line)) {
   ...
}
in >> *aa;
std::stream& operator>>(std::istream& ifs, Base& val) 
{
   std::string line;
   if ( !getline(ifs, line) ) // type of file
   {
      // Problem reading. No point trying to read more.
      return ifs;
   }

   if(line == "type1") 
      val.filetype = "type1";
   if(line == "type2")
      val.filetype = "type2";

   // read remaining contents

   int numLines = 0;
   if ( !(ifs >> numLines) )
   {
      // Problem reading. No point trying to read more.
      return ifs;
   }

   val.vec.clear();    // clear old vector
   vector<int> inner;  // inner vec to push onto main vec

   for ( int n = 0; n < numLines; ++n )
   {
      if ( !getline(ifs, line))
      {
         // Problem reading. No point trying to read more.
         return ifs;
      }

      for(size_t i = 0; i < line.length(); i++) 
      {
         inner.push_back(line[i]);
      }

      val.vec.push_back(inner);
      inner.clear();
   }

   val.height = val.vec.size();
   val.width = val.vec[0].size();
   val.max = val.vec[height-1][width-1];

   return ifs;
}