Nunca visto antes C++ para bucle

Estaba convirtiendo un algoritmo de C++ a C#. Encontré esto para bucle:

for (u = b.size(), v = b.back(); u--; v = p[v]) 
b[u] = v;

No da ningún error en C++, pero sí en C# (no se puede convertir int a bool). Realmente no puedo entender esto para el ciclo, ¿dónde está la condición?

¿Alguien puede explicarme?

PD. Solo para verificar, para adaptar un VECTOR a una LISTA, ¿b.back() corresponde a b[b.Count-1]?

preguntado el 31 de julio de 12 a las 12:07

¿Dónde está la condición? Eso sería u--. Los puntos y comas se utilizan para delimitar las distintas partes del for declaración. -

Este es un bucle bastante normal. C# no convierte números a booleanos implícitamente, por lo que debe convertir la condición en ; u-- != 0; -

@Jessie Good: el buen código no tiene nada que ver con lo que está permitido en el idioma, tiene que ver con el tiempo que tarda un compañero de trabajo desconocido en leer el código. Si causa algún tipo de confusión, no es la mejor solución posible, incluso si es legal. A menudo, una solución más detallada es mucho mejor que una concisa, y la mayoría de los compiladores compilarán lo mismo de cualquier manera. -

Espero que, después de convertir el código, le des a las variables mejores nombres que b, u, v, etc. La única razón por la que fueron nombrados de esta manera es porque alguien quería parecer inteligente al hacer que su código fuera ilegible. -

@houbysoft: este es un problema general de desbordamiento de pila. Si hace una pregunta muy detallada, bien investigada e interesante en un dominio de investigación específico, que conduce a una solución a un problema difícil e interesante, y responde a esa pregunta después de un arduo día de investigación, obtendrá solo unos pocos docena de visitantes y uno o dos votos a favor de algunos expertos en el campo. Si desea obtener muchas repeticiones rápidamente, debe hacer y responder preguntas como estas. "¿Cómo agrego dos números en php?", "¿Qué significa do significa en C++" - obtendrá miles de visitas de principiantes que buscan un tutorial. -

12 Respuestas

La condición de la for el bucle está en el medio - entre los dos puntos y comas ;.

En C++ está bien poner casi cualquier expresión como condición: cualquier cosa que evalúe a cero significa false; medios distintos de cero true.

En su caso, la condición es u--: cuando convierta a C#, simplemente agregue != 0:

for (u = b.size(), v = b.back(); u-- != 0; v = p[v]) 
    b[u] = v; //                     ^^^^ HERE

Respondido 31 Jul 12, 12:07

Por cierto, es posible que Thomas también se haya confundido con el uso de la coma, es muy diferente al punto y coma, le permite hacer varias cosas en una sección del bucle for (en este caso, inicializó dos variables). La última vez que verifiqué estas construcciones inusuales no se consideraron la solución más legible posible y, por lo tanto, algunos pueden desaprobarlos. - Bill K

Si no recuerdo mal, una expresión que contiene una coma tiene el valor de la última subexpresión de la derecha. Esto viene de C y se puede usar en cualquier expresión, no solo en un bucle for. - Giorgio

@Roger Este no sería el mismo bucle ya que está disminuyendo u al final del bucle, en lugar del principio (es decir, después de b[u] = v en lugar de antes). De hecho, necesitaría inicializarlo con u = b.size() - 1 en lugar de. - didier l

Para tu información: te acabo de empujar por encima del límite de 500K. ¿Es como ser el cliente número un millón en algún lugar y ganar algo? En cualquier caso: muchas felicidades; ¡siempre esperando sus respuestas precisas y nítidas! Sigue adelante; Te veo haciendo la cosa de 1 millón... a finales de este siglo. - gato fantasma

Muchas respuestas precisas, pero creo que vale la pena escribir el ciclo while equivalente.

for (u = b.size(), v = b.back(); u--; v = p[v]) 
   b[u] = v;

Es equivalente a:

u = b.size();
v = b.back();
while(u--) {
   b[u] = v;
   v = p[v];
}

Podría considerar la refactorización al formato while() a medida que traduce a C#. En mi opinión, es más claro, menos trampa para los nuevos programadores e igualmente eficiente.

