Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Re: size_t vs vector::size_type

9 réponses
Avatar
Gabriel Dos Reis
"Michel Michaud" <mm@gdzid.com> writes:

| Dans news:m3n088rizo.fsf@merlin.cs.tamu.edu, Gabriel Dos
| Reis <gdr@cs.tamu.edu> a écrit :
| > for (int i = 0; i < N; ++i)
| > v[i] = xxxx;
|
| Commentaire : je suis maintenant fortement d'accord avec
| Koenig, surtout pour les débutants : pour les boucles de
| 0 à N-1, et autres qui parcourent toutes les données, la
| condition devrait être i != N pour éviter que des erreurs
| passent inaperçues jusqu'au « moment opportun » :-).

Peux-tu expliquer pourquoi « la condition *devrait* être », et quelles
erreurs ?

Quand on vient d'expliquer à quelqu'un qu'un indice n'est valable que
s'il est positif et strictement plus que petit que la taille du
tableau, alors il me semble que la manière immédiate de dire cela avec
des symboles est

for (int i = 0; i < N; ++i)
// ...

Une fois qu'il est confortable avec ça, on peut lui expliquer les
subtilités plus tard. Mais le but premier du cours, c'est d'apprendre
la programmation à quelqu'un qui n'a pas de pratique préalable.

| Ce n'est qu'un bonne petite habitude à prendre...

Exactement pour quelle raison ? Pédagogiquement,

for (int i = 0; i < N; ++i)

se lit comme il se prononce et est une transcription de ce qu'on vient
d'expliquer au pauvre débutant.

(Le premier cours de BS contient ceci

[This is] Not!

...
* For
- Beginners who want to become language lawyers
...

En d'autres mots, les choses simples doivent rester simples et
s'écrire comme ils s'entendent.

-- Gaby

9 réponses

Avatar
Michel Michaud
Dans news:, Gabriel Dos
"Michel Michaud" writes:

Dans news:, Gabriel Dos
for (int i = 0; i < N; ++i)
v[i] = xxxx;


Commentaire : je suis maintenant fortement d'accord avec
Koenig, surtout pour les débutants : pour les boucles de
0 à N-1, et autres qui parcourent toutes les données, la
condition devrait être i != N pour éviter que des erreurs
passent inaperçues jusqu'au « moment opportun » :-).


Peux-tu expliquer pourquoi « la condition *devrait* être », et
quelles erreurs ?


Je sais qu'on a déjà eu cette discussion. Je sais aussi que
c'est un avis qui ne fait pas l'unanimité. Alors je veux bien
en reparler, mais je t'accorde dès maintenant que tu peux tout
à fait avoir raison de faire comme tu l'entends...

Quand on vient d'expliquer à quelqu'un qu'un indice n'est valable
que s'il est positif et strictement plus que petit que la taille du
tableau, alors il me semble que la manière immédiate de dire cela
avec des symboles est


Tu parles d'invariant, moi je parle de logique (boucle)...


for (int i = 0; i < N; ++i)
// ...


Si tu veux vérifier qu'il est positif et strictement plus petit,
je te conseille un assert(0<=i && i<N); avant chaque v[i]. C'est
une vérification plus formelle que l'expression d'une boucle, qui
ne dit rien de ce qui se passe dans le code contrôlé par le for.
(i pourrait y devenir négatif ou plus grand que N et revenir à
une valeur valide avec de retourner au test du for...)

Pour moi, for (int i = 0; i < N; ++i) indique que je veux sortir
de la boucle quand i<N est faux donc si i >= N. Ce n'est pas aussi
précis que d'écrire i!=N qui indique que j'arrêterai quand i==N.
Avec i!=N, je sais exactement pourquoi je suis sorti et quelle
était la valeur de i. Pas avec i<N. C'est ce que Koenig indique
et que je trouvais intéressant. Moi au départ j'utilisais i!=N
simplement parce que je voulais avoir la même forme de boucle
qu'avec les itérateurs.

Pour ce qui est des erreurs, je pensais à celles qui auraient
justement fait passer la variable de contrôle à une valeur plus
grande que N au lieu de N. J'ai aussi remarqué qu'il semble plus
facile (pour mes élèves) d'utiliser des bornes « un de plus »
que de jouer avec le choix entre < et <=. Tu peux tenter
l'expérience et m'en reparler en essayant cette question auprès
de tes élèves :

Indiquer quelles boucles feront afficher les valeur entre 1 et
100 :

a) for (int i=0; i < 100; ++i) cout << i << 'n';
b) for (int i=0; i <= 100; ++i) cout << i+1 << 'n';
c) for (int i=0; i != 100; ++i) cout << i+1 << 'n';
d) for (int i=1; i <= 100; ++i) cout << i << 'n';
e) for (int i=1; i != 100; ++i) cout << i << 'n';
f) for (int i=1; i < 100; ++i) cout << i << 'n';
g) for (int i=1; i != 101; ++i) cout << i << 'n';

Une fois qu'il est confortable avec ça, on peut lui expliquer les
subtilités plus tard. Mais le but premier du cours, c'est
d'apprendre la programmation à quelqu'un qui n'a pas de pratique
préalable.

Ce n'est qu'un bonne petite habitude à prendre...


Exactement pour quelle raison ? Pédagogiquement,

for (int i = 0; i < N; ++i)

se lit comme il se prononce et est une transcription de ce qu'on
vient d'expliquer au pauvre débutant.


Moi je dirais que ce que je viens d'expliquer c'est qu'on veut
« boucler de 0 à N-1 » non ? Comment tu prononces le for ci-haut
pour ça sonne comme ça ? Bien sûr, on peut lire « de i=0, tant
que i est plus petit que N » et se dire que c'est exactement ce
que ça va nous donner. Mais le cas du != est alors tout aussi
clair, sinon plus, « de i=0, tant que i n'est pas égal à N »...

N.B. Je ne crois pas réussir à te convaincre, je crois que c'est
un cas où il n'y a pas de « vérité ». Par contre, il faut
simplement reconnaître qu'on peut trouver une justification
aux deux possibilités et on sera suffisamment d'accord pour
clore la discussion. Tiens autres justifications : toi tu
fais comme BS, c'est une bien bonne idée. Moi je fais comme
ARK... :-)

--
Michel Michaud
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/



Avatar
Gabriel Dos Reis
"Michel Michaud" writes:

| Dans news:, Gabriel Dos
| > "Michel Michaud" writes:
| >
| >> Dans news:, Gabriel Dos
| >>> for (int i = 0; i < N; ++i)
| >>> v[i] = xxxx;
| >>
| >> Commentaire : je suis maintenant fortement d'accord avec
| >> Koenig, surtout pour les débutants : pour les boucles de
| >> 0 à N-1, et autres qui parcourent toutes les données, la
| >> condition devrait être i != N pour éviter que des erreurs
| >> passent inaperçues jusqu'au « moment opportun » :-).
| >
| > Peux-tu expliquer pourquoi « la condition *devrait* être », et
| > quelles erreurs ?
|
| Je sais qu'on a déjà eu cette discussion.

Yep. Et je crois que tu l'as eue plus souvent avec James qu'avec moi
:-)

