Neden bitmiyor? [kapalı]


95

Göreviniz: Açıkça sonlandırılması gereken bir program yazmak, ancak hiçbir zaman (bir bilgisayar çökmesine kadar) yapmaz. Basit bir görevi yerine getirmesi gerektiği gibi görünmesini sağlayın: sayıları eklemek, bir şeyi yazdırmak, ... Ama sadece sonsuz bir döngüye yakalanır.

Programınızı çok net ve basit hale getirmeye çalışın, bu da aslında öngörülemeyen bir döngüde sıkışıp kalacak. Seçmenler: Ne kadar "az" olduklarının cevaplarını değerlendirin!

Bu bir popülerlik yarışması: Yaratıcı olun!


6
Birisi lütfen soruyu daha az kapsamlı hale getirmek için neler yapabileceğimi açıklayabilir mi? Ben burada yeniyim. Teşekkür ederim!
9

6
Bu sadece döngülere neden olan yazım hataları ve başlangıç ​​hatalarının büyük bir listesi olacak.
Bill Woodger

İlginç bir soru, ancak henüz gerçekten yaratıcı bir cevap görmedim. Döngü ya da bariz özyinelemeyi kullanmayan birine oy veriyorum!
Yaklaşan

14
Bu sayılır mı bilmiyorum ama Microsoft Office'im şu anda tam olarak böyle davranıyor.
Seviye Nehri St

1
Bu soruyu konu dışı olarak kapatmak için oy veriyorum, çünkü asıl zorluklar artık burada konu dışı değil. meta.codegolf.stackexchange.com/a/8326/20469
kedi

Yanıtlar:


185

JavaScript

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

prompt () bir dize döndürür ve döngü '1' karakterini ekler, asla 100'e eşit olmaz.


13
Beni bununla yakaladın… (aslında) daha yüksek oy alan örnekler sadece sözdizimini kötüye kullanıyorlar… ama bu güzel!
Bwoebi


4
@ Vlakarados: Python kapalı tip dönüşüm yapmaz Javascript yapar. Python'da raw_inputveya Python 3'ü kullanan eşdeğer kod a'yı inputyükseltir TypeError.
user2357112

2
Değerin aslında 100'ün altında olduğunu kontrol etmediğiniz için "100" girdiğinizde normalde durur: '- (
C.Champagne

1
@Sankalp, +burada işleci ekleme değil, dize bitiştirmedir.
Michael M.

87

C

Sadece C'deki üç farklı while-döngüsü türünü gösteren basit bir örnek program.

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

Döngüler açılış kaşlı ayraç önce bir "yapmak" yok iken. Bu aslında, döngü sırasında, aşağıdaki "null ifadesi" ile sonlandırılan (x <10) döngüsünün içinde bir do-while döngüsü oluşturur. Döngünün içinde x arttığından ve ardından do-while döngüsünün durumunda azaldığından, iç döngü hiçbir zaman sonlanmaz ve dış döngü de hiçbir zaman sonlandırılmaz. Sonunda "single-expression" döngüsüne asla erişilmez.

Hala kafanız karıştıysa, buraya bakın (harici olarak barındırılır çünkü codegolf.SE spoilerdeki kod bloklarını sevmez).


8
Haha, bunu çözüm spoylerine bakmadan önce çözdüm. : P
Joe Z.

54
Neden "gider" operatörünü kullanmak için bu kadar mükemmel bir fırsatı yakaladınız? (x --> 0)
corsiKa

2
Vay vay. Bu harika bir şeytan. Beni bulmak için dört okudum.
Patrick M,

1
@JoeZ. Yol çok kolay. En çok oy alan çözüm daha iyiydi. Onu bulamadım.
Anonim Pi

3
@Hat Guy, Bash'in vardır; yap ve yap; sözdizimi yap, böylece C / C ++ olmayan dillere aşina olsalar bile, insanların bundan atıldığını görebiliyorum. tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-7.html
nemec 22:14

85

JavaScript

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

Değişken kaldırma: JavaScript aslında benim ikinci tanımımı alacak var a = true;, onu fonksiyonun en üstünde ilan edecek var a;ve a = true;anlam aatamamı değiştirirken while döngüsüne girdiği zaman tanımsız olacaktır.


3
Bunun neden hiç bitmediğine dair daha iyi bir açıklama ekleyebilir misiniz? Lütfen "değişken kaldırma" hakkında derinlemesine devam edin :)
Sayı9

