Domanda

Ho appena trovato ... ANCORA ... un bug di spreco in tempo reale come segue

for (int i = 0; i < length; i++)
{ //...Lots of code 
    for (int j = 0; i < length; j++)
    {
        //...Lots of code 
    }
}

Hai notato subito l'interno che DOVREBBE ESSERE j? Nemmeno io. Quindi da ora in poi userò:

for (int i = 0; i < length; i++)
{
    for (int i1 = 0; i1 < length; i1++)
    {
    }
}

Quali sono i tuoi consigli per interni ed esterni mentre e per i cicli?

Modifica: grazie per le preziose risposte. Di seguito un breve riassunto dei suggerimenti proposti:

  • uso nomi di variabili significative per variabili di indice (invece uso SomeObjCollectionLength)
  • posiziona il contenuto del ciclo interno in un metodo separato e chiama quel metodo dal ciclo esterno
  • la quantità non gestibile di righe di codice tra il ciclo esterno e quello interno è un segnale forte per l'odore di codice
  • evita di incollare e affrettare le copie, scrivi gli indici variando con cura

Potresti voler controllare il riepilogo di LBushkin per seguenti

  • usa foreach e iteratori quando possibile
  • inizializza le variabili appena prima di inserire i loop
  • Fa sì che ogni ciclo esegua una sola funzione. Evita di mescolare le responsabilità in un singolo ciclo
  • Quando possibile, fai in modo che i tuoi loop siano abbastanza corti da poterli visualizzare contemporaneamente
È stato utile?

Soluzione

Non usare i & amp; j (o qualsiasi altra variabile a lettera singola) come nomi di indice. Usa nomi propri e non ti imbatterai in questo tipo di problemi.

Altri suggerimenti

Una delle soluzioni più semplici e pulite è posizionare i contenuti del loop interno in un metodo in modo che diventi:

for (int i = 0; i < length; i++)
{
    DoSomething();
}

private void DoSomething(int outerValue)
{
    for (int i = 0; i < length; i++)
    {
        // Do something else
    }

}

Per me, "odore di codice" qui è "molto codice".

Se la quantità di codice nei loop è particolarmente grande, la distanza tra i loop interni ed esterni significa che non è altrettanto probabile che vengano confrontati l'uno con l'altro per correttezza.

Certo, guardare all'inizio del ciclo interno in isolamento dovrebbe portare il problema alla tua attenzione, ma avere la struttura principale in una sezione di codice quanto più piccola possibile dà al tuo cervello meno da digerire.

Potrebbe essere possibile estrarre le sezioni "lotti di codice" in funzioni / metodi separati, al fine di ridurre le dimensioni della struttura principale, ma ciò potrebbe non essere sempre pratico.

Direi anche che 'i1' non è una scelta particolarmente buona del nome della variabile, poiché ciò tende a incoraggiare 'i2', 'i3' ecc., il che non porta realmente a un codice comprensibile. Forse sostituire tutte le variabili del ciclo con qualcosa di più significativo aiuterebbe la chiarezza del codice e ridurrebbe le possibilità dell'errore originale.