| Je sais aussi que
| c'est un avis qui ne fait pas l'unanimité. Alors je veux bien
| en reparler, mais je t'accorde dès maintenant que tu peux tout
| à fait avoir raison de faire comme tu l'entends...

Mais j'espère bien ! ;-p

| > Quand on vient d'expliquer à quelqu'un qu'un indice n'est valable
| > que s'il est positif et strictement plus que petit que la taille du
| > tableau, alors il me semble que la manière immédiate de dire cela
| > avec des symboles est
|
| Tu parles d'invariant, moi je parle de logique (boucle)...

Non, non, pas du tout. Je parle de la simplicité d'expression d'idées.
Tu parles de comment Koenig fait. Mais comme je t'ai indiqué dans le
précédent message, le public auquel on s'adresse n'est pas celui visé
par Koenig.

| > for (int i = 0; i < N; ++i)
| > // ...
|
| Si tu veux vérifier qu'il est positif et strictement plus petit,
| je te conseille un assert(0<=i && i<N); avant chaque v[i]. C'est

(1) Ce n'est pas de ça que je parle.
(2) Mettre assert() dans la boucle ne rend pas la chose plus claire.
(3) assert() est une macro qui peut être desactivée, alors pour la
vérification formelle, bof.

Donc, je crois que là tu donnes des non-raisons.

| une vérification plus formelle que l'expression d'une boucle, qui

Cela n'en est pas. Mais de toute façon, cela importe peu, puisqu'il ne
s'agit pas de la vérification formelle, mais de l'expression de l'idée
qu'on veut visiter le tableau dans l'ordre croissant des indices (et
qu'on a expliqué quelles valeurs étaient acceptables).

| ne dit rien de ce qui se passe dans le code contrôlé par le for.
| (i pourrait y devenir négatif ou plus grand que N et revenir à
| une valeur valide avec de retourner au test du for...)

Bah non. C'est impossible. Si tu as un compilateur qui fait autre
chose, change de compilateur.

| Pour moi, for (int i = 0; i < N; ++i) indique que je veux sortir
| de la boucle quand i<N est faux donc si i >= N.

Et c'est ce qu'on vient d'expliquer au débutant : Visite le tableau
dans l'ordre croissant des indices. NB: L'indexation n'est valable que
pour les valeurs positives et strictement plus petites que la taille
du tableau. Alors si tu lis qu'on sort de la boucle quand i < N est
faux, alors *great!*; c'est presque litéralement ce qu'on a dit.

| Ce n'est pas aussi
| précis que d'écrire i!=N qui indique que j'arrêterai quand i==N.

En réalité, en termes d'expressions d'idées, i != N n'est pas aussi
immédiate que i < N. Sur le plan de la sémantique formelle, les deux
sont équivalent. Mais les undergraduates en première année sans
expérience de programmation préalable font rarement de la sémantique
formelle le deuxième jour.

| Avec i!=N, je sais exactement pourquoi je suis sorti et quelle
| était la valeur de i. Pas avec i<N.

Là, ce raisonnement est faux.

| C'est ce que Koenig indique
| et que je trouvais intéressant. Moi au départ j'utilisais i!=N
| simplement parce que je voulais avoir la même forme de boucle
| qu'avec les itérateurs.

Je peux comprendre ton but. Mais ici, encore une fois, c'est un cours
de programmation pour des débutants et au deuxième cours, on va pas
leur parler d'itérateurs. Par contre on veut qu'ils sachent utiliser
des tableaux pour faire des choses simples. Si je faisais un cours de
de C++ à un niveau DEA par exemple, oui bien sûr le premier jour, je
ferais un rappel bref de la théorie des catégories, des types, puis j'en
arriverais aux concepts et aux templates, puis aux itérateurs avec une
classification beaucoup plus fine que ce qu'on trouve dans la norme ou
la plupart des bouquins, et éventuellement je mentionnerais comment on
peut écrire une boucle for minimaliste abstraite.
Mais, je doute que cette démarche ait quelqu'efficacité sur le public
visé par BS.

Encore une fois, je ne dis pas que ta boucle est fausse. Je justifie
simplement pourquoi je crois que la manière classique est immédiate
pour le public visé.

| Pour ce qui est des erreurs, je pensais à celles qui auraient
| justement fait passer la variable de contrôle à une valeur plus
| grande que N au lieu de N. J'ai aussi remarqué qu'il semble plus
| facile (pour mes élèves) d'utiliser des bornes « un de plus »
| que de jouer avec le choix entre < et <=. Tu peux tenter
| l'expérience et m'en reparler en essayant cette question auprès
| de tes élèves :

Comme j'ai expliqué il n'y a pas longtemps, je n'enseigne pas ici.
(En fait, mes seuls « élèves » sont les élèves en thèse avec BS; et
bientôt les graduates avec qui je fais un groupe d'étude sur la
programmation template. Mais ceux là ont déjà dépassé le stade :-).

Il arrive simplement que presque toujours, je suis d'accord avec
ses choix pédagogiques -- il y a cependant des points vraiment mineurs
sur lesquels on a des avis légèrement différents. On en discute,
chacun justifiant sa vision. Il arrive même que des fois, le lendemain
on change d'avis et qu'on argue pour exactement la position défendue
par l'autre la veille :-)

| Indiquer quelles boucles feront afficher les valeur entre 1 et
| 100 :
|
| a) for (int i=0; i < 100; ++i) cout << i << 'n';
| b) for (int i=0; i <= 100; ++i) cout << i+1 << 'n';
| c) for (int i=0; i != 100; ++i) cout << i+1 << 'n';
| d) for (int i=1; i <= 100; ++i) cout << i << 'n';
| e) for (int i=1; i != 100; ++i) cout << i << 'n';
| f) for (int i=1; i < 100; ++i) cout << i << 'n';
| g) for (int i=1; i != 101; ++i) cout << i << 'n';

Je ferai passer le message à son assistant en cours.

| > Une fois qu'il est confortable avec ça, on peut lui expliquer les
| > subtilités plus tard. Mais le but premier du cours, c'est
| > d'apprendre la programmation à quelqu'un qui n'a pas de pratique
| > préalable.
| >
| >> Ce n'est qu'un bonne petite habitude à prendre...
| >
| > Exactement pour quelle raison ? Pédagogiquement,
| >
| > for (int i = 0; i < N; ++i)
| >
| > se lit comme il se prononce et est une transcription de ce qu'on
| > vient d'expliquer au pauvre débutant.
|
| Moi je dirais que ce que je viens d'expliquer c'est qu'on veut
| « boucler de 0 à N-1 » non ? Comment tu prononces le for ci-haut
| pour ça sonne comme ça ?

for all valid increasing values of "i";
do // ...

pour toutes les valeurs valides et croissantes de « i »
faire // ...

| Bien sûr, on peut lire « de i=0, tant
| que i est plus petit que N » et se dire que c'est exactement ce
| que ça va nous donner. Mais le cas du != est alors tout aussi
| clair, sinon plus, « de i=0, tant que i n'est pas égal à N »...

