Perché non finisce? [chiuso]


95

Il tuo compito: scrivere un programma che dovrebbe ovviamente terminare, ma non lo fa mai (nella misura di un crash del computer). Fai sembrare che dovrebbe svolgere un semplice compito: aggiungere numeri, stampare qualcosa, ... Ma viene catturato in un ciclo infinito.

Cerca di rendere il tuo programma molto chiaro e semplice, mentre in realtà rimarrà bloccato in un ciclo imprevisto. Elettori: giudica le risposte su quanto siano "subdoli"!

Questo è un concorso di popolarità: sii creativo!


6
Qualcuno potrebbe spiegare cosa posso fare per rendere la domanda meno ampia? Sono nuovo qui. Grazie!
Numero 9

6
Questa sarà solo una grande lista di errori di battitura e errori per principianti che causano loop.
Bill Woodger,

Domanda interessante, ma non ho ancora visto risposte veramente creative. Prometto voti a chiunque non usi loop o ricorsioni evidenti!
Approaching

14
Non so se questo conta, ma al momento il mio Microsoft Office si comporta esattamente così.
Level River St

1
Sto votando per chiudere questa domanda come fuori tema perché le sfide subdole non sono più in tema qui. meta.codegolf.stackexchange.com/a/8326/20469
cat

Risposte:


185

Javascript

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

prompt () restituisce una stringa e il ciclo aggiunge il carattere '1', non sarà mai uguale a 100.


13
Mi hai preso con quello ... gli esempi (in realtà) più votati stanno solo abusando della sintassi ... ma quello è carino!
bwoebi,

4
Chrome su Kubuntu non ha risposto, ho appeso tutto e ho dovuto resettare duramente :)
Sergey Telshevsky

4
@Vlakarados: Python non eseguirà la conversione di tipo implicita di Javascript. Su Python, il codice equivalente che utilizza raw_inputo Python 3 inputgenera a TypeError.
user2357112

2
Non si verifica il fatto che il valore sia effettivamente inferiore a 100, quindi si interrompe normalmente quando si immette "100": '- (
C.Champagne

1
@Sankalp, l' +operatore qui è la concatenazione di stringhe, non l'aggiunta.
Michael M.

87

C

Solo un programma di esempio di base che illustra i tre diversi tipi di while-loop in 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;
}

Mentre i loop non hanno un "do" prima dell'apertura parentesi graffa. Questo in realtà crea un ciclo do-while all'interno del ciclo (x <10) che termina con la seguente "istruzione null" mentre il ciclo. Poiché x viene incrementato all'interno del loop e quindi decrementato nelle condizioni del loop do-while, il loop interno non termina mai, e quindi nemmeno il loop esterno. Il ciclo "single-statement" alla fine non viene mai raggiunto.

Se sei ancora confuso, guarda qui (ospitato esternamente perché a codegolf.SE non piacciono i blocchi di codice negli spoiler).


8
Haha, ho capito questo prima di guardare lo spoiler della soluzione. : P
Joe Z.

54
Perché hai perso un'eccellente opportunità di usare l'operatore "vai a"? (x --> 0)
corsiKa

2
Oh wow Questo è meravigliosamente malvagio. Mi ci sono volute quattro letture per trovarlo.
Patrick M,

1
@JoeZ. Troppo facile. La soluzione più votata era migliore. Quello che non ho trovato.
Anonimo Pi

3
@Hat Guy, Bash ha il per; do e while; fare la sintassi in modo che io possa vedere le persone che vengono scartate da questo, anche se hanno familiarità con linguaggi non 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;
})();

Sollevamento di variabili: JavaScript prenderà effettivamente la mia seconda definizione di var a = true;, la dichiarerà nella parte superiore della funzione come var a;e modificherà il mio assegnamento al a = true;significato anon sarà definito nel momento in cui entra nel ciclo while.


3
Potresti aggiungere una spiegazione migliore del perché questo non si interrompe mai? Si prega di approfondire il "sollevamento variabile" :)
Numero 9

1
@ Numero9 Spero che sia d'aiuto, google ha esempi molto migliori di questo;)
Newbrict

25
Merda, questo è anche peggio dell'inserimento di punti e virgola. +1!
tomsmeding

