2

オーバーロードされた抽出演算子を使用して、ベクトルの要素を単純に計算しようとしています。ベクトル contians Point。これは、2 つの double を含む単なる構造体です。ベクトルは 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;
 }

ポイントの挿入/抽出が正しいと判断し、それを使用して挿入および計算できます

そして、私はできるはずだと思います......

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;

問題はありません。

何日も答えを見つけようとしましたが、本当に迷ってしまいました。

コメントと書式設定が不足していることをお許しください。また、欠落している部分もあります。

4

5 に答える 5

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

これに対処する明白な方法の 1 つは、各ポリゴンに含まれる頂点の数をプレフィックスとして付けることです。そのため、同じデータは次のようになります。

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

これがどれだけ長くなっているかを見て、私は今のところここでやめようと思います.

于 2010-04-06T15:38:27.203 に答える
3

この質問に対するこの回答を見てください。

ここでの一般的な考え方は、含まれているすべてのオブジェクトを出力するためにベクトルを実際にループする必要があるということですが、std::copyを使用してそれを行うことができます。コピーのターゲットとして、単純に を使用します(ドキュメンテーションstd::ostream_iterator< Point >( std::cout )については、こちらを参照してください)。次に、オーバーロードされたforを使用して個々のポイントを出力します。これは次のようになります。ostream_iteratoroperator <<Point

std::copy( vertices.begin(), vertices.end(), std::ostream_iterator< Point >( std::cout ) );
于 2010-04-06T14:37:22.693 に答える
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 参照として渡す必要があります。

于 2010-04-06T14:39:50.967 に答える
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;

ドライバーで

私はそれを何度も試したと確信しています。何が違うのかわかりませんが、みんなに感謝します。

于 2010-04-07T06:26:50.243 に答える
0

これをサポートするには...

cout << myPoly[i] << endl;  

... Polygon クラスに、その頂点メンバーの operator[] を単に呼び出す public operator[] を与えることができます。

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

この方法で書き込みと読み取りをサポートすることを選択した場合は、非 const 参照を返す非 const オーバーロードを作成しますが、それ以外は同じように見えます。明らかに、そのバージョンにある種のエラーまたは不変チェックを追加することをお勧めします。

于 2010-04-06T15:49:44.490 に答える