J'évite de faire cela. De la même manière que j'évite de faire du
commentaire qui paraphrase le code.
En fait, il y a fort longtemps, un de mes professeurs de maths (je ne
sais pas si c'était la sixième ou la quatrième) ne lisait jamais
les phrases mathématiques en prononçant les symboles l'un après l'autre --
il n'appelle pas ça « lire » mais « déchiffrer ». Il les lisait en
utilisant des termes assez simples et immédiates. J'ai pris le pli et
c'est devenu un reflexe (pavlovien).

Par exemple, il ne prononce pas

$forall x in A bigmid P(x)$ ...

« quelque soit x dans A tel que P(x) »

mais il lisait plutôt :

Pour tous les éléments x de A possédant la propriété P

De cette manière, on pouvait suivre le raisonnement même si on n'avait
pas les yeux constamment rivés sur la craie.
(Évidemment, ce n'est pas toujours facile de faire de telles phrases,
mais une fois qu'on a pratiqué, ça vient assez vite)

| N.B. Je ne crois pas réussir à te convaincre, je crois que c'est
| un cas où il n'y a pas de « vérité ». Par contre, il faut

Je ne cherche pas « la vérité ». Je suis plus intéressé par une
démarche pédagogique.

| simplement reconnaître qu'on peut trouver une justification
| aux deux possibilités et on sera suffisamment d'accord pour
| clore la discussion.

Si tu as a bien suivi le débat, tu auras remarqué que c'est toi qui
parle de « *devrait* être », alors je dirais que ton commentaire
s'adresse plus à toi qu'à moi :-)

| Tiens autres justifications : toi tu
| fais comme BS, c'est une bien bonne idée. Moi je fais comme
| ARK... :-)

En ce qui me concerne, il ne s'agit pas de suivisme (BS et moi avons
des avis différents sur d'autres points) mais simplement d'une
démarche pédagogique en face d'un public donné. Le public de BS n'est
pas exactement celui de ARK et vice versa.

-- Gaby
Avatar
kanze
"Michel Michaud" wrote in message
news:<G%jSb.41922$...
Dans news:, Gabriel Dos
"Michel Michaud" writes:

Dans news:, Gabriel Dos
for (int i = 0; i < N; ++i)
v[i] = xxxx;


Commentaire : je suis maintenant fortement d'accord avec Koenig,
surtout pour les débutants : pour les boucles de 0 à N-1, et autres
qui parcourent toutes les données, la condition devrait être i != N
pour éviter que des erreurs passent inaperçues jusqu'au « moment
opportun » :-).


Peux-tu expliquer pourquoi « la condition *devrait* être », et
quelles erreurs ?


Je sais qu'on a déjà eu cette discussion. Je sais aussi que c'est un
avis qui ne fait pas l'unanimité. Alors je veux bien en reparler, mais
je t'accorde dès maintenant que tu peux tout à fait avoir raison de
faire comme tu l'entends...


Je crois que c'est avec moi que tu l'as eu, et non avec Gaby. (Je ne
sais pas ce qui se passe en ce moment, mais ça fait plusieurs fois de
suite que je me trouve d'accord avec Gaby.)

Quand on vient d'expliquer à quelqu'un qu'un indice n'est valable
que s'il est positif et strictement plus que petit que la taille du
tableau, alors il me semble que la manière immédiate de dire cela
avec des symboles est


Tu parles d'invariant, moi je parle de logique (boucle)...


for (int i = 0; i < N; ++i)
// ...


Si tu veux vérifier qu'il est positif et strictement plus petit, je te
conseille un assert(0<=i && i<N); avant chaque v[i].


On peut vouloir aller dans une certaine direction sans vouloir aller aux
extrèmes.

C'est une vérification plus formelle que l'expression d'une boucle,
qui ne dit rien de ce qui se passe dans le code contrôlé par le for.
(i pourrait y devenir négatif ou plus grand que N et revenir à une
valeur valide avec de retourner au test du for...)


On ne modifie pas la variable de contrôle d'un for dans la boucle.

Pour moi, for (int i = 0; i < N; ++i) indique que je veux sortir de la
boucle quand i<N est faux donc si i >= N.


Est-ce que tu penses qu'il veut continuer dans la boucle si i > N ?

Ce n'est pas aussi précis que d'écrire i!=N qui indique que
j'arrêterai quand i==N. Avec i!=N, je sais exactement pourquoi je suis
sorti et quelle était la valeur de i.


C'est donc un espèce d'invariant sur ce qui suit la boucle. L'idée vaut
la peine d'être considérée.

L'argument serait plus fort si i existait encore après la boucle.
Exprimer une garantie sur la valeur d'une variable qui n'existe plus ne
me semble pas particulièrement utile:-).

Pas avec i<N. C'est ce que Koenig indique et que je trouvais
intéressant. Moi au départ j'utilisais i!=N simplement parce que je
voulais avoir la même forme de boucle qu'avec les itérateurs.

Pour ce qui est des erreurs, je pensais à celles qui auraient
justement fait passer la variable de contrôle à une valeur plus grande
que N au lieu de N. J'ai aussi remarqué qu'il semble plus facile (pour
mes élèves) d'utiliser des bornes « un de plus » que de jouer avec le
choix entre < et <=. Tu peux tenter l'expérience et m'en reparler en
essayant cette question auprès de tes élèves :

Indiquer quelles boucles feront afficher les valeur entre 1 et
100 :

a) for (int i=0; i < 100; ++i) cout << i << 'n';
b) for (int i=0; i <= 100; ++i) cout << i+1 << 'n';
c) for (int i=0; i != 100; ++i) cout << i+1 << 'n';
d) for (int i=1; i <= 100; ++i) cout << i << 'n';
e) for (int i=1; i != 100; ++i) cout << i << 'n';
f) for (int i=1; i < 100; ++i) cout << i << 'n';
g) for (int i=1; i != 101; ++i) cout << i << 'n';


Je crois que tout le monde serait d'accord que la seule façon
« correcte » d'écrire ce code, c'est d.

Mais c'est un autre problème.

Une fois qu'il est confortable avec ça, on peut lui expliquer les
subtilités plus tard. Mais le but premier du cours, c'est
d'apprendre la programmation à quelqu'un qui n'a pas de pratique
préalable.

Ce n'est qu'un bonne petite habitude à prendre...


Exactement pour quelle raison ? Pédagogiquement,

for (int i = 0; i < N; ++i)

se lit comme il se prononce et est une transcription de ce qu'on
vient d'expliquer au pauvre débutant.


Moi je dirais que ce que je viens d'expliquer c'est qu'on veut
« boucler de 0 à N-1 » non ?


Ce n'est pas vraiment comme ça que je l'entends. On veut boucler sur
tous les éléments d'un tableau de N éléments.

Si les élèves n'ont pas encore compris ce que c'est qu'un intervalle
sémi-ouvert, c'est perdu d'avance.

Comment tu prononces le for ci-haut pour ça sonne comme ça ? Bien sûr,
on peut lire « de i=0, tant que i est plus petit que N » et se dire
que c'est exactement ce que ça va nous donner. Mais le cas du != est
alors tout aussi clair, sinon plus, « de i=0, tant que i n'est pas
égal à N »...


Je crois qu'on doit le voir un peu plus abstraitement. On veut itérer
sur un intervalle. Sur le côté fermé, la condition est <= ou >=. Sur le
côté ouvert, < ou >. Pour un tableau C++, donc, on a 0 <= i < N. Quand
on fait une comparaison, donc, on compare avec < N ou >= 0.

