OVH Cloud OVH Cloud

indentation switch

25 réponses
Avatar
Yalbrieux
Bonsoir,

Pour une question de lisibilité, j'ai l'habitude d'écrire les séquences
switch ainsi :

switch(..) {
case ... : {
... ;
break ;
}
...
}

(L'éditeur n'est évidemment pas d'accord avec cette indentation)

Qu'en pensez-vous ?
Yves

10 réponses

1 2 3
Avatar
Gabriel Dos Reis
drkm writes:

[...]

| > Note aussi que j'utilise un style rigueureusement SESO ; il n'y aura
| > donc jamais de break dans les {}.
|
| SESO ?

SESE: Single Entry, Single Exit.

-- Gaby
Avatar
Jean-Noël Mégoz
"Michel Michaud" a écrit dans le message de
news:SnvXc.30377$
En fait, je pense que si tu as besoin d'une variable dans le
bloc du switch, il vaut mieux appeler une fonction. Je crois
que mon switch idéal a toujours une seule instruction par
case, très semblable dans tous les cas.


Tout à fait !
C'est pourquoi mes switches ont en fait généralement l'aspect :

switch(...)
{
case 1 : cas1(); break;
case 2 : cas2(); break;
case 3 : cas3(); break;
default : casX(); // doit-on pousser le vice à mettre un break ici
aussi ? ;)
}

...ce qui va à l'encontre de la plupart des règles d'indentation
généralement admises, mais à le mérite d'une grande facilité de lecture !

Avatar
Yalbrieux
Merci à tous pour ce fil très intéressant et ces échanges de points de vues.
Bonne soirée
Yves
Avatar
Michel Michaud
Dans news:,
Question d'habitude. En général, j'ai l'habitude de mettre le
break en dehors des {}. C-à-d comme si la syntaxe d'un cas


Moi aussi, je mettais le break en dehors dans mon standard de
programmation. Maintenant je dis plutôt de ne pas faire de
bloc dans les case (de mettre une fonction).

[...]
Note aussi que j'utilise un style rigueureusement SESO ; il n'y
aura donc jamais de break dans les {}.


Bien sûr... « une » sortie, pas plus, c'est essentiel :

for(;;)
{
instructions;
/***/
if (cond) break;
/***/
instructions;
}

Mais ça n'empêche pas les break dans les {}... :-)

[...]
J'ai l'impression (et James pourra confirmer, car il a vu plus
de standards de programmation différents que moi) que même
ceux qui mettent des {} dans tous les if/else/while/for n'en
mettent pas systématiquement dans les case... Alors je ne
dirais pas c'est une
« bonne pratique, et généralement acceptée ... ».


La structure et l'indentation varient énormement, mais je n'ai
jamais vu des règles de programmation C++ qui permettaient un
case sans {...}. Or que celles qui les exigent pour les
if/else/while/for sont plutôt l'exception.


Tous les standards que tu connais obligeaient les {} dans les
case ??? Vraiment ??? Même pour des switch hyper simples ?
Même en C ???

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


Avatar
drkm
"Michel Michaud" writes:

Dans news:,

La structure et l'indentation varient énormement, mais je n'ai
jamais vu des règles de programmation C++ qui permettaient un
case sans {...}. Or que celles qui les exigent pour les
if/else/while/for sont plutôt l'exception.


Tous les standards que tu connais obligeaient les {} dans les
case ??? Vraiment ??? Même pour des switch hyper simples ?
Même en C ???


Là, tu exagères, tout de même. La phrase suivante de James, que tu
as coupée à l'endroit où tu réponds, était :

En C, c'était plutôt exceptionnel d'exiger les {} dans un case.

Ou c'est encore ton problème de sommeil ?-)

--drkm, en recherche d'un stage : http://www.fgeorges.org/ipl/stage.html


Avatar
Michel Michaud
Dans news:,
"Michel Michaud" writes:
Tous les standards que tu connais obligeaient les {} dans les
case ??? Vraiment ??? Même pour des switch hyper simples ?
Même en C ???


Là, tu exagères, tout de même. La phrase suivante de James,
que tu as coupée à l'endroit où tu réponds, était :

En C, c'était plutôt exceptionnel d'exiger les {} dans un
case.

Ou c'est encore ton problème de sommeil ?-)


Non non, erreur de manipulation. Toutes mes excuses à James.
Merci de m'avoir signalé la chose...

Mais si du code C++ ressemble à s'y méprendre à du code C,
et pour les switch c'est pour moi assez probable, alors faire
une règle différente me surprend de toute façon.

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


Avatar
James Kanze
drkm writes:

|> writes:

|> > "Michel Michaud" wrote in message
|> > news:<SnvXc.30377$...

|> >> Dans news:,