1
@ Sayı9 Yardımcı olur umarım, google bundan daha iyi örneklere sahiptir;)
Newbrict

25
Kutsal bok bu, noktalı virgül yerleştirme işleminden bile daha kötü. 1!
14'te

2
Bu programda gördüğüm tek sorun basit bir iş yapıyor gibi görünmüyor olması ... aslında hiçbir şey yapmaması gerektiği gibi görünüyor. Belki alertdöngüden sonra bir tane ekleyin .
PeterT,

2
Sen değişmelidir a = 1için a = true. Kod hala bu şekilde sonsuz döngüye sahip olacak, ancak sebebinin JavaScript dönüşümünde ints'tan boolean'a bir tuhaflık olmadığı daha açık.
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");
    }
}

Fonksiyonun ilk satırındaki değişmez sayısı '201' değil, küçük harfli 'L' ( uzun veri türü) sonekine sahip '20' şeklindedir . Sayı, 6432'ye ulaşmadan oldukça hızlı bir şekilde taşar, ancak derleme seçeneklerinde taşma kontrolü açılmadığı sürece program devam eder.
Makul bir şekilde, Visual Studio 2013 (ve muhtemelen diğer sürümleri de) size bu kod için bir uyarı verir ve 'l' yerine 'L' kullanmanızı önerir.


12
Oh, lşeye benzemesi gerekiyordu 1! Ben aptalım. : \
Joe Z.

6
İyileştirme önerisi: Beklenen çıktı bölümündeki 1'leri de ls ile değiştirin (karşılaştırmak için gerçek 1'leriniz olduğunda garip karakterleri bulmak daha kolaydır)
Allen Gould

3
Evet, çevreye özgü gibi görünüyor. @ Michael'ın yazı tipi benim ev bilgisayarımdaki yazı tipinden çok farklı görünüyor ( imgur.com/PKIuJpr - Chrome, Windows 8) ve iş bilgisayarımdaki numara benim ev bilgisayarımdan daha iyi çalışıyor gibi gözüküyor. gözünden. Telefonumun tarayıcısı, sabit bir yazı tipinde kod gösteriyor gibi görünmüyor ve hile hiç çalışmıyor.
BenMM

1
FTR, işte çalışma bilgisayarımda nasıl göründüğü ( imgur.com/Opfs3BH - Firefox, Windows 7). Birinin oldukça zeki insanları bile kandırabileceğini düşünüyorum.
BenMM

15
İNSANLAR AYNI BAKAN KARAKTERLERİN KORUNMASINA NEDEN KİMLER?
Anonim Pi

39

C

Hassasiyet nasıl?

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

Bir dizi tam sayıyı <0; 3> bilgisayar belleğinde saklamanız gerektiğini hayal edin. Bu aralıkta sadece 4 tam sayı vardır (0,1,2,3). Bunu bellekte saklamak için 2 bit kullanmak yeterlidir. Şimdi, bir dizi kayan nokta sayısının <0; 3> saklanması gerektiğini düşünün. Sorun, bu aralıkta sonsuz sayıda kayan nokta sayısı olmasıdır. Sonsuz sayıdaki sayıları nasıl saklayabilirim? Bu imkansız. Sadece sınırlı sayıda numara saklayabiliriz. Bu yüzden 0.1 gibi bazı rakamlar aslında farklıdır. 0.1 olması durumunda, 0.100000000000000006'dır. Kayan nokta sayıları kullandığınız durumlarda == veya! = Kullanmamanız şiddetle tavsiye edilir.


1
Bu nasıl çalışıyor?
Mhmd

5
Yuvarlama hataları 0.1 aslında 0.100000000000000006'dır, çünkü ikilide 0.1, ondalıkta 1/3 gibidir - ikili genişleme sonsuzdur ve periyodiktir.
orion

