¿Cuál es la forma “correcta” de escribir un bucle decreciente con un valor de tamaño_t y una condición de contorno? Ejemplo de implementación incorrecta:
for (size_t elemNum = listSize-1; elemNum >= 0; --elemNum) { /* ... */ }
Cuando llegue a cero, volverá al valor máximo en lugar de actuar como una condición límite. Es necesario iterar el bucle a la inversa. Parece un problema que tendría una solución estándar de facto, pero no puedo encontrar cuál es.
El enfoque más sucinto es usar post-incremento:
for (size_t i = listSize; i--;) ...
-
umm, esto no se comportará de manera diferente a –i?
– Jaime
28 de agosto de 2011 a las 22:37
-
oh, ya veo, el incremento está en la condición. Culpa mía
– Jaime
28 de agosto de 2011 a las 22:39
-
Creo que funciona, pero en mi opinión, usar un bucle while como sugirió pmg es más fácil de entender que “usarlo incorrectamente” de esa manera.
– Medo42
28 de agosto de 2011 a las 22:40
-
@ Medo42: ¿Cómo es que el enfoque de ciclo while es menos un “mal uso”? Además, amplía el alcance de la variable de bucle más allá del bucle, lo que es mal karma.
– Marcelo Cantos
28 de agosto de 2011 a las 22:43
-
Me gusta más esta solución. Siempre que se entienda el operador “va a” mencionado en el otro comentario, puedo hacerlo aún más claro como:
for (size_t i = listSize; i --> 0;) { /* ... */ }
– Mark Langen
29 de agosto de 2011 a las 19:52
elemNum = listsize;
while (elemNum--) {
/* work with elemNum varying from `listsize - 1` down to `0` */
}
-
Algunos compiladores admiten el operador especial “va a”,
while (elemNum --> 0) { /* ... */ }
para este propósito.– KerrekSB
28 de agosto de 2011 a las 22:50
-
@Kerrek: creo que te refieres a todos los compiladores que cumplen con el estándar 🙂
– pmg
28 de agosto de 2011 a las 22:53
-
@pmg, un pequeño detalle aquí: el
elemNum
no será 0 después de esto (habrá un ajuste justo después de la última iteración). Dado que el autor de la preguntafor
el bucle ni siquiera hizoelemNum
visible fuera del bucle, probablemente no importe, pero es (muy ligeramente) más limpio hacer la disminución como primera línea dentro del bucle.–Branko Dimitrijevic
28 de agosto de 2011 a las 23:05
-
@Branko No creo que sea un pequeño detalle, sino un contraargumento real. Variables de índice local en
for
los bucles tienen razones, por lo que esta respuesta aquí no es apropiada.– Jens Gusted
29 de agosto de 2011 a las 7:03
No conozco una forma estándar, pero esto debería funcionar:
for (size_t elemNum = listSize-1; elemNum < listSize; --elemNum) { /* ... */ }
-
Esa es una manera bastante ordenada de hacerlo.
– Jaime
28 de agosto de 2011 a las 22:34
-
no, es una forma bastante ofuscada. es tan feo que me gustaría votarlo negativo .. :/
–Karoly Horvath
28 de agosto de 2011 a las 22:37
-
Bueno, no lo veo nada complicado. Lo veo muy elegante e inteligente.
– Diego Sevilla
28 de agosto de 2011 a las 22:40
-
Creo que la solución de pmg es la mejor hasta ahora y la recomendaría sobre la mía.
– Medo42
28 de agosto de 2011 a las 22:42
-
Este enfoque es frágil. El tipo de la variable de bucle puede cambiar más tarde (p. ej., un programador de mantenimiento puede hacerlo para resolver las advertencias de comparación de tipos y puede olvidarse de inspeccionar correctamente el código), y entonces todas las apuestas están canceladas.
– Marcelo Cantos
28 de agosto de 2011 a las 22:46
Podrías usar dos variables en su lugar:
size_t count = 0;
for (size_t elemNum = listSize-1; count < listSize; ++count, --elemNum) { /* ... */ }
for (size_t counter = listSize; counter > 0; --counter) {
size_t index = counter-1;
/* ... use `index` as an index ... */
}
branco dimitrijevic
size_t elemNum = listSize;
while (elemNum > 0) {
--elemNum;
// Do your work here.
}
Jaime
Podrías usar esto como la condición:
elemNum != (size_t)-1
O podría contar y hacer algunos cálculos (que el compilador probablemente optimizará de todos modos) para su índice:
for (size_t i = 1; i <= listSize; i++) {size_t elemNum = listSize-i; /* */}