2010-04-02 10 views
0

J'essaie d'écrire un opérateur d'insertion de flux surchargé pour une classe dont le seul membre est un vecteur. C'est un vecteur de Point s, qui est un struct contenant deux double s. Je suppose que je veux insérer une entrée utilisateur (un groupe de double s) dans un flux que j'envoie ensuite à une méthode de modification. Je travaille hors d'autres exemples d'insertion de flux tels que:Opérateur d'insertion de flux surchargé avec un vecteur

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

mais lorsque je tente quelque chose de similaire:

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

Je reçois une erreur « aucune correspondance pour operator >> etc, etc. » Si je laisse tomber le .vertices, il compile, mais je me dis que ce n'est pas correct. (En passant, vertices est le nom de mon vector <Point>.) Et même si c'est juste, je ne sais pas vraiment quelle syntaxe utiliser dans mon programme pour l'utiliser, et je ne suis pas sûr à 100% sur ce que mon méthode de modificateur doit ressembler.

Voici mon Polygon classe:

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

Désolé d'être si vague; Un conférencier nous a juste donné un bref exemple d'insertion de flux, puis nous a laissé seul.

Répondre

1

Le problème est qu'il n'y a pas d'opérateur d'extraction standard pour les vecteurs (l'insertion est dans un flux, l'extraction à partir d'un flux), vous devrez donc définir les vôtres. En outre, les flux ignorent les espaces par défaut, donc vous n'avez généralement pas besoin d'utiliser std::ws. Vous n'avez pas défini comment l'entrée de vecteur est terminée, donc je suppose qu'une nouvelle ligne indique la fin d'un vecteur.

Puisqu'il s'agit d'un problème scolaire, je ne peux pas vous en donner trop. Pour commencer, voici quelques déclarations que vous devrez remplir, et d'autres qui pourraient s'avérer utiles. C'est une mauvaise forme d'importer l'espace de noms std, donc ce qui suit ne le fait pas.

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

Comme alternative au caractère des fonctions liées (ishs, isvs, hs, eol), vous pouvez lire la ligne suivante dans une chaîne avec getline, puis dans un istringstream et points de lecture de cela. Le vecteur se termine lorsque istringstream atteint eof (ou strin >> pt is false).

Ce que vous devez faire est de tourner les tâches operator>>(istream&, vector<Point>&) dans la méthode et les appels de fonction, puis:

  1. Déclarez les nouvelles méthodes et fonctions.
  2. Écrire une description des tâches (comme dans le commentaire >>).
  3. Transforme la description en appels de méthode et de fonction.
  4. Répétez jusqu'à ce qu'il n'y ait plus de nouvelles méthodes ou fonctions à écrire.

Pourquoi mon Polygon::sides() est différent de votre Polygon::sizeOfVect(): Notez que vector::capacity renvoie le nombre d'éléments d'un vecteur peut contenir sans redimensionnement; c'est à dire, c'est fondamentalement sizeof (vect)/typeof (élément).vector::size est le nombre d'éléments actuellement stockés dans un vecteur. Les deux peuvent différer si vous préallouer l'espace pour les éléments, tels que Polygon::sides(int) fait, ou si vous déposez des éléments à l'arrière. Quoi qu'il en soit, cependant, vector::capacityvector::size.

+0

ok, merci pour tout cela, j'ai juste besoin d'y aller et de le comprendre maintenant. – Julz

Questions connexes