2
L'unico problema che vedo con questo programma è che non sembra che esegua un semplice compito ... sembra che essenzialmente non dovrebbe fare nulla. Forse aggiungere un alertdopo il ciclo.
PeterT

2
Dovresti cambiare a = 1in a = true. Il codice avrà comunque il ciclo infinito in quel modo, ma sarà più chiaro che il motivo non è una stranezza nella conversione JavaScript da ints a booleani.
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");
    }
}

Il numero letterale nella prima riga della funzione non è un '201', ma un '20' con un suffisso 'L' minuscolo ( tipo di dati lungo ). Il numero traboccerà abbastanza rapidamente senza mai toccare 6432, ma il programma continuerà a meno che nelle opzioni di generazione non sia stato attivato il controllo di trabocco.
Sensibilmente, Visual Studio 2013 (e probabilmente anche altre versioni) ti dà un avvertimento per questo codice, raccomandando di usare 'L' invece di 'l'.


12
Oh, ldovrebbe sembrare un 1! Io sono stupido. : \
Joe Z.

6
Suggerimento per il miglioramento: sostituisci anche gli 1 nella sezione di output atteso con ls (è più facile individuare lo strano personaggio quando hai 1 reale da confrontare)
Allen Gould

3
Sì, sembra essere abbastanza specifico per l'ambiente. @ Il carattere di Michael sembra molto diverso dal carattere sul mio computer di casa ( imgur.com/PKIuJpr - Chrome, Windows 8), e il trucco sembra funzionare meglio sul mio computer di lavoro rispetto al mio computer di casa, anche se hanno abbastanza simili Specifiche. Il browser del mio telefono non sembra mostrare il codice in un carattere a passo fisso e il trucco non funziona affatto su di esso.
BenM,

1
FTR, ecco come appare sul mio computer di lavoro ( imgur.com/Opfs3BH - Firefox, Windows 7). Suppongo che si potrebbe anche ingannare le persone abbastanza astute.
BenM,

15
PERCHÉ LE PERSONE TENGONO ABUSI DAI PERSONAGGI CHE LO ASPIRANO?
Anonimo Pi

39

C

Che ne dici di precisione?

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

Immagina di dover memorizzare un intervallo di numeri interi <0; 3> nella memoria del computer. Ci sono solo 4 numeri interi in questo intervallo (0,1,2,3). Basta usare 2 bit per archiviarlo in memoria. Ora immagina di dover memorizzare un intervallo di numeri in virgola mobile <0; 3>. Il problema è che esiste un numero infinito di numeri in virgola mobile in questo intervallo. Come memorizzare un numero infinito di numeri? È impossibile. Possiamo solo memorizzare un numero finito di numeri. Questo è il motivo per cui alcuni numeri come 0.1 sono in realtà diversi. In caso di 0,1 è 0,100000000000000006. Si consiglia vivamente di non utilizzare == o! = In condizioni purché si utilizzino numeri in virgola mobile.


1
Come funziona?
Mhmd

5
Errori di arrotondamento. 0.1 è in realtà 0.100000000000000006 perché 0.1 in binario è come 1/3 in decimale - la sua espansione binaria è infinita e periodica.
Orione,

3
Non è davvero un errore di arrotondamento. I valori in virgola mobile sono rappresentazioni approssimative di un numero. L'esecuzione di confronti esatti tra valori approssimativi non funzionerà.
AKHolland,

4
Questo è il motivo per cui (quasi) non dovresti mai confrontare float / double per l'uguaglianza.
Emanuel Landeholm,

1
Stavo aspettando di vedere questo. Bello.
David Conrad

33

HTML / JavaScript

Immagina di avere una casella di input nella tua pagina:

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

E ora vuoi digitare qualcosa al suo interno ... Prova in Chrome: http://jsfiddle.net/jZp4X/ .

La finestra di dialogo del browser standard chiamata con alertfunzione è modale, quindi quando viene visualizzata toglie lo stato attivo dalla casella di testo, ma quando viene ignorata la casella di testo riceve nuovamente lo stato attivo.


5
in Firefox, l'input non ha l'autofocus alla chiusura dell'avviso, e dalla seconda volta mi offre di non mostrare più avvisi e quindi posso scrivere normalmente nella casella di testo
Einacio

