¿Por qué no está terminando? [cerrado]

95

Su tarea: escribir un programa que obviamente debería terminar, pero nunca lo hace (en la medida de una falla de la computadora). Haga que parezca que debería realizar una tarea simple: agregar números, imprimir algo, ... Pero simplemente queda atrapado en un bucle infinito.

Trate de hacer que su programa sea muy claro y simple, mientras que en realidad se atascará en un bucle imprevisto. Votantes: ¡juzguen las respuestas sobre cuán "descuidados" son!

Este es un concurso de popularidad: ¡Sé creativo!

Número 9
fuente
66
¿Podría alguien explicarme qué puedo hacer para que la pregunta sea menos amplia? Soy nuevo aquí. ¡Gracias!
Número9
66
Esto va a ser una gran lista de errores tipográficos y errores de principiante que causan bucles.
Bill Woodger
Pregunta interesante, pero aún no he visto ninguna respuesta verdaderamente creativa. ¡Prometo votos a cualquiera que no use bucles o recurrencia obvia!
ApproachingDarknessFish
14
No sé si esto cuenta, pero mi Microsoft Office se está comportando exactamente así en este momento.
Level River St
1
Estoy votando para cerrar esta pregunta como fuera de tema porque los desafíos poco claros ya no están en el tema aquí. meta.codegolf.stackexchange.com/a/8326/20469
gato

Respuestas:

185

Javascript

var x=prompt('Enter a value under 100');
while (x != 100) {
  x=x+1;
}
console.log('End!');

prompt () devuelve una cadena y el bucle agrega el carácter '1', nunca será igual a 100.

Michael M.
fuente
13
Me entendiste con eso ... los ejemplos (en realidad) más votados son solo abuso de sintaxis ... ¡pero ese es bueno!
bwoebi
44
Chrome en Kubuntu dejó de responder, colgó todo y tuve que restablecer el
hardware
44
@Vlakarados: Python no hará la conversión de tipo implícita que hace Javascript. En Python, el código equivalente usando raw_inputo Python 3 inputeleva a TypeError.
user2357112
2
No se verifica el hecho de que el valor sea realmente inferior a 100, por lo que se detiene normalmente cuando ingresa "100": '- (
C.Champagne
1
@Sankalp, el +operador aquí es la concatenación de cadenas, no la adición.
Michael M.
87

C

Solo un programa de ejemplo básico que ilustra los tres tipos diferentes de bucles while en C.

int main() {

    int x = 0;

    // Multi-statement while loops are of the form "while (condition) do { ... }" and
    // are used to execute multiple statements per loop; this is the most common form
    while (x < 10) do {
        x++;
    }

    // x is now 10

    // Null-statement while loops are of the form "while (condition) ;" and are used
    // when the expression's side effect (here, decrementing x) is all that is needed
    while (x-- > 0)
        ; // null statement

    // x is now -1

    // Single-statement while loops are of the form "while (condition) statement;"
    // and are used as a shorthand form when only a single statement is needed
    while (x > -10)
        x--;

    // x is now -10

    return 0;
}

Mientras que los bucles no tienen un "hacer" antes de la llave de apertura. En realidad, esto crea un ciclo do-while dentro del ciclo (x <10) que termina con la siguiente "declaración nula" while loop. Dado que x se incrementa dentro del bucle y luego disminuye en la condición del bucle do-while, el bucle interno nunca termina, y tampoco lo hace el bucle externo. El ciclo de "declaración única" al final nunca se alcanza.

Si todavía está confundido, mire aquí (alojado externamente porque codegolf.SE no le gustan los bloques de código en spoilers).

Fraxtil
fuente
8
Jaja, descubrí esto antes de mirar el spoiler de la solución. : P
Joe Z.
54
¿Por qué dejaste pasar una oportunidad tan excelente para usar el operador "va a"? (x --> 0)
corsiKa
2
Oh wow. Esto es maravillosamente malvado. Me llevó cuatro lecturas para encontrarlo.
Patrick M
1
@JoeZ. Demasiado fácil. La solución más votada fue mejor. Ese que no encontré.
Anónimo Pi
3
@ Hat Guy, Bash tiene la sintaxis for; do y while; do para que pueda ver a las personas que se desaniman por esto, incluso si están familiarizados con lenguajes que no son C / C ++. tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-7.html
nemec
85

JavaScript

var a = true;
(function() {
  while(!a){}
  alert("infinite");
  var a = true;
})();

Elevación variable: JavaScript realmente tomará mi segunda definición de var a = true;, la declarará en la parte superior de la función como var a;y modificará mi asignación al a = true;significado ano estará definida en el momento en que ingrese al ciclo while.

