Allocation de mémoire par une structure.

Résolu
XgadaX Messages postés 9 Date d'inscription samedi 7 novembre 2015 Statut Membre Dernière intervention 20 avril 2020 - 19 avril 2020 à 21:05
XgadaX Messages postés 9 Date d'inscription samedi 7 novembre 2015 Statut Membre Dernière intervention 20 avril 2020 - 20 avril 2020 à 15:45
Bonjour,bonsoir,
Je me tourne vers vous après de multiples recherches et 3 jours de tentatives acharnées.
Dans le but de simplifier mes dires j'ai imagée la situation.
Voila mon problème : Je cherche à alloué de la mémoire dans un vector d'une structure toute simple,
ci-dessous vous trouverez les déclarations à connaître.

struct Album
{
 std::string nom;
 std::vector<string> titres;
}unAlbum;

struct Auteur
{
 std::string nom;
 std::vector<Album> albums;
}unAuteur;

std::vector<Auteur> Armoire;


Seulement voila le programme ci-dessous compile :
for(auto auteur : Armoire)
{
 if(auteur.nom == nomRechercheAuteur)
 {
  for (auto album : unAuteur)
  {
   if(album.nom == nomRechercheAlbum)
   {
    album.titres.push_back("nouveau titre"); // ici
   }
  }
 }
}


En revanche, la ligne annotée d'un commentaire ne fonctionne pas.
J'ai tenté toutes les alternatives possibles et imaginables : boucle
for(;;)
,
passage par référence de toute les variables et même
for(auto&& album : unAuteur)

alors que je ne sais pas se que cela signifie.
D'après ce que j'ai compris des nombreuses erreures que je ne peut pas citer... la liste et trop longue,
c'est que l'allocation refuse de se faire car me direz vous la boucle est en train de passer en revue le
vector
,
elle ne peut donc pas l'agrandir.
Oui mais je vous répondrais que même en récupérant la valeur de
album
dans la boucle
et en essayant de refaire
album.titres.push_back("nouveau titre");
après les boucles cela ne fonctionne pas.
Je vous gratifie tout de même d'une erreur qui apparaît en sortie de programme :
invalid parameter passed to C runtime function
.
Celle-ci revient fréquemment pendant l'execution mais encore une fois j'ai eu beau chercher
je ne trouve pas de solution.

En espérant avoir été suffisamment clair.
Je remercie par avance ceux qui songeront à m'aider.

6 réponses

cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
Modifié le 20 avril 2020 à 11:30
Bonjour !

Que veux-tu dire par ne fonctionne pas ? Ça ne compile pas ? Ça plante/crash ? Ça ne fais pas ce que tu veux ? Il faut que tu sois précis si tu veux qu'on t'aide.