6
Ben fatto. +1 per nessun loop o ricorsione.
avvicina

5
Nessun loop in Firefox o Chrome. FF mostra l'avviso una volta quando si fa clic sulla finestra di dialogo, la si elimina e questa è la fine. Puoi fare di nuovo clic per ripetere. Chrome fa lo stesso, ma lascia il riquadro focalizzato e puoi persino digitarlo. Spiacenti, forse nelle versioni precedenti questo era un problema, ma non più.
Roman,

6
IE11 funziona esattamente come Chrome per me. Penso che tu abbia inavvertitamente trovato un esempio di qualcosa che funziona in un modo su ogni browser moderno su Mac e un modo diverso su ogni browser moderno su Windows!
Roman,

1
Funziona normalmente (senza loop) su 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 condizione i >=0è sempre vera perché size_t è senza segno.


2
Bello, ma i compilatori normalmente emettono un avviso per questo;)
Synxis

2
@Synxis Sì, i compilatori lo fanno. Ma solo se attivi gli avvisi del compilatore. g++non ti avvertirò di questo senza di loro.
FDinoff,

5
Dovresti sempre usare -Wall --pedanticcomunque.
Martin Ueding,

3
@queueoverflow L'avvertimento non viene visualizzato solo con quelle bandiere. È necessario -Wsign-compareche può essere attivato con -Wextra.
FDinoff,

7
Un trattino su -pedantic. #pedantic
David Conrad

29

bash

(C'è stata una richiesta per nessun loop o ricorsione)

#!/bin/bash

# Demo arrays

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

echo $foo

echo ${foo[0]}

foo[2] = `yes`

echo $foo

echo ${foo[2]}

Invece di assegnare la stringa 'yes' a foo [2], questo chiama il comando di sistema yes, che riempie foo [2] con una quantità infinita di "yes \ n".


Alla fine bashla memoria si esaurisce e si blocca
Digital Trauma

4
Sì, davvero. Ma un incidente è stato in qualche modo permesso dalla domanda :)
GreenAsJade

Sì, solo un'osservazione :). Upvoted.
Trauma digitale

In effetti, ritengo che i programmi in questa piccola comp che in realtà si bloccano la tua macchina, o qualche altra negazione del servizio, dovrebbero ottenere punti bonus)
GreenAsJade

Correzione: yesè solo un programma coreutils. Non è un syscall.
mniip,

28

C

La lettera "x" è stata persa in un file. È stato scritto un programma per trovarlo:

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

È stato compilato e funzionante e finalmente ha gridato:

Hurray, letter lost in the file is finally found!

Per molti anni le lettere sono state salvate in questo modo fino a quando il nuovo ragazzo è arrivato e ha ottimizzato il codice. Conosceva i tipi di dati e sapeva che è meglio usare valori non firmati che firmati per valori non negativi poiché ha un intervallo più ampio e offre una certa protezione contro gli overflow. Quindi ha cambiato int in unsigned int . Conosceva anche ascii abbastanza bene da sapere che hanno sempre un valore non negativo. Quindi ha anche cambiato carattere in carattere non firmato . Compilò il codice e tornò a casa orgoglioso del buon lavoro che aveva fatto. Il programma sembrava così:

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

È tornato in rovina il giorno successivo. Mancava la lettera "a" e anche se doveva essere nel "file_sviluppo" contenente "abc", il programma lo cercava per sempre stampando solo:

Searching file for missing letter a...

Hanno licenziato il ragazzo e sono tornati alla versione precedente ricordando che non si dovrebbero mai ottimizzare i tipi di dati nel codice di lavoro.

Ma qual è la lezione che avrebbero dovuto imparare qui?

Prima di tutto, se dai un'occhiata alla tabella ASCII noterai che non esiste EOF. Questo perché EOF non è un carattere ma un valore speciale restituito da fgetc (), che può restituire il carattere esteso a int o -1 che indica la fine del file.
Finché stiamo usando il carattere con segno tutto funziona bene - il carattere uguale a 50 viene esteso da fgetc () in int uguale a 50. Quindi lo trasformiamo nuovamente in char e ne abbiamo ancora 50. Lo stesso accade per -1 o qualsiasi altro output proveniente da fgetc ().
Ma guarda cosa succede quando usiamo caratteri non firmati. Iniziamo con un carattere in fgetc () estenderlo a int e quindi vogliamo avere un carattere senza segno. L'unico problema è che non possiamo conservare -1 nel carattere senza segno. Il programma lo sta memorizzando come 255 che non è più uguale a EOF.