Newbrict
fuente
3
¿Podría agregar una mejor explicación de por qué esto nunca termina?
Entra
1
@ Number9 Espero que ayude, google tiene ejemplos mucho mejores que esto;)
Newbrict
25
Santa mierda, esto es incluso peor que la inserción de punto y coma. +1!
tomsmeding
2
El único problema que veo con este programa es que no parece que realice una tarea simple ... parece que esencialmente no debería hacer nada. Tal vez agregue un alertdespués del bucle.
PeterT
2
Deberías cambiarte a = 1a a = true. El código todavía tendrá el bucle infinito de esa manera, pero será más claro que la razón no es una peculiaridad en la conversión de JavaScript de ints a booleans.
Rory O'Kane
49

C#

class Program
{
    // Expected output:
    // 20l
    // 402
    // 804
    // l608
    // 32l6
    // game over man

    static void Main()
    {
        var x = 20l;
        while (x != 6432)
        {
            Console.WriteLine(x);
            x *= 2;
        }
        Console.WriteLine("game over man");
    }
}

El número literal en la primera línea de la función no es un '201', sino un '20' con un sufijo en minúscula 'L' ( tipo de datos largo ). El número se desbordará bastante rápido sin llegar a 6432, pero el programa continuará a menos que se active la verificación de desbordamiento en las opciones de compilación.
De manera sensata, Visual Studio 2013 (y probablemente otras versiones también) le advierte sobre este código y le recomienda que use 'L' en lugar de 'l'.

BenM
fuente
12
¡Oh, lse supone que parece un 1! Soy estúpido. : \
Joe Z.
66
Sugerencia para mejorar: reemplace los 1s en la sección de salida esperada con ls también (es más fácil detectar el personaje extraño cuando tiene 1s reales para comparar)
Allen Gould
3
Sí, parece ser bastante específico del entorno. @ La fuente de Michael se ve muy diferente a la fuente en la computadora de mi casa ( imgur.com/PKIuJpr - Chrome, Windows 8), y el truco parece funcionar mejor en mi computadora de trabajo que en la computadora de mi casa, a pesar de que son bastante similares especificaciones. El navegador de mi teléfono no parece mostrar código en una fuente de tono fijo, y el truco no funciona en absoluto.
BenM
1
FTR, así es como se ve en mi computadora de trabajo ( imgur.com/Opfs3BH - Firefox, Windows 7). Creo que incluso se podría engañar a personas bastante astutas.
BenM
15
¿POR QUÉ LAS PERSONAS SIGUEN ABUSANDO DE PERSONAJES QUE PARECEN LO MISMO?
Anónimo Pi
39

C

¿Qué tal la precisión?

int main(void)
{
    double x = 0;
    while(x != 10) x += 0.1;
    return 0;
}

Imagine que tiene que almacenar un rango de números enteros <0; 3> en la memoria de la computadora. Solo hay 4 números enteros en este rango (0,1,2,3). Es suficiente usar 2 bits para almacenar eso en la memoria. Ahora imagine que tiene que almacenar un rango de números de coma flotante <0; 3>. El problema es que hay un número infinito de números de coma flotante en este rango. ¿Cómo almacenar un número infinito de números? Es imposible. Solo podemos almacenar un número finito de números. Es por eso que algunos números como 0.1 son realmente diferentes. En el caso de 0.1 es 0.100000000000000006. Se recomienda encarecidamente no utilizar == o! = En condiciones siempre que utilice números de coma flotante.

Scony
fuente
1
¿Como funciona esto?
Mhmd
55
Errores de redondeo. 0.1 es en realidad 0.100000000000000006 porque 0.1 en binario es como 1/3 en decimal: su expansión binaria es infinita y periódica.
orion
3
No es realmente un error de redondeo. Los valores de coma flotante son representaciones aproximadas de un número. Realizar comparaciones exactas entre valores aproximados no va a funcionar.
AKHolland
44
Es por eso que (casi) nunca deberías comparar flotante / doble por igualdad.
Emanuel Landeholm
1
Estaba esperando ver este. Agradable.
David Conrad
33

HTML / JavaScript

Imagine que tiene un cuadro de entrada en su página:

<input onfocus="if (this.value === '') alert('Input is empty!');">

Y ahora quieres escribir algo en él ... Pruébalo en Chrome: http://jsfiddle.net/jZp4X/ .

El cuadro de diálogo del navegador estándar llamado con la alertfunción es modal, por lo que cuando se muestra, saca el foco del cuadro de texto, pero cuando se cierra, el cuadro de texto recibe el foco nuevamente.