Como han señalado otros, pero para que mi respuesta sea completa, para que funcione en C #, necesitaría cambiar while(u--) a while(u-- != 0).

... o while(u-- >0) en caso de que comience negativo. (OK, b.size() nunca será negativo, pero considere un caso general en el que tal vez algo más inicializó u).

O, para que quede aún más claro:

u = b.size();
v = b.back();
while(u>0) {
   u--;
   b[u] = v;
   v = p[v];
}

Es mejor ser claro que ser conciso.

Respondido 02 ago 12, 14:08

Esta respuesta no solo aclara el código incorrecto, sino que también brinda una buena alternativa. ¡¡1 de ventaja!! - polvoazul

Aparte, tendría cuidado con el while (u-- >0) forma. Si el espacio se estropea, puede terminar con un bucle "hasta cero": while (u --> 0), que tiende a confundir a todos a primera vista. (No estoy seguro de si es C# válido, pero está en C, y creo que también puede serlo en C++.) - Izkatá

No creo que tu código sea necesariamente más claro. El punto de for en lugar de while es precisamente que pones la inicialización y el incremento/decremento en una declaración, y eso no necesariamente hace que el código sea más difícil de entender. De lo contrario, no deberíamos estar usando for en absoluto. - músico

También es importante reescribir la menor cantidad de código posible. (Después de todo, el bucle for podría cambiar). Has puesto "u--" en dos lugares separados, y el bucle no es realmente más claro (puedo ver lo que hace el bucle for de un vistazo; tengo que escanear con varias líneas). Ser conciso también tiene beneficios. No los minimices. Aún así, es un buen ejemplo de cómo se podría escribir. Hace que sea más fácil de entender para cualquiera que no esté acostumbrado a las declaraciones en C++ (o tal vez incluso en absoluto). - NoKyon

@Izkata: NUNCA es un operador, se analiza como un -- token seguido de un > simbólico. Dos operadores separados. Un ciclo "hasta cero" es solo una combinación directa de post-decremento y mayor que. La sobrecarga de operadores de C++ no crea nuevos operadores, solo reutiliza los existentes. - ben voigt

La condición es u--;, porque está en la segunda posición de la por instrucción.

Si el valor de u--; es diferente de 0, se interpretará como true (es decir, moldeado implícitamente al valor booleano true). Si, en cambio, su valor es 0, se convertirá a false.

Es código muy malo.

Actualizar: Discutí la escritura de bucles "for" en este blog. Sus recomendaciones pueden resumirse en los siguientes párrafos:

Un ciclo for es una construcción práctica, legible (una vez que te acostumbras) y concisa, pero debes usarla bien. Debido a su sintaxis poco común, usarlo de una manera demasiado imaginativa no es una buena idea.

Todas las partes del ciclo for deben ser cortas y legibles. Los nombres de las variables deben elegirse para que sea fácil de entender.

Este ejemplo claramente viola estas recomendaciones.

contestado el 23 de mayo de 17 a las 13:05

¿O se detendrá en u == 0 probablemente...? - Thomas

No; en C++ hay una conversión implícita de int a bool, con 0 convirtiéndose en falso. El ciclo terminará cuando u-- == 0. En C#, no existe tal conversión implícita, por lo que tendría que decir explícitamente u-- == 0. EDITAR: Esto es en respuesta a su primer comentario. - Chris

Es terrible código, por una razón muy simple; no podías comprenderlo fácilmente cuando lo leías. Es "inteligente", un "truco"; hace uso de una combinación de estructuras de codificación y el conocimiento de cómo funcionan entre bastidores, para crear una estructura que hace el trabajo pero que desafía la comprensión, porque no está en la forma que los autores del lenguaje imaginaron y que se comunicó a la mayoría. usuarios de la lengua. - keiths

Excelente respuesta Le daría +1... si no el "Este es un código muy malo". declaración ;) - Sandman4

No entiendo por qué tanta gente parece pensar tu-- es un código realmente malo simplemente porque falta (implícito en C++) ! = 0. Seguro que cualquiera que trabaje con código sabrá perfectamente que 0=falso, cualquier otro valor=verdadero. Hay mucho más margen para la confusión con respecto al incremento previo/posterior de u, o la gente tal vez asumiendo que u = b.tamaño() detectarás siempre ejecutar antes v = b.atrás() (Tengo entendido que la secuencia de ejecución no está definida, pero espero que me corrijan). - FumbleFingers

