Por que não está terminando? [fechadas]


95

Sua tarefa: escrever um programa que obviamente deveria terminar, mas nunca (na extensão de uma pane no computador). Faça com que pareça que ele deve executar uma tarefa simples: adicionar números, imprimir alguma coisa, ... Mas isso fica preso em um loop infinito.

Tente tornar seu programa muito claro e simples, enquanto ele realmente ficará preso em um loop imprevisto. Eleitores: julgue as respostas sobre como elas são "secretas"!

Este é um concurso de popularidade: Seja criativo!


6
Alguém poderia explicar o que posso fazer para tornar a pergunta menos ampla? Eu sou novo aqui. Obrigado!
Number9

6
Esta será apenas uma grande lista de erros de digitação e erros de iniciantes que causam loops.
Bill Woodger

Pergunta interessante, mas ainda não vi respostas realmente criativas. Eu prometo votos a quem não usa loops ou recursão óbvia!
Aproximando-se

14
Não sei se isso conta, mas meu Microsoft Office está se comportando exatamente assim no momento.
Level River St

1
Estou votando para encerrar esta questão como fora do tópico, porque os desafios secretos não estão mais no tópico aqui. meta.codegolf.stackexchange.com/a/8326/20469
cat

Respostas:


185

Javascript

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

prompt () retorna uma string e o loop acrescenta o caractere '1', nunca será igual a 100.


13
Você me pegou com esse ... os exemplos (na verdade) com maior número de votos estão apenas abusando da sintaxe ... mas esse é legal!
bwoebi

4
Chrome no Kubuntu ficou sem resposta, pendurar tudo e eu tive que hard reset :)
Sergey Telshevsky

4
@Vlakarados: Python não fará a conversão implícita de tipo que o Javascript faz. No Python, o código equivalente usando raw_inputou Python 3 inputgera a TypeError.
user2357112

2
Não há verificação do fato de que o valor está realmente abaixo de 100, portanto ele para normalmente quando você digita "100": '- (
C.Champanha,

1
@Ankalp, o +operador aqui é a concatenação de strings, não a adição.
Michael M.

87

C

Apenas um exemplo de programa básico que ilustra os três tipos diferentes de while-loops em 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;
}

Enquanto loops não têm um "fazer" antes da chave de abertura. Na verdade, isso cria um loop do-while dentro do loop (x <10) que é finalizado pela seguinte "instrução nula" while loop. Como x é incrementado dentro do loop e depois diminuído na condição do loop do-while, o loop interno nunca termina, e o loop externo também não. O loop "declaração única" no final nunca é atingido.

Se você ainda está confuso, veja aqui (hospedado externamente porque o codegolf.SE não gosta de blocos de código em spoilers).


8
Haha, eu descobri isso antes de olhar para o spoiler da solução. : P
Joe Z.

54
Por que você passou uma excelente oportunidade para usar o operador "vai para"? (x --> 0)
corsiKa

2
Oh uau. Isso é maravilhosamente mau. Levei quatro leituras para encontrá-lo.
Patrick M

1
@JoeZ. Muito fácil. A solução mais votada foi melhor. Aquele que eu não encontrei.
Anonymous Pi

3
@Hat Guy, Bash tem a sintaxe for; do e while; do, para que eu possa ver as pessoas se impressionando com isso, mesmo que estejam familiarizadas com linguagens não 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;
})();

Içamento variável: o JavaScript realmente pega minha segunda definição de var a = true;, declara-a na parte superior da função como var a;e modifica minha atribuição ao a = true;significado aserá indefinida no momento em que entra no loop while.


3
Você poderia adicionar uma explicação melhor sobre por que isso nunca termina? Por favor, entre em detalhes sobre "levantamento variável" :) #
916

1
@ Number9 Espero que ajude, o Google tem muito melhores exemplos do que isso;)
Newbrict

25
Puta merda, isso é ainda pior que a inserção de ponto e vírgula. +1!
tomsmeding

