Чому це не закінчується? [зачинено]


95

Ваше завдання: Написати програму, яка, очевидно, повинна припинитися, але вона ніколи (в міру збою комп'ютера) не робить. Зробіть це схожим на те, що воно повинно виконувати просте завдання: додавання чисел, друкування чогось, ... Але воно просто потрапляє у нескінченну петлю.

Постарайтеся зробити свою програму дуже зрозумілою і простою, тоді як вона насправді застрягне в непередбаченому циклі. Виборці: оцініть відповіді про те, наскільки вони "недоторкані"!

Це конкурс популярності: будьте креативними!


6
Чи можете мені хтось пояснити, що я можу зробити, щоб зробити питання менш широким? Я тут новий. Дякую!
Число9

6
Це просто великий список помилок друку та помилок початківців, які спричиняють цикл.
Білл Вудгер

Цікаве запитання, але я ще не бачив справді творчих відповідей. Я обіцяю голоси тим, хто не використовує циклів або очевидних рекурсій!
Наближення

14
Я не знаю, чи вважається це, але в даний час мій офіс Microsoft веде себе саме так.
Річка рівня Св.

1
Я голосую за те, щоб закрити це питання поза темою, оскільки обґрунтовані виклики вже не є темою. meta.codegolf.stackexchange.com/a/8326/20469
кіт

Відповіді:


185

Javascript

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

prompt () повертає рядок, і цикл додає символ "1", він ніколи не дорівнює 100.


13
Ви отримали мене з цим… (насправді) приклади з високим голосом - це просто зловживання синтаксисом… але це добре!
bwoebi

4
Chrome на Kubuntu став невідповідним, повісити все, і мені довелося жорстко скинути :)
Сергій Тельшевський

4
@Vlakarados: Python не буде робити неявне перетворення типу, яке робить Javascript. На Python еквівалентний код з використанням raw_inputабо Python 3 inputпідвищує a TypeError.
user2357112

2
Немає перевірки на те, що значення насправді менше 100, тому воно нормально зупиняється, коли ви вводите "100": '- (
C.Champagne

1
@Sankalp, +оператор тут конкатенації рядків, а не додавання.
Майкл М.

87

С

Лише базовий приклад програми, яка ілюструє три різні види циклів while у циклі 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;
}

Хоча петлі не мають "робити" перед відкриттям фігурної дужки. Це фактично створює цикл виконання часу всередині циклу (x <10), який закінчується наступним "null заявою" while циклом. Оскільки х збільшується всередині циклу, а потім зменшується в стані циклу "час роботи", внутрішній цикл ніколи не закінчується, і так само, як і зовнішній цикл. Цикл "one-statement" в кінці ніколи не досягається.

Якщо ви все ще плутаєтеся , подивіться тут (зовні розміщено, оскільки codegolf.SE не любить кодові блоки в спойлерах).


8
Ха-ха, я зрозумів це, перш ніж подивитися на спойлер рішення. : P
Joe Z.

54
Чому ви пропустили таку чудову можливість скористатися оператором "йде в"? (x --> 0)
corsiKa

2
Ух ти. Це дивно зло. Мені довелося чотири читання, щоб знайти його.
Патрік М

1
@JoeZ. Шлях занадто простий. Найбільш схвалене рішення було краще. Та, яку я не знайшов.
Анонімний Пі

3
@Hat Guy, у Bash є синтаксис for; do and while; роби синтаксис, щоб я міг бачити людей, яких це відкинуло, навіть якщо вони знайомі з мовами, які не мають 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;
})();

Змінна підйомність: JavaScript насправді захопить моє друге визначення var a = true;, оголосить його у верхній частині функції як var a;, а зміна мого призначення на a = true;значення aбуде невизначено під час вступу в цикл while.


3
Чи можете ви додати краще пояснення, чому це ніколи не припиняється? Будь ласка,
заглибтеся у

1
@ Number9 Я сподіваюся, що це допомагає, Google має набагато кращі приклади, ніж це;)
Новітня

25
Боже, це ще гірше, ніж вставка з комою. +1!
tomsmeding