Le code que tu as écrit est étrange (je pense qu'en essayant de le simplifier, tu as du omettre des choses, ou te tromper de variables). Par exemple, unAutre est une variable globale qui n'est pas dans ton vecteur de base.

Sur le principe, ça devrait fonctionner car tu modifies un élément qui n'est pas "touché". Tu ne peux modifier un tableau pendant son parcours, mais tu peux modifier les tableaux contenu dans les "cases" du tableau que tu parcours. L'objet et les sous objets ne sont pas la même chose ici.

En C++, class et struct c'est la même chose (à part que struct est public par défaut). Donc je me permets une petite réécriture au propre de ce que tu veux réaliser, en ajoutant des constructeurs et en préfixant les attributs. (Si la manière de printer des choses est trop compliqué, ignore-là, mais pour ta boucle ça devrait être bon).

Ceci fonctionne très bien chez moi (avec le flag c++11, sur un compilateur récent):
#include <iostream>
#include <vector>

struct Album
{
  Album(const std::string& nom, const std::vector<std::string>& titres)
    : _nom(nom), _titres(titres)
  {
  }

  void print(std::ostream& out) const
  {
    out << _nom << "(";
    bool first = true;
    for (auto titre : _titres)
    {
      if (first)
        first = false;
      else
        out << ",";
      out << titre;
    }
    out << ")";
  }

  std::string _nom;
  std::vector<std::string> _titres;
};

struct Auteur
{
  Auteur(const std::string& nom, const std::vector<Album>& albums)
    : _nom(nom), _albums(albums)
  {
  }

  void print(std::ostream& out) const
  {
    out << _nom << ": ";
    bool first = true;
    for (auto album: _albums)
    {
      if (first)
        first = false;
      else
        out << ",";
      album.print(out);
    }
    out << std::endl;
  }

  std::string _nom;
  std::vector<Album> _albums;
};

std::ostream& operator<<(std::ostream& out, const std::vector<Auteur>& armoire)
{
  for (auto auteur : armoire)
    auteur.print(out);

  return out;
}

int main()
{
  std::vector<Auteur> armoire;

  armoire.push_back(Auteur("Auteur1", { Album("Album1", {"titre1", "titre2", "titre3"}) } ));
  armoire.push_back(Auteur("Auteur2", { Album("Album2", {"titreA", "titreB", "titreC"}), Album("Album9", {"titreZ", "titreY"}) } ));
  armoire.push_back(Auteur("Auteur3", { Album("Album3", {"titre9", "titre8", "titre7"}) } ));

  std::cout << "Avant:\n" << armoire << std::endl;

  std::string nomRechercheAuteur = "Auteur2";
  std::string nomRechercheAlbum = "Album2";

  for (auto& auteur : armoire)
  {
    if (auteur._nom == nomRechercheAuteur)
    {
      for (auto& album : auteur._albums)
      {
        if (album._nom == nomRechercheAlbum)
        {
          std::cout << "ok" << std::endl;
          album._titres.push_back("nouveau titre"); // ici
        }
      }
    }
  }

  std::cout << "Apres:\n" << armoire << std::endl;

  return 0;
}


1
pgl10 Messages postés 381 Date d'inscription samedi 18 décembre 2004 Statut Non membre Dernière intervention 25 avril 2024 11
Modifié le 20 avril 2020 à 09:36
Bonjour XgadaX, bonjour CptPingu,
Très intéressant ! Pour indiquer deux Album à l'Auteur1 j'ai écrit ceci :
  armoire.push_back(Auteur("Auteur1", {{ Album("A1", {"t1", "t2", "t3"})},{Album("Aa", {"tx", "ty", "tz"})}} ));

avec ici des noms très brefs pour éviter une ligne trop longue. Et cela fonctionne bien, mais il manque une virgule dans l'affichage des Album d'un Auteur : il faut pour cela ajouter "if(first) ..." dans le print() de Auteur comme dans le print() de Album. Bien cordialement.
1
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
20 avril 2020 à 15:32
Si tu fais un "auto" , alors tu prends une copie de l'un des items.
Si tu fais un "auto&", tu prends vraiment l'objet qui est dans la case.

Si tu te contentes d'un auto, alors tu vas une obtenir une copie temporaire, que tu vas modifier (ça fonctionnera), puis l'objet temporaire sera détruit au sortir de son scope (ici la boucle).
La "vraie" variable n'a jamais été modifiée, seulement sa copie (qui n'est même pas gardée, mais même si elle l'avait été, tu n'aurais pas "touché" à la bonne variable !)
1
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
20 avril 2020 à 11:31
C'est corrigé, merci pgl10 ! J'ai édité mon premier post.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
XgadaX Messages postés 9 Date d'inscription samedi 7 novembre 2015 Statut Membre Dernière intervention 20 avril 2020
20 avril 2020 à 15:17
Bonjour à vous,

Tous d'abord merci pour vos réponses qui m'ont beaucoup aidées puisque le problème est résolu.
Il s'avère que le problème reste un mystère car en réécrivant le code ( que j'avais supprimé ) et en remettant les références comme suit
for(auto& auteur : Armoire)
il fonctionne.
Je vous pose une dernière petite question qui m'intrigue :
Pourquoi le passage par référence est-il nécessaire ?
auteur
même en étant un objet devrait pouvoir être modifié, je rajoute que le programme ne crashait pas il ne faisait simplement pas
album.titres.push_back("nouveau titre");
.

Je vous remercie encore et passerai le sujet en résolu dans quelques jours.
cptpingu++;
pgl10++;
;)
0
XgadaX Messages postés 9 Date d'inscription samedi 7 novembre 2015 Statut Membre Dernière intervention 20 avril 2020
20 avril 2020 à 15:45
Aaaah oui c'est plus clair comme ça, je pensais que la copie se faisait seulement dans le cas d'une fonction avec ses arguments.
Merci encore.
0
Rejoignez-nous