|> >> >> Ceci dit, dans le cas présent, pourquoi alourdir les "case"
|> >> >> avec des accolades alors qu'elles ne sont pas nécessaires ?

|> >> > Tout dépend de ce que représente « ... ». Que dire de :

|> >> > switch ( ... ) {
|> >> > case ... :
|> >> > MyType my_object ;
|> >> > ... ;
|> >> > break ;
|> >> > case ... :
|> >> > MyType my_object ;
|> >> > ... ;
|> >> > break ;
|> >> > }

|> >> > comparé à :

|> >> > switch ( ... ) {
|> >> > case ... : {
|> >> > MyType my_object ;
|> >> > ... ;
|> >> > break ;
|> >> > }
|> >> > case ... : {
|> >> > MyType my_object ;
|> >> > ... ;
|> >> > break ;
|> >> > }
|> >> > }

|> > Que la légalité du premier dépend du type MyType.

|> Ah bon. Je ne savais pas. Je pensais que le premier était illégal,
|> point.

Le premier était légal (et même répandu) en C. On s'arrange donc qu'au
minimum, il soit légal en C++ pour des types légaux en C.

|> Quelle est la règle, ici ? J'ai vu que tu parles plus loin du
|> fait d'avoir un constructeur non-trivial. Est-ce en rapport avec le
|> chemin d'exécution, en plus de la portée identique ?

La règle, c'est qu'entrée dans un bloc en sautant la déclaration d'une
variable (que ce soit par un switch ou au moyen d'un goto) est illégal
si le type dans la déclaration a un constructeur non-trivial. La
logique, c'est que s'il a un constructeur trivial, le code ne peut pas
dépendre sur le fait qu'on a « exécuté » le constructeur:-).

Puisque tous les types possibles en C ont des constructeurs triviaux, la
compatibilité est sauvée.

|> [...]

|> > Question d'habitude. En général, j'ai l'habitude de mettre le
|> > break en dehors des {}. C-à-d comme si la syntaxe d'un cas était :

|> > "case" <constante> ":" "{" statement_list "}" "break" ";"

|> > Ou avec mon indentation habituelle :

|> > case whatever :
|> > {
|> > code ;
|> > }
|> > break ;

|> > L'idée de base, c'est que le break appartient au case, et non au
|> > code régi par le case.

|> Très intéressant.

N'est-ce pas ? Le gag, c'est que quand je regarde le code que j'ai
réelement écrit, les infractions à ma règle sont plus fréquentes que les
instances où j'y ai tenu.

|> > Note aussi que j'utilise un style rigueureusement SESO ; il n'y
|> > aura donc jamais de break dans les {}.

|> SESO ? J'imagine, d'après le contexte, que cela doit signifier
|> quelque chose comme « pas de multiples return ou break, pas de
|> goto ».

« Single entry, Single exit. » En fait, qu'on entre dans chaque bloc
d'en haut, et qu'on sort systèmatiquement d'en bas.

|> > Mais c'est une règle que j'effreinds assez souvent. La plupart des
|> > mes case sont extrèmenent simple : ou bien une seule affectation,
|> > ou bien l'appel d'une fonction.
|> [...]

|> >> Si tu ne mets pas le bloc, dans ce cas-ci, tu auras une erreur.

|> > Seulement si MonType ou MonAutreTypeu a un constructeur non trivial.

|> Quelle est exactement cette règle ? J'aurais dit que l'on ne
|> pouvait pas avoir dans un même bloc deux objets de même noms. Il y
|> aurait donc des exceptions. Quelles sont-elles ?

Je n'avais pas remarqué qu'ils avaient le même nom. En effet, avec le
même nom, le code est illégal. Avec des noms différents, il n'est légal
que si les types ont des constructeurs triviaux.

|> [...]

|> >> En fait, je pense que si tu as besoin d'une variable dans le bloc
|> >> du switch, il vaut mieux appeler une fonction. Je crois que mon
|> >> switch idéal a toujours une seule instruction par case, très
|> >> semblable dans tous les cas. Je sais, on ne peut pas toujours
|> >> avoir l'idéal. :-(

|> > Disons que ou bien, tu n'as qu'une ou deux instructions dans le
|> > switch, ou bien, tu n'as qu'assez peu de case pour que le switch
|> > tient dans une dizaine de lignes.

|> Heu, je n'arrive pas à comprendre cette phrase. À moins que ... En
|> remplaçant le premier « switch » par « case ».

Non. C'est que dans mon code, ou bien, il n'y a qu'une ou deux
instructions maximum dans chaque case, ou bien, le switch entier, avec
tous les case, tient dans une dizaine de lignes. Ce qui veut dire,
évidemment, qu'il n'y a pas beaucoup de case.

|> > Mais je suis comme toi -- j'ai rarement des
|> > case complexe, et malgré les règles, j'ai une tendance à les
|> > écrire sans les {}, simplement parce qu'il ne contient qu'une
|> > seule instruction.

|> > C'est ancien, et ça poserait des problèmes avec mon code actuel,
|> > mais je me rappelle bien d'un compilateur qui appelait
|> > systèmatiquement le destructeur pour tous les temporaires dans le
|> > bloc quand il quittait le bloc. Y compris pour ceux qui était dans
|> > les cases non executés. Donc, même quelque chose d'extrèmement
|> > simple pourrait poser des problèmes s'il n'y avait pas les {}.

|> Plutôt sympa, le compilo ;-)