Le problème se complique pour les boucles déscendantes, parce que
l'affectation, ça établit toujours un rapport == (et donc <= et >=, mais
pas < ou >). L'initialization ne peut se faire donc que sur un côté
fermé. Moi, j'avais toujours cru que la solution classique, connue et
utilisée par tout le monde, c'était donc de maintenir l'indice décalée
d'un, c-à-d d'écrire « for ( int i = N ; i > 0 ; -- i ) » et d'utiliser
i-1 comme indice, mais des discussions récentes en
comp.lang.c++.moderated me font penser que c'était plutôt une idée à
moi. Enfin, pas seulement à moi, parce que Stepanov semble avoir eu la
même idée quand il a conçu les reverse_iterators.

N.B. Je ne crois pas réussir à te convaincre, je crois que c'est
un cas où il n'y a pas de « vérité ». Par contre, il faut
simplement reconnaître qu'on peut trouver une justification
aux deux possibilités et on sera suffisamment d'accord pour
clore la discussion. Tiens autres justifications : toi tu
fais comme BS, c'est une bien bonne idée. Moi je fais comme
ARK... :-)


Je ne sais pas. Si Gaby ET moi sont d'accord, comment peut-on douter:-).

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16




Avatar
Michel Michaud
Dans news:, Gabriel Dos
"Michel Michaud" writes:

Dans news:, Gabriel Dos
Quand on vient d'expliquer à quelqu'un qu'un indice n'est valable
que s'il est positif et strictement plus que petit que la taille
du tableau, alors il me semble que la manière immédiate de dire
cela avec des symboles est


Tu parles d'invariant, moi je parle de logique (boucle)...


Non, non, pas du tout. Je parle de la simplicité d'expression
d'idées.


Je ne suis pas certain de te suivre...

Tu parles de comment Koenig fait. Mais comme je t'ai indiqué dans le
précédent message, le public auquel on s'adresse n'est pas celui
visé par Koenig.


Si tu le dis. Il faudrait que tu me donnes une définition de ton
public, je l'enverrais ensuite à Koenig pour voir ce qu'il en pense.
Évidemment je ne peux ni parler à ta place, ni parler pour lui.

for (int i = 0; i < N; ++i)
// ...


Si tu veux vérifier qu'il est positif et strictement plus petit,
je te conseille un assert(0<=i && i<N); avant chaque v[i]. C'est


(1) Ce n'est pas de ça que je parle.


Tu sais bien que je ne comprends jamais de quoi tu parles. Ça
permet d'allonger nos discussions... :-)

(2) Mettre assert() dans la boucle ne rend pas la chose plus
claire. (3) assert() est une macro qui peut être desactivée,
alors pour la vérification formelle, bof.


On veut quoi exactement là ? Exprimer une idée clairement ? Celle
que la boucle devrait être avec < ? Alors oui, c'est clair ainsi.
J'indiquais simplement qu'il y a d'autres choses qu'on peut
vouloir rendre claires, comme le fait qu'on veut quitter la
boucle quand i!=N n'est plus vrai. Ton idée n'est pas moins bonne
que la mienne et la mienne n'est pas moins bonne que la tienne à
moins d'expliquer ce qui est différent. On a deux idées différentes
à exprimer, les deux me paraissent aussi claires écrites de la
façon qui convient (< ou !=). Je dis qu'il y a un intérêt de plus
avec !=, car on sait la valeur finale qui a fait quitter la boucle.
Il y a forcément d'autres bons côtés à < et/ou à !=. Ça dépendra donc
de ce qu'on trouve important. Moi, l'avantage cité plus le fait
que != est utilisé avec les itérateurs me font choisir !=. YMMV.

[...]
(i pourrait y devenir négatif ou plus grand que N et revenir à
une valeur valide avec de retourner au test du for...)


Bah non. C'est impossible. Si tu as un compilateur qui fait autre
chose, change de compilateur.


On parle de programmeurs débutants ou pas ici ? Alors laisse-moi
te donner un exemple inspiré d'un code que j'ai vu réellement :

for (int= 0; (comme on veut); ++i)
{
// ...

if (++i < N)
{
if (v[i-1] != v[i])
--i;
}

// ...
}

Du code très laid, que je n'accepte pas, mais les débutants ne
font pas toujours exactement ce qu'on demande.

(Avant que tu demandes, ça n'a rien à voir avec la discussion en
cours et ne justifie ni != ni <, c'est juste pour dire que i peut
varier dans une boucle en C ou C++, eh oui... Alors je ne changerai
pas de compilateur même si un étudiant fait une bêtise, d'accord ?)

Pour moi, for (int i = 0; i < N; ++i) indique que je veux sortir
de la boucle quand i<N est faux donc si i >= N.


Et c'est ce qu'on vient d'expliquer au débutant : Visite le tableau
dans l'ordre croissant des indices. NB: L'indexation n'est valable


C'est le ++i qui fait ça. Je mets ++i même avec i!=N...

que pour les valeurs positives


Je pars de 0 aussi et avec ++i, ce sera le cas...

et strictement plus petites que la taille du tableau. Alors


Là tu dis ce que < dit et tu me diras que < correspond ! Moi
je dirais alors

« et doit s'arrêter quand on atteint la taille du tableau »

Et je prétends que != signifie ça exactement.

[...]
En réalité, en termes d'expressions d'idées, i != N n'est pas aussi
immédiate que i < N.


C'est ton avis, tu y as droit. Moi je crois exactement le contraire.
Quand i!=N est faux, je sais exactement dans quel cas je suis.

Sur le plan de la sémantique formelle, les deux
sont équivalent. Mais les undergraduates en première année sans
expérience de programmation préalable font rarement de la sémantique
formelle le deuxième jour.


Et alors ?

Avec i!=N, je sais exactement pourquoi je suis sorti et quelle
était la valeur de i. Pas avec i<N.


Là, ce raisonnement est faux.


J'aime cette démonstration formelle... Surtout que tu ne dis pas
si c'est la première phrase ou la deuxième que tu contestes...
Si tu trouves un moyen pour que i devienne plus grand sans
passer par N, tu dois changer de compilateurs... :-)

C'est ce que Koenig indique
et que je trouvais intéressant. Moi au départ j'utilisais i!=N
simplement parce que je voulais avoir la même forme de boucle
qu'avec les itérateurs.


Je peux comprendre ton but. Mais ici, encore une fois, c'est un
cours de programmation pour des débutants et au deuxième cours, on
va pas leur parler d'itérateurs.


Et alors ? Au troisième ou au vingtième, on y arrivera peut-être.
Ça aura donné quoi de plus d'apprendre à mettre < ?

Par contre on veut qu'ils sachent utiliser des tableaux pour faire
des choses simples. Si je faisais un cours


Il faudrait mieux qualifier simple pour que je puisse en discuter.

[...]
Comme j'ai expliqué il n'y a pas longtemps, je n'enseigne pas ici.
(En fait, mes seuls « élèves » sont les élèves en thèse avec BS; et
bientôt les graduates avec qui je fais un groupe d'étude sur la
programmation template. Mais ceux là ont déjà dépassé le stade :-).