2
O único problema que vejo com este programa é que ele não parece executar uma tarefa simples ... parece que essencialmente não deve fazer nada. Talvez adicione um alertapós o loop.
PeterT

2
Você deve mudar a = 1para a = true. O código ainda terá o loop infinito dessa maneira, mas ficará mais claro que o motivo não é uma peculiaridade na conversão de JavaScript de ints para booleanos.
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");
    }
}

O literal numérico na primeira linha da função não é um '201', mas um '20' com um sufixo 'L' ( tipo de dados longo ) em minúsculas . O número transbordará muito rapidamente, sem atingir 6432, mas o programa continuará, a menos que a verificação de transbordamento tenha sido ativada nas opções de compilação.
Sensivelmente, o Visual Studio 2013 (e provavelmente também outras versões) fornece um aviso para esse código, recomendando que você use 'L' em vez de 'l'.


12
Oh, lé suposto parecer um 1! Eu sou estúpido. : \
Joe Z.

6
Sugestão para melhoria: substituir os 1s na seção de saída esperada com ls bem (é mais fácil de detectar o personagem estranho quando você tem 1s reais para comparar contra)
Allen Gould

3
Sim, parece ser bastante específico do ambiente. A fonte do Michael é muito diferente da fonte do meu computador doméstico ( imgur.com/PKIuJpr - Chrome, Windows 8), e o truque parece funcionar melhor no meu computador comercial do que no meu computador doméstico, mesmo sendo bastante parecido especificações. O navegador do meu telefone parece não mostrar o código em uma fonte de densidade fixa, e o truque não funciona de todo.
21714 BenM

1
FTR, eis a aparência do meu computador de trabalho ( imgur.com/Opfs3BH - Firefox, Windows 7). Acho que se pode até enganar pessoas bastante astutas.
21714 BenM

15
POR QUE AS PESSOAS MANTÊM ABUSANDO PERSONAGENS QUE PARECEM O MESMO?
Anonymous Pi

39

C

Que tal precisão?

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

Imagine que você precise armazenar um intervalo de números inteiros <0; 3> na memória do computador. Existem apenas 4 números inteiros nesse intervalo (0,1,2,3). É suficiente usar 2 bits para armazenar isso na memória. Agora imagine que você precisa armazenar um intervalo de números de ponto flutuante <0; 3>. O problema é que há um número infinito de números de ponto flutuante nesse intervalo. Como armazenar um número infinito de números? É impossível. Só podemos armazenar um número finito de números. É por isso que alguns números como 0,1 são realmente diferentes. No caso de 0,1, é 0.100000000000000006. É altamente recomendável não usar == ou! = Em condições desde que você use números de ponto flutuante.


1
Como é que isso funciona?
Mhmd

5
Erros de arredondamento. 0.1 é realmente 0.100000000000000006 porque 0.1 em binário é igual a 1/3 em decimal - sua expansão binária é infinita e periódica.
orion

3
Não é realmente um erro de arredondamento. Os valores de ponto flutuante são representações aproximadas de um número. Realizar comparações exatas entre valores aproximados não vai funcionar.
18714 AKHolland

4
É por isso que você (quase) nunca deve comparar float / doubles pela igualdade.
Emanuel Landeholm

1
Eu estava esperando para ver este. Agradável.
David Conrad

33

HTML / JavaScript

Imagine que você tem uma caixa de entrada na sua página:

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

E agora você deseja digitar algo ... Experimente no Chrome: http://jsfiddle.net/jZp4X/ .

A caixa de diálogo do navegador padrão chamada com alertfunção é modal; portanto, quando é exibida, o foco é retirado da caixa de texto, mas quando é descartado, a caixa de texto recebe o foco de volta.


5
no firefox, a entrada não tem foco automático ao fechar o alerta e, pela segunda vez, oferece-me para não mostrar mais alertas e, em seguida, eu posso escrever na caixa de texto normalmente
Einacio

6
Agradável. +1 para sem loops ou recursão.
Aproximando-se