3
Gerçekten bir yuvarlama hatası değil. Kayan nokta değerleri, bir sayının yaklaşık gösterimleridir. Yaklaşık değerler arasında kesin karşılaştırmalar yapmak işe yaramayacaktır.
AKHolland

4
Bu nedenle (neredeyse) hiçbir zaman float / double'ları eşitlik için karşılaştırmamalısınız.
Emanuel Landeholm

1
Bunu görmek için bekliyordum. Güzel.
David Conrad

33

HTML / JavaScript

Sayfanızda bir giriş kutunuzun olduğunu hayal edin:

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

Ve şimdi içine bir şeyler yazmak istiyorsunuz ... Chrome'da deneyin: http://jsfiddle.net/jZp4X/ .

İşleviyle birlikte adlandırılan standart tarayıcı iletişim kutusu alertkalıcıdır, bu nedenle görüntülendiğinde odağı metin kutusundan çıkarır, ancak görevden alındığında metin kutusu odağı geri alır.


5
Firefox’ta, giriş otomatik olarak yakın bir zamanda otomatik odaklanmaya sahip değil ve ikinci kez bana daha fazla uyarı göstermemeyi teklif ediyor ve daha sonra normal olarak metin kutusuna yazabiliyorum
Einacio

6
Güzel. Döngü veya özyineleme için +1.
Yaklaşan

5
Firefox'ta veya Chrome'da döngü yok. FF, diyalog tıklandığında uyarıyı bir kez gösterir, siz reddedersiniz ve bu sona erer. Tekrarlamak için tekrar tıklayabilirsiniz. Chrome da aynısını yapar, ancak kutuyu odaklanmış halde bırakır ve hatta yazabilirsiniz. Üzgünüm, belki eski sürümlerde bu bir problemdi, ama artık değil.
RomanSt

6
IE11 benim için tam olarak Chrome ile aynı şekilde çalışıyor. Sanırım yanlışlıkla Mac'teki her modern tarayıcıda bir şekilde çalışan ve Windows'taki her modern tarayıcıda farklı bir şekilde çalışan bir şeyin örneğini buldunuz!
RomanSt

1
MSIE11'de normal çalışıyor (döngü yok)
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;
}

Koşul i >=0her zaman doğrudur, çünkü size_t imzasızdır.


2
Nice, ama derleyiciler normalde bunun için bir uyarı verir;)
Synxis

2
@ Synxis Evet derleyiciler yapar. Ancak sadece derleyici uyarılarını açarsanız. g++bunlar hakkında sizi uyarmaz.
FDinoff

5
Her zaman -Wall --pedanticyine de kullanmalısın .
Martin U

3
@queueoverflow Uyarı yalnızca bu bayraklarla gösterilmez. Açık olana ihtiyacınız -Wsign-comparevar -Wextra.
FDinoff

7
-Perdantik üzerinde bir çizgi. #pedantic
David Conrad

29

darbe

(Döngü veya özyineleme talep edilmedi)

#!/bin/bash

# Demo arrays

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

echo $foo

echo ${foo[0]}

foo[2] = `yes`

echo $foo

echo ${foo[2]}

'Yes' dizesini foo [2] 'ye atamak yerine, bu yes, foo [2]' yi hiç bitmeyen bir miktar "yes \ n" ile dolduran sistem komutunu çağırır .


Sonunda bashhafızası
Digital Trauma

4
Evet, gerçekten de öyle. Ama bir çöküş sorusuna izin verildi :)
GreenAsJade

Evet, sadece bir gözlem :). Upvoted.
Dijital Travma

Aslında, bu küçük
hesap

Düzeltme: yessadece bir coreutils programıdır. Sistem çağrısı değil.
Mart'ta

28

C

Bir dosyada "x" harfi kayboldu. Onu bulmak için bir program yazılmıştır:

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

Derlendi, kaçtı ve sonunda bağırdı:

Hurray, letter lost in the file is finally found!

