¿Hay alguna razón técnica para usar> (<) en lugar de! = Cuando se incrementa en 1 en un bucle 'for'?


198

Casi nunca veo un forbucle como este:

for (int i = 0; 5 != i; ++i)
{}

¿Hay alguna razón técnica para usar >o en <lugar de !=cuando se incrementa en 1 en un forbucle? ¿O esto es más una convención?


104
Lo hace más legible, además, si alguna vez cambia i++a i+=2(por ejemplo), se ejecutará durante mucho tiempo (o posiblemente para siempre). Ahora, dado que normalmente se usa <para aquellos casos en los que incrementa el iterador en más de 1, también podría usarlo <para el caso en que lo incrementa en 1 (por coherencia).
barak manos

112
5 != ies malvado
Slava

27
Siempre debe ser consciente de lo que está haciendo, pero de todos modos cometerá errores. El uso de <reduce la posibilidad de que alguien introduzca un error en este código.
Aurast

40
@OleTange Si estás iterando usando números de coma flotante, ya estás jodido ...
CaptainCodeman

29
@Slava ... no es malvado. Al parecer, nunca ha sido mordido en C por un simple error tipográfico que hace la diferencia entre if ( i == 5 ) ...y if ( i = 5 ). Cosas muy diferentes. Revertir los operandos evita el problema: dado que los literales no lo son lvals, no se pueden asignar y el compilador arroja el error tipográfico. @Zingam: ¡buena programación defensiva!
Nicholas Carey

Respuestas:


303
while (time != 6:30pm) {
    Work();
}

Son las 6:31 pm ... Maldición, ¡ahora mi próxima oportunidad de ir a casa es mañana! :)

Esto para mostrar que la restricción más fuerte mitiga los riesgos y probablemente sea más intuitiva de entender.


25
A veces, intentar "mitigar riesgos" simplemente termina ocultando el error. Si el diseño del bucle impide que las 6:30 pm pasen desapercibidas, el uso <ocultará el error, pero el uso !=dejaría en claro que hay un problema.
Adrian McCarthy

27
@AdrianMcCarthy: No necesariamente; simplemente podría introducir un segundo error, lo que dificultaría el diagnóstico .
Carreras de ligereza en órbita

44
@AdrianMcCarthy: Ese es mi punto; podrías tener algunas instancias que aún no has visto;)
Lightness Races in Orbit

66
Los iteradores son un ejemplo perfecto del punto @AdrianMcCarthy, creo. La comparación recomendada para ellos es! = En lugar de <.
Taekahn

55
He visto exactamente este error (y causó 3 meses de depuración), pero esta respuesta pierde completamente el punto. En el ejemplo dado, es imposible que se pierda la condición final. Incluso podría decir que elegir conscientemente! = Sobre <es hacer una fuerte afirmación de este hecho. Mitigar un riesgo que definitivamente no existe es un olor a código para mí. (Dicho esto, también puede argumentar que <es idiomático, que esa es una buena razón para usarlo como cualquier otro.)
Ian Goldby

95

No hay razón técnica. Pero existe una mitigación de riesgos, mantenibilidad y una mejor comprensión del código.

<o >son restricciones más fuertes que !=y cumplen exactamente el mismo propósito en la mayoría de los casos (incluso diría que en todos los casos prácticos).

Hay una pregunta duplicada aquí ; y una interesante respuesta .


66
Hay algunos tipos, como iteradores, que no admiten <o>, pero admiten == y! =.
Simon B

1
Es un bucle for con int . No hay iteradores
Ely

77
"Pero existe una mitigación de riesgos, mantenibilidad y una mejor comprensión del código". Todos los cuales son, adecuadamente, razones técnicas. :-)
TJ Crowder

@TJCrowder ¿Qué tipo de razón es cuando solo quieres hablar sobre lo que las máquinas harán como resultado?
Brilliand

1
@DanSheppard En general, consideraría que la mitigación del riesgo y la mantenibilidad son razones comerciales, y una mejor comprensión del código es una razón social (aunque esas razones se están aplicando a un asunto técnico en este caso). Las consideraciones de "mitigación de riesgos" no se limitan de ninguna manera a cuestiones técnicas, y las consideraciones de "mejor comprensión del código" pueden cambiar si se encuentra trabajando con un grupo diferente de personas (incluso si las máquinas involucradas no cambian en absoluto )
Brilliand

85

