La boucle en C++
Bonjour
Pourriez-vous me confirmer qu'en C++, dans une boucle comme celle-ci : for(i = i0; i < n; i++) { ...body...}, si i0 change dans body, alors il change aussi dans le for ? (ce qui n'est pas le cas de tous les langages)
Je cherche l'indice du plus grand vecteur pour l'ordre lexicographique dans un vecteur de vecteurs. J'ai fait ce prog qui a l'air de marcher :
int firstIndex(std::vector<std::vector<int>> expnts) { const int n = expnts.size(); int i0 = 0; for(int i = i0; i < n-1; i++) { std::vector<int> vi = expnts[i]; for(int j = i+1; j < n; j++) { std::vector<int> vj = expnts[j]; bool vjmax = std::lexicographical_compare( std::begin(vi), std::end(vi), std::begin(vj), std::end(vj) ); if(vjmax) { i0 = j; break; } else { return i0; } } } return i0; }
Réponses
-
@Saturne : ta question porte sur les règles de portée des identifiants ("scope" en anglais) : https://en.cppreference.com/w/cpp/language/scopeEt donc oui, ton i0 est modifiable par la boucle (pourquoi ne le serait-il pas ?)
-
Je ne sais pas car on peut toujours éviter ça donc personne de sérieux ne code comme cela. D'ailleurs, en C++, ce genre de boucle se code souvent directement avec des itérateurs (iterator en anglais). Comme ça, on n'a pas à se prendre la tête.
-
@troisqua Ben par exemple, pour cet algorithme précisément, la deuxième boucle ne sert à rien car on n'arrive jamais à $j = i+2$. Donc non seulement le programme ne fonctionne pas, mais en plus modifier i0 ne sert à rien, on ne fait que comparer $v_i$ à $v_{i+1}$ jusqu'à obtenir le premier $i0$ tel que $v_{i0} \geq v_{i0+1}$ qui est renvoyé. Donc on peut juste réduire toute cette boucle et mettre à la fin "return n" et dans la boucle "return i" ce qui dispense d'utiliser ce i0 qui ne sert à rien.Un codeur sérieux, il fait en sorte que son code soit lisible rapidement par un autre codeur sérieux. Là, ce n'est clairement pas le cas.
-
Bonjour,
Il me semble qu'en C++for (initialisation; condition; opération) {instructions}
est équivalent àinitialisation; while (condition) { instructions; opération; }
De plus, tu pourrais écrire for(int i = 0; i < n-1; i++) au lieu de for(int i = i0; i < n-1; i++) tout simplement, non ?
Et Bibix a raison quand il dit que le programme ne fait pas ce qu'on lui demande. -
Mais mince, j'ai posté une réponse et elle n'est pas là...
-
Si ton i0 ne "change pas" ce n'est pas un problème de scope lié au langage mais à ce que fait ton algo. Tu peux vérifier cela en affichant la trace de j à l'intérieur de ta comparaison.
-
Le code suivant ne modifie pas i0.
i0 = 0; for(int i = i0; i < 10; i++) i0 = 15;
Il ne faut pas respirer la compote, ça fait tousser.
J'affirme péremptoirement que toute affirmation péremptoire est fausse -
Ce n'est toujours pas assez "sérieux" pour certains mais est-ce bon là ? Vérifié sur un exemple uniquement, mais je vais voir si mon gros code crashe ou pas.
int firstIndex(std::vector<std::vector<signed int>> expnts) { const int n = expnts.size(); int i = 0; while(i < n-1) { std::vector<signed int> vi = expnts[i]; for(j = i + 1; j < n; j++) { std::vector<signed int> vj = expnts[j]; bool vjmax = std::lexicographical_compare( std::begin(vi), std::end(vi), std::begin(vj), std::end(vj) ); if(vjmax) { i = j - 1; break; } else if(j == n-1) { return i; } } i++; } return i; }
-
Pardon il manque un truc... je teste et je reviens.
-
J'ai corrigé dans le message précédent. Mon code crashe encore
-
Non troisqua, Calli a raison.
-
@troisqua Si tu relis mes messages, tu verras que j'ai écrit dans mon premier message que ce n'était pas sérieux car on pouvait toujours faire sans ça puis dans mon deuxième message qu'on pouvait faire la même chose sans $i0$ ce qui montre bien que ce n'est pas sérieux dans ce cas précisément. Tu as bien demandé de préciser pour l'algorithme du premier message de l'OP et je t'ai bien répondu. Si tu voulais des précisions en général, alors il fallait le dire plus tôt.Le nouvelle version est déjà meilleure. Pourquoi ? Parce-qu'il suffit de lire en une seule fois pour comprendre ce qu'il se passe et qu'on n'a aucun doute sur le fonctionnement (sans avoir à aller regarder dans la doc'). Du bon code, c'est pas seulement un code qui marche. C'est d'ailleurs précisément ce que je t'ai répondu.
-
Bon je vais faire un café. Merci en tout cas.
-
J'ai du mal à comprendre la discussion, mais j'essaie de répondre.Saturne a dit :J'ai vérifié et @Calli a raison, le i0 ne change pas.
L'équivalence entre le for et le while que j'ai donnée était pour expliquer le fonctionnement du for. Et ça montre que i0 pourrait changer. Par exemple, dans le code de @Médiat_Suprème ci-dessous (avec correction des erreurs syntaxiques), le i0 change (contrairement à ce qu'il dit).int i0 = 0; for(int i = i0; i < 10; i++) {i0 = 15;}
Ensuite je suis d'accord quand @troisqua dit ça :troisqua a dit :Si ton i0 ne "change pas" ce n'est pas un problème de scope lié au langage mais à ce que fait ton algo. -
Oui mais tu as raison sur l'équivalence entre le "for" et le truc que tu as écrit. Je n'ai pas vérifié sur mon code, je me suis renseigné sur SatckOverflow.
-
@Calli, il n'y a pas d'erreur dans mon code, mon compilateur me l'aurait dit (par contre les balises "code" n'ont pas fonctionné), les accolades ne sont pas requises.
Quant à l'exécution, je ne sais pas où j'ai regardé, car en l'exécutant à nouveau, je constate bien que i0=15.Il ne faut pas respirer la compote, ça fait tousser.
J'affirme péremptoirement que toute affirmation péremptoire est fausse -
@Saturne : Oui dans ton premier code je suis d'accord ! Mais je ne l'avais pas dit dans mon premier message alors je ne comprenais pas pourquoi tu disais "Calli a raison, le i0 ne change pas". C'est tout.
@Médiat_Suprème : Oui ok j'ai juste rajouté le int de la première ligne et des accolades pour plus de clarté. -
Personnellement, je ne suis pas certain de comprendre ce que tu souhaites réaliser. D'ailleurs ton bout de code est globalement incompréhensible (si j'écrivais ça, je me ferais virer sur le champ ).Toutefois, à vu d'œil je te dirais que : il n'y a pas grand intérêt à utiliser while pour la boucle externe : for et while sont globalement équivalents. De plus, il existe depuis C++11 des moyens bien plus élégants et moins prises de tête pour itérer sur les vecteurs, à la manière de Java ou Python :
for(auto v : vs) {
équivalent àfor(auto it=begin(vs); it!=end(vs); ++it) {
ce qui rend d'ailleurs caduc ce genre de lignesfor(j = i + 1; j < n; j++) { std::vector vj = expnts[j];
dignes de personnes qui codent en C++ comme elles coderaient en C. -
... sauf que j'ai besoin de j
-
Et donc ?
-
ça y est mon code marche !!!
Maintenant reste à voir s'il déchire ou pas. -
C'était un des meilleurs ajouts de C++11. Heureux de vous le partager !
-
@dp, peux-tu me dire aussi si les codes suivants sont équivalents s'il te plaît ?
for (map<typea,typeb>::iterator it=mymap.begin(); it!=mymap.end(); ++it) { ... j'utilise ici it->first et it->second ...}
etfor (auto& [a,b] : mymap) {... j'utilise ici a et b ...}
Et idem avec const_iterator, cbegin, cend et auto const& ?
J'ai aussi vu un auto&& sur le net, mais je ne comprends pas la différence avec auto&. -
C'est globalement équivalent, oui. La seconde forme ayant été introduite comme étant un syntactic sugar pour la première. Pour s'en convaincre, on peut essayer sur des exemples.Ce qui nous retourne
#include <iostream> #include <map> int main(int argc, char *argv[]) { std::map<std::string, int> map{{"Paris", 75}, {"Lyon", 69}, {"Clermont-Ferrand", 63}}; for (std::map<std::string,int>::iterator it=map.begin(); it!=map.end(); ++it) { std::cout << it->first << ":" << it->second << std::endl; } for(auto &[key,value] : map) { std::cout << key << ":" << value << std::endl; } return 0; }
Clermont-Ferrand:63 Lyon:69 Paris:75 Clermont-Ferrand:63 Lyon:69 Paris:75
On remarquera que C++ est gentil et effectue le tri automatiquement sur les keys.Pour ce qui est de la différence entre auto&& et auto&, je ne suis pas certain d'être capable de l'expliquer correctement, du coup je te renvoie vers ce lien stackoverflow qui, je trouve est très bien. -
Formidable ! Merci.
Connectez-vous ou Inscrivez-vous pour répondre.
Bonjour!
Catégories
- 165.1K Toutes les catégories
- 59 Collège/Lycée
- 22.1K Algèbre
- 37.5K Analyse
- 6.3K Arithmétique
- 58 Catégories et structures
- 1.1K Combinatoire et Graphes
- 13 Sciences des données
- 5.1K Concours et Examens
- 20 CultureMath
- 51 Enseignement à distance
- 2.9K Fondements et Logique
- 10.7K Géométrie
- 83 Géométrie différentielle
- 1.1K Histoire des Mathématiques
- 79 Informatique théorique
- 3.9K LaTeX
- 39K Les-mathématiques
- 3.5K Livres, articles, revues, (...)
- 2.7K Logiciels pour les mathématiques
- 24 Mathématiques et finance
- 337 Mathématiques et Physique
- 5K Mathématiques et Société
- 3.3K Pédagogie, enseignement, orientation
- 10.1K Probabilités, théorie de la mesure
- 801 Shtam
- 4.2K Statistiques
- 3.8K Topologie
- 1.4K Vie du Forum et de ses membres