Mengapa ini tidak berakhir? [Tutup]


95

Tugas Anda: Untuk menulis sebuah program yang jelas-jelas harus berakhir, tetapi tidak pernah (sejauh crash komputer) tidak. Buat itu terlihat seperti itu harus melakukan tugas sederhana: menambahkan angka, mencetak sesuatu, ... Tapi itu hanya terjebak dalam loop yang tak terbatas.

Cobalah untuk membuat program Anda sangat jelas dan sederhana, sementara itu sebenarnya akan terjebak dalam lingkaran yang tidak terduga. Pemilih: nilai jawaban tentang seberapa "curang" mereka!

Ini adalah kontes popularitas: Jadilah kreatif!


6
Bisakah seseorang tolong jelaskan apa yang bisa saya lakukan untuk membuat pertanyaannya kurang luas? Saya baru disini. Terima kasih!
Nomor

6
Ini hanya akan menjadi daftar besar kesalahan ketik dan kesalahan pemula yang menyebabkan loop.
Bill Woodger

Pertanyaan yang menarik, tetapi saya belum melihat jawaban yang benar-benar kreatif. Saya menjanjikan suara kepada siapa saja yang tidak menggunakan loop atau rekursi yang jelas!
ApproachingDarknessFish

14
Saya tidak tahu apakah ini penting, tetapi Microsoft Office saya berperilaku persis seperti ini saat ini.
Level River St

1
Saya memilih untuk menutup pertanyaan ini sebagai di luar topik karena tantangan curang tidak lagi di-topik di sini. meta.codegolf.stackexchange.com/a/8326/20469
cat

Jawaban:


185

Javascript

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

prompt () mengembalikan sebuah string dan loop menambahkan karakter '1', itu tidak akan pernah sama dengan 100.


13
Anda mendapatkan saya dengan yang itu ... contoh-contoh yang lebih tinggi (sebenarnya) semua hanya menyalahgunakan sintaksis ... tapi yang itu bagus!
bwoebi

4
Chrome di Kubuntu menjadi tidak responsif, menggantung semuanya dan saya harus mengatur ulang dengan keras :)
Sergey Telshevsky

4
@Vlakarados: Python tidak akan melakukan konversi tipe implisit yang dilakukan Javascript. Pada Python, kode yang setara menggunakan raw_inputatau Python 3 inputmemunculkan a TypeError.
user2357112

2
Tidak ada pemeriksaan pada fakta bahwa nilai sebenarnya di bawah 100 sehingga berhenti secara normal ketika Anda memasukkan "100": '- (
C.Champagne

1
@Sankalp, +operator di sini adalah penggabungan string, bukan tambahan.
Michael M.

87

C

Hanya contoh program dasar yang menggambarkan tiga jenis while-loop di 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;
}

Sementara loop tidak memiliki "lakukan" sebelum kurung kurawal pembukaan. Ini sebenarnya membuat loop do-while di dalam loop (x <10) yang diakhiri oleh "pernyataan nol" while. Karena x bertambah di dalam loop dan kemudian dikurangi dalam kondisi loop do-while, loop dalam tidak pernah berakhir, dan demikian juga loop luar. Loop "pernyataan tunggal" pada akhirnya tidak pernah tercapai.

Jika Anda masih bingung, lihat di sini (di-host secara eksternal karena codegolf.SE tidak suka blok kode di spoiler).


8
Haha, saya menemukan yang ini sebelum melihat solusi spoiler. : P
Joe Z.

54
Mengapa Anda melewatkan kesempatan yang sangat bagus untuk menggunakan operator "pergi ke"? (x --> 0)
corsiKa

2
Oh wow. Ini sangat jahat. Butuh saya empat membaca untuk menemukannya.
Patrick M

1
@ Joz. Terlalu mudah. Solusi yang paling banyak dipilih lebih baik. Yang saya tidak temukan.
Anonim Pi

3
@Hat Guy, Bash memiliki sintaksis untuk; lakukan dan sementara; jadi saya bisa melihat orang-orang terlempar oleh ini, bahkan jika mereka terbiasa dengan bahasa 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;
})();