Sí hay una razón Si escribe un bucle for simple (basado en índices antiguos) como este

for (int i = a; i < b; ++i){}

entonces funciona como se esperaba para cualquier valor de ay b(es decir, cero iteraciones cuando en a > blugar de infinito si lo hubiera usado i == b;).

Por otro lado, para iteradores escribirías

for (auto it = begin; it != end; ++it) 

porque cualquier iterador debe implementar un operator!=, pero no para cada iterador es posible proporcionar un operator<.

También basado en rango para bucles

for (auto e : v)

no son solo azúcar sofisticada, sino que reducen considerablemente las posibilidades de escribir código incorrecto.


44
Buen ejemplo Me interesaría un caso en !=lugar de <. Yo personalmente nunca usé eso, creo.
Ely

@Elyasin No encontré uno bueno, y no quería publicar uno malo: imagina que tienes algún tipo de contenedor circular, donde incrementas en + x módulo el tamaño del contenedor N y quieres detener el ciclo cuando alcanzar cierto índice ... bueno, ese es un muy mal ejemplo. Tal vez encuentre uno mejor
idclev 463035818

El mismo bucle con! = En lugar de <deja en claro cuál es la ventaja de <(o>) en este contexto. for (int i=a; i != b; i++) {}
Paul Smith

10
Usar cualquier cosa además !=de los iteradores es bastante peligroso, porque a veces los iteradores pueden ser menos que comparados (es un puntero, por ejemplo), pero la comparación no tiene sentido (es una lista vinculada).
Zan Lynx

1
Aprende a usar el espacio en blanco, en serio.
Miles Rout

70

Puedes tener algo como

for(int i = 0; i<5; ++i){
    ...
    if(...) i++;
    ...
}

Si su variable de bucle está escrita por el código interno, es i!=5posible que no rompa ese bucle. Esto es más seguro para verificar la desigualdad.

Edita sobre legibilidad. La forma de desigualdad se usa con mayor frecuencia. Por lo tanto, esto es muy rápido de leer ya que no hay nada especial que entender (la carga cerebral se reduce porque la tarea es común). Por lo tanto, es genial que los lectores hagan uso de estos hábitos.


66
Este tipo de "if (condición) interna entonces i ++" es lo primero que pensé.
WernerCD

3
Llegó esperando que esta sea la respuesta más votada; Me sorprendió tener que desplazarme tan lejos para encontrarlo. Esto hace mucho más para convencer a un programador novato que "bueno, debes usar la condición más fuerte". Las otras respuestas, si se mantienen en la cima, deberían incorporar esto como una explicación clara y obvia de lo que puede salir mal con el código propuesto por OP.
msouth

1
@msouth Estoy totalmente de acuerdo, pero mi punto de vista es bastante subjetivo;)
johan d

3
@msouth Me encanta cuando un comportamiento de producción inesperado expone mis errores, ¿no? :-)
deworde

3
@msouth Mira, todo lo que tenemos que hacer es nunca cometer errores y todo estará bien. Simples
deworde

48

Y por último pero no menos importante, esto se llama programación defensiva , lo que significa tomar siempre el caso más fuerte para evitar errores actuales y futuros que influyen en el programa.

El único caso en el que no se necesita programación defensiva es donde los estados han sido probados por condiciones previas y posteriores (pero luego, probar que esta es la más defensiva de toda la programación).


2
Un buen ejemplo en apoyo de esto: la memoria es vulnerable a los cambios de bits ( SEU ) causados ​​por la radiación. Cuando se usa un intpara una i != 15condición, el contador funcionará durante mucho tiempo si se voltea algo por encima del cuarto bit, especialmente en máquinas donde sizeof(int)es 64. Los SEU son una preocupación muy real a mayor altitud o en el espacio (debido a la mayor radiación) , o en grandes supercomputadoras (porque hay tanta memoria presente).
Josh Sanford

2
Pensar que su programa funcionará bien cuando la radiación está cambiando su memoria es una forma optimista y una forma de pensar anticatastrófica ... ¡buen comentario! :)
Luis Colorado

37

Yo diría que una expresión como

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

es más expresivo de intención de lo que es

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

El primero claramente dice que la condición es una prueba para un límite superior exclusivo en un rango; este último es una prueba binaria de una condición de salida. Y si el cuerpo del bucle no es trivial, puede que no sea evidente que el índice solo se modifica en la fordeclaración misma.


