Souci avec "Vector"...

Fermé
Hurobaki Messages postés 53 Date d'inscription dimanche 23 mars 2014 Statut Membre Dernière intervention 10 mars 2017 - Modifié par baladur13 le 17/04/2016 à 18:28
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 - 18 avril 2016 à 12:04
Bonjour à tous,

Étant novice en programmation C++, je commence à utiliser les vector. Mais je rencontre un problème sur la suppression des objects dans un vector.

#pragma once
#include "Sensor.h"
#include <vector>
#include <iostream>

using namespace std;

class Zone
{
 private:
  vector<Sensor> sensors;

 public:
  Zone();
  ~Zone();

  void addSensor(const Sensor& s);
  void displayContent();
  bool removeSensor(Sensor s);


};


void Zone::addSensor(const Sensor& s)
{
 sensors.push_back(s);
}

bool Zone::removeSensor(Sensor *s)
{
 for (int i = 0; i < sensors.size(); i++)
 {
  if (s == &sensors[i])
  {
   sensors.erase(sensors.begin() + i);
   return true;
  }
 }
 return false;
}

void Zone::displayContent()
{
 cout << "My vector contains:" << endl;
 for (int unsigned i = 0; i < sensors.size(); i++)
 {
  cout << sensors[i] << endl;
  cout << &sensors[i] << endl;
  
 }
  
 cout << "Thats all" << endl;
}


 Sensor s1("Sensor1");
 Sensor s2("Sensor2");
 Zone z;

 z.addSensor(s1);
 z.addSensor(s2);

 cout << "Adresse premier Sensor : " << &s1 << endl;
 cout << "Adresse second Sensor : " << &s2 << endl;
 z.displayContent();


J'arrive à ajouter des objets dans mon vector sans problème mais lors de la suppression j'aimerai passer en paramètre mon objet et que celui-ci soit retiré de mon vector.

J'ai tenté par les adresses mais elles ne sont pas les mêmes dans le main et dans la méthode ...

Qu'est ce que je ne fais pas bien ?

Merci d'avance pour votre aide

3 réponses

Dalfab Messages postés 706 Date d'inscription dimanche 7 février 2016 Statut Membre Dernière intervention 2 novembre 2023 101
18 avril 2016 à 02:54
Bonjour,
Le problème est dans Sensor.
A l'insertion dans la table, une copie est faite. La recherche dans la table doit se faire sur un critère de reconnaissance.
  • Ou bien le Sensor a une sémantique de valeur et il doit avoir un opérateur d'égalité, la recherche se fera alors par ce test. Par exemple bool operator==( const Sensor& s1, const Sensor &s2) { return s1.nom==s2.nom; }. Un Sensor est identifié par son contenu.
  • Ou bien le Sensor a une sémantique d'entité et la table doit recevoir des pointeurs intelligents qui pourront être comparés (la création d'un Sensor est unique, et il est reconnaissable par son adresse)
0
Hurobaki Messages postés 53 Date d'inscription dimanche 23 mars 2014 Statut Membre Dernière intervention 10 mars 2017
18 avril 2016 à 09:59
Bonjour merci de ta réponse,

J'aimerai faire cela par adresse, si j'ai bien compris je créé une copie dans la méthode et donc cette copie ne possède pas la même adresse que mon objet initial.
Donc pour modifier cela je dois créer un vector de Sensor* ? Ou le problème vient de ma fonction ?

Merci d'avance
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 2
Modifié par cptpingu le 19/04/2016 à 11:10
Bonjour.

Plus simplement, utilise la méthode "find" + "erase" de std::vector. (Cette méthode ne fonctionne qui si tu suis ce que préconise Dalfab, c'est-à-dire si tu donnes à ta classe Sensor un moyen de la comparer avec d'autres Sensor, donc de lui définir son "operator==()").
Exemple:

bool Zone::removeSensor(const Sensor& s)
{
  auto found = _sensors.find(s);
  if (found == _sensors.end()) // Si non trouvé
    return false;

  _sensors.erase(found);
  return true;
}


Quelques conseils:
  • Évite les using namespace, c'est ultra crade et dangereux. Voir: http://0217021.free.fr/portfolio/axel.berardino/articles/bon-usage-using-namespace/
  • Différencie un attribut de classe d'une variable. Généralement, on met un "_" devant. Au lieu de "vector<Sensor> sensors;" préfère: "std::vector<Sensor> _sensors;".
  • Pour les extensions, utilise .cc/.hh ou .cpp/.hpp, mais évite le .h qui est plutôt pour du C (ce n'est pas une erreur technique, mais une convention un peu plus propre).
  • Pour faire un affichage, laisse le choix du flux à l'utilisateur (qui mettra un std::cout, un std::cerr ou un flux de fichier).

Exemple:
void Zone::displayContent(std::ostream& out)
{
  out << "My vector contains:" << std::endl;
  for (auto& elt : _sensors)
    out << elt << std::endl;
  out << "Thats all" << std::endl;
}

Ce qui te permet de faire, au choix:
zone.displayContent(std::cout); // Affichage sortie standard
zone.displayContent(std::err); // Affichage sortie erreur
std::ofstream file("toto.txt"); // Écriture dans un fichier
zone.displayContent(file);
0