开发者

how to cout a vector of structs (that's a class member, using extraction operator)

i'm trying to simply cout the elements of a vector using an overloaded extraction operator. the vector contians Point, which is just a struct containing two doubles. the vector is a private member of a class called 开发者_JAVA技巧Polygon, so heres my 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

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

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

i figure my Point insertion/extraction is right, i can insert and cout using it

and i figure i should be able to just......

cout << myPoly[i] << endl;  

in my driver? (in a loop) or even...

cout << myPoly[0] << endl; 

without a loop? i've tried all sorts of

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

etc etc

also tried all veriations in my extraction function

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

within loops, etc etc.

when i just create a...

vector<Point> myVect;

in my driver i can just...

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

no problems.

tried to find an answer for days, really lost and not through lack of trying!

please excuse my lack of comments and formatting also there's bits and pieces missing.


Taking things in order. First, terminology: operator<< is an insertion operator -- it inserts items into a stream. operator>> is an extraction operator -- it extracts items from the stream.

Second, you have some fairly serious problems in your insertion operators. Let's start at the bottom, point::operator<<. Right now you have:

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

Now, let's consider what happens when we feed some real numbers to this, let's say 1.23 and 4.56. It'll write out:

1.234.56

This is clearly a problem. There's no way, from looking at the data itself, to figure out where the 'x' ends and the 'y' starts. We need to format the data so we can distinguish those:

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

Also note that since we're not going to modify the Point that's passed, I've changed it to a const reference.

When/if you try to store more than a single polygon in a file, you run into the same problem again -- you have a stream of vertices, but nothing to show which vertices belong to which polygons. For example, a square followed by a triangle might look like this:

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

One obvious way to deal with that would be to prefix each polygon with the number of vertices it contains, so the same data would look something like this:

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

Then we can re-generate the original polygons as we read them back in. To do that, we (obviously) need to write our operators appropriately:

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

Looking at how long this is getting, I think I'll stop there for now.


Look at this answer to this question.

The general idea here is, that you do indeed have to loop over your vector in order to print all contained objects, but you can to std::copy to do that for you. As target for the copy you simply use an std::ostream_iterator< Point >( std::cout ) (look here for documentation). The ostream_iterator then uses your overloaded operator << for Point to print the individual points. This would look thus:

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


Your input and output code shouldn't be member functions. Move the parts with istream and ostream outside the class body:

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

Since your struct has only public members, there's no need for friends. Also, when you write an output function, you ought to pass the object as a const reference.


ok, i got the loop working like this.....

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

then just

cout << mainPoly << endl;

in the driver

i'm sure i tried that over and over, dont know what i did differently, but hey it works thanks heaps everyone.


To support this...

cout << myPoly[i] << endl;  

...you could give your Polygon class a public operator[] that simply calls the operator[] of its vertices member.

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

If you choose to support writing as well as reading in this fashion, you'd create a non-const overload that returns a non-const reference, but otherwise looks the same. It might be a good idea to add some kind of error or invariant checking into that version, obviously.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