Il mio miglior consiglio (in nessun ordine particolare) per scrivere un codice loop migliore (gran parte di questo è tratto dall'eccellente libro Codice completo ):

  1. Evita punti di uscita multipli per i loop.
  2. Usa continua / interrompi con parsimonia.
  3. Rifattorizza i cicli annidati in routine separate, quando possibile.
  4. Utilizza nomi di variabili significativi per rendere leggibili i loop nidificati.
  5. Usa i cicli foreach () quando possibile, piuttosto che per i cicli (i = ...).
  6. Inserisci il loop da una sola posizione. Non saltare in loop con goto's. Mai.
  7. Inserisci il codice di inizializzazione immediatamente prima del ciclo.
  8. Conserva le istruzioni di inizializzazione del ciclo con il ciclo a cui sono correlate.
  9. Evita di riutilizzare le variabili tra loop non nidificati. 10. Limitare l'ambito delle variabili indice-ciclo al ciclo stesso.
  10. Utilizzare while (true) per loop infiniti, anziché per (;;)
  11. Nei linguaggi che forniscono costrutti a blocchi (ad es. '{' e '}') li usano invece di rientrare per racchiudere le istruzioni di un ciclo. Sì, anche per loop a linea singola.
  12. Evita loop vuoti.
  13. Evita di mettere le faccende domestiche nel mezzo di un ciclo, posizionale all'inizio e / o alla fine.
  14. Fa sì che ogni ciclo esegua una sola funzione. Evita di mescolare le responsabilità in un singolo ciclo.
  15. Rendi ovvie le condizioni di terminazione del loop.
  16. Non scimmiottare con la variabile indice del ciclo di un ciclo for () per terminarlo.
  17. Evita il codice che dipende dal valore finale dell'indicizzatore di loop.
  18. Prendi in considerazione l'uso dei contatori di sicurezza in circuiti complessi: è possibile verificarli per assicurarsi che il ciclo non venga eseguito troppe o troppe volte.
  19. Utilizzare le istruzioni di interruzione, quando possibile, per terminare mentre i cicli.
  20. Quando possibile, accorcia i loop abbastanza da poterli visualizzare tutti in una volta.

Questo è un errore di copia-incolla, evita copia incolla.

Per quanto riguarda la tua soluzione, non è molto meglio. L'errore può ancora scivolare tra tonnellate di codice. Tendo a usare nomi significativi anche per le variabili temporanee del ciclo.

sfrutta il tuo IDE, su VS, prova ad usare questo: http://msdn.microsoft.com/en-us/library/z4c5cc9b (VS.80) aspx

esempio: digita per , quindi premi scheda Tab in successione

Sono venuto qui per essere intelligente e dire " ho appena scritto bene la prima volta " ;. Ma poi ho visto il tuo esempio e, beh, l'ho fatto troppe volte da solo.

Quando hai bisogno di loop nidificati in questo modo, la mia unica soluzione è essere vigili e pensare quando scrivi il codice.

Ove possibile, è utile usare iteratori e per ogni loop.

Inoltre, non riesco a vedere come la soluzione suggerita sarà migliore. E non sembra neanche bello.

Prima di tutto, riduci le dimensioni del corpo del loop, ovvero sposta le cose in funzioni separate. È generalmente una cattiva idea avere funzioni più lunghe di quelle che possono adattarsi allo schermo, quindi i loop dovrebbero essere ancora più piccoli.

In secondo luogo, utilizzare nomi di variabili significativi in ??casi come questo. Userei ij solo in semplici loop con poche righe di codice. Ad esempio, se stai attraversando un array bidimensionale, " col " e "riga" avrebbe molto più senso, renderebbe il codice più facile da leggere ("quale era?") e più facile individuare errori come questo.

Devi solo prenderti cura di questi problemi, non c'è nessun proiettile magico contro questo. Anche con " migliore denominazione " proponete di perdere di tanto in tanto la traccia se questo è Nth o (N + M) livello di loop nidificato e commettete un errore.

Se è necessario un ciclo nidificato, scriverlo attentamente. Se può essere evitato estraendo il corpo del circuito esterno in una funzione che sarebbe una buona protezione contro l'uso improprio degli indici.

Uso 'ii' e 'jj' per i contatori di loop transitori se ne ho davvero bisogno: sono più facili da cercare rispetto a 'i' e 'j' e anche più facili da individuare in esempi come sopra. Per migliorare, puoi effettivamente utilizzare un nome di variabile reale. Se esegui il loop su una stringa, puoi chiamarla characterIndex o qualcosa del genere. Scrive di più, ma documenta se stesso e fa risparmiare tempo sul debug di problemi oscuri in seguito.

Meglio ancora sarebbe evitare contatori numerici e usare iteratori nominati su una raccolta. A mio avviso rendono più chiaro l'intento.

Infine, se possibile, è bello eliminare completamente il ciclo: Boost :: Foreach è un modo per farlo in C ++, anche se generalmente preferisco usare linguaggi come Python che consentono nativamente l'iterazione diretta sul contenuto di un contenitore senza la necessità di incrementare un valore di indice o iteratore.

Prova a usare più costrutti di loop dichiarativi. Ad esempio, se non hai davvero bisogno di indici (quei i e j ) e il tuo ambiente di programmazione lo consente, puoi usare un foreach costrutto per scorrere la raccolta.

Come in questo come in molte altre cose, ci sono alcuni consigli eccellenti nel Codice completo di Steve McConnell. Vale la pena dedicare del tempo a leggere cosa ha da dire sulla costruzione di un buon codice di looping. Non ho la mia copia del libro a portata di mano qui, ma l'intero libro vale la pena.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top