13
"Quiero que este ciclo se ejecute como máximo 5 veces" frente a "Quiero ejecutar este ciclo tantas veces como sea necesario, excepto exactamente 5 veces, que no quiero".
obispo

+1 por mencionar el límite superior en un rango. Creo que esto es importante para los rangos numéricos. ! = no define un rango adecuado en un ciclo for como estos
element11

22

Los iteradores son un caso importante cuando usas la !=notación con mayor frecuencia :

for(auto it = vector.begin(); it != vector.end(); ++it) {
 // do stuff
}

De acuerdo: en la práctica, escribiría lo mismo confiando en range-for:

for(auto & item : vector) {
 // do stuff
}

pero el punto permanece: uno normalmente compara los iteradores usando ==o !=.


2
Los iteradores a menudo solo tienen una noción de igualdad / desigualdad y no un orden, por eso los usas !=para ellos. Por ejemplo, en una std::vectorse podría utilizar <como el iterador está ligada al índice / puntero, pero en una std::setno existe tal orden estricto, ya que se acerca a un árbol binario.
Martin C.

19

La condición de bucle es un bucle forzado invariante.

Supongamos que no miras el cuerpo del bucle:

for (int i = 0; i != 5; ++i)
{
  // ?
}

en este caso, usted sabe al comienzo de la iteración del ciclo que ino es igual 5.

for (int i = 0; i < 5; ++i)
{
  // ?
}

en este caso, sabe al comienzo de la iteración del bucle que ies menor que 5.

El segundo es mucha, mucha más información que el primero, ¿no? Ahora, la intención del programador es (casi con certeza) la misma, pero si está buscando errores, tener confianza al leer una línea de código es algo bueno. Y el segundo hace cumplir esa invariante, lo que significa que algunos errores que podrían morderlo en el primer caso simplemente no pueden suceder (o no causar corrupción de memoria, por ejemplo) en el segundo caso.

Sabes más sobre el estado del programa, al leer menos código, con < que con!= . Y en las CPU modernas, toman la misma cantidad de tiempo que ninguna diferencia.

Si ino se manipuló en el cuerpo del bucle, y siempre se aumentó en 1, y comenzó menos de5 , no habría diferencia. Pero para saber si fue manipulado, tendría que confirmar cada uno de estos hechos.

Algunos de estos hechos son relativamente fáciles, pero puede equivocarse. Sin embargo, verificar todo el cuerpo del asa es un dolor.

En C ++ puedes escribir un indexestipo tal que:

for( const int i : indexes(0, 5) )
{
  // ?
}

hace lo mismo que cualquiera de los dos forbucles anteriores , incluso hasta que el compilador lo optimiza al mismo código. Aquí, sin embargo, sabes que ino se puede manipular en el cuerpo del bucle, como se declara const, sin que el código corrompa la memoria.

Cuanta más información pueda obtener de una línea de código sin tener que comprender el contexto, más fácil será rastrear lo que va mal. <en el caso de los bucles enteros, le brinda más información sobre el estado del código en esa línea que la !=que brinda .



13

Puede suceder que la variable ise establezca en un valor grande y si solo usa el !=operador, terminará en un bucle sin fin.


1
No es realmente interminable: en la mayoría de las implementaciones de C, se iajustará silenciosamente cuando esté al máximo. Pero sí, muy probablemente más de lo que estás preparado para esperar.
usr2564301

12

Como puede ver en las otras numerosas respuestas, existen razones para usar <en lugar de! = Que ayudará en casos extremos, condiciones iniciales, modificación involuntaria del contador de bucle, etc.

Honestamente, sin embargo, no creo que puedas enfatizar la importancia de la convención lo suficiente. Para este ejemplo, será bastante fácil para otros programadores ver lo que está tratando de hacer, pero provocará una doble toma. Uno de los trabajos durante la programación es hacerlo lo más legible y familiar posible para todos, por lo que inevitablemente cuando alguien tiene que actualizar / cambiar su código, no se necesita mucho esfuerzo para darse cuenta de lo que estaba haciendo en diferentes bloques de código . Si viera a alguien usar !=, supondría que hay una razón por la que lo usaron en lugar de hacerlo <y si fuera un bucle grande, miraría todo el asunto tratando de averiguar qué hiciste que hizo que fuera necesario ... y eso es tiempo perdido.


12

Como ya dijo Ian Newson, no se puede recorrer de forma confiable una variable flotante y salir con ella !=. Por ejemplo,