Yıllarca mektuplar, yeni adam gelip kodu optimize edene kadar bu şekilde kurtarıldı. Veri tiplerine aşina idi ve daha geniş bir yelpazeye sahip olduğu ve taşmalara karşı bir miktar koruma sağladığı için negatif olmayan değerler için imzasız olanların imzasız kullanmanın daha iyi olduğunu biliyordu. Bu yüzden int'yi imzasız int olarak değiştirdi . Ayrıca, Ascii'yi her zaman negatif olmayan bir değere sahip olduğunu bilecek kadar iyi tanıyordu. Bu yüzden de karakterini imzasız karaktere dönüştürdü . Kodu derledi ve yaptığı iyi işle eve gurur duydu. Program şöyle görünüyordu:

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

Ertesi gün bir tahribata geri döndü. "A" harfi eksikti ve "abc" içeren "desert_file" içinde olması gerekiyordu bile olsa, program sonsuza dek yazdırıyordu:

Searching file for missing letter a...

Adamı kaçırdılar ve çalışma kodunda veri türlerini asla optimize etmemesi gerektiğini hatırlayarak önceki sürüme geri döndüler.

Fakat burada öğrenmeleri gereken ders nedir?

Öncelikle, ascii tablosuna bakarsanız EOF olmadığını fark edeceksiniz. Bunun nedeni, EOF bir karakter değil, fgetc () işlevinden döndürülen özel bir değerdir;
İmzalı karakterleri kullandığımız sürece her şey iyi çalışır - 50'ye eşit karakter fgetc () ile int'ye de eşitlenir. Sonra onu tekrar char'e çeviririz ve hala 50'ye sahibiz. Aynı şey -1 veya fgetc () 'den gelen diğer herhangi bir çıktı için olur.
Ama imzasız karakter kullandığımızda neler olduğuna bakın. Fgetc () içindeki bir char ile başlıyoruz, int'ye genişletiyoruz ve ardından imzasız bir karaktere sahip olmak istiyoruz. Tek sorun, imzasız karakterde -1'i koruyamamamızdır. Program artık EOF'ye eşit olmayan 255 olarak saklıyor.

Uyarı
Bölüm 3.1.2.5'e bakınız . ANSI C belgelerinin kopyasındaki türler, char'ın imzalı olup olmadığını sadece uygulamaya bağlı olup olmadığını göreceksiniz. Yani adam muhtemelen kodda gizlenen çok zor bir hata bulduğundan kovulmamalıdır. Derleyiciyi değiştirirken veya farklı mimariye geçerken ortaya çıkabilir. Böylesi bir durumda böcek ortaya çıkarsa kimin kovulacağını merak ediyorum;)

PS. Program, PC Assembly Language'de Paul A. Carter tarafından belirtilen hata etrafında inşa edildi.


7
Çözümle ilgili bir hikaye olmasını seviyorum.
jpmc26

Haha! Sanırım sadece bir tane var. Okuduğunuz için teşekkürler!
Legat

1
Seni seviyorum. Beni hikayelerinle besle pls :(
YoYoYonnY

Bu kesinlikle mükemmel!
kirbyfan64sos

21

regex

Uygun girdiyle, aşağıdaki regex çoğu geri izleme regex motorunun geri izleme cehenneme girmesine neden olabilir:

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

"Programming Puzzles and Code Golf Stack Exchange - Mozilla Firefox"Veya gibi basit girdiler "AVerySimpleInputWhichContainsAnInsignificantSentence."(her iki dizede de netlik için alıntı yapıldı), çoğu geriye dönük regex motorunun uzun süre çalışmasını sağlamak için yeterli.

Yana (\s*\w+)*genişleme sağlar \w+\w+\w+... \w+regex motoru temelde bir dizi bölmek mümkün olan tüm yolları denemek anlamına gelir, kelime karakterleri . Geri izleme cehennemin kaynağı budur.
Kolayca değiştirerek düzeltilebilir \s*için \s+, sonra (\s+\w+)*sadece şekilde genişletilebilir \s+\w+\s+\w+... \s+\w+.


3
Geriye dönen regex motorlarından nefret ediyorum.
David Conrad

2
Bunu önce Perl ile denedim, ama Perl burada bir döngü farkedebiliyor. AWK denemedim, çünkü düzenli ifade AWK'da böyle bir davranışa neden olamaz. PHP, başarısızlıkla eşleşmek için çok uzun süren düzenli ifadeler yapar (saçma, ama bu sizin için PHP - otomatik olarak programlara hatalar ekler). Ancak, aslında Python'da çalışır.
Konrad Borowski

1
@xfix: Perl'in neden geri cehennemden kaçınmayı engellediğine gelince, bu makale nedenini açıklıyor. Ancak, burada gösterildiği gibi davaya karşı yeterli değildir (performans bölümüne doğru aşağı inin). PHP (aslında PCRE kütüphanesi) geri izleme sınırına sahiptir ve uygun bir program, yürütmenin durdurulup durdurulmadığına veya tamamlanıp tamamlanmadığına karar vermek için her zaman işlevin dönüş değerini kontrol etmelidir.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

1
Bu çok kaygan.
alvonellos

20

JavaScript

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

050 Javascript'te sekizli bir sabittir ve 40 değerinde ondalık değere sahip olur.


73
Bunu açık buluyorum. :-)
Justin,