2
Єдина проблема, яку я бачу з цією програмою, полягає в тому, що вона не схожа на те, що виконує просту задачу ... схоже, що вона по суті нічого не повинна робити. Можливо, додайте alertпісля циклу.
PeterT

2
Ви повинні змінитись a = 1на a = true. Код все одно матиме нескінченний цикл таким чином, але буде зрозуміліше, що причина - це не якась химерність перетворення JavaScript від ints до 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");
    }
}

Літеральна цифра в першому рядку функції - це не 201, а «20» із суфіксом «L» ( довгий тип даних). Число буде переповнюватися досить швидко, не потрапляючи до 6432, але програма продовжуватиме роботу, якщо не буде включена перевірка переповнення в параметрах збірки.
Зрозуміло, Visual Studio 2013 (і, мабуть, і інші версії) попереджає цей код, рекомендуючи використовувати "L" замість "l".


12
О, lповинен виглядати як 1! Я дурний. : \
Джо З.

6
Пропозиція щодо вдосконалення: замініть позначки 1 у очікуваному розділі виведення на ls (простіше помітити дивного персонажа, коли для порівняння у вас справжні 1)
Аллен Гулд

3
Так, це, здається, досить специфічно для оточення. @ Шрифт Майкла виглядає дуже інакше, ніж шрифт на моєму домашньому комп’ютері ( imgur.com/PKIuJpr - Chrome, Windows 8), і фокус, здається, працює на моєму робочому комп'ютері, ніж на моєму домашньому комп’ютері, хоча вони мають досить схожі технічні характеристики Браузер мого телефону, схоже, не показує код фіксованим шрифтом, і фокус у ньому зовсім не працює.
БенМ

1
FTR, ось як це виглядає на моєму робочому комп'ютері ( imgur.com/Opfs3BH - Firefox, Windows 7). Я вважаю, що можна навіть обдурити досить пронизливих людей.
БенМ

15
ЧОМУ ЛЮДИ ВЗАЄМО ЗЛУЧАЮТЬ ХАРАКТЕРИ, ЯКІ ПІДТРИМАЮТЬСЯ?
Анонім Пі

39

С

Як щодо точності?

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

Уявіть, що вам потрібно зберегти діапазон цілих чисел <0; 3> в пам'яті комп'ютера. У цьому діапазоні є лише 4 цілих числа (0,1,2,3). Для зберігання цього в пам'яті достатньо використовувати 2 біти. Тепер уявіть, що вам потрібно зберегти діапазон чисел з плаваючою комою <0; 3>. Проблема полягає в тому, що в цьому діапазоні існує нескінченна кількість чисел з плаваючою комою. Як зберігати нескінченну кількість чисел? Це неможливо. Ми можемо зберігати лише обмежену кількість номерів. Ось чому деякі числа на зразок 0,1 насправді різні. У випадку 0,1 це 0,100000000000000006. Настійно рекомендується не використовувати == або! = В умовах, якщо ви використовуєте числа з плаваючою комою.


1
Як це працює?
Mhmd

5
Помилки округлення. 0,1 насправді 0,100000000000000006, оскільки 0,1 у двійковій формі - це як 1/3 у десятковій частині - це бінарне розширення нескінченне та періодичне.
Оріон

3
Насправді помилка округлення. Значення з плаваючою комою є приблизними поданнями числа. Точне порівняння між приблизними значеннями не спрацює.
AKHolland

4
Ось чому ви (майже) ніколи не повинні порівнювати поплавок / дублі за рівності.
Емануель Ландегольм

1
Я чекав, щоб побачити цього. Приємно.
Девід Конрад

33

HTML / JavaScript

Уявіть, що на вашій сторінці є поле введення:

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

А тепер ви хочете щось ввести в нього ... Спробуйте в Chrome: http://jsfiddle.net/jZp4X/ .

Стандартне діалогове вікно веб-переглядача, яке викликається alertфункцією, є модальним, тому коли він відображається, він виводить фокус із текстового поля, але при відхиленні текстове поле отримує фокус назад.