Visión
fuente
55
en firefox, la entrada no tiene enfoque automático al cerrar la alerta, y desde la segunda vez me ofrece no mostrar más alertas y luego puedo escribir en el cuadro de texto normalmente
Einacio
66
Buena esa. +1 para ningún bucle o recursión.
ApproachingDarknessFish
55
No hay bucles ni en Firefox ni en Chrome. FF muestra la alerta una vez cuando se hace clic en el cuadro de diálogo, lo descarta y ahí termina. Puede hacer clic nuevamente para repetir. Chrome hace lo mismo, pero deja el cuadro enfocado e incluso puedes escribirlo. Lo sentimos, tal vez en versiones anteriores esto era un problema, pero ya no.
RomanSt
66
IE11 funciona exactamente igual que Chrome para mí. ¡Creo que sin darse cuenta ha encontrado un ejemplo de algo que funciona de una manera en cada navegador moderno en Mac, y de una manera diferente en cada navegador moderno en Windows!
RomanSt
1
Funciona normalmente (sin bucles) en MSIE11
kinokijuf
32

C ++

#include <iostream>
#include <cstddef>

int main() {
    size_t sum = 0;
    for (size_t i = 10; i >= 0; --i) {
         sum += i;
    }
    std::cout << sum << std::endl;
    return 0;
}

La condición i >=0siempre es verdadera porque size_t no está firmado.

FDinoff
fuente
2
Bonito, pero los compiladores normalmente emiten una advertencia para esto;)
Synxis
2
@Synxis Sí, los compiladores sí. Pero solo si activa las advertencias del compilador. g++no te advertiré sobre esto sin ellos.
FDinoff
55
Siempre debes usar de -Wall --pedantictodos modos.
Martin Ueding
3
@queueoverflow La advertencia no se muestra solo con esas banderas. Necesita lo -Wsign-compareque se puede activar con -Wextra.
FDinoff
77
Una carrera en pedalera. #pedantic
David Conrad
29

golpetazo

(Hubo una solicitud de no bucles o recursión)

#!/bin/bash

# Demo arrays

foo=("Can I have an array?")

echo $foo

echo ${foo[0]}

foo[2] = `yes`

echo $foo

echo ${foo[2]}

En lugar de asignar la cadena 'yes' a foo [2], esto llama al comando del sistema yes, que llena foo [2] con una cantidad interminable de "yes \ n".

GreenAsJade
fuente
Finalmente se queda bashsin memoria y se bloquea
Digital Trauma
44
Sí, de hecho lo hace. Pero la pregunta permitió un choque :)
GreenAsJade
Sí, solo una observación :). Votado.
Trauma digital
De hecho, considero que los programas en esta pequeña comp que realmente bloquean su máquina, o alguna otra denegación de servicio, deberían obtener puntos de bonificación)
GreenAsJade
Corrección: yeses solo un programa coreutils. No es un syscall.
mniip
28

C

La letra "x" se perdió en un archivo. Se escribió un programa para encontrarlo:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
  FILE* fp = fopen("desert_file", "r");
  char letter;
  char missing_letter = argv[1][0];

  int found = 0;
  printf("Searching file for missing letter %c...\n", missing_letter);
  while( (letter = fgetc(fp)) != EOF ) {
    if (letter == missing_letter) found = 1;
  }
  printf("Whole file searched.\n");
  fclose(fp);
  if (found) {
    printf("Hurray, letter lost in the file is finally found!\n");
  } else {
    printf("Haven't found missing letter...\n");
  }
}

Fue compilado y corrió y finalmente gritó:

Hurray, letter lost in the file is finally found!

Durante muchos años, las cartas han sido rescatadas de esta manera hasta que llegó el nuevo tipo y optimizó el código. Estaba familiarizado con los tipos de datos y sabía que es mejor usar valores sin signo que con signo para valores no negativos, ya que tiene un rango más amplio y brinda cierta protección contra desbordamientos. Entonces cambió int por unsigned int . También conocía ascii lo suficientemente bien como para saber que siempre tienen un valor no negativo. Entonces él también cambió el carácter a un carácter sin signo . Compiló el código y se fue a casa orgulloso del buen trabajo que hizo. El programa se veía así:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
  FILE* fp = fopen("desert_file", "r");
  unsigned char letter;
  unsigned char missing_letter = argv[1][0];

  unsigned int found = 0;
  printf("Searching file for missing letter %c...\n", missing_letter);
  while( (letter = fgetc(fp)) != EOF ) {
    if (letter == missing_letter) found = 1;
  }
  printf("Whole file searched.\n");
  fclose(fp);
  if (found) {
    printf("Hurray, letter lost in the file is finally found!\n");
  } else {
    printf("Haven't found missing letter...\n");
  }
}

Volvió a los estragos al día siguiente. Faltaba la letra "a" y, aunque se suponía que estaba en el "archivo_desierto" que contenía "abc", el programa la estaba buscando para siempre imprimiendo solo:

Searching file for missing letter a...

Despidieron al tipo y volvieron a la versión anterior recordando que nunca se deben optimizar los tipos de datos en el código de trabajo.

¿Pero cuál es la lección que deberían haber aprendido aquí?