Il arrive simplement que presque toujours, je suis d'accord avec
ses choix pédagogiques -- il y a cependant des points vraiment
mineurs sur lesquels on a des avis légèrement différents. On en
discute, chacun justifiant sa vision. Il arrive même que des fois,
le lendemain on change d'avis et qu'on argue pour exactement la
position défendue par l'autre la veille :-)


C'est très intéressant, c'est une démarche normale quand on commence
à enseigner. L'expérience montre souvent que ce qui paraissait la
bonne façon ou solution ne passe pas nécessairement ensuite.

Mais justement, peux-tu un instant considérer que ça fait plus de
20 ans que je fais ce métier et que j'ai travaillé avec des gens
qui l'ont fait encore plus longtemps ? Peut-être que je pourrais
vous aider pédagogiquement...

[...]
N.B. Je ne crois pas réussir à te convaincre, je crois que c'est
un cas où il n'y a pas de « vérité ». Par contre, il faut


Je ne cherche pas « la vérité ». Je suis plus intéressé par une
démarche pédagogique.


C'est exactement de ça dont je peux parler avec « autorité ». Pour
le reste, je laisserais ça à James. J'ai découvert bien des choses
depuis 20 ans. Des choses pas toujours évidentes et des techniques
pour aider les élèves à comprendre la programmation. C'est parce
que j'ai réfléchi là-dessus et expérimenté beaucoup que j'ai écrit
des livres, afin d'aider les profs qui commencent ou qui cherchent
une façon de faire qui fonctionne bien.

--
Michel Michaud
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/



Avatar
Michel Michaud
Dans news:,
On ne modifie pas la variable de contrôle d'un for dans la boucle.


Bien sûr. Tout comme on ne fait pas la guerre pour rien... :-)

On parle d'élèves et d'apprentissage ici.

Pour moi, for (int i = 0; i < N; ++i) indique que je veux sortir
de la boucle quand i<N est faux donc si i >= N.


Est-ce que tu penses qu'il veut continuer dans la boucle si i > N ?


Si i > N, anything goes, il y a une erreur dans le programme. Je
préfère continuer si ça permet de mieux m'en rendre compte...

Ce n'est pas aussi précis que d'écrire i!=N qui indique que
j'arrêterai quand i==N. Avec i!=N, je sais exactement pourquoi je
suis sorti et quelle était la valeur de i.


C'est donc un espèce d'invariant sur ce qui suit la boucle. L'idée
vaut la peine d'être considérée.

L'argument serait plus fort si i existait encore après la boucle.
Exprimer une garantie sur la valeur d'une variable qui n'existe
plus ne me semble pas particulièrement utile:-).


Le i n'existe pas, mais la condition de sortie reste vrai. Par
ailleurs, il arrive qu'on ne déclare pas la variable localement.

int indice;

for (indice=0 ; i!=N && !EstCeQueJeCherche(v[i]); ++i)
{}

if (i==N)
cout << "Pas trouvé ce que je cherchais";
else
cout << "Trouvé à " << indice;

[...]
Indiquer quelles boucles feront afficher les valeur entre 1 et
100 :

a) for (int i=0; i < 100; ++i) cout << i << 'n';
b) for (int i=0; i <= 100; ++i) cout << i+1 << 'n';
c) for (int i=0; i != 100; ++i) cout << i+1 << 'n';
d) for (int i=1; i <= 100; ++i) cout << i << 'n';
e) for (int i=1; i != 100; ++i) cout << i << 'n';
f) for (int i=1; i < 100; ++i) cout << i << 'n';
g) for (int i=1; i != 101; ++i) cout << i << 'n';


Je crois que tout le monde serait d'accord que la seule façon
« correcte » d'écrire ce code, c'est d.


Je serais d'accord, mais curieusement c semble plus simple à
plusieurs...

[...]
Moi je dirais que ce que je viens d'expliquer c'est qu'on veut
« boucler de 0 à N-1 » non ?


Ce n'est pas vraiment comme ça que je l'entends. On veut boucler sur
tous les éléments d'un tableau de N éléments.


Oui... dont les indices varient de 0 à N-1...

Si les élèves n'ont pas encore compris ce que c'est qu'un intervalle
sémi-ouvert, c'est perdu d'avance.


Mais justement ! i=0 au départ donc i==0 au départ, par contre on
ne veut pas i==N comme indice...

[...]
Je crois qu'on doit le voir un peu plus abstraitement. On veut
itérer sur un intervalle. Sur le côté fermé, la condition est <= ou
=. Sur le côté ouvert, < ou >. Pour un tableau C++, donc, on a 0
<= i < N. Quand on fait une comparaison, donc, on compare avec < N

ou >= 0.


Sans vouloir t'offusquer, il m'apparaît clairement tu décris comment
tu penses; c'est normal, je m'attends bien à ce que tu sois de ton
avis ! Mais peux-tu un instant voir qu'il y a d'autres façons de
penser ? Si oui, tu verras que ce que je dis se tient tout autant.
Ce n'est pas la même chose, mais ça se tient tout autant.

Le problème se complique pour les boucles déscendantes, parce que
l'affectation, ça établit toujours un rapport == (et donc <= et >=,
mais pas < ou >). L'initialization ne peut se faire donc que sur un
côté fermé. Moi, j'avais toujours cru que la solution classique,
connue et utilisée par tout le monde, c'était donc de maintenir


Il t'arrive souvent de décrire ce que tu as vu comme si c'était
ce que tout le monde fait... Je ne saurais pour ma part prétendre
savoir ce que tout le monde fait. Je peux seulement dire ce que
je vois dans les livres de personnes bien considérés et sur les
forums comme clc++m... Je te dirais quand même que j'ai certainement
vu plus de programmeurs faire la même chose que moi, que toi tu
n'en as vu dans toute ta vie faire du C++ (bon, c'est parce qu'il
n'avait pas le choix, mais tout de même ! :-)

l'indice décalée d'un, c-à-d d'écrire « for ( int i = N ; i > 0 ;
-- i ) » et d'utiliser i-1 comme indice, mais des discussions


Tiens tu vois que tu penses comme ma solution c ci-haut :-)

--
Michel Michaud
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/


Avatar
Samuel Krempp
le Tuesday 03 February 2004 03:05, écrivit :

Pour moi, for (int i = 0; i < N; ++i) indique que je veux sortir
de la boucle quand i<N est faux donc si i >= N.


Et c'est ce qu'on vient d'expliquer au débutant : Visite le tableau
dans l'ordre croissant des indices. NB: L'indexation n'est valable


C'est le ++i qui fait ça. Je mets ++i même avec i!=N...


oui mais i!=N est inutilement explicite.
Si on veut visiter un élément sur 2, on mets i+=2,
et la condition définissant implicitement les i valides reste inchangé, par
contre toi tu seras obligé de chercher quel sera le dernier indice à
tester.
La condition implicite est plus universelle et plus agréable (en tout cas
pour les esprits minimalistes :)

si la boucle se complique encore et qu'on a besoin maintenant de
i += (int) ceil(i*1.12);
la condition i<N est toujours aussi valide,
alors qu'il devient compliqué de trouver le test d'égalité à tester
précisément (et que ce serait de toute façon maladroit de tester une
égalité dans ce cas..)