Pengangkat variabel: JavaScript akan benar-benar mengambil definisi kedua saya var a = true;, menyatakannya di bagian atas fungsi sebagai var a;, dan memodifikasi tugas saya ke a = true;makna aakan ditentukan pada saat memasuki loop sementara.


3
Bisakah Anda menambahkan penjelasan yang lebih baik mengapa ini tidak pernah berakhir? Silakan masuk lebih dalam tentang "variable hoisting" :)
Number9

1
@ Number9 Saya harap ini membantu, google memiliki contoh yang jauh lebih baik daripada ini;)
Newbrict

25
Sial, ini bahkan lebih buruk daripada penyisipan titik koma. +1!
tommeding

2
Satu-satunya masalah yang saya lihat dengan program ini adalah tidak terlihat melakukan tugas yang sederhana ... sepertinya seharusnya tidak melakukan apa-apa. Mungkin menambahkan alertsetelah loop.
PeterT

2
Anda harus berubah a = 1menjadi a = true. Kode masih akan memiliki infinite loop seperti itu, tetapi akan lebih jelas bahwa alasannya bukan beberapa kekhasan dalam konversi JavaScript dari ints ke 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");
    }
}

Angka literal pada baris pertama fungsi bukan '201', tetapi '20' dengan akhiran 'L' ( datatype panjang ) akhiran. Jumlahnya akan meluap dengan cepat tanpa mencapai 6432, tetapi program akan terus berjalan kecuali pemeriksaan melimpah dihidupkan dalam opsi build.
Secara masuk akal, Visual Studio 2013 (dan mungkin versi lain juga) memberi Anda peringatan untuk kode ini, merekomendasikan agar Anda menggunakan 'L' bukannya 'l'.


12
Oh, litu seharusnya terlihat seperti 1! Aku bodoh. : \
Joe Z.

6
Saran untuk perbaikan: ganti 1s di bagian output yang diharapkan dengan ls juga (lebih mudah untuk menemukan karakter aneh ketika Anda memiliki 1s nyata untuk dibandingkan)
Allen Gould

3
Ya, sepertinya cukup spesifik untuk lingkungan. Fon @ Michael terlihat sangat berbeda dengan font di komputer di rumah saya ( imgur.com/PKIuJpr - Chrome, Windows 8), dan triknya tampaknya bekerja lebih baik di komputer kerja saya daripada komputer di rumah saya, meskipun mereka punya cukup mirip spesifikasi. Browser ponsel saya sepertinya tidak menampilkan kode dalam font bernada tetap, dan triknya tidak berfungsi sama sekali.
BenM

1
FTR, beginilah tampilannya di komputer kerja saya ( imgur.com/Opfs3BH - Firefox, Windows 7). Saya rasa seseorang bisa menipu orang yang cukup cerdik.
BenM

15
MENGAPA ORANG-ORANG TETAP MENGALAHKAN KARAKTER YANG MELIHAT SAMA?
Anonim Pi

39

C

Bagaimana dengan presisi?

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

Bayangkan Anda harus menyimpan sejumlah angka integer <0; 3> dalam memori komputer. Hanya ada 4 bilangan bulat dalam kisaran ini (0,1,2,3). Cukup menggunakan 2 bit untuk menyimpannya dalam memori. Sekarang bayangkan Anda harus menyimpan sejumlah angka floating point <0; 3>. Masalahnya adalah ada jumlah angka floating point yang tak terbatas dalam kisaran ini. Bagaimana cara menyimpan jumlah angka yang tidak terbatas? Itu tidak mungkin. Kami hanya dapat menyimpan jumlah angka yang terbatas. Inilah mengapa beberapa angka seperti 0,1 sebenarnya berbeda. Dalam hal 0,1 itu adalah 0,100000000000000006. Sangat disarankan untuk tidak menggunakan == atau! = Dalam kondisi sejauh Anda menggunakan angka floating point.


1
Bagaimana cara kerjanya?
Mhmd

5
Kesalahan pembulatan. 0,1 sebenarnya 0,100000000000000006 karena 0,1 dalam biner seperti 1/3 dalam desimal - ekspansi binernya tidak terbatas & periodik.
orion