Avvertimento
Se dai un'occhiata alla sezione 3.1.2.5 Tipi in copia della documentazione ANSI C scoprirai che se il carattere è firmato o meno dipende esclusivamente dall'implementazione. Quindi probabilmente il ragazzo non dovrebbe essere licenziato poiché ha trovato un bug molto complicato in agguato nel codice. Potrebbe venire fuori quando si cambia il compilatore o si passa a un'architettura diversa. Mi chiedo chi verrebbe licenziato se il bug emergesse in tal caso;)

PS. Il programma è stato costruito attorno al bug menzionato in PC Assembly Language da Paul A. Carter


7
Adoro che ci sia una storia con la soluzione.
jpmc26

Haha! Immagino sia l'unico. Grazie per aver letto!
Legat,

1
Ti amo.
Nutrimi

Questo è assolutamente geniale!
kirbyfan64sos,

21

regex

Con l'input appropriato, il seguente regex può causare la maggior parte del motore regex di backtracking nell'inferno di backtracking:

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

Un input semplice come "Programming Puzzles and Code Golf Stack Exchange - Mozilla Firefox"o "AVerySimpleInputWhichContainsAnInsignificantSentence."(entrambe le stringhe citate per chiarezza) è sufficiente per mantenere la maggior parte dei motori regex di backtrack in funzione per molto tempo.

Dato che (\s*\w+)*consente l'espansione \w+\w+\w+... \w+, il che significa che il motore regex proverà sostanzialmente tutti i modi possibili per dividere una stringa di caratteri di parole . Questa è la fonte dell'inferno di backtracking.
Può essere facilmente risolto modificando \s*a \s+, allora (\s+\w+)*può essere esteso solo \s+\w+\s+\w+... \s+\w+.


3
Odio tornare indietro sui motori regex.
David Conrad,

2
Ho provato prima con Perl, ma sembra che Perl possa notare un loop qui. Non ho provato AWK, perché nessuna espressione regolare può causare tale comportamento in AWK. PHP crea automaticamente un'espressione regolare che impiega troppo tempo per far fallire (il che è sciocco, ma questo è PHP per te - inserisce automaticamente i bug nei programmi). Tuttavia, in realtà funziona in Python.
Konrad Borowski il

1
@xfix: Per quanto riguarda il motivo per cui Perl è riuscito a evitare di risalire all'inferno, questo articolo spiega il motivo. Tuttavia, non è sufficiente rispetto al caso come mostrato qui (scorrere fino alla sezione delle prestazioni). PHP (in realtà la libreria PCRE) ha un limite di backtracking e un programma adeguato dovrebbe sempre verificare il valore di ritorno della funzione per decidere se l'esecuzione è stata interrotta o eseguita fino al completamento.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

1
Questo è così SLICK.
alvonellos,

20

JavaScript

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

050 è una costante ottale in Javascript e sembra avere il valore decimale di 40.


73
Lo trovo ovvio. :-)
Justin

6
Non sapevo che JavaScript lo avesse fatto. Ma dopo aver letto il codice ho detto: "050 deve essere un modo per rappresentare 40, probabilmente base 8 o qualcosa del genere"
Cruncher

Questo deve essere nascosto meglio.
Paŭlo Ebermann,

È ovvio ..
Oliver Ni

18

Haskell

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

Beh, pensaci! Sarebbe lo stesso head $ "Hello" ++ (repeat '!'), cioè dovrebbe solo tornare 'H'.

Nelle liste di haskell sono strutture ricorsive, con il primo elemento in cima. Per aggiungere un elenco, è necessario srotolare tutti quegli elementi, posizionare l'appendice e rimettere gli elementi sollevati. Non funzionerebbe su un elenco infinito. Allo stesso modo, invertire una lista infinita non ti darà magicamente le "Hello"spalle. Rimarrà appeso per sempre.


1
Peccato che in realtà non funziona: - /
John Dvorak

1
Come non funziona?
danmcardle