u = b.size(), v = b.back()

es inicialización.

u--

es la condición.

v = p[v]

es la iteración

Respondido el 02 de junio de 16 a las 12:06

for (u = b.size(), v = b.back(); u--; v = p[v]) 
   b[u] = v;

En el código anterior, u y v se inicializan con b.size() y b.back().

Cada vez que se verifica la condición, también ejecuta la declaración de decremento, es decir u--.

Los programas for el bucle saldrá cuando u se convertirá 0.

Respondido el 18 de diciembre de 17 a las 17:12

Esta será la forma C# de su ciclo.

// back fetches the last element of vector in c++.
for (u = b.size(), v = b.back(); (u--) != 0; v = p[v]) 
{      
  b[u] = v;      
}

Simplemente reemplace el equivalente para size() y back().

Lo que hace es invertir la lista y almacenarla en una matriz. Pero en C# tenemos directamente una función definida por el sistema para esto. Por lo tanto, no necesita escribir este ciclo también.

b = b.Reverse().ToArray();

Respondido 01 ago 12, 14:08

tomando v = b.back(); fuera del inicializador for, ¿no acaba de cambiar la forma en que funciona, ya que el v = p[v] es anulado por - João Portela

v = p[v] no tendrá ningún efecto en el resultado final ya que esta línea se ejecutará al final. Y después de eso, v no se menciona en el ciclo. Esta línea está ahí solo para mostrar cómo se convierte el bucle de C++ a C#. - Narendra

en el codigo c++ v = b.back(); se ejecutó una vez antes de que comenzaran las iteraciones y v = p[v] se ejecuta al principio de cada iteración. En esa versión de C# v = p[v] todavía se ejecuta al comienzo de cada iteración, pero v = b.back(); se ejecuta justo después, cambiando el valor de v para la próxima instrucción b[u] = v;. (tal vez la pregunta fue editada después de leerla) - João Portela

@Rain El problema es v = b.back(). Lo tiene ejecutándose en cada iteración de bucle en lugar de solo en la primera, no sabemos qué back() hace (¿hay efectos secundarios? ¿Cambia la representación interna de b?), por lo que este bucle es no equivalente al de la pregunta. - Izkatá

@Rain Exactamente, échale un vistazo más de cerca tú mismo. los inicialización el paso ocurre solo una vez antes de que comience el bucle, no al comienzo de cada iteración. Su código sería correcto si v = b.back() se movió fuera del bucle, por encima de él. (Además, si está tratando de responderle a alguien, use @ delante de su nombre, por lo que recibimos una notificación) - Izkatá

La condición es el resultado de u--, que es el valor de u antes de que se decremente.

En C y C++, un int is convertible a bool implícitamente haciendo un != 0 comparación (0 es false, todo lo demás es true).

b.back() es el último elemento en un contenedor, que es b[b.size() - 1], Cuando size() != 0.

Respondido 31 Jul 12, 12:07

En C todo lo que no es cero es true en contextos "booleanos", como la condición de fin de ciclo o una declaración condicional. En C# tienes que hacer ese cheque explícito: u-- != 0.

Respondido 31 Jul 12, 12:07

Esta no es la cuestión de OP. Está preguntando sobre la evaluación de la condición terminal (es decir, 'u--' en este caso). - Pie de manzana

Como han dicho otros, el hecho de que C++ tenga conversión implícita a booleano significa que el condicional es u--, que será cierto si el valor es distinto de cero.

Vale la pena agregar que tiene una suposición falsa al preguntar "dónde está el condicional". Tanto en C++ como en C# (y otros lenguajes de sintaxis similar) puede tener un condicional vacío. En este caso, siempre se evalúa como verdadero, por lo que el ciclo continúa para siempre, o hasta que salga alguna otra condición (a través de return, breako throw).

for(int i = 0; ; ++i)
  doThisForever(i);

De hecho, cualquier parte de la declaración for puede omitirse, en cuyo caso simplemente no se ejecuta.