3
Tidak benar-benar kesalahan pembulatan. Nilai floating point adalah perkiraan perkiraan suatu angka. Melakukan perbandingan tepat antara nilai perkiraan tidak akan berfungsi.
AKHolland

4
Inilah sebabnya mengapa Anda (hampir) tidak pernah harus membandingkan float / dobel untuk persamaan.
Emanuel Landeholm

1
Saya sedang menunggu untuk melihat yang satu ini. Bagus.
David Conrad

33

HTML / JavaScript

Bayangkan Anda memiliki kotak input di halaman Anda:

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

Dan sekarang Anda ingin mengetikkan sesuatu di dalamnya ... Coba di Chrome: http://jsfiddle.net/jZp4X/ .

Kotak dialog browser standar yang disebut dengan alertfungsi adalah modal, jadi ketika itu ditampilkan ia mengeluarkan fokus keluar dari kotak teks, tetapi ketika itu ditolak kotak teks menerima kembali fokus.


5
di firefox, input tidak memiliki autofokus pada peringatan dekat, dan dari yang kedua kali menawarkan saya untuk tidak menampilkan lebih banyak peringatan dan kemudian saya dapat menulis di kotak teks secara normal
Einacio

6
Bagus +1 tanpa loop atau rekursi.
ApproachingDarknessFish

5
Tidak ada loop di Firefox atau Chrome. FF menunjukkan peringatan sekali ketika dialog diklik, Anda mengabaikannya dan itulah akhirnya. Bisa klik lagi untuk mengulang. Chrome melakukan hal yang sama, tetapi membiarkan kotak fokus, dan Anda bahkan dapat mengetiknya. Maaf, mungkin pada versi yang lebih lama ini adalah masalah, tetapi sekarang tidak lagi.
RomanSt

6
IE11 bekerja persis sama dengan Chrome untuk saya. Saya pikir Anda telah secara tidak sengaja menemukan contoh sesuatu yang bekerja satu arah pada setiap browser modern di Mac, dan cara yang berbeda pada setiap browser modern di Windows!
RomanSt

1
Bekerja secara normal (tanpa loop) di 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;
}

Kondisi i >=0ini selalu benar karena size_t tidak ditandatangani.


2
Bagus, tetapi kompiler biasanya mengeluarkan peringatan untuk ini;)
Synxis

2
@ Sinxis Ya kompiler lakukan. Tetapi hanya jika Anda menghidupkan peringatan kompiler. g++tidak akan memperingatkan Anda tentang ini tanpa mereka.
FDinoff

5
Anda harus selalu menggunakannya -Wall --pedantic.
Martin Ueding

3
@queueoverflow Peringatan tidak hanya ditampilkan dengan bendera itu. Anda perlu -Wsign-compareyang bisa dihidupkan -Wextra.
FDinoff

7
Satu tanda hubung pada -pedantic. #pedantic
David Conrad

29

pesta

(Ada permintaan untuk tidak ada loop atau rekursi)

#!/bin/bash

# Demo arrays

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

echo $foo

echo ${foo[0]}

foo[2] = `yes`

echo $foo

echo ${foo[2]}

Alih-alih menetapkan string 'ya' untuk foo [2], ini memanggil perintah sistem yes, yang mengisi foo [2] dengan jumlah "ya \ n" yang tidak pernah berakhir.


Akhirnya kehabisan bashmemori dan menabraknya
Digital Trauma

4
Ya, memang benar. Tapi sebuah kecelakaan agak diijinkan oleh pertanyaan :)
GreenAsJade

Ya, hanya pengamatan :). Terpilih.
Digital Trauma

Bahkan, saya rasa program-program dalam komputer kecil ini yang benar-benar merusak mesin Anda, atau penolakan layanan lainnya, harus mendapatkan tanda bonus)
GreenAsJade

Koreksi: yeshanya program coreutils. Bukan syscall.
mniip

28

C

Huruf "x" hilang dalam file. Sebuah program ditulis untuk menemukannya:

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

Itu dikompilasi dan dijalankan dan akhirnya berteriak:

Hurray, letter lost in the file is finally found!