--
Sam



Avatar
kanze
"Michel Michaud" wrote in message
news:<cBDTb.6717$...
Dans news:,

On ne modifie pas la variable de contrôle d'un for dans la boucle.


Bien sûr. Tout comme on ne fait pas la guerre pour rien... :-)


Et pourquoi penses-tu que je suis parti des États-unis ?

Mais je ne mets pas la modification de la variable de contrôle d'un for
au même niveau que faire la guerre.

On parle d'élèves et d'apprentissage ici.


Mais on parlait de ce qu'on *doit* faire.

Pour moi, for (int i = 0; i < N; ++i) indique que je veux sortir de
la boucle quand i<N est faux donc si i >= N.


Est-ce que tu penses qu'il veut continuer dans la boucle si i > N ?


Si i > N, anything goes, il y a une erreur dans le programme. Je
préfère continuer si ça permet de mieux m'en rendre compte...


En effet. Si ça permet de mieux s'en rendre compte...

Dans la pratique, il y a assez de possibilités d'erreur, quelque soit la
façon d'écrire. Ni i < N, ni i != N vont detecter les erreurs. La seule
différence, dans ce contexte, c'est le message que ça donne à celui qui
lit le programme.

Ce n'est pas aussi précis que d'écrire i!=N qui indique que
j'arrêterai quand i==N. Avec i!=N, je sais exactement pourquoi je
suis sorti et quelle était la valeur de i.


C'est donc un espèce d'invariant sur ce qui suit la boucle. L'idée
vaut la peine d'être considérée.

L'argument serait plus fort si i existait encore après la boucle.
Exprimer une garantie sur la valeur d'une variable qui n'existe plus
ne me semble pas particulièrement utile:-).


Le i n'existe pas, mais la condition de sortie reste vrai. Par
ailleurs, il arrive qu'on ne déclare pas la variable localement.

int indice;

for (indice=0 ; i!=N && !EstCeQueJeCherche(v[i]); ++i)
{}

if (i==N)
cout << "Pas trouvé ce que je cherchais";
else
cout << "Trouvé à " << indice;


Certains (Andy Koenig, je crois) dirait que dans ce cas-là, il ne faut
pas utiliser un for. Moi, je l'écris pareil, sauf avec < et >= -- si i
est >= N, je n'ai pas trouvé ce que je cherche.

En fait, il y a plusieurs informations intéressantes. Pour commencer,
i >= 0 && i < N signifie que i est une indice valide du tableau. Mais
c'est aussi intéressant, probablement, que si i n'est pas une indice
valide, j'ai bien testé toutes les indices valides, sans trouver ce que
j'ai cherché. Et peut-être même, que si i est une indice valide, aucune
indice plus petite ne convient (alors qu'il peut y avoir des indices
supérieur qui conviendrait aussi).

À la fin, tu ne peux pas tout dire par le code.

[...]
Indiquer quelles boucles feront afficher les valeur entre 1 et
100 :

a) for (int i=0; i < 100; ++i) cout << i << 'n';
b) for (int i=0; i <= 100; ++i) cout << i+1 << 'n';
c) for (int i=0; i != 100; ++i) cout << i+1 << 'n';
d) for (int i=1; i <= 100; ++i) cout << i << 'n';
e) for (int i=1; i != 100; ++i) cout << i << 'n';
f) for (int i=1; i < 100; ++i) cout << i << 'n';
g) for (int i=1; i != 101; ++i) cout << i << 'n';


Je crois que tout le monde serait d'accord que la seule façon
« correcte » d'écrire ce code, c'est d.


Je serais d'accord, mais curieusement c semble plus simple à
plusieurs...


Il ne s'agit pas ce qui est plus simple, mais ce qui exprime l'énoncé le
plus clairement. Si l'énnoncé, c'est d'afficher toutes les valeurs dans
l'intervalle fermé de 1 à 100, j'ai du mal à voir comment on pourrait
trouver que c s'approche plus de cet énnoncé que d.

[...]
Moi je dirais que ce que je viens d'expliquer c'est qu'on veut
« boucler de 0 à N-1 » non ?


Ce n'est pas vraiment comme ça que je l'entends. On veut boucler sur
tous les éléments d'un tableau de N éléments.


Oui... dont les indices varient de 0 à N-1...


Ou dont les indices sont dans l'intervalle mi-ouvert de [0;N[.

C'est la formulation traditionnelle en C. C'est une formulation que
j'approuve -- je n'ai jamais trop aimé la formulation Pascal sur
intervalle fermé.

Mais c'est une formulation traditionnelle. Un programme C qui utilise
des conventions du genre :

T array[ N - 1 ] ;
for ( int i = 0 ; i <= N ; ++ i ) ...

est aussi correct. Pas du tout idiomatique, et à mon avis, pas du tout
aussi robuste, mais tout à fait correct. (Et je me démande si la
robustesse de la formulation que je préfère ne dépend pas au moins en
partie du fait que c'est idiomatique.)

Si les élèves n'ont pas encore compris ce que c'est qu'un intervalle
sémi-ouvert, c'est perdu d'avance.


Mais justement ! i=0 au départ donc i==0 au départ, par contre on ne
veut pas i==N comme indice...


Ni i == N+1, ni i == N+2, ni ...

[...]
Je crois qu'on doit le voir un peu plus abstraitement. On veut
itérer sur un intervalle. Sur le côté fermé, la condition est <= ou
=. Sur le côté ouvert, < ou >. Pour un tableau C++, donc, on a 0 < > > i < N. Quand on fait une comparaison, donc, on compare avec < N ou
= 0.



Sans vouloir t'offusquer, il m'apparaît clairement tu décris comment
tu penses; c'est normal, je m'attends bien à ce que tu sois de ton
avis ! Mais peux-tu un instant voir qu'il y a d'autres façons de
penser ?


Certainement. Mais je ne saurais pas les décrire.

Je trouve que cette façon de pensée donne de bonnes règles générales. Je
ne suis pas sûr, en revanche, que je l'enseignerais au début ; c'est
peut-être un peu trop abstrait. Mais je ne sais pas. Je ne suis pas
enseignant. (Et sans doute, ça dépend aussi des élèves, et le but de
l'enseignement. Dans un cursus informatique et mathématiques appliquées,
menant à un diplôme universitaire, j'imagine que l'abstraction ne doit
pas poser un problème.)

Le but de la description, ce n'est pas de dire que c'est un absolu,
qu'il n'y a pas d'autre solution. Le but, ici en tout cas, c'est
d'essayer de prendre un peu de récul, et de voir le problème dans un
contexte plus général. Suggérer, d'ailleur, par le problème d'itérer sur
des entiers d'1 à 100, si dessus. Je trouve une règle plus générale, qui
couvre et ce cas, et le cas des indices de tableau.

Si oui, tu verras que ce que je dis se tient tout autant. Ce n'est pas
la même chose, mais ça se tient tout autant.


Mais je n'ai pas vu où tu as essayé de présenter une abstraction. Je ne
doute pas du tout qu'il y a d'autres abstractions possibles. Et je ne
sais pas vraiment s'il faut un tel niveau d'abstraction dans ce cas-ci.
C'est toi qui a présenté le problème d'itération sur l'intervalle 1 à
100. Alors, j'essaie à unifier les deux problèmes.

Le problème se complique pour les boucles déscendantes, parce que
l'affectation, ça établit toujours un rapport == (et donc <= et >=,
mais pas < ou >). L'initialization ne peut se faire donc que sur un
côté fermé. Moi, j'avais toujours cru que la solution classique,
connue et utilisée par tout le monde, c'était donc de maintenir