6
Javascript'in bunu yaptığını bilmiyordum. Ama kodu okuduktan sonra dedim ki: "050, 40, muhtemelen üs 8 veya başka bir şeyi temsil etmenin bir yolu olmalı"
Cruncher

Bunun daha iyi gizlenmesi gerekiyor.
Paŭlo Ebermann

Bu açıktır ..
Oliver Ni

18

Haskell

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

Bir düşün! Aynı şey olurdu head $ "Hello" ++ (repeat '!'), yani sadece geri dönmeli 'H'.

Haskell listelerinde özyinelemeli yapılar bulunur, ilk öğe en üsttedir. Bir listeye eklemek için tüm bu öğeleri açmanız, ekinizi yerleştirmeniz ve kaldırılan öğeleri geri koymanız gerekir. Bu sonsuz bir listede işe yaramaz. Benzer şekilde, sonsuz bir listeyi tersine çevirmek sihirli bir şekilde size "Hello"geri vermez . Sonsuza dek asılacak.


1
Bu gerçekten işe yaramazsa çok kötü: - /
John Dvorak

1
Nasıl çalışmıyor?
danmcardle

@crazedgremlin bunu Fedora'da test ettiğimde işletim sistemi nihayetinde süreci öldürdü. (<5 dakika) çünkü sistemdeki tüm belleği kullandı.
FDinoff

İlginç! Bunun olduğunu anlamadım. Tüm bu sık sık hatıraları toplayan bölgelere girmiyorum.
danmcardle

4
Bu hala geçerli bir çözüm: çıkmıyor, sistem artık destekleyemediği sürece devam ediyor ...
GreenAsJade

16

Windows altında Java

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 sıkışmak için komut satırından sıkışan bir standart çıkış akışına dayanır. Pencerelerin altındaki WinSXS dizini, uzun adlara sahip binlerce dosyaya sahiptir, bu nedenle stdout'u tıkamayacağının garantisi vardır ve waitForgeri döndürülemez, böylece program kilitlenir.


1
Belki yoğunlaşıyorum, ama bu sonuçta geri dönmeyecek mi? Sadece bir süre alabilir. Belki de "clog [ging] stdout" ile ne demek istediğinizi anlamadım.
asteri

4
Eğer akış program bloklarını boşaltmazsa, neden kullandığımı bu yüzden bazı baş ağrılarıma neden oldu; uzun dizin yalnızca arabelleğin tam çalışmasını sağlar
masterX244

Ah, anladım. Güzel! +1
asteri

15

Elma ve portakalları karşılaştırmak ... C

Burada bir kod kullanarak kod olmadığını gördüm goto... (Biliyorsun: Goto kötüdür! )

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

Uyku sadece onu okuyabilmek için. Hiç bitmeyen bir şeyi beklemek için sonsuz bir süreniz yoksa ^ C tuşuna basın ;-)


9
Sinsi piç kurusu, goto bu masumdur :)
orion

rastgele () kullanılan votka mı?
masterX244

1
ahh, "2"! = 2; anladım
masterX244