En primer lugar, si echa un vistazo a la tabla ASCII, notará que no hay EOF. Esto se debe a que EOF no es un carácter, sino un valor especial devuelto por fgetc (), que puede devolver un carácter extendido a int o -1 que denota el final del archivo.
Siempre y cuando estemos usando char con signo, todo funciona bien: fgetc () extiende también un char igual a 50 a int igual a 50. Luego lo transformamos nuevamente a char y todavía tenemos 50. Lo mismo sucede con -1 o cualquier otra salida que provenga de fgetc ().
Pero mira lo que sucede cuando usamos char sin firmar. Comenzamos con un char en fgetc (), lo extendemos a int y luego queremos tener un char sin firmar. El único problema es que no podemos preservar -1 en caracteres sin signo. El programa lo almacena como 255, que ya no es igual a EOF.

Consideración
Si echa un vistazo a la sección 3.1.2.5 Tipos en copia de la documentación de ANSI C , descubrirá que si char está firmado o no depende únicamente de la implementación. Entonces, el tipo probablemente no debería ser despedido ya que encontró un error muy complicado acechando en el código. Podría salir al cambiar el compilador o al cambiar a una arquitectura diferente. Me pregunto quién sería despedido si el error saliera en tal caso;)

PD. El programa fue construido alrededor del error mencionado en el lenguaje ensamblador de PC por Paul A. Carter

Legat
fuente
77
Me encanta que haya una historia con la solución.
jpmc26
¡Jaja! Supongo que es el único. Gracias por leer!
Legat
1
te quiero. Aliméntame con tus historias por favor :(
YoYoYonnY
¡Esto es absolutamente brillante!
kirbyfan64sos
21

Regex

Con la entrada adecuada, la siguiente expresión regular puede hacer que la mayoría de los motores de expresión regular de retroceso entren en el infierno de retroceso:

^\w+(\s*\w+)*$

Una entrada simple como "Programming Puzzles and Code Golf Stack Exchange - Mozilla Firefox"o "AVerySimpleInputWhichContainsAnInsignificantSentence."(ambas cadenas citadas para mayor claridad) es suficiente para mantener la mayoría de los motores regex de marcha atrás funcionando durante mucho tiempo.

Dado que (\s*\w+)*permite la expansión \w+\w+\w+... \w+, lo que significa que el motor de expresiones regulares básicamente probará todas las formas posibles de dividir una cadena de caracteres de palabras . Esta es la fuente del infierno de retroceso.
Fácilmente se puede solucionar cambiando \s*a \s+, entonces (\s+\w+)*sólo puede ser ampliado para \s+\w+\s+\w+... \s+\w+.

n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
fuente
3
Odio dar marcha atrás a los motores regex.
David Conrad
2
Intenté esto con Perl primero, pero parece que Perl puede notar un bucle aquí. No probé AWK, porque ninguna expresión regular puede causar ese comportamiento en AWK. PHP crea automáticamente expresiones regulares que tardan demasiado en coincidir con el error (lo cual es una tontería, pero eso es PHP para usted: inserta automáticamente errores en los programas). Sin embargo, en realidad funciona en Python.
Konrad Borowski
1
@xfix: En cuanto a por qué Perl logró evitar retroceder en el infierno, este artículo explica la razón. Sin embargo, no es suficiente en el caso como se muestra aquí (desplácese hacia abajo hasta la sección de rendimiento). PHP (en realidad la biblioteca PCRE) tiene un límite de retroceso, y un programa adecuado siempre debe verificar el valor de retorno de la función para decidir si la ejecución se detuvo o se ejecutó hasta su finalización.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
1
Esto es muy SLICK.
alvonellos
20

JavaScript

function thiswillLoop(){
var mynumber = 40;
while(mynumber == 40){
mynumber = 050;
}
return "test";
}
thiswillLoop();

050 es una constante octal en Javascript, y resulta que tiene el valor decimal de 40.

wuiyang
fuente
73
Esto me parece obvio. :-)
Justin
66
No sabía que JavaScript hizo esto. Pero después de leer el código dije: "050 tiene que ser alguna forma de representar 40, probablemente base 8 o algo así"
Cruncher
Esto necesita ser escondido mejor.
Paŭlo Ebermann
Es obvio ..
Oliver Ni
18

Haskell

head $ reverse $ (repeat '!') ++ "olleH"

Bueno, piénsalo! Sería lo mismo que head $ "Hello" ++ (repeat '!'), es decir, debería regresar 'H'.

En las listas de haskell hay estructuras recursivas, siendo el primer elemento el más alto. Para agregar a una lista, debe desenrollar todos esos elementos, colocar su apéndice y volver a colocar los elementos levantados. Eso no funcionaría en una lista infinita. Del mismo modo, invertir una lista infinita no te dará la "Hello"espalda mágicamente . Simplemente colgará para siempre.