Selama bertahun-tahun surat telah diselamatkan dengan cara ini sampai orang baru datang dan mengoptimalkan kode. Dia akrab dengan tipe data dan tahu bahwa lebih baik menggunakan unsigned daripada menandatangani untuk nilai-nilai non-negatif karena memiliki rentang yang lebih luas dan memberikan perlindungan terhadap luapan. Jadi dia mengubah int menjadi unsigned int . Dia juga tahu ascii cukup baik untuk mengetahui bahwa mereka selalu memiliki nilai non-negatif. Jadi dia juga mengubah char menjadi char yang tidak ditandatangani . Dia menyusun kode dan pulang dengan bangga atas pekerjaan bagus yang dia lakukan. Programnya terlihat seperti ini:

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

Dia kembali ke malapetaka pada hari berikutnya. Huruf "a" hilang dan meskipun seharusnya berada di "desert_file" yang berisi "abc", program tersebut mencarinya selamanya hanya untuk mencetak:

Searching file for missing letter a...

Mereka memecat orang itu dan kembali ke versi sebelumnya mengingat bahwa orang tidak boleh mengoptimalkan tipe data dalam kode kerja.

Tapi pelajaran apa yang seharusnya mereka pelajari di sini?

Pertama-tama, jika Anda melihat tabel ascii Anda akan melihat bahwa tidak ada EOF. Itu karena EOF bukan karakter tetapi nilai khusus yang dikembalikan dari fgetc (), yang dapat mengembalikan karakter diperluas ke int atau -1 yang menunjukkan akhir file.
Selama kita menggunakan char yang ditandatangani semuanya berfungsi dengan baik - char yang sama dengan 50 diperpanjang oleh fgetc () menjadi int sama dengan 50 juga. Kemudian kita mengubahnya kembali menjadi char dan masih memiliki 50. Hal yang sama terjadi untuk -1 atau output lain yang berasal dari fgetc ().
Tapi lihat apa yang terjadi ketika kita menggunakan char yang tidak ditandatangani. Kami mulai dengan char di fgetc () memperluasnya ke int dan kemudian ingin memiliki char yang tidak ditandatangani. Satu-satunya masalah adalah bahwa kita tidak dapat menyimpan -1 di char yang tidak ditandatangani. Program menyimpannya sebagai 255 yang tidak lagi sama dengan EOF. Jika Anda melihat bagian 3.1.2.

Peringatan
salinan dokumentasi ANSI C Anda akan mengetahui bahwa apakah char ditandatangani atau tidak, semata-mata tergantung pada implementasi. Jadi orang itu mungkin tidak boleh dipecat karena dia menemukan bug yang sangat rumit bersembunyi di kode. Itu bisa keluar ketika mengubah kompiler atau pindah ke arsitektur yang berbeda. Saya ingin tahu siapa yang akan dipecat jika bug keluar dalam kasus seperti itu;)

PS. Program dibangun di sekitar bug yang disebutkan dalam Bahasa Majelis PC oleh Paul A. Carter


7
Saya suka ada cerita dengan solusinya.
jpmc26

Ha ha! Saya kira itu satu-satunya. Terima kasih sudah membaca!
Legat