@crazedgremlin quando l'ho provato su Fedora il sistema operativo alla fine ha interrotto il processo. (<5 minuti) perché ha esaurito tutta la memoria del sistema.
FDinoff,

Interessante! Non mi ero reso conto che questo fosse successo. Non mi avventuro nel territorio divorando tutta la memoria così spesso.
danmcardle,

4
Questa è ancora una soluzione valida: non esce, funziona il più a lungo possibile fino a quando il sistema non può più supportarlo ...
GreenAsJade

16

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

Il programma fa affidamento su un flusso di output standard inceppato dalla riga di comando per rimanere bloccato. La directory di WinSXS in Windows ha più di migliaia di file con nomi lunghi, quindi è quasi sicuro di intasare stdout e waitFornon può tornare, quindi il programma è bloccato


1
Forse sto diventando denso, ma alla fine questo non tornerà? Potrebbe volerci un po 'di tempo. Forse non capisco cosa intendi per "clog [ging] stdout".
asteri,

4
se il flusso non viene svuotato i blocchi di programma, mi ha causato alcuni mal di testa, ecco perché l'ho usato; la directory lunga assicura solo che il buffer sia pieno
masterX244

Ah, capito. Bello! +1
asteri

15

Per confrontare mele e arance ... in C

Sono impressionato dal fatto che qui non esiste un codice usando un goto... (Sai: Goto è malvagio! )

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

Il sonno è solo per poterlo leggere. Premi ^ C se non hai un tempo infinito per aspettare qualcosa che non accade mai ;-)


9
Brutto bastardo, vai in questo innocente :)
orione,

è il random () usato il vodoo?
masterX244

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

2
Beh, "2" probabilmente non può mai essere 2, ma se hai usato un numero più grande (e un multiplo di almeno 4), potrebbe succedere;)
orion

1
@orion: Sì, hai ragione, potrebbe essere. E goto è ancora malvagio, ma i lanci di tipo cattivo sono ancora più malvagi!
max.haredoom

12

C, con alcuni compilatori ottimizzanti

Questo programma incrementa una variabile intera finché non trabocca.

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

L'overflow di numeri interi con segno è un comportamento indefinito. Di solito in pratica si avvolge quando le ottimizzazioni sono disattivate. Con le ottimizzazioni attivate, i compilatori possono e decidere che x + 1 > xè sempre vero.


Forse usare int32_t; un 64 bit int richiederebbe davvero molto, molto tempo (585 anni se ogni iterazione richiede un nanosecondo).
Paul Draper,

11

C ++

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

Lo strano stile di commento è il trucco. Suggerimento: trigrafi.


Questo è un esempio troppo semplice di un ciclo infinito.
Ismael Miguel,

64
Quelle trigraph sono così abusate qui :(
TimWolla

75
Sento quasi che le trigrafi debbano essere inserite in feritoie standard che non sono più divertenti.
undergroundmonorail

6
@TheDoctor: ?? / è una trigrafia per un carattere barra rovesciata, quindi la barra rovesciata unisce la linea in cui x è assegnato 0 alla fine del commento, rendendolo parte del commento.
CasaDeRobison

4
@undergroundmonorail pubblicato
Justin

11

Giava

In particolare, adoro questo effetto collaterale dell'ottimizzazione dell'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");  
    }
  }
}

A causa del box automatico, gli Integeroggetti si comportano quasi come semplici ints qui, con un'eccezione: Il i != maxnei forcicli confronta i riferimenti (identità) degli Integeroggetti, non il loro valore (uguaglianza). Per valori fino a 100, ciò "sorprende" in modo sorprendente, tuttavia, a causa di un'ottimizzazione nella JVM: Java prealloca gli Integeroggetti per i "valori più comuni" e li riutilizza durante il box automatico. Quindi per valori fino a 100 abbiamo identità <==> uguaglianza.


5
Dato che alcuni ragazzi Java considerano ancora il sovraccarico dell'operatore C ++ come un male ...
Daniel

Non è necessaria l'inizializzazione = new Integer(0), poiché in seguito si inizializzano comunque i valori. (Ciò potrebbe rendere la ragione meno ovvia.)
Paŭlo Ebermann,

@ PaŭloEbermann: buon punto, ho modificato il codice.
Daniel

