Читать файл в istream, заменяя переменные класса - PullRequest
0 голосов
/ 22 ноября 2018

Я понимаю, как реализовать перегруженный оператор ostream, но я немного запутался в перегруженном операторе istream.Все примеры в Интернете показывают только краткую демонстрацию (то есть is >> val;), которая не помогает мне в контексте с моими переменными класса и методами.В основном я пытаюсь прочитать файл и заменить содержимое указателей содержимым файла.У меня есть метод фабрики и метод чтения, который уже делает это, но я пытаюсь перегрузить свой оператор istream, чтобы сделать то же самое. Однако, хотя содержимое указателей заменено, я все равно получаю сообщение cerr ниже.Должен ли я передавать что-то в ifs в моей функции >>до сих пор (.cpp)

istream &operator>>(istream &ifs, Base &val) {

  string line;
  getline(ifs, line); // type of file

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

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

  // read remaining contents
  while(getline(ifs, line)) {

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

Моя перегруженная функция ostream выглядит совсем не так, как показано выше (т.е. много значений os << value).Но всякий раз, когда я делаю ifs >> value, я получаю всевозможные ошибки компилятора (то есть я пытался просто делать ifs >> val.image; ifs >> val.height; и т. Д., Но все, что я получал, было ошибками компилятора).Что я должен передать istream (в функции выше), чтобы ошибка выше (ниже основной) не отображалась.

.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 &);
};

1 Ответ

0 голосов
/ 22 ноября 2018

Использование

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

является проблемой.В способе, которым вы реализовали operator>>(std::istream &, Base &), эта логика всегда будет терпеть неудачу.

У вас есть цикл в функции

while(getline(ifs, line)) {
   ...
}

Этот цикл будет прерываться только тогда, когда нет ничего длячтение из файла или произошла ошибка при чтении содержимого файла.Когда этот цикл завершается, ifs.fail() всегда будет истинным.

Вы должны заменить оператор if на просто:

in >> *aa;

Если вам нужно выполнить какую-либо проверку ошибок и напечатать соответствующуюсообщения об ошибках, которые нужно сделать внутри operator>>(std::istream &, Base &).

Обновление в ответ на комментарий ОП

Один из способов убедиться, что 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;
}
...