mniip
fuente
1
Lástima que esto no funcione realmente: - /
John Dvorak
1
Como no funciona
danmcardle
@crazedgremlin cuando probé esto en Fedora, el sistema operativo finalmente eliminó el proceso. (<5 minutos) porque agotó toda la memoria del sistema.
FDinoff
¡Interesante! No me di cuenta de que esto sucedió. No me aventuro a engullir todo el territorio de la memoria con tanta frecuencia.
danmcardle
44
Sigue siendo una solución válida: no sale, se ejecuta todo el tiempo que puede hasta que el sistema ya no puede soportarlo ...
GreenAsJade
16

Java bajo Windows

public class DoesntStop
{
    public static void main(String[]a) throws InterruptedException, IOException
    {
        ProcessBuilder p = new ProcessBuilder("cmd.exe","/c","dir");
        p.directory(new File("C:\\windows\\winsxs"));
        Process P = p.start();
        P.waitFor();
    }
}

El programa se basa en una secuencia de salida estándar atascada desde la línea de comandos para atascarse. El directorio WinSXS en Windows tiene varios miles de archivos con nombres largos, por lo que es casi seguro que obstruirá waitForla salida estándar, y no puede volver, por lo que el programa se encuentra en un punto muerto

masterX244
fuente
1
Tal vez estoy siendo denso, pero ¿no volverá esto eventualmente? Solo podría tomar un tiempo. Tal vez no entiendo lo que quieres decir con "estorbar [ging] stdout".
asteri
44
si la secuencia no se vacía, el programa bloquea, ya me causó algunos dolores de cabeza por eso lo usé; el directorio largo solo garantiza que el búfer se ejecute por completo
masterX244
Ah, te tengo. ¡Agradable! +1
asteri
15

Para comparar manzanas y naranjas ... en C

Estoy impresionado de que no haya ningún código aquí usando un goto... (Ya sabes: ¡ Goto es malvado! )

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
    char *oranges = "2";
    long int apples;

next_harvest:

    apples = random() % 3;

    printf("%ld apples comp. %s oranges ...\n", apples, oranges);

    if( apples != (long int)oranges )
    {
        sleep(1);
        goto next_harvest;
    }

    return 0;
}

El sueño es solo para poder leerlo. Presione ^ C si no tiene una cantidad interminable de tiempo para esperar algo que nunca sucede ;-)

max.haredoom
fuente
99
Bastardo astuto, goto es inocente en esto :)
orion
¿Se usa el random () el vudú?
masterX244
1
ahh, "2"! = 2; lo tengo
masterX244
2
Bueno, "2" probablemente nunca puede ser 2, pero si usara un número mayor (y un múltiplo de al menos 4), podría suceder;)
orion
1
@orion: Sí, tienes razón, podría serlo. ¡Y goto sigue siendo malvado, pero los castings de tipo malo son aún más malvados!
max.haredoom
12

C, con ciertos compiladores optimizadores

Este programa incrementa una variable entera hasta que se desborda.

#include <stdio.h>
#include <stdint.h>
int main()
{
    int32_t x = 0;
    while(x + 1 > x)
        x++;
    printf("Got overflow!\n");
    return 0;
}

El desbordamiento de entero firmado es un comportamiento indefinido. Por lo general, en la práctica se ajusta cuando las optimizaciones están desactivadas. Con las optimizaciones activadas, los compiladores pueden decidir y x + 1 > xsiempre deciden que eso siempre es cierto.

immibis
fuente
Quizás uso int32_t; un int de 64 bits tomaría mucho, mucho, mucho tiempo (585 años si cada iteración toma un nanosegundo).
Paul Draper
11

C ++

int main()
{
  int x = 1;
  //why doesn't this code terminate??/
  x = 0;
  while(x) {} //no-op/
  return 0;
}

El estilo de comentario extraño es el truco. Sugerencia: trigrafos.