1
Aku cinta kamu. Beri saya cerita Anda, pls :(
YoYoYonnY

Ini benar-benar brilian!
kirbyfan64sos

21

Regex

Dengan input yang tepat, regex berikut ini dapat menyebabkan mesin regex backtracking masuk ke neraka backtracking:

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

Input sederhana seperti "Programming Puzzles and Code Golf Stack Exchange - Mozilla Firefox"atau "AVerySimpleInputWhichContainsAnInsignificantSentence."(kedua string dikutip untuk kejelasan) sudah cukup untuk membuat mesin regex yang paling mundur berjalan untuk waktu yang lama.

Karena (\s*\w+)*memungkinkan untuk ekspansi \w+\w+\w+... \w+, yang berarti mesin regex pada dasarnya akan mencoba semua cara yang mungkin untuk memisahkan serangkaian karakter kata . Ini adalah sumber dari neraka yang mundur.
Hal ini dapat dengan mudah diperbaiki dengan mengubah \s*ke \s+, maka (\s+\w+)*hanya dapat diperluas untuk \s+\w+\s+\w+... \s+\w+.


3
Aku benci mundur mesin regex.
David Conrad

2
Saya mencoba ini dengan Perl terlebih dahulu, tetapi tampaknya Perl dapat melihat loop di sini. Saya tidak mencoba AWK, karena tidak ada ekspresi reguler yang dapat menyebabkan perilaku seperti itu di AWK. PHP secara otomatis membuat ekspresi reguler yang membutuhkan waktu terlalu lama untuk dicocokkan dengan kegagalan (yang konyol, tapi itu PHP untuk Anda - secara otomatis memasukkan bug ke dalam program). Namun, ini sebenarnya berfungsi dengan Python.
Konrad Borowski

1
@xfix: Mengenai mengapa Perl berhasil menghindari backtracking hell, artikel ini menjelaskan alasannya. Namun, itu tidak cukup terhadap kasus seperti yang ditunjukkan di sini (gulir ke bawah ke bagian kinerja). PHP (sebenarnya perpustakaan PCRE) memiliki batas mundur, dan program yang tepat harus selalu memeriksa nilai balik fungsi untuk memutuskan apakah eksekusi dihentikan, atau berlari ke penyelesaian.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

1
Ini sangat SLICK.
alvonellos

20

JavaScript

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

050 adalah konstanta oktal dalam Javascript, dan kebetulan memiliki nilai desimal 40.


73
Saya menemukan ini jelas. :-)
Justin

6
Saya tidak tahu javascript melakukan ini. Tetapi setelah membaca kode saya berkata: "050 harus menjadi cara mewakili 40, mungkin basis 8 atau sesuatu"
Cruncher

Ini perlu disembunyikan lebih baik.
Paŭlo Ebermann

Sudah jelas ..
Oliver Ni

18

Haskell

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

Nah, pikirkan itu! Itu akan sama dengan head $ "Hello" ++ (repeat '!'), yaitu hanya harus kembali 'H'.

Dalam daftar haskell adalah struktur rekursif, dengan elemen pertama yang paling atas. Untuk menambahkan ke daftar, Anda harus membuka gulungan semua elemen itu, letakkan lampiran Anda, dan kembalikan elemen yang terangkat. Itu tidak akan bekerja pada daftar yang tak terbatas. Demikian pula, membalik daftar yang tak terbatas tidak akan secara ajaib memberi Anda "Hello"dukungan. Itu hanya akan menggantung selamanya.


1
Sayang sekali ini tidak benar-benar bekerja: - /
John Dvorak

1
Bagaimana cara kerjanya?
danmcardle

@crazedgremlin ketika saya menguji ini pada Fedora OS akhirnya membunuh prosesnya. (<5 menit) karena menghabiskan semua memori pada sistem.
FDinoff

Menarik! Saya tidak menyadari bahwa ini terjadi. Saya tidak berani menjelajahi wilayah yang sering menelan semua memori.
danmcardle

4
Itu masih solusi yang valid: tidak keluar, itu berjalan selama bisa sampai sistem tidak dapat mendukungnya lagi ...
GreenAsJade

16

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

Program mengandalkan aliran output standar macet dari commandline untuk macet. Direktori WinSXS di bawah windows memiliki ribuan file dengan nama panjang sehingga hampir dijamin untuk menyumbat stdout, dan waitFortidak dapat kembali sehingga program menemui jalan buntu


1
Mungkin saya menjadi padat, tetapi bukankah ini akan kembali pada akhirnya? Mungkin perlu beberapa saat. Mungkin saya tidak mengerti apa yang Anda maksud dengan "clog [ging] stdout".
asteri

4
jika aliran tidak dikosongkan blok program, membuat saya sakit kepala sudah karena itu saya menggunakannya; direktori panjang hanya memastikan bahwa buffer berjalan penuh
masterX244

Ah, mengerti. Bagus! +1
asteri

15

Untuk membandingkan apel dan jeruk ... di C

Saya terkesan bahwa tidak ada kode di sini menggunakan goto... (Anda tahu: Goto itu jahat! )

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

Tidur hanya untuk bisa membacanya. Tekan ^ C jika Anda tidak memiliki banyak waktu untuk menunggu sesuatu yang tidak pernah terjadi ;-)


9
Anda bajingan licik, kebohongan tidak bersalah dalam hal ini :)
orion