9

Rubino / 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;
}

Ciò funziona correttamente in C , conto alla rovescia da 9 a 1 in STDOUT. Quando eseguito in Ruby, non termina, perché

0 non è un valore falso in Ruby.


Impara le lingue contemporaneamente ... 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]]);

Entrambi i loop usano la stessa variabile loop, quindi a seconda dell'ingresso, il loop interno può impedire che il loop esterno finisca mai.


Che lingua è questa?
RononDex,

@ronondex Javascript
tomsmeding

1
Ah, sì, è Javascript. Mi sono ricordato di abilitare il hilighting della sintassi ma ho dovuto dimenticare di inserirlo anche nel titolo :)
Aleksi Torhamo

1
Lo trovo ovvio. :-)
rafaelcastrocouto

@rafaelcastrocouto Sì, lo è, ma è anche molto facile perdere, ad esempio quando si sposta un loop da una funzione all'altra o si guarda semplicemente il codice. Inoltre, tieni presente che in realtà funziona correttamente in alcune lingue, tra cui C, a causa dell'ombreggiatura variabile. :)
Aleksi Torhamo,

7

C

Questo dovrebbe stampare una tabella di codici per tutti i caratteri ASCII, da 0 a 255. A charè abbastanza grande da scorrere su di essi.

#include <stdio.h>

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

Tutti i caratteri sono inferiori a 256. 255 ++ dà 0 a causa dell'overflow, quindi la condizione è i < 256sempre valida. Alcuni compilatori lo avvertono, altri no.


Per far sembrare sembra fare qualcosa di più utile, magari usa qualcosa come printf("%3d %2x: %c", i, i, i);(per una tabella di codici) nel tuo ciclo.
Paŭlo Ebermann,

@ PaŭloEbermann: ottima idea.
Rafał Cieślak,

Uso questo trucco nella mia classe, con caratteri non firmati stampabili tra 32 e 128. :)
cpri

7

Pitone

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

dovrebbe essere exit()e non exit. A quanto ho capito, exit()è il comando per uscire dall'interprete Python. In questo caso la chiamata è alla rappresentazione della funzione e non alla funzione vedi: exit-discussione . In alternativa breaksarebbe una scelta migliore.


Potresti spiegare cosa exitè in realtà? Sembra essere una classe, ma a cosa serve? Potresti anche cambiare print min print(m)modo che funzioni anche con Python 3.
Martin Thoma

1
Questo genere di cose ... Come quando il mio elseif non ha funzionato perché era elif .
Anonimo Pi

Grazie alla @moosedichiarazione di stampa aggiornata e al messaggio sullo spoiler
Willem,

6

C ++

Che ne dici del classico C ++ - trappola del programmatore?

int main()
{
   bool keepGoing = false;

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

   return 0;
}

Non capisco? Si tratta di usare. = anziché ==?
Mhmd

@ user689 esattamente. keepGoing = trueera pensato per confrontare il valore di keepGoing, invece assegna il valore a keepGoing; inoltre l'intera istruzione keepGoing = truevaluta true(che è ciò che ti permette di scrivere cose simili a=b=c=d=0) portando a un ciclo infinito.
CompuChip

3
Questo è sempre più motivo per usare le condizioni di yoda.
Ryan,

@RyanEdwardDougherty Haha in quel modo non li ho mai sentiti chiamare. Per la risata mattutina grazie.
CompuChip

@RyanEdwardDougherty: Ovviamente == true(o in stile Yoda true ==) è comunque ridondante e la condizione dovrebbe semplicemente essere letta while (keepGoing).
Celtschk,

6

Javascript

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

Le variabili utilizzate in 1a e 3a riga sono diverse da quelle usate in 2a e 3a riga.
Uno usa un (U + 0061) mentre l'altro usa un (U + 0430)


Non vedo un problema qui. L'ho eseguito e ha funzionato bene. Cosa mi sto perdendo?
Andrew Shepherd

molto probabilmente funzionerà ovunque poiché l'unicode verrà probabilmente convertito. Hai un +1 poiché è il più invisibile che puoi!
rafaelcastrocouto,

