Digamos que tiene el siguiente for
bucle *:
for (int i = 0; i < 10; ++i) {
// ...
}
que comúnmente también podría escribirse como:
for (int i = 0; i != 10; ++i) {
// ...
}
Los resultados finales son los mismos, entonces, ¿hay algún argumento real para usar uno sobre el otro? Personalmente uso el primero en caso de que i
por alguna razón se vuelva loco y se salte el valor 10.
* Disculpe el uso de números mágicos, pero es solo un ejemplo.
int i = 10; while(i --> 0) { /* stuff */ }
while ((i--) > 0)
Respuestas:
La razón para elegir uno u otro es debido a la intención y, como resultado de esto, aumenta la legibilidad .
Intención: el ciclo debe ejecutarse mientras
i
sea menor que 10, no mientrasi
no sea igual a 10. Aunque este último puede ser el mismo en este caso particular, no es lo que quiere decir, por lo que no debería ser escrito asíLegibilidad: el resultado de escribir lo que quiere decir es que también es más fácil de entender. Por ejemplo, si usa
i != 10
, alguien que lee el código puede preguntarse si dentro del buclei
podría haber más de 10 y si el bucle debería continuar (por cierto: es un mal estilo meterse con el iterador en otro lugar que no sea en la cabeza de lafor
declaración, pero eso no significa que la gente no lo haga y, como resultado, los mantenedores lo esperan).fuente
i
sea "menor que 10", debe ejecutarse siempre que no se alcance el límite superior (en este caso). Cuando se utiliza la lógica del intervalo C ++ / rango del iterador, es mucho más lógico expresar esto a través de!=
que<
.<
realidad lo expresa con precisión.for
bucle. Usar<
aquí sería una tontería. Además, Deckard parece reconocer eso. Estoy muy de acuerdo con su comentario en respuesta al mío.!=
El
<
patrón generalmente se puede usar incluso si el incremento no es exactamente 1.Esto permite una única forma común de hacer bucles independientemente de cómo se haga realmente.
fuente
i
modificar dentro del bucle de forma totalmente segura si es necesario.<
, como los iteradores sobre una secuencia, por!=
lo que sería una forma común de hacer bucles en C ++.<
patrón porque requiere una pulsación de tecla en lugar de dos con el>
patrón y cuatro con!=
. Es una cuestión de eficacia similar a OCD realmente.En C ++, la recomendación de Scott Myers en C ++ más eficaz (elemento 6) es usar siempre el segundo, a menos que tenga una razón para no hacerlo, ya que significa que tiene la misma sintaxis para los índices de iterador e entero para que pueda cambiar sin problemas entre un
int
iterador sin ningún cambio en la sintaxis.En otros idiomas esto no se aplica, así que supongo
<
que probablemente sea preferible debido al punto de Thorbjørn Ravn Andersen.Por cierto, el otro día estaba discutiendo esto con otro desarrollador y dijo que la razón para preferir
<
más!=
se debe a quei
accidentalmente podría incrementar en más de uno, y que podría causar la condición de ruptura no se cumplirá; eso es IMO una carga de tonterías.fuente
<
tener una programación más defensiva que!=
entonces ...<
es más defensivo y mis colegas odian si escribo!=
y no lo hago. Sin embargo, hay un caso para!=
C ++ y eso es lo que he presentado.i++
es cuando se cambia un ciclo while en un ciclo for. Sin embargo, no estoy seguro de que tener la mitad del número de iteraciones sea mejor que un bucle (casi) infinito; esto último probablemente haría que el error sea más obvio.Usar (i <10) es, en mi opinión, una práctica más segura. Captura el número máximo de casos potenciales para dejar de fumar: todo lo que es mayor o igual que 10. Contraste esto con el otro caso (i! = 10); solo detecta un posible caso de abandono, cuando tengo exactamente 10.
Un subproducto de esto es que mejora la legibilidad. Además, si el incremento es otro 1, puede ayudar a minimizar la probabilidad de un problema si cometemos un error al escribir el caso para dejar de fumar.
Considerar:
Aunque es probable que ambos casos sean defectuosos / incorrectos, es probable que el segundo sea MÁS incorrecto ya que no se cerrará. El primer caso se cerrará, y existe una mayor probabilidad de que se cierre en el lugar correcto, aunque 14 es probablemente el número incorrecto (15 probablemente sería mejor).
fuente
Aquí hay otra respuesta que nadie parece haber llegado todavía.
for
Los bucles deben usarse cuando necesita iterar sobre una secuencia . El uso!=
es el método más conciso para establecer la condición de terminación del bucle. Sin embargo, el uso de un operador menos restrictivo es un lenguaje de programación defensiva muy común. Para los enteros no importa: es solo una elección personal sin un ejemplo más específico. Recorrer colecciones con iteradores que desea usar!=
por las razones que otros han declarado. Si considera secuencias defloat
odouble
, entonces desea evitar!=
a toda costa.Lo que quería señalar es que
for
se usa cuando necesita iterar sobre una secuencia. La secuencia generada tiene un punto de inicio, un intervalo y una condición de finalización. Estos se especifican de manera concisa dentro de lafor
declaración. Si se encuentra (1) sin incluir la parte del paso delfor
(2) especificando algotrue
como la condición de protección, entonces no debería estar usando unfor
bucle.El
while
bucle se utiliza para continuar procesando mientras se cumple una condición específica. Si no está procesando una secuencia, entonces probablemente desee unwhile
bucle. Los argumentos de la condición de guardia son similares aquí, pero la decisión entre awhile
y unfor
bucle debe ser muy consciente. Elwhile
bucle se subestima en los círculos de C ++ IMO.Si está procesando una colección de elementos (un
for
uso de bucle muy común ), entonces realmente debería usar un método más especializado. Desafortunadamente,std::for_each
es bastante doloroso en C ++ por varias razones. En muchos casos, la separación del cuerpo de unfor
bucle en una función independiente (aunque algo dolorosa) da como resultado una solución mucho más limpia. Cuando trabaje con colecciones, considerestd::for_each
,std::transform
ostd::accumulate
. La implementación de muchos algoritmos se vuelve concisa y clara como el cristal cuando se expresa de esta manera. Sin mencionar que aislar el cuerpo del bucle en una función / método separado lo obliga a concentrarse en el algoritmo, sus requisitos de entrada y resultados.Si está utilizando Java, Python, Ruby o incluso C ++ 0x , entonces debería estar utilizando una colección foreach loop adecuada . A medida que los compiladores de C ++ implementen esta característica,
for
desaparecerán varios bucles y este tipo de discusiones.fuente
while
,for
yforeach
(o equivalente de idioma)while
bucle se usa para continuar procesando hasta que no se cumpla una condición específica<
) o al operador indulgente en los valores que falla (!=
).Usar "menor que" es (generalmente) semánticamente correcto, realmente quiere decir contar hasta
i
que ya no sea menor que 10, por lo que "menor que" transmite sus intenciones claramente. El uso de "no igual" obviamente funciona prácticamente en casos de llamada, pero transmite un significado ligeramente diferente. En algunos casos, esto puede ser lo que necesita, pero en mi experiencia este nunca ha sido el caso. Si realmente tuvo un caso en el quei
podría ser más o menos de 10 pero desea seguir haciendo bucles hasta que sea igual a 10, entonces ese código realmente necesitaría comentarios muy claramente, y probablemente podría escribirse mejor con alguna otra construcción, como como unwhile
bucle quizás.fuente
Una razón por la que preferiría un
less than
sobre anot equals
es actuar como guardia. En algunas circunstancias limitadas (mala programación o desinfección) elnot equals
podría omitir mientrasless than
todavía estaría en vigencia.Aquí hay un ejemplo donde la falta de una verificación de desinfección ha dado resultados extraños: http://www.michaeleisen.org/blog/?p=358
fuente
Aquí es una de las razones por las que podría preferir utilizar
<
en lugar de!=
. Si está utilizando un lenguaje que tiene un alcance de variable global, ¿qué sucede si se modifica otro códigoi
? Si está utilizando en<
lugar de!=
, lo peor que sucede es que la iteración termina más rápido: tal vez algunos otros incrementos de códigoi
por accidente, y omita algunas iteraciones en el bucle for. Pero, ¿qué sucede si realiza un ciclo de 0 a 10, y el ciclo llega a 9, y algunos subprocesos mal escritos aumentani
por alguna extraña razón? Entonces su ciclo termina esa iteración e incrementosi
modo que el valor ahora sea 11. Como el ciclo ha omitido la condición de salida (i
nunca igual a 10), ahora se repetirá infinitamente.No necesariamente tiene que ser una lógica de tipo de subprocesos y variables globales particularmente extraña lo que causa esto. Puede ser que esté escribiendo un bucle que necesita retroceder. Si está mutando
i
dentro del bucle y arruina su lógica,!=
es menos probable que tenga un límite superior en lugar de un a lo que lo dejará en un bucle infinito.fuente
En el mundo embebido, especialmente en entornos ruidosos, no puede contar con que la RAM necesariamente se comporte como debería. En un condicional (para, mientras, si) donde compara usando '==' o '! =' Siempre corre el riesgo de que sus variables omitan ese valor crucial que termina el ciclo - esto puede tener consecuencias desastrosas - Mars Lander Nivel de consecuencias. El uso de '<' o '>' en la condición proporciona un nivel adicional de seguridad para atrapar las 'incógnitas desconocidas'.
En el ejemplo original, si
i
se catapultara inexplicablemente a un valor mucho mayor que 10, la comparación '<' detectaría el error de inmediato y saldría del bucle, pero '! =' Continuaría contando hasta que sei
envuelva más allá de 0 y viceversa. a 10.fuente
for (i=4; i<length; i++) csum+=dat[i];
donde los paquetes legítimos siempre tendríanlength
al menos cuatro, pero uno podría recibir paquetes corruptos. Si los diferentes tipos de paquetes tienen diferentes requisitos de longitud, es posible que desee validar la longitud como parte del procesamiento que es diferente para cada tipo de paquete, pero primero valide la suma de verificación como parte de la lógica común. Si se recibe un paquete de menor longitud, en realidad no importa si el cálculo de la suma de verificación informa "bueno" o "malo", pero no debería bloquearse.