Apakah vodoo acak () digunakan?
masterX244

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

2
Yah "2" mungkin tidak akan pernah menjadi 2, tetapi jika Anda menggunakan jumlah yang lebih besar (dan kelipatan setidaknya 4), itu bisa terjadi;)
orion

1
@orion: Ya Anda benar, bisa jadi. Dan kebohongan masih jahat, tetapi coran tipe buruk bahkan lebih jahat!
max.haredoom

12

C, dengan kompiler pengoptimal tertentu

Program ini menambah variabel integer hingga melimpah.

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

Overflow integer yang ditandatangani adalah perilaku yang tidak terdefinisi. Biasanya dalam praktiknya membungkus, ketika optimasi dimatikan. Dengan optimisasi aktif, kompiler dapat dan memang memutuskan itu x + 1 > xselalu benar.


Mungkin digunakan int32_t; int 64 bit akan memakan waktu sangat lama, sangat, sangat lama (585 tahun jika setiap iterasi membutuhkan satu nanosecond).
Paul Draper

11

C ++

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

Gaya berkomentar yang aneh adalah triknya. Petunjuk: trigraph.


Ini adalah contoh yang terlalu mendasar dari loop tak terbatas.
Ismael Miguel

64
Trigraph itu terlalu sering digunakan di sini :(
TimWolla

75
Saya hampir merasa seperti trigraph harus dimasukkan ke dalam Standard Loopholes yang tidak lagi lucu.
undergroundmonorail

6
@TheDoctor: ?? / adalah trigraph untuk karakter backslash, jadi backslash membuat garis di mana x ditugaskan 0 hingga akhir komentar, menjadikannya bagian dari komentar.
CasaDeRobison

4
@undergroundmonorail Diposting
Justin

11

Jawa

Saya khususnya menyukai efek samping optimasi autoboxing ini:

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

Karena autoboxing, Integerobjek berperilaku hampir seperti biasa intdi sini, dengan satu pengecualian: The i != maxin the forloop membandingkan referensi (identitas) dari Integerobjek, bukan nilai mereka (kesetaraan). Untuk nilai hingga 100, ini secara mengejutkan "berfungsi" karena optimasi di JVM: Java mengalokasikan ulang Integerobjek untuk "nilai paling umum" dan menggunakannya kembali saat melakukan autoboxing. Jadi untuk nilai hingga 100, kami memiliki identitas <==> kesetaraan.


5
Mengingat bahwa beberapa orang Jawa masih menganggap C ++ operator-overloading sebagai kejahatan ...
Daniel

Anda tidak perlu inisialisasi = new Integer(0), karena Anda menginisialisasi nilai setelahnya. (Ini mungkin membuat alasannya kurang jelas.)
Paŭlo Ebermann

@ PaŭloEbermann: Poin bagus, saya sudah mengedit kode.
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;
}

Ini bekerja dengan benar dalam C , menghitung mundur dari 9 ke 1 dalam STDOUT. Ketika dijalankan di Ruby, itu tidak berakhir, karena

0 bukan nilai yang salah di Ruby.


Lakukan bahasa sekaligus ... mengesankan.
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]]);

Kedua loop menggunakan variabel loop yang sama, jadi tergantung pada input, loop dalam dapat menjaga loop luar dari penyelesaian.


Bahasa apa ini?
RononDex

@ronondex Javascript
tomsmeding

1
Ah, ya, itu Javascript. Saya ingat untuk mengaktifkan sintaks yang lucu tetapi harus lupa untuk memasukkannya dalam judul juga :)
Aleksi Torhamo

1
Saya menemukan ini jelas. :-)
rafaelcastrocouto

@rafaelcastrocouto Ya, memang seperti itu, tetapi juga sangat mudah untuk dilewatkan, misalnya ketika memindahkan satu loop dari satu fungsi ke fungsi lain atau hanya melirik kode. Juga, perhatikan bahwa ini benar-benar berfungsi dengan benar dalam beberapa bahasa, termasuk C, karena variabel shadowing. :)
Aleksi Torhamo

7

C

Ini harus mencetak tabel kode untuk semua karakter ASCII, dari 0 hingga 255. A charcukup besar untuk diulanginya.