5
в Firefox, вхід не має автоматичного фокусування на тривожному закритті, і з другого разу він пропонує мені не показувати більше сповіщень, і тоді я можу писати у текстовому полі звичайно
Einacio

6
Хороший. +1 для відсутності циклів і повторів.
Наближення

5
Немає циклів ні в Firefox, ні в Chrome. FF показує попередження один раз, коли натискається діалогове вікно, ви відхиляєте його, і це закінчується. Можна повторити його, щоб повторити. Chrome робить те саме, але залишає поле зосередженим, і ви навіть можете вводити його. Вибачте, можливо, у старих версіях це було проблемою, але вже не.
RomanSt

6
IE11 працює для мене точно так само, як і Chrome. Я думаю, ви ненароком знайшли приклад того, що працює в один спосіб у кожному сучасному браузері на Mac, а по-іншому - у кожному сучасному браузері в Windows!
RomanSt

1
Працює нормально (без циклів) на 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;
}

Умова i >=0завжди відповідає дійсності, оскільки size_t не підписаний.


2
Хороший, але компілятори зазвичай
надсилають

2
@Synxis Так, компілятори. Але лише якщо ви включите попередження компілятора. g++не попередить вас про це без них.
FDinoff

5
Ви завжди повинні використовувати -Wall --pedantic.
Мартін Удінг

3
@queueoverflow Попередження не відображається лише з цими прапорами. Вам потрібно, з чим -Wsign-compareможна ввімкнути -Wextra.
FDinoff

7
Один тире на -педантичний. #pedantic
Девід Конрад

29

баш

(Був запит про відсутність циклів чи рекурсії)

#!/bin/bash

# Demo arrays

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

echo $foo

echo ${foo[0]}

foo[2] = `yes`

echo $foo

echo ${foo[2]}

Замість присвоєння рядку "так" foo [2], це викликає системну команду yes, яка заповнює foo [2] незмінним числом "так \ n".


Врешті-решт bashпам’яті втрачається і випадає з неї
Digital Trauma

4
Так, це дійсно так. Але аварія була дозволена питанням :)
GreenAsJade

Так, просто спостереження :). Отримано.
Цифрова травма

Насправді я вважаю, що програми цього маленького комп’ютера, які фактично забивають вашу машину, або якийсь інший відмова в обслуговуванні, повинні отримувати бонусні бали)
GreenAsJade

Виправлення: yesце лише основна програма. Не систематичний виклик.
mniip

28

С

Буква «х» була загублена у файлі. Для його пошуку була написана програма:

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

Він був складений і пробіг, і він нарешті кричить:

Hurray, letter lost in the file is finally found!

Протягом багатьох років листи рятувались таким чином, поки не прийшов новий хлопець і не оптимізував код. Він був знайомий з типами даних і знав, що для негативних значень краще використовувати непідписані, ніж підписані, оскільки він має ширший діапазон і забезпечує певний захист від переливів. Тож він змінив int на непідписаний int . Він також досить добре знав ascii, щоб знати, що вони завжди мають негативне значення. Тому він також змінив char на непідписаний char . Він склав код і пішов додому пишаючись хорошою справою, яку зробив. Програма виглядала так:

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

На наступний день він повернувся до хаосу. Лист "a" відсутній, і хоча він мав бути у "desert_file", що містить "abc", програма шукала його назавжди, роздруковуючи лише:

Searching file for missing letter a...

Вони звільнили хлопця і повернулися до попередньої версії, пам’ятаючи, що ніколи не слід оптимізувати типи даних у робочому коді.

Але який урок вони мали б тут засвоїти?

Перш за все, якщо ви подивитеся на таблицю ascii, ви помітите, що немає EOF. Це тому, що EOF - це не символ, а особливе значення, повернене з fgetc (), яке може повернути символ, розширений до int, або -1, що позначає кінець файлу.
Поки ми використовуємо підписаний char, все працює добре - char рівний 50 розширюється fgetc () на int, рівний 50. Потім ми перетворюємо його назад у char і все ще має 50. Те саме відбувається для -1 або будь-якого іншого виводу, що надходить від fgetc ().
Але подивіться, що станеться, коли ми використовуємо неподписані знаки. Ми починаємо з char у fgetc (), розширюємо його до int, а потім хочемо мати неподписаний char. Єдина проблема полягає в тому, що ми не можемо зберегти -1 у неподписаних знаках. Програма зберігає його як 255, що вже не дорівнює EOF.