Il t'arrive souvent de décrire ce que tu as vu comme si c'était ce que
tout le monde fait...


La plupart du temps ironiquement. Je sais bien, par exemple, que la
plupart des gens ne pensent jamais des pré- et des post-conditions d'une
fonction, et que la vaste majorité ne savent même pas que close peut
échouer, avec une perte de données.

Sinon, c'est à prendre comme une technique rhétorique. Ici, il s'agit
d'une discussion entre toi, moi, et Gaby. Nous avons tous assez
d'expérience pour savoir ce qui est une nécessité de base, et ce qui est
une question de style ou de préférence personnelle. Il y a bien des cas
limites, mais ceci n'en fait pas partie (je crois que tu en seras
d'accord). AMA, c'est tellement évident qu'on ne parle que de nos
préférences personnelles qu'il ne me semblait pas la peine d'ajouter des
AMHA sur toutes les phrases.

En fait, j'irais plus loin -- j'argue plutôt pour reflechir que d'une
conviction profonde. L'idiome classique, depuis les premiers jours de C,
c'était bien i<N. Ne serait-ce que parce que c'est ce que faisait
Kernighan et Richie. N'ayant pas vu de motivation particulière à le
récuser, je l'ai adopté ; j'écris mes boucles comme ça depuis prèsque
vingt ans (et comme j'ai dit, je le préfère nettement à l'autre
alternatif que j'avais vu, le i<=N-1 de Pascal).

Maintenant, tu viens, et tu me dis que ce n'est pas bien. Qu'il y a des
raisons concrètes (en dehors de la tradition) pour préférer un autre
style. Alors, je refléchis sur la question. Pour conclure que tes
raisons ne sont pas aussi concluantes que ça. Et qu'il y a aussi des
raisons techniques (en dehors de la tradition) pour préférer ce que j'ai
toujours fait.

Ceci dit, je trouve que dans les deux cas, les raisons techniques sont
bien faibles ; qu'elles ne valent pas assez pour rompre avec la
tradition. La tradition, en fin de compte, c'est ce que le lecteur du
code s'attend à voir. Si tu fais autrement, le lecteur commence par
poser la question « pourquoi » ? Qu'est-ce qu'il y a de particulier qui
fait que tu fais différemment.

Maintenant, il faut bien dire que les traditions dépend d'où tu te
situes. Et qu'elles peuvent aussi évoluer. Moi, je viens de C, et j'ai
toujours vu i<N. Toujours. Mais je conçois bien que sous l'influence de
la STL, à la longue, il se développe une autre tradition en C++. Ou à la
place de, ou à côté de la tradition C. Et le jour où je me trouve dans
une boîte où les autres écrivent tous i!=N, moi aussi, j'écrirai i!=N.
C'est une question où, pour moi, l'uniformité est plus importante que
les arguments techniques (ou où les arguments techniques sont tellement
faibles qu'ils n'arrivent pas à s'imposer, si tu préfères).

Je ne saurais pour ma part prétendre savoir ce que tout le monde fait.


Tout le monde, peut-être pas. Mais quand on a fait autant de boîtes que
j'ai fait, et qu'on a vu la même chose dans toutes ces boîtes, on
commence bien à penser que les autres choses, ce sont des exceptions.

Je peux seulement dire ce que je vois dans les livres de personnes
bien considérés et sur les forums comme clc++m... Je te dirais quand
même que j'ai certainement vu plus de programmeurs faire la même chose
que moi, que toi tu n'en as vu dans toute ta vie faire du C++ (bon,
c'est parce qu'il n'avait pas le choix, mais tout de même ! :-)


Je ne sais pas. Combien as-tu vu qui le faisait avant la STL ?

C'est un peu comme l'histoire de ++i ou i++. En C, et avant la STL en
C++, j'ai toujours vue i++ (quand on ne se servait pas du résultat).
Sans doute pour la simple raison que c'est ce que faisait Kernighan et
Ritchie. Aujourd'hui, on décerne une nette préférence pour ++i. Et
quoiqu'on dise, les raisons réelement techniques y sont pour peu, au
moins si je peux crois aux benchmarks que j'ai fait. Mais qu'importe.
Comme j'ai dit, les traditions changent. Et ++i est certainement la
tradition de l'avenir -- dans un nouveau projet, c'est sans doute la
convention que j'adopterai, ne serait-ce que pour éviter les discussions
avec les gens qui sont convaincu que i++ est mauvais.

l'indice décalée d'un, c-à-d d'écrire « for ( int i = N ; i > 0 ;
-- i ) » et d'utiliser i-1 comme indice, mais des discussions


Tiens tu vois que tu penses comme ma solution c ci-haut :-)


Non. J'applique un idiome que j'ai vu au début de mon apprentissage en
C, et que je croyais à peu près universel. Je n'y pense rien ; j'imite
aveuglement.

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16



Avatar
Michel Michaud
Dans news:401f8b6d$0$25440$, Samuel
le Tuesday 03 February 2004 03:05, écrivit :

Pour moi, for (int i = 0; i < N; ++i) indique que je veux sortir
de la boucle quand i<N est faux donc si i >= N.


Et c'est ce qu'on vient d'expliquer au débutant : Visite le
tableau dans l'ordre croissant des indices. NB: L'indexation
n'est valable


C'est le ++i qui fait ça. Je mets ++i même avec i!=N...


oui mais i!=N est inutilement explicite.


« inutilement explicite », un nouvel argument ! :-)

Si on veut visiter un élément sur 2, on mets i+=2,
et la condition définissant implicitement les i valides reste
inchangé, par contre toi tu seras obligé de chercher quel sera le
dernier indice à tester.


Pas toi ? C'est ça que tu dis ? Si tu avais mis ++i et que tu
mets +=2, je crois que tu devras réfléchir pour savoir si tu
traiteras toutes les valeurs désirées. C'est un gros changement
à la logique d'un programme.

Moi, si j'écris !=N c'est que je veux arrêter quand j'arrive là
(à N). Si c'est une boucle sur des nombres 2 par 2, je devrai
réfléchir où je veux me rendre. Le fait que < arrêtera « à un
moment ou un autre » ne m'impressionne guère et ne me semble
donc d'aucune utilité.