for (double x=0; x!=1; x+=0.1) {}

en realidad se repetirá para siempre, porque 0.1 no puede representarse exactamente en coma flotante, por lo tanto, el contador pierde por poco 1. Con < esto termina.

(Sin embargo, tenga en cuenta que es básicamente un comportamiento indefinido si obtiene 0.9999 ... como el último número aceptado, lo que viola el supuesto menor que, o si ya sale a 1.0000000000000001).


10

Considero que el adjetivo "técnico" significa comportamiento / peculiaridades del lenguaje y efectos secundarios del compilador, como el rendimiento del código generado.

Para este fin, la respuesta es: no (*). El (*) es "consulte el manual de su procesador". Si está trabajando con algún sistema RISC o FPGA de caso extremo, es posible que deba verificar qué instrucciones se generan y cuánto cuestan. Pero si usted está usando casi cualquier arquitectura moderna convencional, entonces no hay diferencia significativa nivel de procesador de costo entre lt, eq, ney gt.

Si está utilizando un caso extremo se puede encontrar que !=requiere tres operaciones ( cmp, not, beq) frente a dos ( cmp, blt xtr myo). De nuevo, RTM en ese caso.

En su mayor parte, las razones son defensivas / endurecimiento, especialmente cuando se trabaja con punteros o bucles complejos. Considerar

// highly contrived example
size_t count_chars(char c, const char* str, size_t len) {
    size_t count = 0;
    bool quoted = false;
    const char* p = str;
    while (p != str + len) {
        if (*p == '"') {
            quote = !quote;
            ++p;
        }
        if (*(p++) == c && !quoted)
            ++count;
    }
    return count;
}

Un ejemplo menos ingenioso sería donde está utilizando valores de retorno para realizar incrementos, aceptando datos de un usuario:

#include <iostream>
int main() {
    size_t len = 5, step;
    for (size_t i = 0; i != len; ) {
        std::cout << "i = " << i << ", step? " << std::flush;

        std::cin >> step;
        i += step; // here for emphasis, it could go in the for(;;)
    }
}

Pruebe esto e ingrese los valores 1, 2, 10, 999.

Podrías evitar esto:

#include <iostream>
int main() {
    size_t len = 5, step;
    for (size_t i = 0; i != len; ) {
        std::cout << "i = " << i << ", step? " << std::flush;
        std::cin >> step;
        if (step + i > len)
            std::cout << "too much.\n";
        else
            i += step;
    }
}

Pero lo que probablemente querías era

#include <iostream>
int main() {
    size_t len = 5, step;
    for (size_t i = 0; i < len; ) {
        std::cout << "i = " << i << ", step? " << std::flush;
        std::cin >> step;
        i += step;
    }
}

También hay un sesgo hacia una convención <, porque a menudo se basa en ordenar en contenedores estándar operator<, por ejemplo, el hash en varios contenedores STL determina la igualdad al decir

if (lhs < rhs) // T.operator <
    lessthan
else if (rhs < lhs) // T.operator < again
    greaterthan
else
    equal

Si lhsy rhses una clase definida por el usuario que escribe este código como

if (lhs < rhs) // requires T.operator<
    lessthan
else if (lhs > rhs) // requires T.operator>
    greaterthan
else
    equal

El implementador tiene que proporcionar dos funciones de comparación. Así se <ha convertido en el operador favorito.


Para facilitar la lectura, i + = paso debe estar en la parte de control. En el caso de que lo hicieras = 0
Mikkel Christiansen

1
Si bien eso ayudaría a la legibilidad de un buen código, quería enfatizar la falla en la versión errónea
kfsone

9

Hay varias formas de escribir cualquier tipo de código (generalmente), en este caso solo hay dos formas (tres si cuenta <= y> =).

En este caso, las personas prefieren> y <para asegurarse de que incluso si sucede algo inesperado en el bucle (como un error), no se repetirá infinitamente (MALO). Considere el siguiente código, por ejemplo.

for (int i = 1; i != 3; i++) {
    //More Code
    i = 5; //OOPS! MISTAKE!
    //More Code
}

Si usáramos (i <3), estaríamos a salvo de un bucle infinito porque coloca una restricción más grande.

Realmente es su elección si desea un error en su programa para cerrar todo o seguir funcionando con el error allí.

Espero que esto haya ayudado!