Caveat
Якщо ви подивитесь на розділ 3.1.2.5 Типи в копії документації ANSI C, ви дізнаєтесь, підписаний чи ні знак char залежить тільки від реалізації. Тож хлопця, мабуть, не слід звільняти, оскільки він знайшов дуже хитру помилку, що ховається в коді. Це може вийти при зміні компілятора або переході до іншої архітектури. Цікаво, кого б звільнили, якби помилка вийшла в такому випадку;)

PS. Програма була побудована навколо помилки, згаданої Пол А. Картером у мові складання ПК


7
Мені подобається, що є історія з рішенням.
jpmc26

Ха-ха! Я здогадуюсь, це єдиний. Дякуємо за прочитане!
Легат

1
Я тебе люблю.
Погодуй

Це абсолютно геніально!
kirbyfan64sos

21

Регекс

При відповідному введенні наступний регулярний вираз може призвести до того, що більшість механізмів зворотного відстеження переходять у пекельне відстеження:

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

Простого введення, такого як "Programming Puzzles and Code Golf Stack Exchange - Mozilla Firefox"або "AVerySimpleInputWhichContainsAnInsignificantSentence."(обидва рядки цитуються для ясності) достатньо, щоб тривалий час працювала більшість зворотних регексівних двигунів.

Оскільки (\s*\w+)*дозволяє розширення \w+\w+\w+... \w+, що означає, що механізм регулярного вирівнювання в основному випробує всі можливі способи розділити рядок символів слова . Це джерело зворотного пекла.
Це може бути легко виправлена шляхом зміни \s*в \s+, то (\s+\w+)*можна розкласти тільки \s+\w+\s+\w+... \s+\w+.


3
Я ненавиджу зворотні двигуни регексу.
Девід Конрад

2
Я спробував це спочатку з Perl, але, здається, Perl може помітити цикл тут. Я не пробував AWK, тому що жоден регулярний вираз не може викликати таку поведінку в AWK. PHP автоматично робить регулярне вираження, яке займає занадто багато часу, щоб збігатися з ладом (що нерозумно, але це PHP для вас - він автоматично вставляє помилки в програми). Однак насправді це працює в Python.
Конрад Боровський

1
@xfix: Щодо того, чому Perl вдалося уникнути зворотного відстеження, ця стаття пояснює причину. Однак цього недостатньо проти справи, як показано тут (прокрутіть до розділу продуктивності). PHP (насправді бібліотека PCRE) має обмеження зворотного відстеження, і належна програма завжди повинна перевіряти значення повернення функції, щоб вирішити, чи було зупинено виконання чи добіг до завершення.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

1
Це так СЛІЧ.
alvonellos

20

JavaScript

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

050 - вісімкова константа в Javascript, і це, мабуть, десяткове значення 40.


73
Я вважаю це очевидним. :-)
Джастін

6
Я не знав, що JavaScript це зробив. Але, прочитавши код, я сказав: "050 має бути певним чином представити 40, можливо, базу 8 чи щось"
Cruncher

Це потрібно краще приховати.
Paŭlo Ebermann

Очевидно ..
Олівер Ні

18

Хаскелл

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

Ну, подумайте! Це було б те саме head $ "Hello" ++ (repeat '!'), тобто слід просто повернутися 'H'.

У списках haskell є рекурсивні структури, причому перший елемент є найвищим. Щоб додати до списку, вам слід розгорнути всі ці елементи, розмістити додаток і повернути підняті елементи назад. Це не працює в нескінченному списку. Аналогічно, перевернення нескінченного списку не магічно "Hello"поверне вас назад. Він просто повіситься назавжди.


1
Шкода, що насправді це не працює: - /
Джон Дворак

1
Як це не працює?
danmcardle

@crazedgremlin, коли я тестував це на Fedora, операційна система врешті-решт знищила процес. (<5 хвилин), оскільки він зайняв усю пам'ять у системі.
FDinoff

