Sinnvolle Formatierung vieler geschachtelter Kontrollstrukturen



  • Werner Salomon schrieb:

    Dieses Code-Bild

    for( .. ) {  // oder while oder if
            for( .. ) {
                for( .. )  {
                    // und hier viele Zeilen Code
                }
            }
        }
    } // Ende der Funktion
    

    weißt auf ein ungünstiges Design hin.

    Finde ich gar nicht mal. Solange die äußeren beiden Schleifen keinen Code enthalten zählt das für mich nur als eine Schleifen. Ist dann einfach nur eine Schleife über alle Elemente einer verschachtelten Datenstruktur. Wenn auf den verschiedenen Ebenen aber auch noch verstreuter Code steht stimme ich dir zu.



  • Erstmal Danke für die Beiträge.

    Hier mal eine typische while Schleife aus einem Programm von mir:

    while(ncounter_bip<MAX_VAR_MUSTER){
    
    for (ik=0;ik<ADSIZE;++ik) 
    {
       hilfsneuronen_bip[ik]=0;
       for (il=0;il<ADSIZE;++il) {                         
       hilfsneuronen_bip[ik]=hilfsneuronen_bip[ik]+adjazenz_bip[ik][il]*neuronen_bip[il];} //Update Regel   
    
       if (hilfsneuronen_bip[ik]>threshold) {hilfsneuronen_bip[ik]=1;}             //Treshold                                  
       else hilfsneuronen_bip[ik]=0;
    }
    
    for (ik=0;ik<ADSIZE;++ik) {neuronen_bip[ik]=hilfsneuronen_bip[ik];}
    
    nzahl_bip=0;
    for(ik=0;ik<ADSIZE;++ik){nzahl_bip=nzahl_bip + neuronen_bip[ik]*pow(2,ik);}//Neuronale Aktivität -> Zahl
    
    if(Basins_bip[nzahl_bip]==0){Basins_bip[nzahl_bip]=nattractor_bip;}
    
    else{if(Basins_bip[nzahl_bip]==nattractor_bip)
    {
       nattractor_bip=nattractor_bip+1;
       while(Basins_bip[ncounter_bip]>0){ncounter_bip=ncounter_bip+1;}
       ih1_bip=ncounter_bip;
       Basins_bip[ncounter_bip]=nattractor_bip;
       for(ik=0;ik<ADSIZE;++ik){neuronen_bip[ik]=ih1_bip%2; ih1_bip=(ih1_bip-neuronen_bip[ik])/2;}//Zahl -> Neuronale Aktivität
    }
    
    else{
       in=0;
       for(ik=0;ik<MAX_VAR_MUSTER;++ik){
       if(Basins_bip[ik]==nattractor_bip){
       in=in+1;
       Basins_bip[ik]=Basins_bip[nzahl_bip];}}
    
       while(Basins_bip[ncounter_bip]>0){
       ncounter_bip=ncounter_bip+1;
       in=in+1;}
    
       Basins_bip[ncounter_bip]=nattractor_bip;
       if(nattractor_bip>100){
       cout << "Warnung: Attraktor > 100";
       exit(EXIT_FAILURE);}
    
       ih1_bip=ncounter_bip;
    
       for(ik=0;ik<ADSIZE;++ik){neuronen_bip[ik]=ih1_bip%2; ih1_bip=(ih1_bip-neuronen_bip[ik])/2;}
      }
     }
    }
    

    Frage mich wie man das nun besser formatiert.

    Lieben Gruß
    cpp_Jungspund



  • Benutze Leerzeichen!



  • 1. Einrücken
    2. Nicht so viel in eine Zeile packen
    3. Egal welchen Style du hast, immer einheitlich bleibem, ganz wichtig!

    Beispiel:

    while(ncounter_bip < MAX_VAR_MUSTER) { 
    	for (ik=0; ik<ADSIZE; ++ik) { 
    		hilfsneuronen_bip[ik] = 0; 
    		for (il=0; il<ADSIZE; ++il) {                         
    			hilfsneuronen_bip[ik] = hilfsneuronen_bip[ik] + adjazenz_bip[ik][il] * neuronen_bip[il];
    		} //Update Regel   
    
    		if (hilfsneuronen_bip[ik] > threshold)  //Treshold 
    			hilfsneuronen_bip[ik] = 1;                                              
    		else 
    			hilfsneuronen_bip[ik] = 0; 
    	}
    
    	for (ik=0; ik<ADSIZE; ++ik) {
    		neuronen_bip[ik] = hilfsneuronen_bip[ik];
    	} 
    
    	nzahl_bip = 0; 
    	for(ik=0; ik<ADSIZE; ++ik) {
    		nzahl_bip = nzahl_bip + neuronen_bip[ik] * pow(2, ik); //Neuronale Aktivität -> Zahl 
    	}
    
    	if(Basins_bip[nzahl_bip] == 0) {
    		Basins_bip[nzahl_bip] = nattractor_bip;
    	} else {
    		if(Basins_bip[nzahl_bip] == nattractor_bip) { 
    			nattractor_bip = nattractor_bip + 1; 
    			while(Basins_bip[ncounter_bip] > 0) {
    				ncounter_bip = ncounter_bip+1;
    			} 
    			ih1_bip = ncounter_bip; 
    			Basins_bip[ncounter_bip] = nattractor_bip; 
    			for(ik=0; ik<ADSIZE; ++ik) {
    				neuronen_bip[ik] = ih1_bip % 2;
    				ih1_bip = (ih1_bip - neuronen_bip[ik]) / 2; //Zahl -> Neuronale Aktivität
    			}
    		} else { 
    			in = 0; 
    			for(ik=0; ik<MAX_VAR_MUSTER; ++ik) { 
    				if(Basins_bip[ik] == nattractor_bip) { 
    					in = in + 1; 
    					Basins_bip[ik] = Basins_bip[nzahl_bip];
    				}
    			} 
    
    			while(Basins_bip[ncounter_bip] > 0) { 
    				ncounter_bip = ncounter_bip + 1; 
    				in = in + 1;
    			} 
    
    			Basins_bip[ncounter_bip] = nattractor_bip; 
    			if(nattractor_bip > 100) { 
    				cout << "Warnung: Attraktor > 100"; 
    				exit(EXIT_FAILURE);
    			} 
    
    			ih1_bip = ncounter_bip; 
    
    			for(ik=0; ik<ADSIZE; ++ik) {
    				neuronen_bip[ik] = ih1_bip % 2;
    				ih1_bip = (ih1_bip - neuronen_bip[ik]) / 2;
    			} 
    		}
    	}
    }
    


  • Schau Dir die Header <algorithm> und <numeric> an.

    Danach entwickel einen gewissen Spass daran, die Dinger anzuwenden...
    fill() accumulate(), transform(), generate(), copy() Meist geht dabei eine explizite for()-Schleife flöten.

    Nutz das Range-based-for aus C++11. for(auto& a : arr)... .

    Ich habe mir dummerweise die erste Schleife rausgesucht und nach fertigen Algorithmen geschaut um die umzusetzen.
    Das klappt auch...allerdings geht die Leserlichkeit flöten 🙂

    for (ik=0; ik<ADSIZE; ++ik) {
            hilfsneuronen_bip[ik] = 0;
            for (il=0; il<ADSIZE; ++il) {                        
                hilfsneuronen_bip[ik] = hilfsneuronen_bip[ik] + adjazenz_bip[ik][il] * neuronen_bip[il];
            } //Update Regel  
    
            if (hilfsneuronen_bip[ik] > threshold)  //Treshold
                hilfsneuronen_bip[ik] = 1;                                              
            else
                hilfsneuronen_bip[ik] = 0;
        }
    

    ➡

    // angenommen: double adjazenz_bip[ADSIZE][ADSIZE] und double hilfsneuronen[ADSIZE]
    // geht sicher auch generisch mit decltype()...o.ae.
    transform(begin(adjazenz_bip), end(adjazenz_bip), begin(hilfsneuronen), [=](double (&adj)[ADSIZE]){
          return inner_product(begin(adj), end(adj), begin(neuronen_bip), 0)>threshold?1:0;
        });
    

    Hoffentlich habe ich mich nicht vertan... 😉



  • Funktionen verwenden.
    Richtwert: nicht mehr als 10 Zeilen pro Funktion.

    Die meisten Funktionen haben unter 6 Zeilen!



  • Shade Of Mine schrieb:

    Funktionen verwenden.
    Richtwert: nicht mehr als 10 Zeilen pro Funktion.

    Die meisten Funktionen haben unter 6 Zeilen!

    Das geht bei mir höchstens im Arithmetischen Mittel auf.
    Man kann es auch übertreiben...

    EDIT: außerdem:

    for 
    {
     //...
    }
    

    vs

    for {
    }
    

    oder gar

    for () { /* ... */}
    

    Ich halte von solchen über den Daumen gebrochenen Sachen nichts.



  • Shade Of Mine schrieb:

    Funktionen verwenden.
    Richtwert: nicht mehr als 10 Zeilen pro Funktion.

    Die meisten Funktionen haben unter 6 Zeilen!

    Im letzten Jahrtausend galt noch irgendwas mit "nicht mehr als auf den Bildschirm paßt".
    Und der hatte aber schon (min) 25 Zeilen.



  • DirkB schrieb:

    Im letzten Jahrtausend galt noch irgendwas mit "nicht mehr als auf den Bildschirm paßt".
    Und der hatte aber schon (min) 25 Zeilen.

    Nein, diese waren 80x24 und hatten dementsprechend 24 Zeilen.



  • Ein C64 hatte ja sogar schon 25 Zeilen. Und wenn jetzt einer kommt mit, aber nur 40 Zeichen pro Zeile: der C128 hatte dann ein 80*25 Zeilen Modus und sogar einen 80*50 Modus.



  • Einfach den Breitbildmonitor hochkant aufstellen. Und schon gelten andere Maßstäbe.



  • Da war der Finger zu schnell..
    Wollte eigentlich noch sagen: Such einfach mal nach "c++ Style(s)", und nimm den, der dir am besten gefällt..



  • Die Vielfalt der Antworten und Ratschläge zeigt, dass man hier seinen eigenen Style finden und festhalten sollte. 😉



  • Das sieht wirklich grässlich aus. Ein wichtiger Tipp ist, viel mehr Leerraum zu lassen. Ich versuche mal den Code ein wenig lesbarer zu formatieren:

    while (ncounter_bip < MAX_VAR_MUSTER)
    {
        for (ik = 0; ik < ADSIZE; ++ik)
        {
            hilfsneuronen_bip[ik] = 0;
    
            for (il=0; il < ADSIZE; ++il)
                hilfsneuronen_bip[ik] = hilfsneuronen_bip[ik]
                                      + adjazenz_bip[ik][il] * neuronen_bip[il]; // Update Regel
    
            if (hilfsneuronen_bip[ik] > threshold)
                hilfsneuronen_bip[ik] = 1;       // Treshold
            else
                hilfsneuronen_bip[ik] = 0;
        }
    
        for (ik=0; ik < ADSIZE; ++ik)
            neuronen_bip[ik] = hilfsneuronen_bip[ik];
    
        nzahl_bip = 0;
        for (ik=0; ik<ADSIZE; ++ik)
            nzahl_bip = nzahl_bip + neuronen_bip[ik] * pow(2, ik);   // Neuronale Aktivität -> Zahl
    
        if (Basins_bip[nzahl_bip] == 0)
        {
            Basins_bip[nzahl_bip] = nattractor_bip;
        }
        else if (Basins_bip[nzahl_bip] == nattractor_bip)
        {
            nattractor_bip = nattractor_bip + 1;
            while (Basins_bip[ncounter_bip] > 0)
                ncounter_bip = ncounter_bip + 1;
    
            ih1_bip = ncounter_bip;
            Basins_bip[ncounter_bip] = nattractor_bip;
    
            for (ik=0; ik<ADSIZE; ++ik)
            {
                neuronen_bip[ik] = ih1_bip % 2;
                ih1_bip = (ih1_bip - neuronen_bip[ik]) / 2;  // Zahl -> Neuronale Aktivität
            }
        }
        else
        {
            in = 0;
            for (ik=0; ik < MAX_VAR_MUSTER; ++ik)
            {
                if (Basins_bip[ik] == nattractor_bip)
                {
                    in = in + 1;
                    Basins_bip[ik] = Basins_bip[nzahl_bip];
                }
            }
    
            while (Basins_bip[ncounter_bip] > 0)
            {
                ncounter_bip = ncounter_bip + 1;
                in = in + 1;
            }
    
            Basins_bip[ncounter_bip] = nattractor_bip;
    
            if (nattractor_bip > 100)
            {
                cout << "Warnung: Attraktor > 100";
                exit(EXIT_FAILURE);
            }
    
            ih1_bip = ncounter_bip;
    
            for (ik=0; ik < ADSIZE; ++ik)
            {
                neuronen_bip[ik] = ih1_bip % 2;
                ih1_bip = (ih1_bip - neuronen_bip[ik]) / 2;
            }
      }
    }
    

    Ein Paar Regeln, die ich hier verwendet habe:

    • um jeden Operator Leerzeichen
    • ein Statement pro Zeile
    • Bei Kontrollstrukturen vor der Klammer ein Leerzeichen ( while (...) )
    • Jede geschweifte Klammer bekommt eine eigene Zeile
    • Leerzeilen zwsichen Kontrollstrukturen und auch sonst nicht mit Leerzeilen geizen
    • Einheitlich einrücken (eigentlich komisch, dass man das überhaupt erwähnen muss, aber leider sehe ich oft code, wo selbst die Einrückung nicht stimmt)
    • Prinzipiell ist der Hinweis, Probleme in Funktionen auszulagern immer gut, so dass das Unterproblem auch einen Namen bekommt.
    • Eine Regel, die ich hier nicht verwendet habe, aber ich noch empfehle ist die einheitliche Benennung von Variablen, also z.B. immer mit Kleinbuchstaben anfangen (siehe Dein nattractor_bip vs. Basins_bip )

    Es gibt viele Stile. Ich habe meinen Stil, bin aber gerne bereit, mich dem Team, in dem ich arbeite anzupassen. Ich finde ein einheitlicher Stil im Team ist wichtiger als mein eigener.



  • Noch ein Hinweis von mir: Wenn es geht kombinierte Operatoren +=, -=, usw. und ++, -- verwenden.
    Bei Zeilen wie

    ncounter_bip = ncounter_bip + 1;
    

    muss ich mehrmals hin und her gucken ob beides wirklich die gleichen Variablen sind oder ob die sich nicht doch in einem Zeichen unterscheiden. Bei

    ++ncounter_bip;
    

    ist mir sofort klar was passiert.

    Andere Stelle:

    hilfsneuronen_bip[ik] = 0;
    for (il=0; il < ADSIZE; ++il)
        hilfsneuronen_bip[ik] = hilfsneuronen_bip[ik]
                              + adjazenz_bip[ik][il] * neuronen_bip[il]; // Update Regel
    

    könnte man += verwenden. Dadurch wird die Zeile auch deutlich kürzer weil man den langen Variablennamen nicht zweimal nennen muss.



  • tntnet schrieb:

    Das sieht wirklich grässlich aus. Ein wichtiger Tipp ist, viel mehr Leerraum zu lassen.

    Nö. Alle vermeidbaren Leerzeichen müssen weg. Dafür ruhig die Schrift größer stellen.



  • Leere Zeilen, für kleine 'Sinnabschnitte' halte ich jedoch für ziemlich Lesbarkeitsfördernd. Wenn diesen Sinnabschnitten hier und da noch ein kleiner Kommentar vorausgeht, umso besser.

    Außerdem: Lieber mehr tippen, als Namen zu kryptische Abkürzungen zu machen. Es sei denn die Variable wird wieder so lang, dass man zu lange braucht um sie zu lesen.

    volkard schrieb:

    tntnet schrieb:

    Das sieht wirklich grässlich aus. Ein wichtiger Tipp ist, viel mehr Leerraum zu lassen.

    Nö. Alle vermeidbaren Leerzeichen müssen weg. Dafür ruhig die Schrift größer stellen.

    (Not sure if troll or serious...)

    for(int i=2;i<10;++i)
    

    vs

    for(int i = 2; i < 10; i++) // preferable
    

    Allerdings:

    someFunc ( i + otherFunc ( 2 , 3 ) , 10 ); // igitt
    

    Wie bereits erwänht ist es ratsam ein paar style guides zu überfliegen und sich das rauszupicken, was man selbst mag. Oder man entscheidet sich für ein und richtet sich nach dem.

    EDIT: Ich halte es außerdem für ratsam sich nicht von dem Style der STL (snake case) leiten zu lassen. Das ist meiner Meinung nach boost und STL vorbehalten, sowie C libs.



  • Alle vermeidbaren Leerzeichen müssen weg.

    Das meinst Du nicht ernst, oder etwa doch? 😃



  • Erhard Henkes schrieb:

    Alle vermeidbaren Leerzeichen müssen weg.

    Das meinst Du nicht ernst, oder etwa doch? 😃

    Hin und wieder poste ich doch in diesem Forum Code, oder? Du hast schon tausende von Code-Snippets von mir gesehen.

    Hoffentlich ist aufgefallen, daß mein Code die Tendenz hat, besser lesbar zu sein als vergleichbarer Code von anderen.

    Und meistens habe ich keine vermeidbaren Leerzeichen drin. Anscheinend fällt es bei mir nicht so auf, kann mich gerade nicht dran erinnern, deswegen mal angemeckert worden zu sein. Nubes hingegen werden ständig deswegen angemeckert. Das läßt mich schließen, daß es nicht an den Leerzeichen liegt.



  • 5cript schrieb:

    for(int i=2;i<10;++i)
    

    vs

    for(int i = 2; i < 10; i++) // preferable
    

    Allerdings:

    someFunc ( i + otherFunc ( 2 , 3 ) , 10 ); // igitt
    

    Ähm, wenn die Leerzeichen wenigstens Sinneinheiten zusammenfassen würden

    for( int i=2 ; i<10 ; i++ ) // preferable
    

    dann könnte ich sie mir gefallen lassen. Aber genau das geschieht nicht. Es geht sogar soweit, daß man in Styleguides vollständige Regeln reinschreibt, wo Leerzeichen hingehören. Genau dann kann man sie auch vollständig weglassen. Es ist bloß eine Sache der Gewöhnung.

    for(int i = 2; i < 10; i++) // preferable
    
    for(int i = 2; i < 10; i += 1) // preferable
    

    Vor dem letzten i ist ein Leerzeichen entstanden, weil ich '++' durch '+= 1' ersetzt habe. Muss das denn sein?


Anmelden zum Antworten