5
Sem loops no Firefox ou Chrome. O FF mostra o alerta uma vez quando a caixa de diálogo é clicada, você o dispensa e esse é o fim. Pode clicar novamente para repetir. O Chrome faz o mesmo, mas deixa a caixa focada e você pode até digitar nela. Desculpe, talvez em versões mais antigas isso tenha sido um problema, mas não mais.
RomanSt

6
O IE11 funciona exatamente como o Chrome para mim. Acho que você encontrou inadvertidamente um exemplo de algo que funciona de maneira única em todos os navegadores modernos do Mac e de maneira diferente em todos os navegadores modernos do Windows!
RomanSt

1
Funciona normalmente (sem loops) em 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;
}

A condição i >=0é sempre verdadeira porque size_t não está assinado.


2
Boa, mas um aviso compiladores normalmente saída para isso;)
Synxis

2
@ Synxis Sim, compiladores. Mas somente se você ativar os avisos do compilador. g++não avisará sobre isso sem eles.
precisa saber é o seguinte

5
Você sempre deve usar de -Wall --pedanticqualquer maneira.
Martin Ueding 17/03/14

3
@queueoverflow O aviso não aparece apenas com esses sinalizadores. Você precisa do -Wsign-compareque pode ser ativado -Wextra.
FDinoff

7
Um traço na costa atlântica. #pedantic
David Conrad

29

bater

(Houve um pedido de não loops ou recursão)

#!/bin/bash

# Demo arrays

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

echo $foo

echo ${foo[0]}

foo[2] = `yes`

echo $foo

echo ${foo[2]}

Em vez de atribuir a string 'yes' a foo [2], isso chama o comando do sistema yes, que preenche foo [2] com uma quantidade interminável de "yes \ n".


Eventualmente fica bashsem memória e trava-o #
Digital Trauma

4
Sim, é verdade. Mas um acidente foi tipo de permitido pela pergunta :)
GreenAsJade

Sim, apenas uma observação :). Votado.
Digital Trauma

Na verdade, eu acho que os programas nesta pequena amostra que realmente travar a sua máquina, ou alguma outra negação de serviço, deve começar marcas bônus)
GreenAsJade

Correção: yesé apenas um programa coreutils. Não é um syscall.
Mniip 22/03

28

C

A letra "x" foi perdida em um arquivo. Um programa foi escrito para encontrá-lo:

#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");
  }
}

Foi compilado e rodado e finalmente gritou:

Hurray, letter lost in the file is finally found!

Por muitos anos, as cartas foram resgatadas dessa maneira até que o novo funcionário veio e otimizou o código. Ele conhecia os tipos de dados e sabia que é melhor usar valores não assinados do que assinados para valores não negativos, pois ele possui um intervalo mais amplo e oferece alguma proteção contra estouros. Então ele mudou int para unsigned int . Ele também conhecia ascii o suficiente para saber que eles sempre têm valor não negativo. Então ele também mudou char para char não assinado . Ele compilou o código e voltou para casa orgulhoso do bom trabalho que fez. O programa ficou assim:

#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");
  }
}

Ele voltou a uma confusão no dia seguinte. A letra "a" estava faltando e, embora devesse estar no "desert_file" que contém "abc", o programa estava procurando por ele para sempre imprimir apenas:

Searching file for missing letter a...

Eles demitiram o cara e voltaram para a versão anterior, lembrando que nunca se deve otimizar tipos de dados no código de trabalho.

Mas qual é a lição que eles deveriam ter aprendido aqui?

Primeiro de tudo, se você der uma olhada na tabela ascii, notará que não há EOF. Isso ocorre porque o EOF não é um caractere, mas um valor especial retornado de fgetc (), que pode retornar o caractere estendido para int ou -1, indicando o final do arquivo.
Enquanto estivermos usando char assinado, tudo funcionará bem - char igual a 50 é estendido por fgetc () para int igual a 50 também. Depois, transformamos novamente em char e ainda temos 50. O mesmo acontece para -1 ou qualquer outra saída proveniente de fgetc ().
Mas veja o que acontece quando usamos caracteres não assinados. Começamos com um caractere em fgetc () estendendo-o para int e, em seguida, queremos ter um caracter não assinado. O único problema é que não podemos preservar -1 em caracteres não assinados. O programa está armazenando-o como 255, que não é mais igual ao EOF.

