Vectors C++ : éffacer une case
RésoluJe souhaite réaliser un programme qui trouve les nombres chanceux avant un certain N donné. Pour cela, jutilise un vector, et il semble y avoir un problème de compil à un certain niveau, que je narrive pas a résoudre.
But de linstruction : Effacer la case i dun vector lorsque que i est paire :
Création du Vector dans le main : vector <bool> V(50);
Passage en paramètre dans ma fonction : int nombre_chanceux(vector <bool> V)
Instruction qui bloque dans la fonction : for(int i=2;i<V.size();i++) if(i%2==0) V.remove(i);
Ma commande V.remove doit désallouer V[i], mais a prirori, il y a un soucis...
Merci davance.
Azerty
Configuration: Windows Vista Firefox 2.0.0.11
24 réponses
Problème central : supprimer les éléments pairs d'un vector<bool> en C++ et confondre remove avec erase, car erase nécessite un itérateur et non un indice pour fonctionner correctement. Les réponses recommandent d'utiliser erase avec un itérateur, par exemple V.erase(V.begin() + i), plutôt que remove ou une suppression en milieu qui déplace les indices et rend l’algorithme peu fiable. Le contexte évoque aussi les particularités de vector<bool> qui peut compliquer les opérations et pousse à envisager des alternatives comme reconstruire le vecteur ou changer de conteneur (list, par exemple). En pratique, une approche consiste à filtrer les éléments à conserver en une passe, ou à utiliser std::remove_if avec erase pour gérer proprement les suppressions tout en conservant l'intégrité du conteneur.</bool></bool>
-
Bon, j'ai réussi, même si je dois avouer qu'un prof m'a aidé à regarder le déroulement du programme au brouillon. IL me manquait juste un petit qqch.
#include <vector> #include <iostream> using namespace std; void init(vector <int> &V) { for(int i=0;i<V.size();i++) V[i]=i+1; } void nombre_chanceux(vector <int> &V) { for(int i=1;i<V.size();i++) V.erase(V.begin() + i); int p; for (int z=1;z<V.size();z++) { p=1; while ( p*(V[z]-1)<V.size() ) { V.erase(V.begin() + p*(V[z]-1)); p++; } } } int main() { vector <int> V(50); init(V); nombre_chanceux(V); for(int i=0;i<V.size();i++) cout << "Nombres Chanceux : " << V[i] << " " << endl; system("PAUSE"); return 0; }
Sinon char sniper, je nai pas encore vus les listes, je ne suis qu'en S1 de DUT Informatique. Quant a la deuxième technique, je lavais testé, elle marchait, mais je voulais réussir celle-ci, qui est plus pertinente à mon gout.
Merci beaucoup à toi le père, pour tes nombreux conseils et l'aide que tu m'as apportée. ;)
Azerty -
ContributeurSalut.
Bon alors, vector c'est du C++ standard, c'est un template qui fait partie de la STL.
Si tu as vraiment besoin de du remove, utilise d'autre modèles de la STL que vector. <list> par exemple. Vector est très bien à condition de ne pas avoir de nombre à insérer ou à supprimer au mileu, et de ne pas avoir à faire de tri.
voir là : https://en.cppreference.com/w/
pour tes suppression de nombre, je pense que je parcourerai le tableau et mettrai les valeur à supprimer à 0 sans modifier la taille dans un premier temps.
Puis dans un second tableau, je récupère les nombres qui n'ont pas été supprimer avec vector::push_back(T)
Voila. -
Bonsoir,
Pour le erase, je n'avais aucune chance de deviner...
Pour la logique de ton programme, ta condition ( i % j ) ne convient visiblement pas. Elle est vraie ( !=0) dès que i n'est pas un mutilple de j, ce qui doit arriver assez souvent. Je pense que tu voulais écrire ( i% j == 0 ).
Mais ça ne suffit pas encore bon.
Pourquoi le -1 dans V.erase(V.begin() + i-1); ? A cause de l'élément effacé qui décale la suite du vecteur, je suppose. Je crois bien que le -1 est mal placé.
Un conseil : si le programme passe en compilation, fais le tourner en affichant l'état de ton vecteur juste avant le z+=1 pour mieux comprendre ce qui se passe. -
Voila, j'ai demandé à ma proff de programmation, elle m'a expliqué tout en me disant que ce n'était pas du programme de DUT Semestre 1, ce pourquoi, j'avais du mal...
Quand je met V.erase(i), ce n'est donc pas possible car i nest pas une adresse. Il faut donc utiliser V.begin() qui est donc ladresse du Vectore et faire V.erase(V.begin() + i)
Ainsi, V.erase agit sur une adresse : V.begin()+ i
et non sur un entier comme je le faisais ;)
De la sorte, j'obtiens le programme qui suit, dans lequel j'ai encore une erreur queje n'arrives toujours pas à corriger malgrès mes vérifications. Ce n'est donc plus une erreur de compilation, mais de raisonnement.
#include <vector> #include <iostream> using namespace std; void init(vector <int> &V) { for(int i=0;i<V.size();i++) V[i]=i+1; } void nombre_chanceux(vector <int> &V) { for(int i=1;i<V.size();i++) V.erase(V.begin() + i); int z=1; int j=V[z]; while(j<V.size()) { int i=1; while(i<V.size()) { if(i%j) V.erase(V.begin() + i-1); i++; } z+=1; j=V[z]; } } int main() { vector <int> V(50); init(V); nombre_chanceux(V); for(int i=0;i<V.size();i++) cout << "Nombres Chanceux : " << V[i] << " "; system("PAUSE"); return 0; } -
faut commencer a i=1 ;)
touché ! -
oui cets plus simple comme tu las dis, je constate, par contre, faut commencer a i=1 ;)
Sur ce, si je trouve pour le erase, et que jai encore un soucis, on revéra. Sinon, encore merci et bonne continuation. -
Je suis vraiment mauvais Ne dis jamais ça. Je suis sûr que ça n'est même pas vrai. Ce n'est pas du tout évident de compter des éléments dans un vecteur qui est en constante modification. Je parie que 99,9% des programmeurs débutants tombent dedans.
je remplace donc le i<V.size() par i<2*V.size() ;)
tu ne crois pas qu'il serait beaucoup plus simple de faire
for(int i=2;i<V.size();i++) V.erase(i);
Pour ce qui est de faire un 'erase' correct, quand tu auras la réponse, nous pourrons continuer d'avancer.
A bientôt -
arf oui effectivement, maintenant que tu le dis... Je suis vraiment mauvais... =/ désolé, seulement quelques mois de prog derrière mois, et je fais pas que ça =$. je remplace donc le i<V.size() par i<2*V.size() ;)
Pour ce qui est de la compilation, je chercherai une prof pour maider demain je pense.
En tout cas, merci beaucoup, tu mas beaucoup aidé ;)
Azerty -
J'avoue que ça ne m'aide pas beaucoup. Je n'en sais pas assez sur la définition de vector, ce n'est pas du C++ standard. J'ai peur de ne pas pouvoir d'aider plus loin sur le problème de compilation
En ce qui concerne l'élimination des nombres pairs, le problème c'est que tu élimines l'élément i/2 jusqu'à ce que i atteigne la fin du vecteur. A ce moment là, la deuxième moitié du vecteur n'aura jamais été traitée. tu auras bien au début 1,3,5,.. mais à la fin tu auras toujours ...47,48,49,50. -
si on peut compiler, ca ira mieux pour moi je pense, je pourrai voir ce qui va pas, après, je vais plutot dire : Je pense que ca marche.
Mais compte tenu de ton expérience, je ne parierai pas...
Le fichier Vector, il me mettent ca dedans :
/** @file vector * This is a Standard C++ Library header. You should @c #include this header * in your programs, rather than any of the "st[dl]_*.h" implementation files. */ #ifndef _GLIBCXX_VECTOR #define _GLIBCXX_VECTOR 1 #pragma GCC system_header #include <bits/functexcept.h> #include <bits/stl_algobase.h> #include <bits/allocator.h> #include <bits/stl_construct.h> #include <bits/stl_uninitialized.h> #include <bits/stl_vector.h> #include <bits/stl_bvector.h> #ifndef _GLIBCXX_EXPORT_TEMPLATE # include <bits/vector.tcc> #endif #ifdef _GLIBCXX_DEBUG # include <debug/vector> #endif #endif /* _GLIBCXX_VECTOR */
-
ça marche sans problème on parie ?
toujours le même problème de compilation je l'avais oublié celui-là ! Peux-tu montrer le contenu de ton fichier inclus <vector.h> -
toujours le même problème de compilation, donc impossible, mais jai fait ca sur papier, ça marche sans problème...
Sinon, quand jai dis avoir corrigé les problèmes, jai changé mon vector de booléens en vector d'int... -
effectivemet, cest corrigé
Quelle correction ?
Pour ce qui est de ma première boucle la remarque est vraie pour toutes les boucles où tu fais des erase
for(int i=2;i<V.size();i++) if(i%2==0) V.erase(i/2);
As-tu essayé d'éxécuter ce petit bout et d'imprimer le contenu du vecteur ? Je ne l'ai pas fait, mais à mon avis, une petite surprise t'attend -
Si V est un tableau de booléens, ne penses-tu pas qu'il y a un problème de type dans int j=V[z] ?
euh oui effectivemet, cest corrigé, cest parce que je nétais pas partis du même principe au départ, désolé.
Pour ce qui est de ma première boucle, je naurais jamais percuté ce problème je crois, merci beaucoup.
J'ai corrigé cela, ca donne ça :for(int i=2;i<V.size();i++) if(i%2==0) V.erase(i/2);
Essaye avec V0 contenant 1 dès le départ, normalement ca marche. -
ok, vu http://pagesperso-orange.fr/yoda.guillaume/Nb30a50/Nb31Nb.htm#ChUlam
N'empêche qu'il y a pas mal de problèmes, on va y aller tranquillement
Si V est un tableau de booléens, ne penses-tu pas qu'il y a un problème de type dans int j=V[z] ?
Gros piège : quand tu effaces un élément d'un vecteur, ça decale toute la queue du vecteur de 1 cran vers l'avant. Fais un petit dessin ou simule avec des jetons, tu verras que pour en effacer un sur 2 il ne faut pas effacer le n°2, puis le n°4 puis le n°6 etc... -
Les erreurs ont été corrigées pour le void, le return et l'appel de fonction.
Je te demande ce qu'est un nombre chanceux. Tu me renvoies à un texte où il n'y a pas le mot chanceux. Merci de tes explications claires. Pourquoi ne dis-tu pas que tu cherches à établir la liste des nombres premiers ?
Euh, cest difficile a éxpliquer, voila pourquoi, je t'ai passé ce texte. De plus, je ne cherche pas les nombres, chanceux. L'image où on voit les chiffres est très similaire a celle de l'exercice que je dois réaliser. Je nai pas lu, et je me suis donc trompé d'énoncé, je te pris de m'excuser.
Je n'ai pas l'énoncé en question ici, mais je vais tenter de t'expliquer.
Tu prend la suite des nombres entiers positifs :1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19.......................
Jia choisis de travailler avec un vecteur. Le 2 est donc dans la case N°1.
A partir de cette premire case. Elle contient le chiffre 2, tu supprimers donc un nombre sur 2 a partir de la case 1.
Ainsi, il te reste :1 3 5 7 9 11 13 15 17 19................
Jusque ici, on supprimait les nombres de deux en deux. désormais, le 2 nest plus dans notre Vector, mais par contre, le suivant est un 3, donc on commence a supprimer un nombre sur 3 en partant du premier encore.
Ainsi, tu obtiens :1 3 7 9 13 15 19........
on a enlevé le 5, le 11, le 17.....
tu as supprimé un nombre sur 3, celui que suit dans le vector est 7, donc on commence a supprimer un nombre sur 7, ainsi, on perd le 19 etc etc etc...
Vouala lénoncé, cest un peu barbarre, désolé, jespère que tu as compris que les survivants avant un nombre N donné,(ici, jai mis 50 par défaut) seront appellés ,nombres chanceux avant 50 ;) -
En fait, je nai aucune valeur a retourner
Alors n'en retourne pas ! Explique-moi quel raisonnement t'amène à retourner une valeur quand tu n'as aucune valeur à retourner.
Déclare ta fonction void et ne mets pas de 'return';. Dans le programme principal, appelle simplement nombre_chanceux(V); au lieu de N = nombre_chanceux(V);-
Je te demande ce qu'est un nombre chanceux. Tu me renvoies à un texte où il n'y a pas le mot chanceux. Merci de tes explications claires. Pourquoi ne dis-tu pas que tu cherches à établir la liste des nombres premiers ?
Quant à ta boucle dans nombre_chanceux, tu es assez loin de la réalité. Mais je ne veux pas de donner de résultat tout fait, on va y aller pas à pas. Il faut que tu testes successivement si chaque entier>1 est un diviseur d'un vecteur de ta liste
Tu utilises 3 variables i,j et z
Précise clairement laquelle représente quel entier >1 tu es en train de tester, laquelle te sert à parcourir les éléments de ton vecteur V et à quoi sert la 3ème. Tu devrais déjà corriger de toi même un certain nombre d'erreurs. -
De même, je ne suis pas sûr que ton appel à init initialise quoi que ce soit. init initialise la copie de V que tu passes à init, mais pas V lui même. Il faudrait que init soit défini void init(vector <bool> &V) ( remarque le '&') ; de même pour nombre_chanceux
=> Oups désolé, erreur de débutant, jai corrigé ca ;)
Je ne sais pas ce que tu cherches à faire ni ce qu'est un nombre chanceux. Mais ta fonction retourne toujours 0. Tu n'utilises pas la valeur retournée, alors pourquoi en retournes-tu une ? J'ai un doute là.
En fait, je nai aucune valeur a retourner, car je ne fais que désalloumer les emplacements dun Vecteur au fur et a mesure que mes boucles se font. Si cela peut taider, tu pourras trouver lénoncé de mon exercice a cette page la :
http://leri.univ-reims.fr/...
si le lien est pas entier, faut enlever ce quil y a après pdf ala fin ;)
Cest l'exercice 1 ;) -
Croyez vous que je me sois trompé au niveau du return de ma fonction chanceux ?
Je ne sais pas ce que tu cherches à faire ni ce qu'est un nombre chanceux. Mais ta fonction retourne toujours 0. Tu n'utilises pas la valeur retournée, alors pourquoi en retournes-tu une ? J'ai un doute là.
De même, je ne suis pas sûr que ton appel à init initialise quoi que ce soit. init initialise la copie de V que tu passes à init, mais pas V lui même. Il faudrait que init soit défini void init(vector <bool> &V) ( remarque le '&') ; de même pour nombre_chanceux -
joublis que le complateur me donne cette indication, mais sans numéro de ligne :
In function `int nombre_chanceux(std::vector<bool, std::allocator<bool> >)':
cest ma prof qui mavait donné remove, mais elle nen était pas sur. Jai donc recherché la, jai trouvé la classe Vector en C++ et effectivemen,t remove ne semble pas en faire partie, ca devait être du Java... La voici :
https://en.cppreference.com/w/cpp/container/vector
Jia donc remplacé mon "remove" par un "erase", mais toujours une erreur que je ne sais déchiffrer :
no matching function for call to `std::vector<bool, std::allocator<bool> >::erase(int&)'
Je vais vous mettre mon programme pour plus de facilité :#include <vector> #include <iostream> using namespace std; void init(vector <bool> V) { for(int i=0;i<V.size();i++) V[i]=true; } int nombre_chanceux(vector <bool> V) { for(int i=2;i<V.size();i++) if(i%2==0) V.erase(i); int z=1; int j=V[z]; while(j<V.size()) { int i=1; while(i<V.size()) { if(i%V[z]) V.erase(i-1); i++; } z+=1; j=V[z]; } return 0; } int main() { vector <bool> V(50); init(V); int N; N = nombre_chanceux(V); for(int i=0;i<V.size();i++) cout << "Nombres Chanceux : " << V[i] << " "; system("PAUSE"); return 0; }
Croyez vous que je me sois trompé au niveau du return de ma fonction chanceux ?
EDIT : Fin de lerreur dans la compilation :
note C:\Dev-Cpp\include\c++\3.4.2\bits\stl_bvector.h:843 candidates are: std::_Bit_iterator std::vector<bool, _Alloc>::erase(std::_Bit_iterator) [with _Alloc = std::allocator<bool>]
note C:\Dev-Cpp\include\c++\3.4.2\bits\stl_bvector.h:843 std::_Bit_iterator std::vector<bool, _Alloc>::erase(std::_Bit_iterator, std::_Bit_iterator) [with _Alloc = std::allocator<bool>]
- 1
- 2