'' contro '! =' come condizione in un ciclo 'for'?

26

Supponiamo di avere il seguente for loop *:

for (int i = 0; i < 10; ++i) {
    // ...
}

che potrebbe essere comunemente scritto anche come:

for (int i = 0; i != 10; ++i) {
    // ...
}

I risultati finali sono gli stessi, quindi ci sono argomenti reali per l'utilizzo di uno sull'altro? Personalmente uso il primo nel caso in cui i per qualche motivo vada in tilt e salti il valore 10.

* Scusa l'uso di numeri magici, ma è solo un esempio.

    
posta gablin 25.04.2011 - 11:32
fonte

9 risposte

57

Il motivo per scegliere l'uno o l'altro è a causa di intento e come risultato di ciò, aumenta leggibilità .

Intenzione: il ciclo deve essere eseguito fino a quando i è minore di 10, non fino a quando i non è uguale a 10. Anche se quest'ultimo potrebbe essere lo stesso in questo caso particolare, non è cosa intendi, quindi non dovrebbe essere scritto così.

Leggibilità: un risultato della stesura di ciò che intendi è che è anche più facile da capire. Ad esempio, se utilizzi i != 10 , qualcuno che legge il codice potrebbe chiedersi se all'interno del ciclo ci sia un certo modo in cui i potrebbe diventare più grande di 10 e che il ciclo dovrebbe continuare (btw: è uno stile pessimo da pasticciare con l'iteratore da qualche parte altro che in testa al for -statement, ma ciò non significa che le persone non lo facciano e di conseguenza i maintainer se lo aspettano).

    
risposta data 25.04.2011 - 11:53
fonte
46

Il modello < è generalmente utilizzabile anche se l'incremento non corrisponde esattamente a 1.

Ciò consente un singolo modo comune di fare loop indipendentemente da come è effettivamente fatto.

    
risposta data 25.04.2011 - 11:34
fonte
19

In C ++ la raccomandazione di Scott Myers in C ++ più efficace (punto 6) è sempre quella di usare il secondo a meno che non si abbia una ragione perché non significa che si ha la stessa sintassi per gli indici iteratore e intero in modo da poterlo scambiare perfettamente tra int e iteratore senza alcuna modifica nella sintassi.

In altre lingue questo non si applica quindi suppongo che < sia probabilmente preferibile a causa del punto di Thorbjørn Ravn Andersen.

A proposito, l'altro giorno stavo discutendo di questo con un altro sviluppatore e ha detto che il motivo per preferire < su != è perché i potrebbe accidentalmente incrementare di più di uno, e questo potrebbe causare la rottura condizione da non rispettare; questo è IMO un carico di sciocchezze.

    
risposta data 25.04.2011 - 11:52
fonte
11

Usare (io < 10) è secondo me una pratica più sicura. Cattura il numero massimo di potenziali casi in cui smettere di fumare - tutto ciò che è maggiore o uguale a 10. Contrastalo con l'altro caso (i! = 10); prende solo un possibile caso in cui smettere di fumare - quando ho esattamente 10 anni.

Un sottoprodotto di questo è che migliora la leggibilità. Inoltre, se l'incremento dovesse essere qualsiasi altro 1, può aiutare a ridurre al minimo la probabilità di un problema se dovessimo commettere un errore quando scriviamo il caso di smettere.

Si consideri:

1) for (i = 1; i < 14; i+=2)

2) for (i = 1; i != 14; i+=2)

Sebbene entrambi i casi siano probabilmente errati / errati, il secondo è probabilmente PIÙ sbagliato in quanto non si chiuderà. Il primo caso si chiuderà, e c'è una maggiore possibilità che si fermi nel punto giusto, anche se 14 è probabilmente il numero sbagliato (probabilmente 15 sarebbe meglio).

    
risposta data 25.04.2011 - 15:07
fonte
9

Ecco un'altra risposta che nessuno sembra aver ancora trovato. È necessario utilizzare for loops quando è necessario eseguire un'iterazione su una sequenza . L'utilizzo di != è il metodo più conciso per dichiarare la condizione di terminazione per il ciclo. Tuttavia, l'utilizzo di un operatore meno restrittivo è un idioma di programmazione difensivo molto comune. Per i numeri interi non importa - è solo una scelta personale senza un esempio più specifico. In loop su raccolte con iteratori che si desidera utilizzare != per i motivi indicati da altri. Se consideri le sequenze di float o double , allora vuoi evitare != a tutti i costi.

Quello che volevo sottolineare è che for è usato quando è necessario iterare su una sequenza. La sequenza generata ha un punto di partenza, un intervallo e una condizione di terminazione. Questi sono specificati in modo conciso nell'istruzione for . Se ti trovi (1) non includendo la porzione di passo di for o (2) che specifica qualcosa come true come condizione di guardia, allora non dovresti usare un ciclo for !