Embargo
Se você der uma olhada na seção 3.1.2.5 Tipos de cópia da documentação ANSI C, descobrirá que se char é assinado ou não, depende apenas da implementação. Portanto, o cara provavelmente não deve ser demitido, pois encontrou um bug muito complicado à espreita no código. Pode surgir ao alterar o compilador ou mudar para uma arquitetura diferente. Gostaria de saber quem seria demitido se o bug fosse lançado nesse caso;)

PS. O programa foi criado com base no bug mencionado na linguagem Assembly de PC por Paul A. Carter


7
Eu amo que há uma história com a solução.
Jpmc26

Haha! Eu acho que é o único. Obrigado pela leitura!
Legat 22/03

1
Eu te amo. Alimente-me com suas histórias pls :(
YoYoYonnY

Isso é absolutamente brilhante!
Kirbyfan64sos

21

Regex

Com a entrada apropriada, o seguinte regex pode fazer com que a maioria dos mecanismos de regex de retorno volte ao inferno:

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

Uma entrada simples como "Programming Puzzles and Code Golf Stack Exchange - Mozilla Firefox"or "AVerySimpleInputWhichContainsAnInsignificantSentence."(ambas as strings citadas para maior clareza) é suficiente para manter a maioria dos mecanismos regex de retorno por um longo tempo.

Uma vez que (\s*\w+)*permite a expansão \w+\w+\w+... \w+, o que significa que o mecanismo regex basicamente tentará todas as maneiras possíveis de dividir uma sequência de caracteres de palavras . Esta é a fonte do inferno de voltar atrás.
Ele pode ser facilmente corrigido alterando \s*para \s+, em seguida, (\s+\w+)*só pode ser expandida para \s+\w+\s+\w+... \s+\w+.


3
Eu odeio voltar atrás em mecanismos regex.
David Conrad

2
Tentei isso com o Perl primeiro, mas parece que o Perl pode perceber um loop aqui. Não tentei o AWK, porque nenhuma expressão regular pode causar esse comportamento no AWK. O PHP cria automaticamente expressões regulares que demoram muito para corresponder à falha (o que é bobagem, mas isso é PHP para você - ele insere erros automaticamente nos programas). No entanto, ele realmente funciona em Python.
precisa

1
@xfix: Quanto ao motivo pelo qual o Perl conseguiu evitar voltar atrás, este artigo explica o motivo. No entanto, não é suficiente no caso, como mostrado aqui (role para baixo até a seção desempenho). O PHP (na verdade a biblioteca PCRE) possui um limite de retorno e um programa adequado deve sempre verificar o valor de retorno da função para decidir se a execução foi interrompida ou executada até a conclusão.
N

1
Isso é tão LISO.
alvonellos

20

Javascript

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

050 é uma constante octal em Javascript e o valor decimal é 40.


73
Eu acho isso óbvio. :-)
Justin

6
Eu não sabia que o javascript fazia isso. Mas depois de ler o código que eu disse: "050 Tem que haver alguma maneira de representar 40, provavelmente de base 8 ou algo assim"
Cruncher

Isso precisa ser melhor escondido.
Paŭlo Ebermann 24/03

É óbvio ..
Oliver Ni

18

Haskell

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

Bem, pense nisso! Seria o mesmo que head $ "Hello" ++ (repeat '!'), ou seja, deveria apenas retornar 'H'.

Nas listas haskell, existem estruturas recursivas, com o primeiro elemento sendo o mais alto. Para anexar a uma lista, é necessário desenrolar todos esses elementos, colocar seu apêndice e colocar os elementos levantados de volta. Isso não funcionaria em uma lista infinita. Da mesma forma, reverter uma lista infinita não lhe dará magicamente as "Hello"costas. Vai ficar para sempre.


1
Pena que isso realmente não funciona: - /
John Dvorak

1
Como isso não funciona?
Danmcardle