2
Eh, "2" muhtemelen 2 olamaz, ancak daha büyük bir sayı (ve en az 4 katı) kullandıysanız, olabilir;)
orion

1
@ orion: Evet haklısınız, olabilir. Ve goto hala kötü, ama kötü tip dökümler daha da kötü!
max.haredoom

12

C, belirli optimizasyon derleyicilerle

Bu program, taşana kadar bir tamsayı değişkeni artırır.

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

İmzalanan tamsayı taşması tanımsız davranış. Genellikle pratikte, optimizasyonlar kapatıldığında sarar. En iyileştirmeler açıkken, derleyiciler x + 1 > xbunun daima doğru olduğuna karar verebilir ve karar verebilir .


Belki de kullanın int32_t; 64 bitlik bir int gerçekten, gerçekten, çok uzun sürecektir (her bir yineleme bir nanosaniye alırsa 585 yıl).
Paul Draper

11

C ++

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

Tuhaf yorum tarzı hiledir. İpucu: Trigraphs


Bu sonsuz bir döngünün çok temel bir örneğidir.
Ismael Miguel

64
Bu Trigraph'lar burada aşırı kullanıldılar :(
TimWolla

75
Neredeyse eğlenceli olmayan, Standart Loopholes'a ilk harflerin koyulması gerektiğini düşünüyorum.
undergroundmonorail

6
@TheDoctor: ?? / bir ters eğik çizgi karakteri için bir işarettir, bu nedenle ters eğik çizgi, x'in yorumun sonuna 0 atandığı satırı ekler ve yorumun bir parçası haline getirir.
CasaDeRobison

4
@undergroundmonorail Yayınlanan
Justin,

11

Java

Özellikle otomatik kutu optimizasyonunun bu yan etkisini seviyorum:

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

Autoboxing yüzünden, Integernesnelerin hemen hemen düz gibi davranan inttek bir istisna dışında, burada s: i != maxiçinde fordöngüler karşılaştırır referansları (kimlik) Integernesneler, onların değeri (eşitlik). 100'e kadar olan değerler için bu Integer, JVM'deki bir optimizasyondan dolayı yine de şaşırtıcı şekilde "işe yarıyor": Java, nesneleri "en yaygın değerler" için önceden dağıtır ve bunları otomatik kutulama sırasında yeniden kullanır. Öyleyse 100'e kadar olan değerler için kimliğimizin <==> eşitliği vardır.


5
Bazı Java'lıların hala C ++ operatörünün aşırı yüklendiğini kötülük olarak gördüğü düşünüldüğünde ...
Daniel

= new Integer(0)Yine de değerleri başlattığınız için başlatmaya ihtiyacınız yoktur . (Bu nedeni daha az belirgin hale getirebilir.)
Paŭlo Ebermann

@ PaŭloEbermann: İyi nokta, kodu değiştirdim.
Daniel

9

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

Bu , C'de doğru çalışır ve STDOUT'da 9'dan 1'e geri sayım yapar. Ruby'de çalıştırıldığında, sonlandırılmaz, çünkü

Ruby'de 0 yanlış değer değildir.


Aynı anda dilleri yapın ... etkileyici.
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]]);

Her iki ilmek de aynı ilmek değişkenini kullanır, böylece girişe bağlı olarak iç ilmek dış ilmeğin bitmesini önleyebilir.


Bu hangi dil?
RononDex

@ronondex Javascript
to 17:14

1
Ah, evet, bu Javascript. Sözdizimi
yükseltmeyi mümkün kıldığımı

1
Bunu açık buluyorum. :-)
rafaelcastrocouto

@ rafaelcastrocouto Evet, bu bir tür, ama aynı zamanda, örneğin bir döngüden bir fonksiyondan diğerine bir döngü taşırken veya sadece kodun üzerine bakarak kaçırmak çok kolaydır. Ayrıca, bunun değişken gölgelenme nedeniyle C de dahil olmak üzere bazı dillerde doğru şekilde çalıştığını unutmayın. :)
Aleksi Torhamo

7

C

Bu, 0'dan 255'e kadar tüm ASCII karakterleri için bir kod tablosu yazdırmalıdır. A char, üzerlerinde yineleme yapmak için yeterince büyüktür.