Pomo de la puerta
fuente
Este es un ejemplo demasiado básico de un bucle infinito.
Ismael Miguel
64
Esos Trigraphs están tan sobreutilizados aquí :(
TimWolla
75
Casi siento que los trigrafos deberían ponerse en lagunas estándar que ya no son divertidas
undergroundmonorail
66
@TheDoctor: ?? / es un trigrafo para un carácter de barra diagonal inversa, por lo que la barra diagonal inversa divide la línea donde x se asigna 0 al final del comentario, haciéndolo parte del comentario.
CasaDeRobison
44
@undergroundmonorail Publicado
Justin
11

Java

En particular, me encanta este efecto secundario de la optimización de autoboxing:

class BoxingFun {
  public static void main( String[] args) {
    Integer max;
    Integer i;

    max = 100;
    for( i = 1; i != max; i++ ) {
      System.out.println("Not endless");  
    }
    max = 200;
    for( i = 1; i != max; i++ ) {
      System.out.println("Endless");  
    }
  }
}

Debido al autoboxing, los Integerobjetos se comportan casi como simples intaquí, con una excepción: el i != maxen los forbucles compara las referencias (identidad) de los Integerobjetos, no su valor (igualdad). Sin embargo, para valores de hasta 100 esto sorprendentemente "funciona" debido a una optimización en la JVM: Java asigna previamente Integerobjetos para los "valores más comunes" y los reutiliza cuando se realiza el autoboxing. Entonces, para valores de hasta 100 tenemos identidad <==> igualdad.

Daniel
fuente
55
Dado que algunos chicos de Java todavía consideran que la sobrecarga de operadores de C ++ es malvada ...
Daniel
No necesita la inicialización = new Integer(0), ya que de todos modos está inicializando los valores después. (Esto podría hacer que la razón sea menos obvia.)
Paŭlo Ebermann
@ PaŭloEbermann: Buen punto, he editado el código.
Daniel
9

Ruby / C

#include <stdio.h>
#ifdef llama
def int(*args)
end
def main(arg)
  yield
end
void = nil
#endif
#define do {
#define end }
int main(void) {
  int x = 10;
  while(x-=1) do
    printf("%i\n",x);
  end
    return 0;
}

Esto funciona correctamente en C , contando de 9 a 1 en STDOUT. Cuando se ejecuta en Ruby, no termina, porque

0 no es un valor falso en Ruby.

histocrat
fuente
Haz idiomas a la vez ... impresionante.
Paul Draper
7

JavaScript

// This multiplies the elements in the inner lists and sums the results.
function sum_of_products(var items)
{
        var total = 0;
        for(var i = 0; i < items.length; i++) {
                var subitems = items[i];
                var subtotal = 1;
                for(var i = 0; i < subitems.length; i++) {
                        subtotal *= subitems[i];
                }       
                total += subtotal;
        }
        return total;
}

// Should return 1*2 + 3*4*5 + 6*7*8*9 + 10*11 = 3196
sum_of_products([[1, 2], [3, 4, 5], [6, 7, 8, 9], [10, 11]]);

Ambos bucles usan la misma variable de bucle, por lo que dependiendo de la entrada, el bucle interno puede evitar que el bucle externo termine.

Aleksi Torhamo
fuente
¿Qué lenguaje es este?
RononDex
@ronondex Javascript
tomsmeding
1
Ah, sí, es Javascript. Recordé habilitar el resaltado de sintaxis, pero tuve que olvidar ponerlo también en el título :)
Aleksi Torhamo
1
Esto me parece obvio. :-)
rafaelcastrocouto
@rafaelcastrocouto Sí, es cierto, pero también es muy fácil pasarlo por alto, por ejemplo, al mover un bucle de una función a otra o simplemente mirar el código. Además, tenga en cuenta que esto realmente funciona correctamente en algunos lenguajes, incluido C, debido al sombreado variable. :)
Aleksi Torhamo
7

C

Esto debería imprimir una tabla de códigos para todos los caracteres ASCII, de 0 a 255. A chares lo suficientemente grande como para iterar sobre ellos.

#include <stdio.h>

int main(){
    char i;
    for(i = 0; i < 256; i++){
        printf("%3d 0x%2x: %c\n", i, i, i);
    }
    return 0;
}

Todos los caracteres son inferiores a 256. 255 ++ da 0 debido al desbordamiento, por lo que la condición i < 256siempre se mantiene. Algunos compiladores lo advierten, otros no.

Rafał Cieślak
fuente
Hacerlo parece hacer algo más útil, quizás use algo como printf("%3d %2x: %c", i, i, i);(para una tabla de códigos) en su bucle.
Paŭlo Ebermann
@ PaŭloEbermann: Gran idea.
Rafał Cieślak
Utilizo este truco en mi clase, con caracteres imprimibles sin signo entre 32 y 128. :)
cpri
7

Pitón

a = True
m = 0
while a:
    m = m + 1
    print(m)
    if m == 10:
        exit

debería ser exit()y no exit. Según tengo entendido, exit()es el comando para salir del intérprete de Python. En este caso, la llamada es a la representación de la función y no a la función ver: salida-discusión . Alternativamente breaksería una mejor opción.

Willem
fuente
¿Podría explicar qué exites realmente? Parece ser una clase, pero ¿para qué se utiliza? También puede cambiar print mpara print(m)que esto también funcione con Python 3.
Martin Thoma
1
Ese tipo de cosas ... Como cuando mi elseif no funcionaba porque era elif .
Anónimo Pi
Gracias @moosecomunicado impreso actualizado y el mensaje de spoiler
Willem
6

C ++

¿Qué tal la clásica C ++ - trampa del programador?