N'est-ce pas ? Je me rappelle quand j'ai commencé le C++. Après avoir eu
pas mal de problèmes avec les destructeurs qui n'étaient pas appelés
(voir g++ 1.49, par exemple, qui n'appelait pas les destructeurs des
variables locales si on sortait de la fonction par un return), j'ai
écrit un petit programme d'une quarantaine de lignes qui comptait les
appels des constructeurs et des destructeurs. Je l'ai posté sur le
reseau, et il n'y a pas eu un seul compilateur qui en finissait avec le
même nombre de constructeurs et de destructeurs. La plupart du temps,
c'était les destructeurs que le compilateur oubliait, mais dans au moins
trois cas, j'avais des appels aux destructeurs des objets qui n'ont
jamais été construits.

--
James Kanze
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Avatar
James Kanze
"Michel Michaud" writes:

|> > La structure et l'indentation varient énormement, mais je n'ai
|> > jamais vu des règles de programmation C++ qui permettaient un case
|> > sans {...}. Or que celles qui les exigent pour les
|> > if/else/while/for sont plutôt l'exception.

|> Tous les standards que tu connais obligeaient les {} dans les case
|> ??? Vraiment ??? Même pour des switch hyper simples ? Même en C ???

Pas en C (encore que j'en ai vu une qui l'exigeait même en C). Mais bien
en C++.

Il faut dire que dans le temps, la durée de vie des temporaires
n'étaient pas bien figées, et un certain nombre de compilateurs les
maintenait jusqu'à la fin du bloc. (Il y a au moins un compilateur qui
le fait encore, pour éviter de « casser » le code des clients qui y
comptaient.) Et il arrivait alors que le compilateur générait des appels
aux destructeurs de tous les temporaires à la fin du bloc. Y compris
pour les temporaires dans les case qu'on n'a pas exécuté. Alors, le plus
sûr, c'était de *toujours* mettre des {...}.

Ça ne veut pas dire qu'il n'y avait pas effraction à la règle, ni que je
la suis rigueureusement dans mon code personel.

--
James Kanze
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Avatar
James Kanze
"Michel Michaud" writes:

|> Mais si du code C++ ressemble à s'y méprendre à du code C, et pour
|> les switch c'est pour moi assez probable, alors faire une règle
|> différente me surprend de toute façon.

Je n'ai pas fait du C et du C++ dans les mêmes boîtes, ni à la même
époque. Il n'y a donc jamais eu un cas où on avait à la fois des règles
C et des règles C++.

En fait, dans la pratique, la plupart de mes switch aujourd'hui sont
bien dans le code qui pourrait (prèsque) être du C. Et je ne suis pas ma
propre règle très rigueureusement:-).

--
James Kanze
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Avatar
drkm
James Kanze writes:

drkm writes:

|> writes:

|> > Seulement si MonType ou MonAutreTypeu a un constructeur non
|> > trivial.

|> Quelle est exactement cette règle ? J'aurais dit que l'on ne
|> pouvait pas avoir dans un même bloc deux objets de même noms. Il
|> y aurait donc des exceptions. Quelles sont-elles ?

Je n'avais pas remarqué qu'ils avaient le même nom. En effet, avec
le même nom, le code est illégal. Avec des noms différents, il n'est
légal que si les types ont des constructeurs triviaux.


Ok. On ne peut donc jamais avoir deux objets du même nom dans la
même portée. Donc les deux switch suivants sont illégaux, le premier
car deux objets ont le même nom, le second car le constructeur n'est
pas trivial :

switch ( ... ) {
case ... :
int i ;
break ;
case ... :
int i ;
break ;
}

class Integer {
public:
Integer( int i = 0 )
: myInt( i ) {
}
private:
int myInt ;
} ;

switch ( ... ) {
case ... :
Integer i1 ;
break ;
case ... :
Integer i2 ;
break ;
}

C'est bien ça ? C'est bien les diagnostiques que donne GCC 3.3.1,
en tout cas.

Et pour préciser mon premier article, c'est bien parce que les deux
objets portaient le même nom que je l'ai posté.

--drkm, en recherche d'un stage : http://www.fgeorges.org/ipl/stage.html

1 2 3