¿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!


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.


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).


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.


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'.


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.


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.


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.


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".


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


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+.


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.


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.


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


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 ;-)


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.


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.


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.


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.


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.


¿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.


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.


¿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;
}

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)


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


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.


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.


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 .


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.


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.


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" ).

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.