Цікаво! Я не усвідомлював, що це сталося. Я так часто не ризикую зайняти територію пам’яті з усією пам’яттю.
danmcardle

4
Це все-таки правильне рішення: воно не виходить, воно працює до тих пір, поки система не зможе його більше підтримувати ...
GreenAsJade

16

Java під 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();
    }
}

Програма покладається на заклинений стандартний вихідний потік з командного рядка, щоб застрягнути. У каталозі WinSXS під Windows є кілька тисяч файлів з довгими іменами, тому майже гарантовано засмітити stdout, і waitForнеможливо повернутись, тому програма зайшла в тупик


1
Можливо, я щільний, але чи не повернеться це врешті? Це може зайняти деякий час. Можливо, я не розумію, що ви маєте на увазі під "забивати [ging] stdout".
астері

4
якщо потік не випорожнюється програмними блоками, це викликало у мене вже головні болі, ось чому я його використовував; довгий каталог лише гарантує, що буфер працює повноцінно
masterX244

Ах, готча. Приємно! +1
астері

15

Для порівняння яблук і апельсинів ... в С

Мені вражено, що тут немає жодного фрагмента коду, використовуючи goto... (Ви знаєте: Гото - це зло! )

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

Сон - це лише те, що його можна прочитати. Натисніть ^ C, якщо у вас немає нескінченної кількості часу, щоб чекати чогось, що ніколи не трапиться ;-)


9
Ти підлий ублюдок, гото невинний у цьому :)
orion

чи є випадкова () використовувана вода?
masterX244

1
ах, "2"! = 2; отримав
masterX244

2
Ну, "2", ймовірно, ніколи не може бути 2, але якщо ви використали більшу кількість (і кратну принаймні 4), це може статися;)
orion

1
@orion: Так, ти маєш рацію, могло бути. І гото все-таки є злом, але погані кастинги ще більше зла!
max.haredoom

12

C, з певними оптимізаторами компіляторів

Ця програма збільшує цілу змінну, поки вона не переповнюється.

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

Переповнене ціле число - це невизначена поведінка. Зазвичай на практиці він завершується, коли оптимізація вимкнена. Увімкнувши оптимізацію, компілятори можуть і вирішують, що x + 1 > xзавжди відповідає дійсності.


Можливо, використовувати int32_t; 64-бітний інт зайняв би дуже, дуже, дуже довго (585 років, якщо кожна ітерація займе наносекунд).
Пол Дрейпер

11

C ++

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

Дивний стиль коментування - трюк. Підказка: триграфи.


Це занадто базовий приклад нескінченного циклу.
Ісмаїл Мігель

64
Ці Триграфи тут надто зловживають :(
TimWolla

75
Я майже відчуваю, що триграфи слід розміщувати в стандартних лазівках, які вже не смішні.
підземниймонорельс

6
@TheDoctor: ?? / є триграфом для символу зворотної косої риси, тому зворотна косої риски сплаює лінію, де x призначено 0 до кінця коментаря, що робить його частиною коментаря.
CasaDeRobison

4
@undergroundmonorail Опубліковано
Джастін

11

Java

Я особливо люблю цей побічний ефект оптимізації автобоксингу:

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, Integerоб'єкти поводяться майже як прості intз тут, з одним винятком: i != maxв forпетлях порівнює посилання (ідентичність) з Integerоб'єктів, а не їхня значення (рівність). Для значень до 100 це дивно "працює", проте завдяки оптимізації в JVM: Java попередньо розміщує Integerоб'єкти для "найпоширеніших значень" і повторно використовує їх при автобоксінгу. Отже, для значень до 100 ми маємо тотожність <==> рівність.


5
Враховуючи, що деякі хлопці Java все ще вважають перевантаження C ++ оператором як зло ...
Даніель,

Вам не потрібна ініціалізація = new Integer(0), оскільки ви інакше потім ініціалізуєте значення. (Це може зробити причину менш очевидною.)
Paŭlo Ebermann

@ PaŭloEbermann: Добре, я відредагував код.
Даніель

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

Це правильно працює на C , відраховуючи від 9 до 1 в STDOUT. При запуску в Ruby він не припиняється, оскільки

0 не є хибним значенням у Ruby.


Мови відразу ... вражаючі.
Пол Дрейпер

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

Обидві петлі використовують одну і ту ж змінну циклу, тому залежно від введення, внутрішній цикл може утримувати зовнішню петлю від будь-якого закінчення.


Яка мова це?
RononDex

@ronondex Javascript
tomsmeding

1
А, так, це Javascript. Я згадав, щоб увімкнути синтаксис, але мусив забути поставити його і в назві :)
Алексі Торхамо