int main()
{
   bool keepGoing = false;

   do {
       std::cout << "Hello, world!\n";
   } while( keepGoing = true );

   return 0;
}
CompuChip
fuente
No entiendo esto? ¿Se trata de usar? = en lugar de ==?
Mhmd
@ user689 exactamente. keepGoing = trueestaba destinado a comparar el valor de keepGoing, en su lugar, asigna el valor a keepGoing; Además, toda la declaración se keepGoing = trueevalúa true(lo que te permite escribir cosas como a=b=c=d=0) que conduce a un bucle infinito.
CompuChip
3
Esta es una razón más para usar las condiciones de yoda.
Ryan
@RyanEdwardDougherty Jaja así nunca escuché que los llamaran. Por la mañana reír, gracias.
CompuChip
@RyanEdwardDougherty: Por supuesto == true(o al estilo Yoda true ==) es redundante de todos modos, y la condición simplemente debería leerse while (keepGoing).
celtschk
6

Javascript

var а = 0;
a = 1;
while(а<10){
    a++;
}

Las variables utilizadas en la primera y tercera línea son diferentes de las utilizadas en la segunda y tercera línea.
Uno usa a (U + 0061) mientras que el otro usa а (U + 0430)

Clyde Lobo
fuente
No veo un problema aquí. Lo ejecuté y funcionó bien. ¿Qué me estoy perdiendo?
Andrew Shepherd
Esto probablemente funcionará en todas partes ya que el Unicode probablemente se convertirá. ¡Obtuve un +1 ya que es lo más invisible posible!
rafaelcastrocouto
Solo para ocultarlo por completo (reemplace á con U + 0430) Si este fuera su código, buena suerte para encontrar el problema: var a;var points = 0;function fiftyfifty() {points++;if (Math.random() > 0.5)return true;}; á = fiftyfifty(); while (a === undefined) {á = fiftyfifty();} console.log("Points: " + points);me daría por vencido, lo eliminaría para siempre, limpiaría mi computadora, tal vez un escáner de virus solo para estar seguro y reescribirlo por completo. EDITAR: Porque var a = 0; a = 1;no es muy realista
YoYoYonnY
6

Java:

public class LoopBugThing{
   public static void main(String[] args)
   {
      int i = 0;
      while(i < 10)
      {
         //do stuff here
         i = i++;
      }
      System.out.println("Done!");
   }
}

El "i = i ++" es un error bastante común para principiantes y puede ser sorprendentemente difícil de encontrar

Richo
fuente
5

C ++

Un poco al azar?

class Randomizer
{
   private:
   int max;

   public:
   Randomizer(int m)
   {
      max = m;
      srand(time(NULL));
   }

   int rand()
   {
      return (rand() % max);
   }
};

int main()
{
  Randomizer r(42);
  for (int i = 0; i < 100; i++)
  {
     i += r.rand();
  }
  return (0);
}

No llama a la función randsino que llama recursivamente a la Randomizer::randfunción.

calimbak
fuente
55
Paréntesis adicionales en la declaración de devolución, qué asco.
David Conrad
1
Sin embargo, esto eventualmente será segfault.
kirbyfan64sos
5

Haskell

Algún código para calcular el tiempo de un determinado valor de la función de Ackermann. Para valores muy bajos, generalmente termina. En mi máquina, valores muy bajos significan algo así como 3 5 o menos con código compilado y -O. En ghci valores bajos significa algo así como 3 3.

El 'símbolo parece estropear el resaltado de sintaxis, no estoy seguro de por qué. En algunos lugares son necesarios, por lo que no se pueden eliminar todos.

Editar: cambio de idioma.

{-# LANGUAGE NamedFieldPuns #-}
import Control.Concurrent.STM
import Control.Concurrent
import Data.Time.Clock.POSIX

data D = D { time :: !POSIXTime
           , m :: !Integer
           , n :: !Integer
           , res :: !(Maybe Integer)
           } deriving Show

startvalue = D 0 3 8 Nothing

-- increment time in D. I belive lensen make code like
-- this prettier, but opted out.
inctime t t' (d@D{time}) = d {time = time + t' - t }

-- Counting time
countTime :: TVar D -> POSIXTime -> IO ()
countTime var t = do
    t' <- getPOSIXTime
    atomically $ modifyTVar' var (inctime t t')
    countTime var t'

-- Ackermann function
ack m n
    | m == 0    = n + 1
    | n == 0    = ack (m - 1) 1
    | otherwise = ack (m - 1) (ack m (n - 1))

-- Ackerman function lifted to the D data type and strict
ack' (d@D{m, n}) = let a = ack m n
                   in seq a (d { res = Just a })

-- fork a counting time thread, run the computation
-- and finally print the result.
main = do
    d <- atomically (newTVar startvalue)
    forkIO (getPOSIXTime >>= countTime d)
    atomically $ modifyTVar' d ack'
    (atomically $ readTVar d) >>= print