@crazedgremlin quando testei isso no Fedora, o sistema operacional acabou com o processo. (<5 minutos) porque consumiu toda a memória do sistema.
FDinoff

Interessante! Eu não percebi que isso aconteceu. Não me aventuro no território de devorar toda a memória com tanta frequência.
22414 Danmcardle

4
Isso ainda é uma solução válida: ela não sair, ele é executado, contanto que puder até que o sistema não pode suportar mais isso ...
GreenAsJade

16

Java no 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();
    }
}

O programa depende de um fluxo de saída padrão atolado da linha de comando para ficar travado. O diretório WinSXS no Windows possui vários milhares de arquivos com nomes longos, por isso é quase garantido que entupir o stdout e waitFornão pode retornar, portanto o programa está em um impasse.


1
Talvez eu esteja sendo densa, mas isso não voltará eventualmente? Pode demorar um pouco. Talvez eu não entenda o que você quer dizer com "entupir [sting] stdout".
Asteri

4
se o fluxo não é esvaziado os blocos do programa, já me causaram algumas dores de cabeça por isso que eu o usei; o diretório longo apenas garante que o buffer seja executado completamente
masterX244

Ah, entendi. Agradável! +1
asteri

15

Para comparar maçãs e laranjas ... em C

Estou impressionado que não há nenhum código aqui usando um goto... (Você sabe: Goto é mau! )

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

O sono é apenas para poder lê-lo. Pressione ^ C se você não tiver um tempo infinito para esperar por algo que nunca acontece ;-)


9
Seu bastardo sorrateiro, goto é inocente nessa:)
orion

é o random () o vodoo usado?
masterX244

1
ahh, "2"! = 2; entendeu
masterX244

2
Bem, "2" provavelmente nunca pode ser 2, mas se você usasse um número maior (e um múltiplo de pelo menos 4), isso poderia acontecer;)
orion 17/03/14

1
@orion: Sim, você está certo, pode ser. E ir embora ainda é mau, mas as peças vazadas de tipo ruim são ainda mais más!
max.haredoom

12

C, com certos compiladores de otimização

Este programa incrementa uma variável inteira até que ela exceda.

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

Estouro de número inteiro assinado é um comportamento indefinido. Geralmente, na prática, ele é encerrado quando as otimizações são desativadas. Com as otimizações ativadas, os compiladores podem e decidem que isso x + 1 > xsempre é verdade.


Talvez use int32_t; um int de 64 bits levaria muito, muito, muito tempo (585 anos se cada iteração demorar um nanossegundo).
Paul Draper

11

C ++

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

O estilo estranho de comentar é o truque. Dica: trigramas.


Este é um exemplo muito básico de um loop infinito.
Ismael Miguel

64
Esses Trigraphs são tão usado em demasia aqui :(
TimWolla

75
Eu quase sinto que os trigrafs devem ser colocados em brechas padrão que não são mais engraçadas.
Undergroundmonorail

6
@TheDoctor: ?? / é um trigrafo para um caractere de barra invertida; portanto, a barra invertida une a linha em que x é atribuído 0 ao final do comentário, tornando-o parte do comentário.
CasaDeRobison 16/03

4
@undergroundmonorail Postado
Justin

11

Java

Eu particularmente adoro esse efeito colateral da otimização do 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");  
    }
  }
}

Por causa da caixa automática, os Integerobjetos se comportam quase como intaqui, com uma exceção: o i != maxnos forloops compara as referências (identidade) dos Integerobjetos, não o valor (igualdade). Para valores de até 100, isso surpreendentemente "funciona", no entanto, devido a uma otimização na JVM: Java pré-aloca Integerobjetos para os "valores mais comuns" e os reutiliza ao autobox. Portanto, para valores de até 100, temos identidade <==> igualdade.


5
Tendo em conta que alguns caras Java ainda consideram C ++ operador sobrecarga como o mal ...
Daniel

Você não precisa da inicialização = new Integer(0), pois está inicializando os valores posteriormente. (Isso pode tornar a razão menos óbvia.)
Paulo Ebermann

