如何cout结构的向量(这是一个类成员,使用提取运算符)

时间:2010-04-06 14:34:04

标签: c++ vector operator-overloading extraction

我试图使用重载的提取运算符简单地对向量的元素进行cout。矢量contians Point,它只是一个包含两个双精度的结构。 vector是一个名为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

我的Polygon.h

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

我认为我的Point插入/提取是正确的,我可以使用它插入和cout

我认为我应该能够......

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 个答案:

答案 0 :(得分:5)

把事情整理好。首先,术语: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;
}

另请注意,由于我们不会修改传递的Point,因此我将其更改为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;
}

看看这有多久,我想我现在就会停在那里。

答案 1 :(得分:3)

查看this answerthis question

这里的一般想法是,你确实必须遍历你的向量以打印所有包含的对象,但你可以std::copy为你做这件事。作为副本的目标,您只需使用std::ostream_iterator< Point >( std::cout )(在此处查看documentation)。 ostream_iterator然后使用重载的operator << Point来打印各个点。这看起来如此:

std::copy( vertices.begin(), vertices.end(), std::ostream_iterator< Point >( std::cout ) );

答案 2 :(得分:2)

您的输入和输出代码不应是成员函数。使用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;
}

由于你的结构只有公共成员,所以不需要朋友。此外,当您编写输出函数时,您应该将对象作为const引用传递。

答案 3 :(得分:1)

好吧,我让循环像这样......

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;

在驱动程序中

我确定我一遍又一遍地尝试过,不知道我做了什么不同,但嘿它有效 谢谢大家。

答案 4 :(得分:0)

支持这个......

cout << myPoly[i] << endl;  

...你可以给你的Polygon类一个公共运算符[],只需调用其顶点成员的operator []。

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

如果您选择以这种方式支持写入和读取,您将创建一个非const重载,返回非const引用,但看起来相同。显然,在某个版本中添加某种错误或不变检查可能是一个好主意。