Solo per nasconderlo completamente (sostituiscilo con U + 0430) Se questo era il tuo codice, buona fortuna a trovare il 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);mi arrenderei, lo cancellerei per sempre, pulivo il mio computer, forse scanner di virus solo per essere sicuro e riscrivo completamente. EDIT: Perché var a = 0; a = 1;non è molto realistico
YoYoYonnY

6

Giava:

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

"I = i ++" è un errore per principianti abbastanza comune e può essere sorprendentemente difficile da trovare


5

C ++

Un po 'casuale?

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

Non chiama la funzione randma chiama ricorsivamente la Randomizer::randfunzione.


5
Parentesi extra nella dichiarazione di ritorno, schifo.
David Conrad,

1
Questo finirà per segfault, però.
kirbyfan64sos,

5

Haskell

Alcuni codici per calcolare il tempo di un dato valore della funzione Ackermann. Per valori molto bassi di solito termina. Sulla mia macchina valori molto bassi significano qualcosa come 3 5 o più piccolo con codice compilato e-O . In ghci valori bassi significano qualcosa come 3 3.

Il 'simbolo sembra incasinare l'evidenziazione della sintassi, non so perché. In alcuni punti sono necessari, quindi non è possibile rimuoverli tutti.

Modifica- lingua cambiata.

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

Questo provoca un livelock. Il thread di conteggio provoca ripetutamente il rollback del calcolo di Ackermann poiché toccano la stessa TVar.


contrassegnandolo come lang-hs invece di lang-haskell sembra funzionare meglio (è una delle estensioni nel
setter

5

Java: nessun loop o ricorsione

Ho appena iniziato a studiare espressioni regolari e ho scritto il mio primo programma per verificare se la mia stringa corrisponde a un'espressione regolare.

Sfortunatamente, il programma non produce alcun risultato. Tiene il terminale. Aiuta a trovare il problema. Non ho fatto uso di loop, non vi è alcuna ricorsione. Sono completamente sconcertato.

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

Cosa ho fatto di sbagliato? Perché il mio programma non finisce? Per favore aiuto!

Link Ideone qui .

Questo è uno stupido esempio di catastrofico backtracking . La complessità è O (2 n / 2 ). Mentre il programma potrebbe non funzionare a tempo indeterminato, che sarebbe probabilmente sopravvivono sia vivente e non vivente oggetti in giro e non-così-around .


5

C

Dovresti avere bisogno solo di uno dei due loop, ma quale ti serve dipende dal tuo compilatore.

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 semplice superamento dei limiti che reimposta i su un valore non terminante. I compilatori possono differire dal fatto che essi allocare i sopra o sotto un sullo stack, quindi ho incluso sforamenti in entrambe le direzioni.


5

C / C ++

C ++ consente solo le facili dichiarazioni di variabili in linea utilizzate qui, ma è altrettanto facile fare questo errore nella vecchia 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;
}

Nel ciclo interno, 'j' viene confrontato ma mai incrementato. ("I ++" dovrebbe in realtà essere "j ++"). Questo non è tanto un trucco subdolo, ma più di un vero errore che ho commesso in passato;) Qualcosa a cui fare attenzione.


2
Questo di solito mi richiede almeno 5 minuti per il debug. Lo odio quando l'ho fatto.
ace_HongKongIndipendenza

4

C #

Di seguito è una semplice classe che esegue un'operazione aritmetica (somma) su un array di input di grandi dimensioni utilizzando un thread in background. È incluso un programma di esempio.

Tuttavia, anche se è abbastanza semplice, non termina mai. Nota che non c'è gioco di prestigio (personaggi simili, punti e virgola nascosti / mancanti, trigrafi ;-), ecc.)

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

Questo è un esempio di un brutto bug del mondo reale che potrebbe apparire anche nel tuo codice. Secondo il modello di memoria .NET e le specifiche C #, un ciclo come quello in WaitAndGetResultpotrebbe non terminare mai a meno che non si specifichi la variabile come volatile, poiché viene modificata da un altro thread. Vedi questa domanda StackOverflow per i dettagli. Il bug dipende dall'implementazione di .NET, quindi potrebbe o meno influire su di te. Ma di solito, l'esecuzione di una build di rilascio su un processore x64 sembra mostrare il problema. (L'ho provato con “csc.exe / o + / debug- infinite.cs” .)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.