@ PaŭloEbermann: Bom ponto, eu editei o código.
24414 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;
}

Isso funciona corretamente em C , com contagem regressiva de 9 para 1 em STDOUT. Quando executado em Ruby, ele não termina, porque

0 não é um valor falso no Ruby.


Faça idiomas de uma vez ... impressionante.
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]]);

Os dois loops usam a mesma variável de loop, portanto, dependendo da entrada, o loop interno pode impedir que o loop externo termine.


Que língua é essa?
RononDex

@ronondex Javascript
tomsmeding

1
Ah, sim, é Javascript. Lembrei-me de ativar o hilighting da sintaxe, mas tive que esquecer de colocá-lo no título também :) #
Aleksi Torhamo

1
Eu acho isso óbvio. :-)
rafaelcastrocouto

@rafaelcastrocouto Sim, meio que é, mas também é muito fácil de perder, por exemplo, ao mover um loop de uma função para outra ou apenas olhando o código. Além disso, observe que isso realmente funciona corretamente em alguns idiomas, incluindo C, devido ao sombreamento variável. :)
Aleksi Torhamo

7

C

Isso deve imprimir uma tabela de códigos para todos os caracteres ASCII, de 0 a 255. A charé grande o suficiente para iterar sobre eles.

#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 os caracteres são menores que 256. 255 ++ fornece 0 devido ao estouro, portanto, a condição i < 256sempre é válida. Alguns compiladores alertam sobre isso, outros não.


Fazer parecer parecer algo mais útil, talvez use algo como printf("%3d %2x: %c", i, i, i);(para uma tabela de códigos) em seu loop.
Paŭlo Ebermann 24/03

@ PaŭloEbermann: Ótima idéia.
Rafał Cieślak 24/03

Eu uso este truque em minha sala de aula, com caracteres não assinados imprimíveis entre 32 e 128. :)
cpri

7

Pitão

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

deveria ser exit()e não exit. Pelo que entendi, exit()é o comando para sair do interpretador python. Nesse caso, a chamada é para a representação da função e não para a função, consulte: exit-discussion . Alternativamente, breakseria uma escolha melhor.


Poderia explicar o que exitrealmente é? Parece ser uma aula, mas para que é usada? Você também pode alterar print ma print(m)forma que isso também funciona com o Python 3.
Martin Thoma

1
Esse tipo de coisa ... Como quando meu elseif não funcionava porque era elif .
Anonymous Pi

Obrigado @moosedeclaração de impressão atualizada e a mensagem de spoiler
Willem

6

C ++

E a clássica armadilha para programadores em C ++?

int main()
{
   bool keepGoing = false;

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

   return 0;
}

Eu não entendo isso? É sobre o uso. = em vez de ==?
Mhmd 17/03/2014

@ user689 exatamente. keepGoing = truefoi concebido para comparar o valor de keepGoing, em vez disso, atribui o valor a keepGoing; além disso, a declaração inteira é keepGoing = trueavaliada como true(o que permite escrever coisas como a=b=c=d=0) levando a um loop infinito.
21414 CompuChip

3
Esta é cada vez mais uma razão para usar as condições de yoda.
Ryan

@RyanEdwardDougherty Haha assim, eu nunca os ouvi sendo chamados. Pela manhã rir obrigado.
21414 CompuChip

@RyanEdwardDougherty: Naturalmente == true(ou no estilo Yoda true ==) é redundante de qualquer maneira, e a condição deve simplesmente ser lida while (keepGoing).
22614 Celtschk

6

Javascript

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

As variáveis ​​usadas na 1ª e na 3ª linha são diferentes das usadas na 2ª e 3ª linha.
Um usa um (U + 0061) enquanto o outro usa um (U + 0430)


Não vejo problema aqui. Eu executei e funcionou bem. o que estou perdendo?
Andrew Shepherd

isso provavelmente funcionará em qualquer lugar, pois o unicode provavelmente será convertido. Recebeu +1, pois é o mais invisível que você pode obter!
Rafaelcastrocouto 20/03