#include <stdio.h>

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

Semua karakter kurang dari 256. 255 ++ memberi 0 karena melimpah, sehingga kondisinya i < 256selalu bertahan. Beberapa kompiler memperingatkan tentang hal itu, beberapa tidak.


Untuk membuatnya sepertinya melakukan sesuatu yang lebih bermanfaat, mungkin menggunakan sesuatu seperti printf("%3d %2x: %c", i, i, i);(untuk tabel kode) di loop Anda.
Paŭlo Ebermann

@ PaŭloEbermann: Ide bagus.
Rafał Cieślak

Saya menggunakan trik ini di ruang kelas saya, dengan karakter yang tidak dapat dicetak yang dapat dicetak antara 32 dan 128. :)
cpri

7

Python

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

seharusnya exit()dan tidak exit. Seperti yang saya pahami, exit()adalah perintah untuk keluar dari juru bahasa python. Dalam hal ini panggilan adalah untuk representasi fungsi dan bukan ke fungsi, lihat: keluar-diskusi . Atau breakakan menjadi pilihan yang lebih baik.


Bisakah Anda jelaskan apa yang exitsebenarnya? Tampaknya menjadi kelas, tetapi untuk apa ini digunakan? Anda juga bisa mengubah print mke print(m)sehingga ini juga bekerja dengan Python 3.
Martin Thoma

1
Orang-orang macam hal ... Seperti ketika saya elseif tidak bekerja karena itu elif .
Anonim Pi

Terima kasih atas @moosepernyataan cetak yang diperbarui dan pesan spoiler
Willem

6

C ++

Bagaimana dengan C ++ klasik - jebakan programmer?

int main()
{
   bool keepGoing = false;

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

   return 0;
}

Saya tidak mengerti ini? Apakah ini tentang menggunakan. = bukannya ==?
Mhmd

@ user689 tepatnya. keepGoing = truedimaksudkan untuk membandingkan nilai keepGoing, alih-alih memberikan nilai keepGoing; selain itu seluruh pernyataan keepGoing = truedievaluasi menjadi true(yang memungkinkan Anda untuk menulis hal-hal seperti a=b=c=d=0) yang mengarah ke loop tak terbatas.
CompuChip

3
Ini semakin menjadi alasan untuk menggunakan kondisi yoda.
Ryan

@RyanEdwardDougherty Haha seperti itu saya tidak pernah mendengar mereka dipanggil. Untuk pagi hari tertawa terima kasih.
CompuChip

@RyanEdwardDougherty: Tentu saja == true(atau Yoda-style true ==) mubazir, dan kondisinya harus dibaca while (keepGoing).
celtschk

6

Javascript

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

Variabel yang digunakan dalam baris 1 dan 3 berbeda dari yang digunakan pada baris 2 dan 3.
Satu menggunakan a (U + 0061) sedangkan yang lain menggunakan a (U + 0430)


Saya tidak melihat masalah di sini. Saya menjalankannya dan itu bekerja dengan baik. Apa yang saya lewatkan?
Andrew Shepherd

ini kemungkinan besar akan bekerja di mana saja karena unicode mungkin akan dikonversi. Dapatkan +1 karena ini adalah yang paling tidak terlihat yang bisa Anda dapatkan!
rafaelcastrocouto

Hanya untuk menyembunyikannya sepenuhnya (ganti á dengan U + 0430) Jika ini adalah kode Anda, semoga berhasil menemukan masalahnya: var a;var points = 0;function fiftyfifty() {points++;if (Math.random() > 0.5)return true;}; á = fiftyfifty(); while (a === undefined) {á = fiftyfifty();} console.log("Points: " + points);Saya akan menyerah, hapus ini selamanya, bersihkan komputer saya, mungkin pemindai virus hanya untuk memastikan dan menulis ulang sepenuhnya. EDIT: Karena var a = 0; a = 1;tidak terlalu realistis
YoYoYonnY

6

Jawa:

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 ++" adalah kesalahan pemula yang sangat umum dan bisa sangat sulit ditemukan


5

C ++

Sedikit acak?

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

Tidak memanggil fungsi randmelainkan memanggil Randomizer::randfungsi secara rekursif .