1
Я вважаю це очевидним. :-)
rafaelcastrocouto

@rafaelcastrocouto Так, це так, але це також дуже легко пропустити, наприклад, переміщуючи цикл з однієї функції на іншу або просто оглядаючи код. Крім того, зауважте, що це дійсно правильно працює в деяких мовах, включаючи C, завдяки змінному затіненню. :)
Алексі Торхамо

7

С

Це має надрукувати таблицю коду для всіх символів ASCII, від 0 до 255. A charє достатньо великою, щоб повторити їх.

#include <stdio.h>

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

Усі символи менше 256. 255 ++ дає 0 через переповнення, тому умова i < 256завжди виконується. Деякі укладачі попереджають про це, деякі ні.


Щоб зробити, здається, зробити щось більш корисне, можливо, скористайтеся чимось на зразок printf("%3d %2x: %c", i, i, i);(для таблиці кодів) у своєму циклі.
Paŭlo Ebermann

@ PaŭloEbermann: Чудова ідея.
Rafał Cieślak

Я використовую цей трюк у своєму класі, з символами для друку без підпису між 32 та 128. :)
cpri

7

Пітон

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

так має бути exit()і ні exit. Як я розумію, exit()це команда вийти з інтерпретатора python. У цьому випадку заклик до представлення функції, а не до функції див. Вихід-обговорення . Альтернативно, breakбув би кращий вибір.


Не могли б ви пояснити, що exitнасправді є? Здається, це клас, але для чого він використовується? Крім того, можна змінити , print mщоб print(m)таким чином , що це також працює з Python 3.
Martin Thoma

1
Такі речі ... Як колись мій інший працював, тому що це був еліф .
Анонімний Пі

Дякуємо @mooseоновленій заяві про друк та спойлерному повідомленню
Віллем

6

C ++

Як щодо класичної C ++ - пастки програміста?

int main()
{
   bool keepGoing = false;

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

   return 0;
}

Я цього не розумію? Це про використання. = замість ==?
Mhmd

@ user689 точно. keepGoing = trueмалася на увазі порівняння значення keepGoing, замість цього воно присвоює значення keepGoing; крім того, все твердження keepGoing = trueоцінюється до true(що дозволяє вам писати такі речі a=b=c=d=0), що веде до нескінченного циклу.
CompuChip

3
Це все більше причин використовувати умови йоди.
Райан

@RyanEdwardDougherty Ха-ха так, що я ніколи не чув, щоб вони дзвонили. За ранковий сміх дякую.
CompuChip

@RyanEdwardDougherty: Звичайно == true(або стиль Yoda true ==) все одно зайвий, і умова повинна просто прочитати while (keepGoing).
celtschk

6

Javascript

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

Змінні, які використовуються в 1-му та 3-му рядках, відрізняються від тих, що використовуються у 2-му та 3-му рядках.
Один використовує в (U + 0061) , в той час як інші використовують а (U + 0430)


Я не бачу тут проблеми. Я його запустив, і це справно працювало. Що я пропускаю?
Андрій Пастух

це, швидше за все, буде працювати всюди, оскільки unicode, ймовірно, буде перетворений. Отримав +1, оскільки це найпомітніший, що можна отримати!
rafaelcastrocouto

