while form espaƱol diferencia c# c++ c while-loop do-while

c# - form - ''do... while'' vs. ''while''



do while c# windows form (27)

Cualquier tipo de entrada de consola funciona bien con do-while porque se solicita la primera vez y se vuelve a solicitar cada vez que falla la validación de entrada.

Posibles duplicados:
Mientras que vs. Do While
¿Cuándo debería usar do-while en vez de while while?

He estado programando desde hace un tiempo (2 años de trabajo + 4.5 años de grado + 1 año de preuniversitario), y nunca he utilizado un ciclo de do-while antes de ser forzado a participar en el curso de introducción a la programación. Tengo una sensación creciente de que estoy haciendo mal la programación si nunca me encuentro con algo tan fundamental.

¿Podría ser que no me he encontrado con las circunstancias correctas?

¿Cuáles son algunos ejemplos en los que sería necesario usar un do-while en lugar de un tiempo?

(Mi escolaridad fue casi todo en C / C ++ y mi trabajo está en C #, así que si hay otro idioma en el que tiene sentido porque doiled funciona de manera diferente, entonces estas preguntas realmente no se aplican).

Para aclarar ... sé la diferencia entre un while y un do-while . Mientras comprueba la condición de salida y luego realiza tareas. do-while realiza tareas y luego verifica la condición de salida.


El escenario más común en el que me encuentro cuando uso un ciclo do / while es en un pequeño programa de consola que se ejecuta en función de una entrada y se repetirá tantas veces como quiera el usuario. Obviamente, no tiene sentido que un programa de consola se ejecute ninguna vez; pero más allá de la primera vez depende del usuario, por do tanto, do / en lugar de hacerlo solo.

Esto le permite al usuario probar un montón de entradas diferentes si lo desea.

do { int input = GetInt("Enter any integer"); // Do something with input. } while (GetBool("Go again?"));

Sospecho que los desarrolladores de software usan cada vez menos estos días, ahora que prácticamente todos los programas bajo el sol tienen una GUI de algún tipo. Tiene más sentido con las aplicaciones de consola, ya que es necesario actualizar continuamente la salida para proporcionar instrucciones o solicitar al usuario nueva información. Con una GUI, en cambio, el texto que proporciona esa información al usuario solo puede sentarse en un formulario y nunca debe repetirse mediante programación.


Es tan simple como eso:

precondición vs poscondición

  • while (cond) {...} - condición previa, ejecuta el código solo después de verificar.
  • do {...} while (cond) - postcondición, el código se ejecuta al menos una vez.

Ahora que conoces el secreto ... úsalo sabiamente :)


Es una estructura bastante común en un servidor / consumidor:

DOWHILE (no shutdown requested) determine timeout wait for work(timeout) IF (there is work) REPEAT process UNTIL(wait for work(0 timeout) indicates no work) do what is supposed to be done at end of busy period. ENDIF ENDDO

REPEAT UNTIL(cond) siendo un do {...} while(!cond)

A veces, la espera de trabajo (0) puede ser más económica para la CPU (incluso la eliminación del cálculo del tiempo de espera puede ser una mejora con tasas de llegada muy altas). Además, hay muchos resultados de la teoría de colas que hacen que el número servido en un período ocupado sea una estadística importante. (Véase, por ejemplo, Kleinrock - Vol 1.)

Similar:

DOWHILE (no shutdown requested) determine timeout wait for work(timeout) IF (there is work) set throttle REPEAT process UNTIL(--throttle<0 **OR** wait for work(0 timeout) indicates no work) ENDIF check for and do other (perhaps polled) work. ENDDO

donde check for and do other work puede ser exorbitantemente costoso para poner en el ciclo principal o quizás un núcleo que no admite una operación de tipo waitany(waitcontrol*,n) eficiente o tal vez una situación en la que una cola priorizada pueda matar de hambre el otro trabajo y el acelerador se usa como control de inanición.

Este tipo de equilibrio puede parecer un truco, pero puede ser necesario. El uso ciego de grupos de hilos frustraría completamente los beneficios de rendimiento del uso de un hilo provisional con una cola privada para una estructura de datos complicada de alta tasa de actualización, ya que el uso de un grupo de subprocesos en lugar de un hilo interino requeriría una implementación segura.

Realmente no quiero entrar en un debate sobre el pseudo código (por ejemplo, si el shutdown solicitado debe probarse en el UNTIL) o los subprocesos del guardián versus los grupos de subprocesos; esto solo pretende dar un sabor de un caso de uso particular de la estructura de flujo de control.


Esta es mi opinión personal, pero esta pregunta exige una respuesta arraigada en la experiencia:

  • He estado programando en C durante 36 años, y nunca uso bucles do / while en el código normal.

  • El único uso convincente para esta construcción es en macros donde puede envolver múltiples declaraciones en una sola declaración a través de un do { multiple statements } while (0)

  • He visto innumerables ejemplos de bucles do / while con detección de errores falsos o llamadas a funciones redundantes.

  • Mi explicación para esta observación es que los programadores tienden a modelar los problemas incorrectamente cuando piensan en términos de loops do / while. O pierden una condición final importante o se pierden la posible falla de la condición inicial que mueven hasta el final.

Por estas razones, he llegado a creer que cuando hay un ciclo do / while, hay un error y regularmente desafío a los programadores novatos para que me muestren un ciclo do / while donde no puedo detectar un error cercano.

Este tipo de bucle se puede evitar fácilmente: use a for (;;) { ... } y agregue las pruebas de finalización necesarias donde sean apropiadas. Es bastante común que haya más de una prueba de ese tipo.

Aquí hay un ejemplo clásico:

/* skip the line */ do { c = getc(fp); } while (c != ''/n'');

Esto fallará si el archivo no termina con una nueva línea. Un ejemplo trivial de dicho archivo es el archivo vacío.

Una mejor versión es esta:

int c; // another classic bug is to define c as char. while ((c = getc(fp)) != EOF && c != ''/n'') continue;

Alternativamente, esta versión también oculta la variable c :

for (;;) { int c = getc(fp); if (c == EOF || c == ''/n'') break; }

Intente buscar while (c != ''/n''); en cualquier motor de búsqueda, y encontrará errores como este (recuperado el 24 de junio de 2017):

En ftp://ftp.dante.de/tex-archive/biblio/tib/src/streams.c , la función getword(stream,p,ignore) , tiene un do / while y, por supuesto, al menos 2 bugs:

  • c se define como un char y
  • hay un bucle infinito potencial while (c!=''/n'') c=getc(stream);

Conclusión: evite los bucles do / while y busque errores cuando vea uno.


Esta es mi teoría de por qué la mayoría de la gente (incluyéndome a mí) prefiere while () {} loops para {} while (): Un ciclo while () {} puede adaptarse fácilmente para funcionar como un ciclo do..while () mientras que lo opuesto no es verdad. Un ciclo while es en cierto modo "más general". También a los programadores les gustan los patrones fáciles de captar. Un ciclo while dice al principio qué es su invariante y esto es algo bueno.

Esto es lo que quiero decir sobre lo "más general". Toma este ciclo de hacer ... mientras:

do { A; if (condition) INV=false; B; } while(INV);

Transformar esto en un ciclo while es sencillo:

INV=true; while(INV) { A; if (condition) INV=false; B; }

Ahora, tomamos un ciclo model while:

while(INV) { A; if (condition) INV=false; B; }

Y transforma esto en un bucle do..while, cede esta monstruosidad:

if (INV) { do { A; if (condition) INV=false; B; } while(INV) }

Ahora tenemos dos controles en los extremos opuestos y si el invariante cambia debe actualizarlo en dos lugares. En cierto modo, hazlo ... es como los destornilladores especializados en la caja de herramientas que nunca usas, porque el destornillador estándar hace todo lo que necesitas.


Esta es una especie de respuesta indirecta, pero esta pregunta me hizo pensar en la lógica detrás de esto, y pensé que valía la pena compartirlo.

Como todos han dicho, utilizas un bucle do ... while while cuando quieras ejecutar el cuerpo al menos una vez. Pero, ¿bajo qué circunstancias querrías hacer eso?

Bueno, la clase más obvia de situaciones en las que puedo pensar sería cuando el valor inicial ("sin primacía") de la condición de verificación es el mismo que cuando se quiere salir . Esto significa que debe ejecutar el cuerpo del bucle una vez para cebar la condición a un valor que no sea de salida, y luego realizar la repetición real en función de esa condición. Como los programadores son tan flojos, alguien decidió envolver esto en una estructura de control.

Entonces, por ejemplo, leer caracteres de un puerto serie con un tiempo de espera puede tomar la forma (en Python):

response_buffer = [] char_read = port.read(1) while char_read: response_buffer.append(char_read) char_read = port.read(1) # When there''s nothing to read after 1s, there is no more data response = ''''.join(response_buffer)

Tenga en cuenta la duplicación de código: char_read = port.read(1) . Si Python tuviera un do ... while loop, podría haber usado:

do: char_read = port.read(1) response_buffer.append(char_read) while char_read

El beneficio adicional para los lenguajes que crean un nuevo alcance para los bucles: char_read no contamina el espacio de nombres de la función. Pero tenga en cuenta también que hay una mejor manera de hacerlo, y eso es mediante el uso del valor None de Python:

response_buffer = [] char_read = None while char_read != '''': char_read = port.read(1) response_buffer.append(char_read) response = ''''.join(response_buffer)

Así que aquí está el quid de mi punto: en idiomas con tipos que initial_value == exit_value , la situación initial_value == exit_value surge con mucha menos frecuencia, y esa puede ser la razón por la que no la encuentras. No estoy diciendo que nunca ocurra, porque todavía hay momentos en que una función devolverá None para significar una condición válida. Pero en mi opinión apresurada y brevemente considerada, esto pasaría mucho más si los idiomas que usabas no permitieran un valor que signifique: esta variable aún no se ha inicializado.

Este no es un razonamiento perfecto: en realidad, ahora que los valores nulos son comunes, simplemente forman un elemento más del conjunto de valores válidos que una variable puede tomar. Pero, en la práctica, los programadores tienen una manera de distinguir entre una variable que está en estado sensible, que puede incluir el estado de salida de bucle, y que está en un estado no inicializado.


Estoy programando alrededor de 12 años y hace solo 3 meses me encontré con una situación en la que era realmente conveniente usar do-while ya que siempre era necesaria una iteración antes de verificar una condición. Así que adivina tu gran momento está por delante :).