uno podría argumentar que el bucle infinito sería un buen indicador del error, pero otro argumentaría que i = 5 no es necesariamente un error
njzk2

7

La razón más común para usar <es la convención. Más programadores piensan en bucles como este como "mientras el índice está dentro del rango" en lugar de "hasta que el índice llegue al final". Hay un valor que se apega a la convención cuando puedes.

Por otro lado, muchas respuestas aquí afirman que usar el <formulario ayuda a evitar errores. Yo diría que en muchos casos esto solo ayuda a ocultar errores. Si se supone que el índice de bucle alcanza el valor final y, en cambio, en realidad va más allá, entonces está sucediendo algo que no esperaba que puede causar un mal funcionamiento (o ser un efecto secundario de otro error). La <probable que retrasar el descubrimiento del error. los!= es más probable que conduzca a una parada, bloqueo o incluso un accidente, lo que ayudará a detectar el error antes. Cuanto antes se encuentre un error, más barato será repararlo.

Tenga en cuenta que esta convención es peculiar de la indexación de matrices y vectores. Al atravesar casi cualquier otro tipo de estructura de datos, usaría un iterador (o puntero) y buscaría directamente un valor final. En esos casos, debe asegurarse de que el iterador alcance y no sobrepase el valor final real.

Por ejemplo, si está recorriendo una cadena de C simple, generalmente es más común escribir:

for (char *p = foo; *p != '\0'; ++p) {
  // do something with *p
}

que

int length = strlen(foo);
for (int i = 0; i < length; ++i) {
  // do something with foo[i]
}

Por un lado, si la cadena es muy larga, la segunda forma será más lenta porque strlenes otro paso a través de la cadena.

Con un C ++ std :: string, usaría un bucle for basado en rango, un algoritmo estándar o iteradores, incluso si la longitud está disponible. Si está utilizando iteradores, la convención es usar en !=lugar de <, como en:

for (auto it = foo.begin(); it != foo.end(); ++it) { ... }

Del mismo modo, iterar un árbol o una lista o una eliminación generalmente implica buscar un puntero nulo u otro centinela en lugar de verificar si un índice permanece dentro de un rango.


3
Tienes toda la razón al enfatizar la importancia del idioma en la programación. Si miro algún código y tiene un patrón familiar, no necesito perder el tiempo para inferir el patrón, pero puedo ir directamente al núcleo del mismo. Supongo que ese es mi enfoque principal con las comparaciones de Yoda: no parecen idiomáticas, por lo que termino teniendo que leerlas dos veces para asegurarme de que significan lo que creo que significan.
Toby Speight

7

Una razón para no usar esta construcción son los números de coma flotante. !=Es una comparación muy peligrosa para usar con flotadores, ya que rara vez se evaluará como verdadero incluso si los números se ven iguales. <o >elimina este riesgo.


Si su iterador de bucle es un número de coma flotante, entonces el !=versus <es el menor de sus problemas.
Lundin

7

Hay dos razones relacionadas para seguir esta práctica que tienen que ver con el hecho de que un lenguaje de programación es, después de todo, un lenguaje que será leído por los humanos (entre otros).

(1) Un poco de redundancia. En lenguaje natural, generalmente proporcionamos más información de la estrictamente necesaria, como un código de corrección de errores. Aquí, la información adicional es que la variable de bucle i(¿ve cómo utilicé la redundancia aquí? Si no sabía lo que significa "variable de bucle", o si olvidó el nombre de la variable, después de leer "variable de bucle i" tiene el nombre completo información) es inferior a 5 durante el ciclo, no solo diferente de 5. La redundancia mejora la legibilidad.

(2) Convención. Los idiomas tienen formas estándar específicas de expresar ciertas situaciones. Si no sigue la forma establecida de decir algo, aún se lo entenderá, pero el esfuerzo para el destinatario de su mensaje es mayor porque ciertas optimizaciones no funcionarán. Ejemplo:

No hables de la mezcla caliente. ¡Solo ilumina la dificultad!

La primera oración es una traducción literal de un idioma alemán. El segundo es un idioma común en inglés con las palabras principales reemplazadas por sinónimos. El resultado es comprensible, pero lleva mucho más tiempo comprenderlo que esto:

No andes por las ramas. ¡Solo explica el problema!