Il ciclo while viene utilizzato per continuare l'elaborazione mentre viene soddisfatta una condizione specifica. Se non stai elaborando una sequenza, probabilmente preferisci un ciclo while . Gli argomenti della condizione di guardia sono simili qui, ma la decisione tra un ciclo while e un ciclo for dovrebbe essere molto consapevole. Il ciclo while è sottovalutato nei cerchi C ++ IMO.

Se stai elaborando una raccolta di elementi (un utilizzo molto comune di for -loop), allora dovresti davvero usare un metodo più specializzato. Sfortunatamente, std::for_each è piuttosto doloroso in C ++ per una serie di motivi. In molti casi, la separazione del corpo di un ciclo for in una funzione indipendente (sebbene alquanto dolorosa) risulta in una soluzione molto più pulita. Quando lavori con le raccolte, considera std::for_each , std::transform o std::accumulate . L'implementazione di molti algoritmi diventa concisa e cristallina quando espressa in questo modo. Per non parlare del fatto che isolare il corpo del loop in una funzione / metodo separato ti costringe a concentrarti sull'algoritmo, i suoi requisiti di input e i suoi risultati.

Se stai usando Java, Python, Ruby o anche C ++ 0x , allora dovresti usare un ciclo appropriato di raccolta foreach . Poiché i compilatori C ++ implementano questa funzione, un certo numero di cicli for scompariranno così come lo saranno questi tipi di discussioni.

    
risposta data 25.04.2011 - 15:54
fonte
4

L'uso di "meno di" è (di solito) semanticamente corretto, significa veramente contare fino a quando i non è più inferiore a 10, quindi "meno di" trasmette chiaramente le tue intenzioni. Usare "non uguale" ovviamente funziona praticamente in casi di chiamata, ma trasmette un significato leggermente diverso. In alcuni casi questo potrebbe essere ciò di cui hai bisogno, ma nella mia esperienza questo non è mai stato il caso. Se hai davvero un caso in cui i potrebbe essere più o meno di 10 ma vuoi continuare a fare il ciclo fino a 10, allora quel codice avrebbe davvero bisogno di commenti molto chiari, e probabilmente potrebbe essere scritto meglio con altri costrutto, ad esempio un while loop forse.

    
risposta data 25.04.2011 - 12:06
fonte
2

Una delle ragioni per cui preferirei un less than a un not equals è di agire come una guardia. In alcune circostanze limitate (programmazione errata o disinfezione) il not equals potrebbe essere saltato mentre less than sarebbe ancora in vigore.

Ecco un esempio in cui la mancanza di un controllo di disinfezione ha portato a risultati strani: link

    
risposta data 25.04.2011 - 15:19
fonte
0

Ecco uno dei motivi per cui potresti preferire l'utilizzo di < anziché != . Se si sta utilizzando un linguaggio con scope della variabile globale, cosa succede se un altro codice modifica i ? Se stai usando < piuttosto che != , la cosa peggiore che accade è che l'iterazione termina più velocemente: forse un altro codice incrementa il i per caso e salti alcune iterazioni nel ciclo for. Ma cosa succede se si esegue il ciclo da 0 a 10 e il ciclo arriva a 9 e alcuni thread mal scritti incrementano i per qualche strana ragione. Quindi il ciclo termina tale iterazione e incrementa i in modo che il valore sia ora 11. Poiché il ciclo ha saltato la condizione di uscita ( i mai uguale a 10), il loop verrà ora ripetuto all'infinito.

Non necessariamente deve essere una logica particolarmente strana di tipo threading-and-global-variables che causa questo. Potrebbe essere solo che stai scrivendo un ciclo che deve tornare indietro. Se stai mutando i all'interno del ciclo e sviti la logica, avere un limite superiore anziché un != è meno probabile che ti lasci in un ciclo infinito.

    
risposta data 25.04.2011 - 12:04
fonte
0

Nel mondo embedded, specialmente in ambienti rumorosi, non si può contare sulla RAM che si comporta necessariamente come dovrebbe. In un condizionale (per, mentre, se) in cui si confronta usando '==' o '! =' Si corre sempre il rischio che le variabili saltino quel valore cruciale che termina il ciclo - questo può avere conseguenze disastrose - Mars Lander conseguenze di livello. Utilizzando '<' o ">" nella condizione fornisce un ulteriore livello di sicurezza per catturare le "incognite sconosciute".

Nell'esempio originale, se i è stato inspiegabilmente catapultato a un valore molto più grande di 10, il "<" il confronto prenderebbe subito l'errore e uscirà dal ciclo, ma '! =' continuerà a contare fino a che i si è spostato intorno a 0 e torna a 10.

    
risposta data 25.04.2011 - 18:50
fonte

Leggi altre domande sui tag