Hacer mientras es útil para cuando quiere ejecutar algo al menos una vez. En cuanto a un buen ejemplo para usar do while vs. while, digamos que desea hacer lo siguiente: Una calculadora.

Puede abordar esto utilizando un ciclo y verificando después de cada cálculo si la persona quiere salir del programa. Ahora probablemente pueda suponer que una vez que se abra el programa, la persona quiere hacer esto al menos una vez para que pueda hacer lo siguiente:

do { //do calculator logic here //prompt user for continue here } while(cont==true);//cont is short for continue


He usado un do while cuando estoy leyendo un valor de centinela al principio de un archivo, pero aparte de eso, no creo que sea anormal que esta estructura no se use con demasiada frecuencia, do-while s are realmente situacional.

-- file -- 5 Joe Bob Jake Sarah Sue -- code -- int MAX; int count = 0; do { MAX = a.readLine(); k[count] = a.readLine(); count++; } while(count <= MAX)


Las respuestas hasta ahora resumen el uso general de do-while. Pero el OP pidió un ejemplo, así que aquí hay uno: obtener la opinión del usuario. Pero la entrada del usuario puede no ser válida, por lo que debe solicitar una entrada, validarla, continuar si es válida, de lo contrario, repetir.

Con do-while, obtienes la entrada mientras que la entrada no es válida. Con un ciclo while regular, recibe la entrada una vez, pero si no es válida, la obtiene una y otra vez hasta que sea válida. No es difícil ver que el primero es más corto, más elegante y más simple de mantener si el cuerpo del bucle se vuelve más complejo.


Lo he usado en una función TryDeleteDirectory. Fue algo como esto

do { try { DisableReadOnly(directory); directory.Delete(true); } catch (Exception) { retryDeleteDirectoryCount++; } } while (Directory.Exists(fullPath) && retryDeleteDirectoryCount < 4);


Lo he usado en una función que devolvió la siguiente posición de personaje en una cadena utf-8:

char *next_utf8_character(const char *txt) { if (!txt || *txt == ''/0'') return txt; do { txt++; } while (((signed char) *txt) < 0 && (((unsigned char) *txt) & 0xc0) == 0xc0) return (char *)txt; }

Tenga en cuenta que esta función se escribe desde la mente y no se prueba. El punto es que tienes que hacer el primer paso de todos modos y tienes que hacerlo antes de poder evaluar la condición.


Lo he usado para un lector que lee la misma estructura varias veces.

using(IDataReader reader = connection.ExecuteReader()) { do { while(reader.Read()) { //Read record } } while(reader.NextResult()); }


Los usé bastante cuando estaba en la escuela, pero no tanto desde entonces.

En teoría, son útiles cuando desea que el cuerpo del bucle se ejecute una vez antes de la verificación de la condición de salida. El problema es que para las pocas instancias en las que no quiero el cheque primero, generalmente quiero el control de salida en el medio del cuerpo del bucle en lugar de hacerlo al final. En ese caso, prefiero usar lo conocido for (;;) con una if (condition) exit; en algún lugar del cuerpo

De hecho, si estoy un poco inestable en la condición de salida del bucle, a veces me resulta útil comenzar a escribir el bucle como un for (;;) {} con una instrucción de salida donde sea necesario, y luego, cuando termino, puede ver si puede "limpiarse" moviendo inicilizaciones, condiciones de salida y / o código de incremento dentro de los paréntesis de for .


Me encontré con esto mientras investigaba el ciclo adecuado para usar en una situación que tengo. Creo que esto satisfará completamente una situación común en la que un bucle do .. while es una mejor implementación que un bucle while (lenguaje C #, ya que usted indicó que es el principal para el trabajo).

Estoy generando una lista de cadenas basada en los resultados de una consulta SQL. El objeto devuelto por mi consulta es un SQLDataReader. Este objeto tiene una función llamada Read () que avanza el objeto a la siguiente fila de datos, y devuelve verdadero si había otra fila. Devolverá falso si no hay otra fila.

Usando esta información, quiero devolver cada fila a una lista, luego detener cuando ya no haya más datos para devolver. A Do ... While el bucle funciona mejor en esta situación, ya que garantiza que se agregará un elemento a la lista ANTES de verificar si hay otra fila. La razón por la que esto debe hacerse ANTES de verificar el tiempo (condición) es que cuando se comprueba, también avanza. Usar un bucle while en esta situación haría que omitiera la primera fila debido a la naturaleza de esa función en particular.

En breve:

Esto no funcionará en mi situación.

//This will skip the first row because Read() returns true after advancing. while (_read.NextResult()) { list.Add(_read.GetValue(0).ToString()); } return list;

Esta voluntad.

//This will make sure the currently read row is added before advancing. do { list.Add(_read.GetValue(0).ToString()); } while (_read.NextResult()); return list;


No puedo imaginar cómo has ido tanto sin usar un do...while loop.

Hay uno en otro monitor en este momento y hay varios de tales bucles en ese programa. Son todos de la forma:

do { GetProspectiveResult(); } while (!ProspectIsGood());


Si siempre quiere que el ciclo se ejecute al menos una vez. No es común, pero sí lo uso de vez en cuando. Un caso en el que es posible que desee utilizarlo es intentar acceder a un recurso que podría requerir un reintento, por ej.

do { try to access resource... put up message box with retry option } while (user says retry);


Siendo un programador geezer, muchos de mis proyectos de programación escolar utilizaban interacciones basadas en menús de texto. Prácticamente todos usaron algo así como la siguiente lógica para el procedimiento principal:

do display options get choice perform action appropriate to choice while choice is something other than exit

Desde los días de la escuela, he descubierto que uso el ciclo while con más frecuencia.


Una de las aplicaciones que he visto está en Oracle cuando miramos conjuntos de resultados.

Una vez que tienes un conjunto de resultados, primero lo recuperas (haces) y desde ese punto en adelante ... verifica si la recuperación devuelve un elemento o no (mientras el elemento se encuentra ...). Lo mismo podría aplicarse a cualquier otro " las implementaciones similares a fetch.


Una situación en la que siempre debe ejecutar un fragmento de código una vez, y dependiendo de su resultado, posiblemente más veces. Lo mismo se puede producir con un ciclo while regular también.

rc = get_something(); while (rc == wrong_stuff) { rc = get_something(); } do { rc = get_something(); } while (rc == wrong_stuff);


Uso bucles do-while todo el tiempo cuando leo en archivos. Trabajo con muchos archivos de texto que incluyen comentarios en el encabezado:

# some comments # some more comments column1 column2 1.234 5.678 9.012 3.456 ... ...

Utilizaré un ciclo do-while para leer hasta la línea "column1 column2" para poder buscar la columna de interés. Aquí está el pseudocódigo:

do { line = read_line(); } while ( line[0] == ''#''); /* parse line */

Luego haré un ciclo while para leer el resto del archivo.


Veo que esta pregunta se ha respondido adecuadamente, pero me gustaría agregar este caso de uso muy específico. Puede comenzar a usar do ... mientras más frecuentemente.

do { ... } while (0)

a menudo se usa para #defines de varias líneas. Por ejemplo:

#define compute_values / area = pi * r * r; / volume = area * h

Esto funciona bien para:

r = 4; h = 3; compute_values;

-pero- hay un gotcha para:

if (shape == circle) compute_values;

como esto se expande a:

if (shape == circle) area = pi *r * r; volume = area * h;

Si lo envuelve en un do ... mientras (0) loop se expande adecuadamente a un solo bloque:

if (shape == circle) do { area = pi * r * r; volume = area * h; } while (0);


do-while es mejor si el compilador no es competente en la optimización. do-while tiene un solo salto condicional, a diferencia de for y while, que tienen un salto condicional y un salto incondicional. Para las CPU que están canalizadas y no hacen predicción de bifurcación, esto puede marcar una gran diferencia en el rendimiento de un ciclo cerrado.

Además, dado que la mayoría de los compiladores son lo suficientemente inteligentes como para realizar esta optimización, todos los loops que se encuentran en el código descompilado usualmente serán do-while (si el descompilador incluso se molesta en reconstruir bucles a partir de gotos locales hacia atrás).


do while lo mismo si quieres ejecutar el bloque de código al menos una vez. while por otro lado, no siempre se ejecutará según los criterios especificados.


while bucles verifican la condición antes del bucle, lo do...while bucles verifican la condición después del bucle. Esto es útil si desea basar la condición en los efectos secundarios del bucle en ejecución o, como dicen otros carteles, si desea que el bucle se ejecute al menos una vez.

Entiendo de dónde vienes, pero el do-while es algo que casi nunca se usa, y nunca me he usado. No lo estás haciendo mal.

No lo estás haciendo mal. Es como decir que alguien lo está haciendo mal porque nunca han usado el primitivo de byte . Simplemente no es tan comúnmente utilizado.


Console.WriteLine("hoeveel keer moet je de zin schrijven?"); int aantal = Convert.ToInt32(Console.ReadLine()); int counter = 0; while ( counter <= aantal) { Console.WriteLine("Ik mag geen stiften gooien"); counter = counter + 1;