Esto es cierto incluso en el caso de que los sinónimos utilizados en la primera versión se ajusten mejor a la situación que las palabras convencionales en el idioma inglés. Fuerzas similares están en vigor cuando los programadores leen el código. Esta es también la razón 5 != iy 5 > ison formas extrañas de expresarlo a menos que esté trabajando en un entorno en el que es estándar intercambiar lo más normal i != 5y i < 5de esta manera. Tales comunidades dialectales existen, probablemente porque la consistencia hace que sea más fácil recordar escribir en 5 == ilugar de ser natural pero propenso a errores i == 5.


1
Ausgezeichnet . Del mismo modo, uno no escribiría la prueba como i < 17+(36/-3)(incluso cuando estas son constantes utilizadas en otro lugar; ¡entonces debe escribir sus nombres para mayor claridad!).
usr2564301

6

El uso de comparaciones relacionales en tales casos es más un hábito popular que cualquier otra cosa. Ganó su popularidad en los tiempos en que consideraciones conceptuales como las categorías de iteradores y su comparabilidad no se consideraban de alta prioridad.

Yo diría que uno debería preferir usar comparaciones de igualdad en lugar de comparaciones relacionales siempre que sea posible, ya que las comparaciones de igualdad imponen menos requisitos a los valores que se comparan. Ser EqualityComparable es un requisito menor que ser LessThanComparable .

Otro ejemplo que demuestra la aplicabilidad más amplia de la comparación de igualdad en tales contextos es el enigma popular con la implementación de unsignediteración hasta 0. Se puede hacer como

for (unsigned i = 42; i != -1; --i)
  ...

Tenga en cuenta que lo anterior es igualmente aplicable a la iteración con signo y sin signo, mientras que la versión relacional se desglosa con tipos sin signo.


2

Además de los ejemplos, donde la variable de bucle cambiará (no intencionalmente) dentro del cuerpo, existen otras razones para usar los operadores más pequeños o más grandes que:

  • Las negaciones hacen que el código sea más difícil de entender
  • <o >es solo un char, pero !=dos

44
La segunda bala es, en el mejor de los casos, una razón frívola. El código debe ser correcto y claro. Compacto es mucho menos importante.
Jonathan Leffler

@JonathanLeffler Bueno, en un TDD REPL, ese personaje adicional es un nano-segundo adicional para el análisis, y multiplicado por mil millones de iteraciones para encontrar el error causado por la escritura 5 != $i, que solo me llevó un segundo entero de mi vida. Uh ... risita
obispo

1

Además de las diversas personas que han mencionado que mitiga el riesgo, también reduce la cantidad de sobrecargas de funciones necesarias para interactuar con varios componentes estándar de la biblioteca. Como ejemplo, si desea que su tipo se pueda almacenar en std::set, o se use como una clave std::map, o se use con algunos de los algoritmos de búsqueda y clasificación, la biblioteca estándar generalmente se usa std::lesspara comparar objetos, ya que la mayoría de los algoritmos solo necesitan un orden débil estricto . Por lo tanto, se convierte en un buen hábito usar las <comparaciones en lugar de las !=comparaciones (donde tiene sentido, por supuesto).


1
puede tener razón sobre el número de sobrecargas, pero al considerar los requisitos de los objetos, entonces para casi cualquier objeto se puede definir un !=operador, pero no siempre es posible definir un orden estricto y débil. En este sentido !=, sería mejor, ya que impone menos requisitos al tipo. Sin embargo, todavía me quedo con el <.
idclev 463035818

0

No hay problema desde una perspectiva de sintaxis, pero la lógica detrás de esa expresión 5!=i no es sólida.

En mi opinión, usar !=para establecer los límites de un bucle for no es lógicamente correcto porque un bucle for aumenta o disminuye el índice de iteración, por lo que configurar el bucle para iterar hasta que el índice de iteración se salga de los límites (!= a algo) no es un Implementación adecuada.

Se va a trabajar, pero es propenso al mal comportamiento ya que el manejo de los datos límite se pierde cuando se utiliza !=para un problema incrementales (lo que significa que usted sabe desde el principio si vale incrementos o decrementos), por eso en lugar de !=la <>>==>se utilizan.


2
La lógica está perfectamente bien. Cuando ies 5el ciclo sale. ¿Querías decir algo más?
Dan Getz

1
Si los datos no se transfieren correctamente debido al calor, electro.magnetic influye en que su código se ejecute para siempre. Si hace esto en una estación de trabajo o servidor normal con RAM ECC, no hay problema (ni lógico, técnico ni físico)
Markus
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.