Apenas para ocultá-lo completamente (substitua á por U + 0430) Se esse fosse o seu código, boa sorte em encontrar o 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);eu desistiria, excluiria isso para sempre, limpe meu computador, talvez antivírus, apenas para ter certeza e reescrevê-lo completamente. Edição: Porque var a = 0; a = 1;não é muito 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!");
   }
}

O "i = i ++" é um erro bastante comum para iniciantes e pode ser surpreendentemente difícil de encontrar


5

C ++

Um pouco aleatório?

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

Não chama a função, randmas chama recursivamente a Randomizer::randfunção.


5
Parênteses extras na declaração de retorno, eca.
David Conrad

1
Isso acabará por falhar, no entanto.
Kirbyfan64sos

5

Haskell

Algum código para cronometrar o cálculo de um determinado valor da função Ackermann. Para valores muito baixos, geralmente termina. Na minha máquina, valores muito baixos significam algo como 3 5 ou menos com código compilado e -O. Em ghci, valores baixos significam algo como 3 3.

O 'símbolo parece atrapalhar o realce da sintaxe, sem saber por quê. Em alguns lugares, eles são necessários, portanto, não é possível remover todos eles.

Editar - idioma alterado.

{-# 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

Isso causa um livelock. O fio de contagem faz com que o cálculo de Ackermann seja revertido uma vez que eles tocam no mesmo TVar.


marcá-lo como Lang-hs em vez de lang-haskell parece funcionar melhor (é uma das extensões do Google prettifier )
Einacio

5

Java - sem loops ou recursão

Comecei a aprender expressões regulares e escrevi meu primeiro programa para testar se minha string corresponde a uma expressão regular.

Infelizmente, o programa não produz nenhum resultado. Ele sustenta o terminal. Por favor, ajude a encontrar o problema. Eu não fiz nenhum uso de loops, não há recursão envolvida. Estou completamente perplexo.

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!");
     }
}

O que eu fiz errado? Por que meu programa não termina? Por favor ajude!

Ideone link aqui .

Este é um exemplo estúpido de retorno catastrófico . A complexidade é O (2 n / 2 ). Embora o programa possa não ser executado indefinidamente, provavelmente sobreviveria a objetos vivos e não-vivos por aí e não por aí .


5

C

Você só precisa de um dos dois loops, mas o que você precisa depende do seu 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);
        }

}

Uma saturação de limites simples que redefine i para um valor não final. Os compiladores podem diferir se eles alocam i acima ou abaixo de um na pilha, então incluí excedentes nas duas direções.


5

C / C ++

O C ++ permite apenas as declarações fáceis de variáveis ​​em linha usadas aqui, mas é tão fácil cometer esse erro em 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;
}

No loop interno, 'j' é comparado, mas nunca incrementado. (O 'i ++' deve realmente ser 'j ++'). Este não é um truque sorrateiro, mas um erro real que cometi no passado;) Algo a se observar.


2
Isso normalmente leva pelo menos 5 minutos para depurar. Eu odeio quando fiz isso.
ace_HongKongIndependence

4

C #

A seguir, é apresentada uma classe simples que executa uma operação aritmética (soma) em uma matriz de entrada grande usando um encadeamento em segundo plano. Um programa de amostra está incluído.

No entanto, embora seja bastante direto, nunca termina. Observe que não há truques manuais (aparência de personagem, ponto-e-vírgula oculto / ausente, trigramas ;-), 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 é um exemplo de um bug desagradável do mundo real que também pode aparecer no seu código. De acordo com o modelo de memória .NET e a especificação C #, um loop como esse WaitAndGetResultpode nunca terminar, a menos que você especifique a variável como volátil, porque é modificada por outro encadeamento. Veja esta pergunta StackOverflow para obter detalhes. O bug depende da implementação do .NET, portanto, pode ou não afetá-lo. Mas geralmente, executar uma versão compilada em um processador x64 parece exibir o problema. (Tentei com “csc.exe / o + / debug- infinite.cs” .)

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.