оператор вставки перегруженного потока с вектором - PullRequest
0 голосов
/ 02 апреля 2010

Я пытаюсь написать перегруженный оператор вставки потока для класса, единственным членом которого является вектор. Это вектор Point с, то есть struct, содержащий два double с. Я полагаю, что я хочу вставить пользовательский ввод (набор double s) в поток, который я затем отправляю методу-модификатору. Я работаю над другими примерами вставки потока, такими как:

std::ostream& operator<< (std::ostream& o, Fred const& fred)
 {
   return o << fred.i_;
 }

но когда я пытаюсь что-то подобное:

 istream & operator >> (istream &inStream, Polygon &vertStr)
     {
        inStream >> ws;
        inStream >> vertStr.vertices;
        return inStream;
     }

Я получаю сообщение об ошибке "нет совпадения для operator >> и т. Д. И т. Д." Если я опускаю .vertices, он компилируется, но я думаю, что это неправильно. (Кстати, vertices - это имя моего vector <Point>.) И даже если это правильно, я на самом деле не знаю, какой синтаксис использовать в моей программе, чтобы использовать его, и я также не на 100% уверен в том, как должен выглядеть мой метод-модификатор.

Вот мой Polygon класс:

//header

#ifndef POLYGON_H
#define POLYGON_H
#include "Segment.h"
#include <vector>
class Polygon
{
 friend std::istream & operator >> (std::istream &inStream, Polygon &vertStr);
 public:
   //Constructor
    Polygon(const Point &theVerts);
    //Default Constructor
    Polygon();
    //Copy Constructor
    Polygon(const Polygon &polyCopy);
    //Accessor/Modifier methods
    inline std::vector<Point> getVector() const {return vertices;}
    //Return number of Vector elements
    inline int sizeOfVect() const {return (int) vertices.capacity();}
    //add Point elements to vector
    inline void setVertices(const Point &theVerts){vertices.push_back (theVerts);}

 private:
   std::vector<Point> vertices;
};
#endif

//Body

using namespace std;
 #include "Polygon.h"
// Constructor
Polygon::Polygon(const Point &theVerts)
    {
        vertices.push_back (theVerts);
        }
//Copy Constructor
Polygon::Polygon(const Polygon &polyCopy)
{
    vertices = polyCopy.vertices;
}
//Default Constructor
Polygon::Polygon(){}

istream & operator >> (istream &inStream, Polygon &vertStr)
 {
    inStream >> ws;
    inStream >> vertStr;
    return inStream;
 }

Извините, что так расплывчато; лектор только что дал нам краткий пример вставки потока, а затем оставил нас в покое.

1 Ответ

1 голос
/ 03 апреля 2010

Проблема в том, что нет стандартного извлечения оператора для векторов (вставка в поток, извлечение из потока), поэтому вам нужно определить свой собственный. Кроме того, потоки пропускают пробелы по умолчанию, поэтому вам обычно не нужно использовать std::ws. Вы не определили, как завершается ввод вектора, поэтому я предполагаю, что новая строка указывает конец вектора.

Так как это школьная проблема, я не могу дать вам слишком много. Для начала приведем несколько объявлений, которые вы можете заполнить, а некоторые могут оказаться полезными. Неправильно импортировать пространство имен std, поэтому следующее не делает.

#include <list>

// returns true if ch is a horizontal space. Locales are a little tricky,
// so you could skip them for now and instead start with the functions defined 
// in header <ctype>
bool ishs(char ch, std::locale loc=std::locale::global());
// return true if ch is a vertical space
bool isvs(char ch);
// return true if the next character in stream 'in' is a vertical space.
bool eol(std::istream& in);

// reads & discards horizontal spaces
std::istream& hs(std::istream& in);

class Point {
public:
  // Scalar is so you can use 'Point::Scalar' rather than 'double', 
  // making it easy should you which to change the type that a Point holds.
  // When you've covered templates, this will make it trivial to templatize Point.
  typedef double Scalar;
  ...
};

class Polygon {
public:
     // adds pt as the last of this polygon's vertices
     // Note: this is basically your "setVertices" with a different name
   Polygon& append(const Point& pt);
     // adds the points from 'start' to 'end' to this polygon
   template <typename _Iter>
   Polygon& append(_Iter start, _Iter end);
     // remove all points in this polygon
   void erase();
     // returns the number of sides on this polygon, 
     // which is also the number of vertices
     // Note: this is different from your "sizeOfVect"; see below for more
   int sides() const { return vertices.size(); }
     // set aside space for polygon to have 's' sides.
   voids sides(int s) { vertices.resize(s); }
}

/* reads the next two numbers on the current line into pt.
   Throws an exception if there is only one number.
 */
std::istream& operator>>(std::istream& in, Point& pt);
/* reads numbers on the current line into points on 'poly'.
   Throws an exception if there is only one number. Preferably,
   won't alter 'poly' if there are an odd amount of numbers.

   you could also put the contents of this operator into >>(istream&, Polygon&)
 */
std::istream& operator>>(std::istream& in, std::vector<Point>& vertices) {
    std::list<Point::Scalar> points;
    Point pt;
    // while not at eol(in), read into pt and add it to points
    // After that, empty vertices, then add the Points in points to vertices
    ...
}

В качестве альтернативы функциям, связанным с символами (ishs, isvs, hs, eol), вы можете прочитать следующую строку в строку с getline, отсюда в istringstream и прочитайте пункты из этого. Вектор заканчивается, когда istringstream достигает eof (или strin >> pt ложно ).

Что вам нужно сделать, это превратить задачи в operator>>(istream&, vector<Point>&) в вызовы методов и функций, затем:

  1. Объявите новые методы и функции.
  2. Напишите описание задач (как это сделано в комментарии >>).
  3. Превратить описание в вызовы методов и функций.
  4. Повторяйте, пока не останется больше новых методов или функций для записи.

Почему мой Polygon::sides() отличается от вашего Polygon::sizeOfVect(): обратите внимание, что vector::capacity возвращает количество элементов, которое вектор может содержать без изменения размера; то есть это в основном sizeof (vect) / typeof (element). vector::size - количество элементов, хранящихся в данный момент в векторе. Они могут отличаться, если вы предварительно выделите место для элементов, например, Polygon::sides(int), или если вы вставите элементы сзади. Независимо от того, что, однако, vector::capacityvector::size.

...