Просто щоб його повністю приховати (замініть á на U + 0430) Якщо це був ваш код, удачі знайдіть проблему: var a;var points = 0;function fiftyfifty() {points++;if (Math.random() > 0.5)return true;}; á = fiftyfifty(); while (a === undefined) {á = fiftyfifty();} console.log("Points: " + points);я б відмовився, видаліть це назавжди, очистіть комп’ютер, можливо сканер вірусів, щоб бути впевненим і переписати його повністю. EDIT: Тому що var a = 0; a = 1;це не дуже реально
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 = i ++" - досить поширена помилка для початківців, і її можна напрочуд важко знайти


5

C ++

Трохи випадкового?

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

Не викликає функцію, randа натомість викликає рекурсивно Randomizer::randфункцію.


5
Додаткові дужки у зворотній заяві, юк.
Девід Конрад

1
Однак , зрештою, це буде сегментарно.
kirbyfan64sos

5

Хаскелл

Деякий код для обчислення часу заданого значення функції Акермана. За дуже низьких значень він зазвичай припиняється. На моїй машині дуже низькі значення означають щось на зразок 3 5 або менших зі складеним кодом та-O . У ghci низькі значення означають щось на зразок 3 3.

'Символ , здається, заплуталися підсвічування синтаксису, не знаю , чому. У деяких місцях вони потрібні, тому не можна їх видалити.

Правка - змінена мова.

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

Це спричиняє живіт. Обчислювальна нитка неодноразово змушує обчислення Ackermann повернутися назад, оскільки вони торкаються тієї ж телевізори.


позначення його як lang-hs замість lang-haskell, здається, працює краще (це одне з розширень у Google
Googt predtifier

5

Java - Ні циклів, ні рекурсії

Я щойно почав вивчати регулярні вирази і написав свою першу програму, щоб перевірити, чи відповідає моя рядок звичайному виразу.

На жаль, програма не дає жодного результату. Він утримує термінал. Будь ласка, допоможіть у пошуку проблеми. Я не використовував циклів, ніякої рекурсії не було. Я повністю збита з пантелику.

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

Що я зробив неправильно? Чому моя програма не закінчується? Будь ласка, допоможіть!

Ideone посилання тут .

Це дурний приклад катастрофічного зволікання . Складність становить O (2 п / 2 ). Хоча програма може не працювати нескінченно довго, вона, ймовірно, переживе як живі, так і неживі об'єкти навколо, а не навколо .


5

С

Вам знадобиться лише одна з двох циклів, але яка вам потрібна, залежить від вашого компілятора.

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

}

Просте перевищення меж, яке скидає i до значення, що не закінчується. Укладачі можуть відрізнятися від виділяти вони I вище або нижче в стеці, тому я включив перевитрата в обох напрямках.


5

C / C ++

C ++ просто дозволяє легко використовувати вбудовані змінні декларації, що використовуються тут, але це так само просто зробити цю помилку у звичайному старому 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;
}

У внутрішній петлі 'j' порівнюється, але ніколи не збільшується. ('I ++' насправді має бути 'j ++'). Це не стільки підступний трюк, а більше фактична помилка, яку я зробив у минулому;) Щось, на що слідкувати.


2
Зазвичай на це потрібно щонайменше 5 хвилин. Я ненавиджу це, коли я це робив.
ace_HongKongIndependence

4

C #

Далі наведено простий клас, що виконує арифметичну операцію (підсумовування) на великому вхідному масиві за допомогою фонової нитки. Зразок програми включений.

Однак, хоч це і досить прямо, він ніколи не припиняється. Зауважте, що немає витонченості руки (символьні лококалікеси, приховані / пропущені крапки з комою, триграфи ;-) тощо)

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

Це приклад неприємної помилки в реальному світі, яка також може з’явитися у вашому коді. Відповідно до моделі пам'яті .NET та специфікації C #, цикл, такий як той, у WaitAndGetResultніколи не може закінчитися, якщо ви не вказали змінну як мінливу, оскільки вона модифікована іншим потоком. Докладніше див. У цьому питанні StackOverflow . Помилка залежить від реалізації .NET, тому може вплинути на вас або не вплинути. Але зазвичай запущена версія випуску на процесорі x64, здається, відображає проблему. (Я спробував це з "csc.exe / o + / debug- infinite.cs" .)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.