5
Tanda kurung tambahan dalam pernyataan balasan, huek.
David Conrad

1
Ini pada akhirnya akan segfault.
kirbyfan64sos

5

Haskell

Beberapa kode waktu menghitung nilai yang diberikan dari fungsi Ackermann. Untuk nilai yang sangat rendah biasanya berakhir. Pada komputer saya nilai yang sangat rendah berarti sekitar 3 5 atau lebih kecil dengan kode yang dikompilasi dan -O. Dalam ghci nilai rendah berarti sekitar 3 3.

The 'simbol tampaknya mengacaukan sintaks, tidak yakin mengapa. Di beberapa tempat mereka dibutuhkan sehingga tidak dapat menghapus semuanya.

Edit- bahasa yang diubah.

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

Ini menyebabkan livelock. Thread penghitungan berulang kali menyebabkan komputasi Ackermann untuk mundur karena mereka menyentuh TVar yang sama.


menandainya sebagai lang-hs alih-alih lang-haskell tampaknya berfungsi lebih baik (itu salah satu ekstensi di prettifier google )
Einacio

5

Java - Tidak ada loop atau rekursi

Saya baru mulai belajar ekspresi reguler dan menulis program pertama saya untuk menguji apakah string saya cocok dengan ekspresi reguler.

Sayangnya, program ini tidak membuahkan hasil. Itu memegang terminal. Tolong bantu dalam menemukan masalah. Saya belum menggunakan loop, tidak ada rekursi yang terlibat. Saya benar-benar bingung.

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

Apa yang telah saya lakukan salah? Mengapa program saya tidak berakhir? Tolong bantu!

Tautan ideone di sini .

Ini adalah contoh bodoh dari kemunduran bencana . Kompleksitasnya adalah O (2 n / 2 ). Meskipun program ini mungkin tidak berjalan tanpa batas waktu, program itu mungkin hidup lebih lama dari benda hidup dan tidak hidup di sekitar dan tidak begitu di sekitar .


5

C

Anda seharusnya hanya membutuhkan satu dari dua loop, tetapi yang mana yang Anda butuhkan tergantung pada kompiler Anda.

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

}

Batas sederhana dikalahkan yang mengatur ulang i ke nilai yang tidak berakhir. Compiler dapat berbeda pada apakah mereka mengalokasikan i di atas atau di bawah a di stack, jadi saya sudah memasukkan overruns di kedua arah.


5

C / C ++

C ++ hanya memungkinkan deklarasi variabel inline mudah yang digunakan di sini, tetapi sama mudahnya untuk membuat kesalahan ini di 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;
}

Di loop dalam, 'j' dibandingkan tetapi tidak pernah bertambah. ('I ++' sebenarnya harus 'j ++'). Ini bukan trik licik tetapi lebih dari kesalahan aktual yang saya buat di masa lalu;) Sesuatu yang harus diperhatikan.


2
Ini biasanya membutuhkan waktu setidaknya 5 menit untuk debug. Aku benci ketika aku melakukan ini.
ace_HongKongIndependence

4

C #

Berikut ini adalah kelas sederhana yang melakukan operasi aritmatika (penjumlahan) pada array input besar menggunakan utas latar belakang. Program sampel disertakan.

Namun, meskipun cukup mudah, itu tidak pernah berakhir. Perhatikan bahwa tidak ada sulap (karakter lookalikes, tersembunyi / hilang titik koma, trigraph ;-), dll.)

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

Ini adalah contoh dari bug jahat dunia nyata yang mungkin muncul dalam kode Anda juga. Sesuai model .NET memory dan spesifikasi C #, loop seperti yang ada di WaitAndGetResultmungkin tidak akan pernah berhenti kecuali Anda menetapkan variabel sebagai volatile, karena itu dimodifikasi oleh utas lainnya. Lihat pertanyaan StackOverflow ini untuk detailnya. Bug tergantung pada implementasi .NET, sehingga mungkin atau mungkin tidak mempengaruhi Anda. Tetapi biasanya, menjalankan rilis yang dibangun pada prosesor x64 tampaknya menampilkan masalah. (Saya mencobanya dengan "csc.exe / o + / debug- infinite.cs" .)

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.