Esto provoca un livelock. El hilo de contar repetidamente hace que el cálculo de Ackermann retroceda ya que tocan el mismo TVar.

monocelda
fuente
marcarlo como lang-hs en lugar de lang-haskell parece funcionar mejor (es una de las extensiones en el prettifier de google )
Einacio
5

Java: sin bucles ni recursividad

Acabo de comenzar a aprender expresiones regulares y escribí mi primer programa para probar si mi cadena coincide con una expresión regular.

Lamentablemente, el programa no produce ningún resultado. Sostiene la terminal. Por favor, ayuda a encontrar el problema. No he hecho ningún uso de bucles, no hay recurrencia involucrada. Estoy completamente desconcertado.

import java.util.regex.*;

public class LearnRegex {
     public static void main(String[] args) {
         Pattern p = Pattern.compile("(x.|x.y?)+");
         String s = new String(new char[343]).replace("\0", "x");
         if (p.matcher(s).matches())
             System.out.println("Match successful!");
     }
}

¿Qué he hecho mal? ¿Por qué no termina mi programa? ¡Por favor ayuda!

Ideone enlace aquí .

Este es un ejemplo estúpido de retroceso catastrófico . La complejidad es O (2 n / 2 ). Si bien el programa podría no ejecutarse indefinidamente, probablemente sobreviviría tanto a los objetos vivos como a los no vivos alrededor y no tanto .

devnull
fuente
5

C

Solo debe necesitar uno de los dos bucles, pero el que necesita depende de su compilador.

main()
{
        int i, a[10];

        i = 0;
        while (i <= 10) {
            i++;
            a[i] = 10 - i;
            printf("i = %d\n", i);
        }

        /* Now do it in reverse */

        i = 10;
        while (i >= 0) {
            i--;
            a[i] = 10 - i;
            printf("i = %d\n", i);
        }

}

Un desbordamiento de límites simple que restablece i a un valor sin terminación. Los compiladores pueden diferir en si asignan i por encima o por debajo de a en la pila, por lo que he incluido excesos en ambas direcciones.

alexis
fuente
5

C / C ++

C ++ solo permite las declaraciones de variables en línea fáciles de usar aquí, pero es igual de fácil cometer este error en el viejo y simple C ...

#include <stdio.h>

int main(void)
{
    int numbers[] = {2, 4, 8};

    /* Cube each item in the numbers array */
    for(int i = 0; i < 3; i++) {
      for(int j = 0; j < 3; i++) {
        numbers[j] *= numbers[j];
      }
    }

    /* Print them out */
    for(int i = 0; i < 3; i++) {
      printf("%d\n", numbers[i]);
    }

    return 0;
}

En el bucle interno, 'j' se compara pero nunca se incrementa. (El 'i ++' en realidad debería ser 'j ++'). Esto no es tanto un truco disimulado sino más bien un error real que he cometido en el pasado;) Algo a tener en cuenta.

Dave Ceddia
fuente
2
Esto generalmente me lleva al menos 5 minutos para depurar. Odio cuando hice esto.
ace_HongKongIndependence
4

C#

La siguiente es una clase simple que realiza una operación aritmética (suma) en una matriz de entrada grande utilizando un hilo de fondo. Se incluye un programa de muestra.

Sin embargo, aunque es bastante sencillo, nunca termina. Tenga en cuenta que no hay juegos de manos (parecidos a personajes, puntos y comas ocultos / faltantes, trigrafos ;-), etc.)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

class Program
{
    static void Main()
    {
        var summer = new BackgroundSummer(Enumerable.Range(1, 1234567));
        Console.WriteLine(summer.WaitAndGetResult());
    }
}

public class BackgroundSummer
{
    private IEnumerable<int> numbers;
    private long sum;
    private bool finished;

    public BackgroundSummer(IEnumerable<int> numbers)
    {
        this.numbers = numbers;
        new Thread(ComputingThread).Start();
    }

    public long WaitAndGetResult()
    {
        while (!finished) { /* wait until result available */ }
        return sum;
    }

    private void ComputingThread()
    {
        foreach(var num in numbers)
        {
            sum += num;
        }
        finished = true;
    }
}

Este es un ejemplo de un error desagradable del mundo real que también puede aparecer en su código. Según el modelo de memoria .NET y la especificación de C #, un bucle como el que está en WaitAndGetResultpodría no terminar nunca a menos que especifique la variable como volátil, ya que es modificada por otro hilo. Vea esta pregunta de StackOverflow para más detalles. El error depende de la implementación de .NET, por lo que puede afectarlo o no. Pero, por lo general, ejecutar una compilación de lanzamiento en un procesador x64 parece mostrar el problema. (Lo probé con "csc.exe / o + / debug- infinite.cs" ).

Mormegil
fuente