как вырезать вектор структур (это член класса, используя оператор извлечения) - PullRequest
2 голосов
/ 06 апреля 2010

Я пытаюсь просто расположить элементы вектора, используя перегруженный оператор извлечения. вектор contians Point, который представляет собой просто структуру, содержащую два двойных числа. вектор является закрытым членом класса с именем Polygon, так что вот мой Point.h

#ifndef POINT_H
#define POINT_H
#include <iostream>
#include <string>
#include <sstream>
struct Point
{
  double x;
  double y;
  //constructor
  Point()
  {
   x = 0.0;
   y = 0.0;
  }

friend std::istream& operator >>(std::istream& stream, Point &p)
    {
    stream >> std::ws;
    stream >> p.x;
    stream >> p.y;
    return stream;
    }
friend std::ostream& operator << (std::ostream& stream, Point &p)
{
stream << p.x <<  p.y;
return stream;
}    
};
#endif

мой полигон.ч

#ifndef POLYGON_H
#define POLYGON_H
#include "Segment.h"
#include <vector>
class Polygon
{
    //insertion operator needs work
 friend std::istream & operator >> (std::istream &inStream, Polygon &vertStr);
 // extraction operator
 friend std::ostream & operator << (std::ostream &outStream, const Polygon &vertStr);

   public:
   //Constructor
    Polygon(const std::vector<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 vertices.size();}
    //add Point elements to vector
    inline void setVertices(const Point &theVerts){vertices.push_back (theVerts);}

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

и Polygon.cc

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

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

// extraction operator
 ostream & operator << (ostream &outStream, const Polygon::Polygon &vertStr)
{
    outStream << vertStr.vertices << endl;
    return outStream;
 }

Я полагаю, что моя точка вставки / извлечения правильная, я могу вставлять и использовать ее

и я полагаю, что смогу просто ......

cout << myPoly[i] << endl;  

в моем драйвере? (в цикле) или даже ...

cout << myPoly[0] << endl; 

без петли? я пробовал все виды

myPoly.at[i];
myPoly.vertices[i];

и т. Д. И т. П.

также пробовал все варианты в моей функции извлечения

outStream << vertStr.vertices[i] << endl;

внутри петель и т. Д. И т. Д.

когда я просто создаю ...

vector<Point> myVect;

в моем драйвере я могу просто ...

cout << myVect.at(i) << endl;

без проблем.

пытался найти ответ в течение нескольких дней, действительно потерян и не из-за отсутствия попыток!

прошу прощения за отсутствие комментариев и форматирования также отсутствуют кусочки.

Ответы [ 5 ]

5 голосов
/ 06 апреля 2010

Принимая вещи в порядок. Во-первых, терминология: operator<< является оператором вставки - он вставляет элементы в поток. operator>> - оператор извлечения - он извлекает элементы из потока.

Во-вторых, у вас есть довольно серьезные проблемы в ваших операторах вставки. Давайте начнем с низу, point::operator<<. Прямо сейчас у вас есть:

friend std::ostream& operator << (std::ostream& stream, Point &p)
{
    stream << p.x <<  p.y;
    return stream;
} 

Теперь давайте рассмотрим, что произойдет, когда мы добавим к этому вещественные числа, скажем, 1,23 и 4,56. Он выпишет:

1.234.56

Это явно проблема. Из просмотра самих данных невозможно определить, где заканчивается «x» и начинается «y». Нам нужно отформатировать данные, чтобы мы могли различать их:

std::ostream &operator<<(std::ostream &stream, Point const &p) { 
    return stream << p.x << " " << p.y;
}

Также обратите внимание, что поскольку мы не собираемся изменять пройденную точку, я изменил ее на const ссылку.

Когда / если вы пытаетесь сохранить более одного многоугольника в файле, вы снова сталкиваетесь с той же проблемой - у вас есть поток вершин, но нет ничего, чтобы показать, какие вершины принадлежат каким полигонам. Например, квадрат, за которым следует треугольник, может выглядеть так:

0 0
1 0
1 1
0 1
1 1
2 2
0 2

Один из очевидных способов справиться с этим - поставить перед каждым многоугольником число вершин, которые он содержит, поэтому одни и те же данные будут выглядеть примерно так:

4
0 0
1 0
1 1 
0 1
3
1 1
2 2 
0 2

Затем мы можем заново сгенерировать исходные многоугольники, когда будем их читать. Для этого нам (очевидно) необходимо написать наши операторы соответствующим образом:

std::ostream &operator<<(std::ostream &os, Polygon const &p) {
    std::vector<Point> v = p.getVector();
    os << v.size << "\n";

    // write each point out using operator<< for Point:
    std::copy(v.begin(), v.end(), std::ostream_iterator<Point>(os, "\n"));
    return os;
}

std::istream &operator>>(std::istream &is, Polygon &p) {     
    size_t size;
    is >> size;
    Point temp;
    for (int i=0; i<size; i++) {
        is >> temp;
        p.setVertices(temp);
    }
    return is;
}

Глядя на то, как долго это длится, я думаю, что пока остановлюсь на этом.

3 голосов
/ 06 апреля 2010

Посмотрите на этот ответ на этот вопрос .

Общая идея здесь заключается в том, что вам действительно нужно перебрать свой вектор для печати всех содержащихся объектов, но вы можете std :: copy , чтобы сделать это за вас. В качестве цели для копии вы просто используете std::ostream_iterator< Point >( std::cout ) (смотрите здесь документация ). ostream_iterator затем использует вашу перегруженную operator << для Point для печати отдельных точек. Это будет выглядеть так:

std::copy( vertices.begin(), vertices.end(), std::ostream_iterator< Point >( std::cout ) );
2 голосов
/ 06 апреля 2010

Ваш код ввода и вывода не должен быть функциями-членами.Переместите части с помощью istream и ostream за пределы тела класса:

struct Point
{
   Point() : x(0.0), y(0.0) { }
   double x;
   double y;
};

inline std::istream& operator>> (std::istream& stream, Point& p)
{
    stream >> std::ws;
    stream >> p.x;
    stream >> p.y;
    return stream;
}

inline std::ostream& operator<< (std::ostream& stream, const Point& p)
{
  stream << p.x <<  p.y;
  return stream;
}

Поскольку в вашей структуре есть только открытые члены, друзья не нужны.Кроме того, когда вы пишете функцию вывода, вы должны передать объект как константную ссылку.

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

хорошо, у меня цикл работает следующим образом .....

ostream & operator << (ostream &outStream, const Polygon::Polygon &vertStr) 
{ 
for (int i = 0; i < vertStr.sizeOfVect(); i++) 
{ 
outStream << vertStr.vertices.at(i) << endl; 
} 
return outStream; 
} 

, а затем просто

cout << mainPoly << endl;

в драйвере

я уверенЯ пробовал это снова и снова, не знаю, что я сделал по-другому, но эй, это работает, спасибо всем.

0 голосов
/ 06 апреля 2010

Для поддержки этого ...

cout << myPoly[i] << endl;  

... вы могли бы дать вашему классу Polygon открытый оператор [], который просто вызывает оператор [] своего члена-вершины.

Point const& Polygon::operator[](size_t n) const 
{
   return vertices[n];
}  

Если вы решите поддерживать запись, а также чтение таким образом, вы создадите неконстантную перегрузку, которая возвращает неконстантную ссылку, но в остальном выглядит одинаково. Было бы неплохо добавить в эту версию какую-то проверку на наличие ошибок или инвариантов, очевидно.

...