#include <stdio.h>

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

Tüm karakterler 256'dan küçüktür. 255 ++, taşma nedeniyle 0 verir, bu nedenle koşul i < 256her zaman bekler. Bazı derleyiciler bunun hakkında uyarıyor, bazıları değil.


Yapmak daha faydalı bir şey yapmak gibi görünüyor, belki de printf("%3d %2x: %c", i, i, i);döngüde (kod tablosu için) gibi bir şey kullanın .
Paŭlo Ebermann

@ PaŭloEbermann: Harika bir fikir.
Rafał Cieślak

Bu numarayı
sınıfımda

7

piton

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

olmalı exit()ve olmamalı exit. Anladığım kadarıyla exit()python yorumlayıcısından çıkma komutu. Bu durumda çağrı fonksiyonun temsilidir, fonksiyona değil bkz: çıkış-tartışma . Alternatif breakolarak daha iyi bir seçim olacaktır.


Lütfen exitgerçekte ne olduğunu açıklayabilir misiniz ? Sınıf gibi görünüyor, ama ne için kullanılıyor? Ayrıca değişebilir print miçin print(m)bu da Python 3. ile çalışır, böylece
Martin Thoma

1
Şeylerin Bu tarz ... gibi benim zaman elseif öyleydi çünkü işe yaramadı elif .
Anonim Pi

Teşekkürler @moosegüncellenmiş baskı bildirimi ve spoiler mesajı
Willem

6

C ++

Peki ya klasik C ++ - programcının tuzağı?

int main()
{
   bool keepGoing = false;

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

   return 0;
}

Bunu anlamadım mı? Kullanma hakkında mı. = yerine ==?
Mhmd

@ user689 tam olarak. keepGoing = truedeğerini karşılaştırmak için kullanılır keepGoing, bunun yerine değeri atarkeepGoing ; Ayrıca bütün deyimi keepGoing = trueolarak değerlendirilirse true(gibi şeyler yazmasına olanak tanır budur a=b=c=d=0sonsuz bir döngüye yol açan).
CompuChip

3
Bu, yoda koşullarını kullanmak için daha fazla sebep.
Ryan

@RyanEdwardDougherty Haha, onların arandığını hiç duymamıştım. Sabah gülmek için teşekkürler.
CompuChip

@RyanEdwardDougherty: Tabii ki == true(veya Yoda tarzı true ==) zaten gereksizdir ve koşul basitçe okumalıdır while (keepGoing).
celtschk

6

JavaScript

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

1. ve 3. satırda kullanılan değişkenler, 2. ve 3. satırda kullanılanlardan farklıdır.
Biri a (U + 0061) kullanırken diğeri а (U + 0430) kullanır


Burada bir problem görmüyorum. Koştum ve iyi çalıştı. Neyi kaçırıyorum?
Andrew Shepherd

unicode muhtemelen dönüştürüleceği için bu muhtemelen her yerde işe yarayacak. Alabileceğiniz en görünmez olduğundan, +1 aldınız!
rafaelcastrocouto

Sadece tamamen gizlemek için (á yerine U + 0430 yazınız.) Bu sizin kodunuz var a;var points = 0;function fiftyfifty() {points++;if (Math.random() > 0.5)return true;}; á = fiftyfifty(); while (a === undefined) {á = fiftyfifty();} console.log("Points: " + points);olsaydı , sorunu bulmakta iyi şanslar: pes ederdim, sonsuza dek silerim, bilgisayarımı temizler, belki de virüs tarayıcıyı emin ve tamamen yeniden yazardım. EDIT: Çünkü var a = 0; a = 1;çok gerçekçi değil
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!");
   }
}

"İ = i ++" oldukça yaygın bir başlangıç ​​hatasıdır ve bulmak şaşırtıcı derecede zor olabilir


5

C ++

Biraz rastgele mi?

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

Fonksiyonu çağırmaz, randbunun yerine özyinelemeli Randomizer::randfonksiyonu çağırır .


5
Dönüş ifadesinde fazladan parantez, yuck.
David Conrad

