Pour moi, do{...}while(0)
c'est bien. Si vous ne voulez pas voir le do{...}while(0)
, vous pouvez leur définir des mots-clés alternatifs.
Exemple:
SomeUtilities.hpp:
#define BEGIN_TEST do{
#define END_TEST }while(0);
SomeSourceFile.cpp:
BEGIN_TEST
if(!condition1) break;
if(!condition2) break;
if(!condition3) break;
if(!condition4) break;
if(!condition5) break;
//processing code here
END_TEST
Je pense que le compilateur supprimera la while(0)
condition inutile do{...}while(0)
dans la version binaire et convertira les ruptures en saut inconditionnel. Vous pouvez vérifier sa version en langage assembleur pour en être sûr.
L'utilisation goto
produit également un code plus propre et c'est simple avec la logique condition-alors-saut. Vous pouvez effectuer les opérations suivantes:
{
if(!condition1) goto end_blahblah;
if(!condition2) goto end_blahblah;
if(!condition3) goto end_blahblah;
if(!condition4) goto end_blahblah;
if(!condition5) goto end_blahblah;
//processing code here
}end_blah_blah:; //use appropriate label here to describe...
// ...the whole code inside the block.
Notez que l'étiquette est placée après la fermeture }
. Il s'agit d'éviter un problème possible en goto
plaçant accidentellement un code entre les deux parce que vous n'avez pas vu l'étiquette. C'est maintenant comme do{...}while(0)
sans code de condition.
Pour rendre ce code plus propre et plus compréhensible, vous pouvez le faire:
SomeUtilities.hpp:
#define BEGIN_TEST {
#define END_TEST(_test_label_) }_test_label_:;
#define FAILED(_test_label_) goto _test_label_
SomeSourceFile.cpp:
BEGIN_TEST
if(!condition1) FAILED(NormalizeData);
if(!condition2) FAILED(NormalizeData);
if(!condition3) FAILED(NormalizeData);
if(!condition4) FAILED(NormalizeData);
if(!condition5) FAILED(NormalizeData);
END_TEST(NormalizeData)
Avec cela, vous pouvez faire des blocs imbriqués et spécifier où vous souhaitez quitter / sauter.
BEGIN_TEST
if(!condition1) FAILED(NormalizeData);
if(!condition2) FAILED(NormalizeData);
BEGIN_TEST
if(!conditionAA) FAILED(DecryptBlah);
if(!conditionBB) FAILED(NormalizeData); //Jump out to the outmost block
if(!conditionCC) FAILED(DecryptBlah);
// --We can now decrypt and do other stuffs.
END_TEST(DecryptBlah)
if(!condition3) FAILED(NormalizeData);
if(!condition4) FAILED(NormalizeData);
// --other code here
BEGIN_TEST
if(!conditionA) FAILED(TrimSpaces);
if(!conditionB) FAILED(TrimSpaces);
if(!conditionC) FAILED(NormalizeData); //Jump out to the outmost block
if(!conditionD) FAILED(TrimSpaces);
// --We can now trim completely or do other stuffs.
END_TEST(TrimSpaces)
// --Other code here...
if(!condition5) FAILED(NormalizeData);
//Ok, we got here. We can now process what we need to process.
END_TEST(NormalizeData)
Le code spaghetti n'est pas la faute de goto
, c'est la faute du programmeur. Vous pouvez toujours produire du code spaghetti sans utiliser goto
.