En general, un software de chat en vivo es ideal para todas las organizaciones, ya que permite conocer de cerca a la audiencia, identificar los problemas que están experimentando y resolverlos para aumentar la lealtad a la marca, la credibilidad y las valoraciones de satisfacción. for(A; B; C){D} or for(A; B; C)D; se convierte en:

{A}
loopBack:
if(!(B))
  goto escapeLoop;
{D}
{C}
goto loopBack;
escapeLoop:

Se puede omitir uno o más de A, B, C o D.

Como resultado de esto, algún favor for(;;) para bucles infinitos. lo hago porque mientras while(true) es más popular, lo leí como "hasta que la verdad deje de ser verdad", lo que suena algo apocalíptico en comparación con mi lectura for(;;) como "para siempre".

Es cuestion de gustos, pero como no soy la unica persona en el mundo que le gusta for(;;) vale la pena saber lo que significa.

Respondido 28 ago 12, 01:08

todas las respuestas son correctas :-

for loop se puede utilizar de varias maneras, como se indica a continuación:

Single Statement inside For Loop
Multiple Statements inside For Loop
No Statement inside For Loop
Semicolon at the end of For Loop
Multiple Initialization Statement inside For
Missing Initialization in For Loop
Missing Increment/Decrement Statement
Infinite For Loop
Condition with no Conditional Operator.

Respondido 23 ago 12, 10:08

El error encontrado en el propio C# despeja la duda. El bucle for busca un

FALSO

condición para terminar. Y como sabemos,

(BOOL) FALSO = (int) 0

pero C# no puede procesar esto por sí solo a diferencia de C++. Así que la condición que está buscando es

tu--

pero tienes que dar explícitamente la condición en C# como

tu-- != 0

or

tu-- > 0

Pero aún trate de evitar este tipo de práctica de codificación. los

mientras bucle

indicado anteriormente en la respuesta es una de las versiones más simplificadas de su

en bucle.

Respondido 23 ago 12, 08:08

@Downvoter: Votar a la baja está bien en la medida en que no esté satisfecho con la solución, pero al mismo tiempo, tómese el tiempo para indicar el motivo, para que las respuestas puedan mejorar. - Abhinet

Si está acostumbrado a C/C++, este código no es tan difícil de leer, aunque es bastante conciso y no tan bueno como código. Así que déjame explicarte las partes que son más Cismo que cualquier otra cosa. En primer lugar, la sintaxis general de un bucle C for se ve así:

for (<initialization> ; <condition>; <increment>)
{
    <code...>
}

El código de inicialización se ejecuta una vez. Luego, la condición se prueba antes de cada ciclo y, por último, se llama al incremento después de cada ciclo. Así que en tu ejemplo encontrarás que la condición es u--

Por que u-- ¿funciona como una condición en C y no en C#? Porque C implícitamente convierte muchas cosas demasiado bools y puede causar problemas. Para un número, todo lo que no sea cero es verdadero y el cero es falso. Por lo tanto, contará hacia atrás desde b.size () -1 a 0. Tener el efecto secundario en la condición es un poco molesto y sería preferible ponerlo en la parte de incremento del ciclo for, aunque mucho C código hace esto. Si yo estuviera escribiendo lo haría más así:

for (u = b.size() - 1, v = b.back(); u>=0; --u) 
{
    b[u] = v;
    v = p[v]
}

La razón de esto es, al menos para mí, es más clara. Cada parte del ciclo for hace su trabajo y nada más. En el código original la condición modificaba la variable. La parte de incremento estaba haciendo algo que debería estar en el bloque de código, etc.

El operador de coma también puede estar tirándote de un bucle. En C algo como x=1,y=2 parece una declaración en lo que respecta al compilador y encaja en el código de inicialización. Simplemente evalúa cada una de las partes y devuelve el valor de la última. Así por ejemplo:

std::cout << "(1,2)=" << (1,2) << std::endl;

imprimiría 2.

Respondido 27 ago 12, 18:08

El problema con su reescritura es que si b.size() no está firmado, iterará durante mucho tiempo. (Además, te falta un punto y coma). Pero al menos no tomaste el enfoque "'Dick and Jane' es un buen inglés" que hicieron muchas de las otras respuestas y comentarios, elogiando las reescrituras absurdamente detalladas que son solo más fáciles. para leer por neófitos y otros programadores inexpertos. - jim balter

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.