Par ailleurs, je signale que je n'ai jamais dit qu'il faut mettre
le != dans toutes les boucles. Si la condition que je veux tester
est <, je mettrai volontier <. Je répète (encore) que l'idée est
simplement d'indiquer à quoi je pense pour des itérations dans
[X, N[ (pour reprendre l'idée de James), qui est qu'il faut
arrêter quand on arrive à N. Si cette idée n'est pas celle
inscrite dans l'esprit de quelqu'un, alors != n'a aucun sens.
Par contre, il est nécessaire de la comprendre si on veut
pouvoir utiliser les itérateurs : on arrête quand on arrive à
end(). Alors je prétends qu'on peut la comprendre aussi pour
entier et appliquer la même logique sans difficulté.

La condition implicite est plus universelle et plus agréable (en
tout cas pour les esprits minimalistes :)


Plus universelle ? Je ne vois pas, je peux trouver des cas où
!= est nécessaire. Plus agréable ? Là j'avoue que pour ceux qui
sont habitués à < (et ne veulent pas en changer sans se battre
d'abord :-), c'est plus rassurant de voir <. Mais même si je ne
trouve rien d'agréable à l'emploi des itérateurs dans list, je
ne commencerai pas à dire que ce serait mieux autrement et que
je n'utiliserai pas ce qui existe...

si la boucle se complique encore et qu'on a besoin maintenant de
i += (int) ceil(i*1.12);
la condition i<N est toujours aussi valide,


Ah ? Vraiment ? Moi avec des réels, je réfléchirais vraiment au
cas particulier à l'étude. Et je suis loin d'être certain que
mettre < sera toujours ce que je voudrai. Je ne dis pas que je
mettrai != ou même <=, mais peut-être que j'aurai à tester du
genre abs((i-N)/N) < epsilon... Encore une fois, si je trouve que
la condition est <, je n'aurai aucune difficulté à l'écrire. Mais
penser que < est universel, ça me semble très très risqué. Tu
viens de me donner une raison de plus de ne pas l'employer en
général !

alors qu'il devient compliqué de trouver le test d'égalité à tester
précisément (et que ce serait de toute façon maladroit de tester une
égalité dans ce cas..)


Pour la dernière fois, je n'ai jamais dit que toutes les boucles
devaient être écrite avec !=. Seulement celles où c'est « ce qu'il
faut ». Et je prétends que pour itérer jusqu'à une borne supérieure
entière non comprise, != est naturel, correct et permet d'éviter
de camoufler des erreurs.

Mais je comprends bien qu'il est inutile d'essayer de convaincre
les gens sur des points de religion comme celui-là. Aussi bien
discuter de la vraie bonne position des accolades ! :-)

--
Michel Michaud
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/




Avatar
Michel Michaud
Dans news:,
"Michel Michaud" wrote in message
news:<cBDTb.6717$...
On parle d'élèves et d'apprentissage ici.


Mais on parlait de ce qu'on *doit* faire.


Je crois qu'on est plutôt rendu à parler de ce qu'on peut montrer
et de ce qu'on peut y comprendre. Je ne crois pas qu'on puisse
trouver ce qu'on *doit* faire. Je peux seulement dire ce que *je*
pense qu'on doit faire ou indiquer ce que d'autres pensent.

[...]
Ou dont les indices sont dans l'intervalle mi-ouvert de [0;N[.

C'est la formulation traditionnelle en C. C'est une formulation que
j'approuve -- je n'ai jamais trop aimé la formulation Pascal sur
intervalle fermé.

Mais c'est une formulation traditionnelle. Un programme C qui
utilise des conventions du genre :

T array[ N - 1 ] ;
for ( int i = 0 ; i <= N ; ++ i ) ...

est aussi correct. Pas du tout idiomatique, et à mon avis, pas du
tout aussi robuste, mais tout à fait correct. (Et je me démande si


Tu es certain ??? :-)

la robustesse de la formulation que je préfère ne dépend pas au
moins en partie du fait que c'est idiomatique.)

Si les élèves n'ont pas encore compris ce que c'est qu'un
intervalle sémi-ouvert, c'est perdu d'avance.


Mais justement ! i=0 au départ donc i==0 au départ, par contre on
ne veut pas i==N comme indice...


Ni i == N+1, ni i == N+2, ni ...


On ne se rendra pas là. Encore une fois, que tu aimes ou non la
STL et maintenant la SL, il faut != pour les itérateurs. Et
l'idée d'arrêter à une certaine « position » est naturelle.

[...]
Sinon, c'est à prendre comme une technique rhétorique. Ici, il
s'agit d'une discussion entre toi, moi, et Gaby. Nous avons tous
assez d'expérience pour savoir ce qui est une nécessité de base, et
ce qui est une question de style ou de préférence personnelle. Il y


C'est pourquoi je parlais bien de ce qui est bien pour les débutants
et fonctionnent aussi pour les autres.

a bien des cas limites, mais ceci n'en fait pas partie (je crois
que tu en seras d'accord). AMA, c'est tellement évident qu'on ne
parle que de nos préférences personnelles qu'il ne me semblait pas
la peine d'ajouter des AMHA sur toutes les phrases.

En fait, j'irais plus loin -- j'argue plutôt pour reflechir que
d'une conviction profonde. L'idiome classique, depuis les premiers
jours de C, c'était bien i<N. Ne serait-ce que parce que c'est ce
que faisait Kernighan et Richie. N'ayant pas vu de motivation
particulière à le récuser, je l'ai adopté ; j'écris mes boucles
comme ça depuis prèsque vingt ans (et comme j'ai dit, je le préfère
nettement à l'autre alternatif que j'avais vu, le i<=N-1 de Pascal).


Je sais que tu ne veux pas changer (inutilement) James. Mais il
y en a qui apprennent aujourd'hui et qui n'ont pas besoin de faire
comme K&R.

Maintenant, tu viens, et tu me dis que ce n'est pas bien. Qu'il y a
des raisons concrètes (en dehors de la tradition) pour préférer un
autre style. Alors, je refléchis sur la question. Pour conclure que
tes raisons ne sont pas aussi concluantes que ça. Et qu'il y a
aussi des raisons techniques (en dehors de la tradition) pour
préférer ce que j'ai toujours fait.


Alors je ne t'ai pas convaincu. Et toi non plus. :-(

Ceci dit, je trouve que dans les deux cas, les raisons techniques
sont bien faibles ; qu'elles ne valent pas assez pour rompre avec la
tradition. La tradition, en fin de compte, c'est ce que le lecteur
du code s'attend à voir. Si tu fais autrement, le lecteur commence
par poser la question « pourquoi » ? Qu'est-ce qu'il y a de
particulier qui fait que tu fais différemment.


Alors en C++, il faudrait revoir les itérateurs ?

Maintenant, il faut bien dire que les traditions dépend d'où tu te
situes. Et qu'elles peuvent aussi évoluer. Moi, je viens de C, et
j'ai toujours vu i<N. Toujours. Mais je conçois bien que sous


Et je suppose que tu as toujours vu i++. Moi pas. Vraiment. Depuis
1983, je mets ++i. Et ce n'est pas moi qui a inventé de faire
comme ça. Tu connais Thomas Plum au moins...

[...]
Je peux seulement dire ce que je vois dans les livres de personnes
bien considérés et sur les forums comme clc++m... Je te dirais
quand même que j'ai certainement vu plus de programmeurs faire la
même chose que moi, que toi tu n'en as vu dans toute ta vie faire
du C++ (bon, c'est parce qu'il n'avait pas le choix, mais tout de
même ! :-)


Je ne sais pas. Combien as-tu vu qui le faisait avant la STL ?


Je faisais une blague James, parce qu'il y des centaines d'élèves
qui ont appris avec moi !

--
Michel Michaud
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/