1
Bu olacak sonunda da, segfault.
kirbyfan64sos

5

Haskell

Ackermann işlevinin belirli bir değerinin hesaplanmasında zaman zaman bazı kodlar. Çok düşük değerler için genellikle sonlandırılır. Makinemde çok düşük değerler derlenmiş kodlu 3 5 veya daha küçük bir değer anlamına gelir -O. Ghci'de düşük değerler 3 3 gibi bir şey ifade ediyor.

'Sembol pisliği dizim, niçin emin görünüyor. Bazı yerlerde ihtiyaç duyuldukları için hepsini kaldıramazsınız.

Dil değiştirildi

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

Bu bir livelock'a neden olur. Sayma ipliği, Ackermann hesaplamasının aynı TVar'a dokundukları için geri dönmesine neden olur.


lang-haskell yerine lang-hs olarak işaretlemek daha iyi çalışıyor gibi görünüyor ( google prettifier içindeki uzantılardan biri )
Einacio

5

Java - Döngü veya özyineleme yok

Düzenli ifadeler öğrenmeye başladım ve dizimin düzenli bir ifadeyle eşleşip eşleşmediğini test etmek için ilk programımı yazdım.

Ne yazık ki, program herhangi bir sonuç vermedi. Terminali tutar. Lütfen sorunu bulmakta yardımcı olun. Döngülerden herhangi birini kullanmadım, özyinelemeyle ilgisi yok. Ben tamamen şaşırdım.

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

Neyi yanlış yaptım? Programım neden bitmiyor? Lütfen yardım et!

Ideone bağlantı burada .

Bu felaket bir geriye dönüşün aptalca bir örneğidir . Karmaşıklık O (2 n / 2 ). Program süresiz olarak devam olmasa da, muhtemelen daha uzun yaşamak istiyorum yaşayan ve her iki cansız nesneleri etrafında ve değil çok etrafında .


5

C

İki döngüden sadece birine ihtiyacınız olmalı, fakat hangisine ihtiyacınız var derleyicinize bağlı.

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

}

Basit bir sınırlama, i'yi sonlandırıcı olmayan bir değere sıfırlar . Derleyiciler onlar tahsis konusunda farklılık i üstünde veya altında bir yığın, bu yüzden her iki yönde de taşmaları ekledik.


5

C / C ++

C ++ burada kullanılan kolay satır içi değişken bildirimlerini sağlar, ancak bu hatayı düz eski C de yapmak kolaydır.

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

İç döngüde, 'j' karşılaştırılır fakat asla artmaz. ('İ ++' aslında 'j ++' olmalıdır). Bu çok sinsi bir hile değil, geçmişte yaptığım gerçek bir hata;) Dikkat edilmesi gereken bir şey.


2
Bu genellikle hata ayıklama için en az 5 dakika sürer. Bunu yaptığım zaman nefret ediyorum.
ace_HongKongIndependence 22:14

4

C #

Aşağıda, bir arka plan iş parçacığı kullanarak büyük bir giriş dizisinde aritmetik işlem (toplama) yapan basit bir sınıftır. Bir örnek program dahil edilmiştir.

Ancak, oldukça basit olmasına rağmen, asla sona ermez. El çabukluğu olmadığına dikkat edin (karakter görünümleri, gizli / eksik noktalı virgül, trigraph ;-), vb.)

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

Bu, aynı zamanda kodunuzda görünebilecek gerçek dünyadan iğrenç bir böcek örneğidir. .NET bellek modeli ve C # belirtimi uyarınca, WaitAndGetResultdeğişkeni geçici olarak belirtmediğiniz sürece, içinde olan gibi bir döngü asla sona ermeyebilir, çünkü başka bir iş parçacığı tarafından değiştirilir. Ayrıntılar için bu StackOverflow sorusuna bakın. Hata, .NET uygulamasına bağlıdır, bu nedenle sizi etkileyebilir veya etkilemeyebilir. Ancak, genellikle, bir x64 işlemcide bir yayın derlemesi çalıştırmanın sorunu gösterdiği görülüyor. ( “Csc.exe / o + / debug- infinite.cs” ile denedim .)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.