Напишіть рядок у програмі, який виглядає марним [закритим]


26

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

int main(void) {
    /* The line below is actually needed. */
    2 + 2;

    return 0;
}

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


2
Для чого потрібен рядок у прикладі?
Гарі БН

3
@GariBN Це не так: "у цьому прикладі рядок насправді не потрібен, це лише приклад".
еліксинід

9
@EdCottrell Приємно знати ... Я думав, що пропустив якусь основну річ ...
Gari BN

2
Так воно і потрібно. Для прикладу. :-)
Флоріан F

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

Відповіді:


33

С

int main(int argc, char **argv) {
    switch(argc) {
        case 2:
            ;
            int allowed = 0;
        case 3:
            argc--;
            break;
        default:
            argc = 3;
    }
    return 0;
}

Не збирається, якщо ми видалимо сингл ;.

Редагувати :

Рішення нижче:

Це трапляється тому, що caseзаява є лише міткою, і, як таке, повинно супроводжуватися твердженням (яке стандарт називає "специфікатором дій, які слід виконувати", що виключає декларації). Щоб запобігти цьому, ми випередити декларацію ;, а пусте заяву . Технічні характеристики caseетикетки можна знайти тут на стор. 142 (131 документ)


4
GCC каже, що "мітка може бути лише частиною заяви, а декларація - не твердженням".
Vortico

1
Мене це просто покусало в програмі, яку я пишу для школи.
Кевін - Відновіть Моніку

Це робить реальні програми насправді такі потворні: \.
Вал каже Відновити Моніку

23

C / C ++

Просто якийсь код, написаний у стилі вступу / навчального посібника ...

Підручник № 2 : читання чисел, виконання математичних операцій над ними та друк результатів.

//////////////////////////////////////////////////
///////////////////////////////////////////////////
/////                                            //
/////           T  U  T  O  R  I  A  L           //
/////                                            //
///////////////////////////////////////////////////

#include "stdio.h"

int main()
{
    ///////////////////////////////////////////////
    // Local variables (int means integer!!)      /
    int a, b, result;

    ///////////////////////////////////////////////
    // Reading them in                            /
    scanf("%d", &a);
    scanf("%d", &b);

    ///////////////////////////////////////////////
    // Performing an operation, e.g. addition!!!  /
    result = a+b;

    ///////////////////////////////////////////////
    // Why is the next line absolutely mandatory??/
    result = 42;
    printf("The result is: %d", result);

}

Видалення рядка, result = 42;який на перший погляд виглядає і зайвим, і, вважаючи заявлену мету, насправді неправильним, насправді призведе до того, що програма не буде робити те, про що йдеться в описі.

Чому?

Триграфи знову страйкують! ?? / буде замінено препроцесором на \ , що, у свою чергу, об'єднає наступний рядок у коментар. Результат = 42; стає частиною коментаря, тому "зберігає" лінію друку. З результатом = 42; рядок видалено, рядок printf проковтне коментар. Деякі компілятори можуть попередити, або триграфи можуть бути вимкнено за замовчуванням і повинні бути включені, щоб цей приклад працював. Виділення синтаксису також може зрадити його, але є компілятори та IDE, навколо яких не залишається ніхто мудрішим.


Принаймні в gcc, ви повинні вказати, що ви хочете використовувати триграфи, додавши цей прапор (-trigraphs). Без цього gcc піднімає попередження і ігнорує триграфи.
Гарі БН

4
Хороший! Я радий, що не прокрутився занадто далеко, перш ніж з'ясувати це. Ви можете змінити блок-котирування в текст спойлера, запустивши його >!замість просто >.
писклива косточка

@squeamishossifrage: спасибі, це був мій початковий намір, я використовував >!лише не в кожному рядку. Я хоч і не відображає мене так, як я їх писав. Цікаво, що аналізатор SE це не зіпсує :)
vsz

1
Я знав, що щось підступне було вдруге другого, я побачив місцевий включити "stdio.h"замість фактичної бібліотеки включати,<stdio.h>
Braden Best

1
Щойно я побачив зайві коментарі, я вголос сказав: "Де триграф? Треба бути триграфа-- Ага, там є".
кіт

19

Пробіл

На жаль, я не можу показати свою програму тут, оскільки StackExchange знімає весь пробіл. Те саме стосується pastebin.com та pastie.org, тому я також не можу посилатися на нього.

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


41
Але, на щастя, нічого цінного не буде втрачено, тому що вся мова марна :-)
пискливе осифраж

1
@Timwi, що з вікном "необроблені дані пасти"?
Бреден Кращий

1
@Timwi Я просто тестував це тут , і я бачу, що ти маєш на увазі. Але якщо ви введете текст, який не є пробілом, він буде надсилатись, а нераціональні дані вставити будуть недоторканими. Наприклад, ви можете поставити додатковий рядок із написом "Скопіюйте неочищені дані та видаліть цей рядок"
Braden Best

8
замінити \ t на t. Замініть "" на s, замініть \ n на n
Cruncher

7
Найкраща свавілля коли-небудь: опублікуйте щось без фактичного написання коду.
Каз Вулф

9

JavaScript:

for (var a = 0, b = 4; ++a < b; a++)b+-

2 + 2; // This line is needed, or it will alert twice!
alert(a);

Причина, по якій це працює, полягає в тому, що тіло forє b+-, ні b++або b--; отже, якщо ви видалите потрібний рядок, він додасть bзначення -alert(a).


"це додасть bзначення alert(a)": Отже, чи не повинно b+-бути b+=?
Гауранг Тадон

@GaurangTandon Ні; ідея полягає в тому, що це виглядає b++або b--.
Зубна щітка

що означає b + - фактично?
Mhmd

5
@ user689 b + -2 + 2. Ось чому, якщо ви видалите рядок за допомогою 2 + 2;, він оцінює до b + -alert(a);.
Зубна щітка

8

C:

#include <stdio.h>
#include <string.h>

int main() {
    int i,sum;
    char s[4];

    /* Add all the integers < 1000 that contain no '0' or '9' */
    sum=0;
    for (i=0; i<1000; i++) {
        sprintf(s,"%d",i);
        if (strchr(s,'0')) goto skip;
        if (strchr(s,'9')) goto skip;
        sum += i;
      skip:
        i = i; /* Don't delete this line! */
    }
    printf("The answer is %d\n",sum);  /* <<< Should be 258948 */
    return 0;
}

Якщо ви видалите рядок, i = i;код не працює. Це відбувається тому...

... насправді він навіть не складеться. Відповідно до стандарту C, мітки як пропуск у наведеному вище прикладі повинні бути пов’язані із заявою. Навіть одного крапки з комою було б достатньо, але якщо ви видалите цілий рядок, у мітки немає відповідного оператора, і компіляція не вдається. Ця відповідь пояснюється трохи детальніше.


7

APL

Ось функція APL:

i_←{
  ⍺←⎕IO ⋄ ⎕IO←⍺
  ⍵⍴⍳×/⍵
}

Це робить те ж саме, що і монадики J i.:

      i_ 5 5
 1  2  3  4  5
 6  7  8  9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25

Він може приймати необов'язковий лівий аргумент, який дає зміщення:

      0 i_ 5 5
 0  1  2  3  4
 5  6  7  8  9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24

Лінія ⍺←⎕IO ⋄ ⎕IO←⍺виглядає марним ( «Присвоїти ⎕IOдо , а потім призначити на ⎕IO"), але перша частина працює тільки якщо не лівий аргумент не заданий, тому насправді це що - то зробити:

  • якщо не вказано, встановіть значення (глобальний) ⎕IO.
  • встановити (локально) ⎕IOна

7

C #

Func<int, int> fibo;
fibo = null; //Note that this can be set to *any* Func<int, int> reference.  It doesn't matter.
fibo = x => x < 1 ? 1 : fibo(x-1) + fibo(x-2);

Змінна fiboповинна бути призначена перед тим, як ви зможете використовувати її всередині лямбда, навіть якщо ви призначаєте цю лямбда fiboсобі. Якщо ви видалите (здавалося б, марне) призначення, станеться помилка компілятора ("Використання непризначеної локальної змінної" fibo "").


Це не нульовий довідковий виняток, це помилка компілятора неініціалізованої змінної. Крім того, краще перенести декларацію до власної лінії, оскільки декларація не є марною.
Кендалл Фрей

@KendallFrey Добре! Виправлено.
Бен Рейх

5

Пакет Windows:

echo hello
pause
echo world

Встановіть програму, що працює, та змініть файл на:

rem test01
pause
echo hello world

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


Я не бачу жодних коментарів.
Оріон

4
REM (зауваження) є коментарем оператор - stackoverflow.com/questions/11269338
OJW

4

Java

package stackexchange;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class Curl
{
    public void getUrl(String address)
    {
        try {
            URL url = new URL(address);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            BufferedReader input = new BufferedReader(new InputStreamReader(conn.getInputStream()));

            /* don't remove this line! */
            http://codegolf.stackexchange.com

            while( true ){
                String line = input.readLine();
                if( line==null ) break http;
                System.out.println(line);
            }

            input.close();

        } catch(IOException ex){
            // ignore.
        }
    }

    public static void main(String[] args) {
        Curl curl = new Curl();
        curl.getUrl("http://codegolf.stackexchange.com");
    }
}

Це робоча програма, яка отримує веб-сторінку з URL-адреси. Ви можете бути здивовані, що лінія

            http://codegolf.stackexchange.com

компілює без навіть попередження. Насправді програма не компілюється без неї.

Це насправді ярлик, http:з подальшим коментарем, //codegolf.... Мітка поширюється на час і використовується у break http;виписці.


1
Будь-яке пояснення, будь ласка, або я видаляю цей рядок, що б ви не сказали.
Білл Вудгер

3

Рубін

require 'prime'

# Given a regular expression, return the smallest prime containing it
# and the substring of the prime that matches it
def smallest_prime_matching_regexp(regexp)
  match = 'this assignment is necessary even though the value is never used'
  prime = Prime.find { |n| match = n.to_s[regexp] }
  return prime, match
end

[ /4/, /1+2/, /[02468]{2,}/ ].each do |regexp|
  prime, match = smallest_prime_matching_regexp(regexp)
  puts "#{regexp.inspect}:\t#{prime} (#{match})"
end

Подібна річ з’явилася на роботі нещодавно - співробітник фактично позначив мою, здавалося б, непотрібну ініціалізацію під час перегляду коду, і я дуже спокусився вкласти пояснення всередину блоку спойлерів. Тож я це зроблю тут.

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

Виведіть як:

/4/:    41 (4)
/1+2/:  127 (12)
/[02468]{2,}/:  223 (22)

Виведений перший рядок методу видалено:

невизначена локальна змінна або метод `відповідає 'для основного: Об'єкт (NameError)


1
Досить очевидно, для чого це потрібно ... і в будь-якому випадку, кращим способом написати це було б простоmatch = Prime.find { |n| n.to_s[regexp] }
Дорнорубка

1
Це не буде робити те, що я хочу ... Prime.findповертається n(наприклад, 223), і це matchповинно бути n.to_s[regexp](наприклад, "22"). Очевидно, я надумав проблему, щоб зробити це необхідним.
гістократ

Ах, вибачте, не помітив , що ви дзвонили findна Primeі не масив. У будь-якому разі, все ще досить легко помітити, для чого потрібен цей рядок ...
Doorknob

Досить справедливо. Можливо, мій колега просто був непомітним.
гістократ

Ага. Ніяких змінних оголошень, а протилежний підхід до дефолту локального / нелокального до того, що робить Python. Це стане дивно, якщо я коли-небудь вирішу вчитися Рубі.
user2357112 підтримує Моніка

3

PHP

<?php
$some_html_text= <<<EOT
<h1>This is a Header </h1>
<body> This is a body </body>
EOT;
//This is a comment    

Ось, \n//This is a commentтреба. Без нього код не запуститься.

Принаймні \n, потрібне знаряддя після EOT;належного запуску


3

JAVASCRIPT

var a = function(b) {
    return b;
}

; // This must be here

(function() {
    // more code
}());

Без крапки з комою тоді aстане те, що коли-небудь повертається значенням 2-ї функції - в цьому випадку це undefined. Оскільки функція, призначена спочатку, aбуде виконуватися відразу з другою функцією в якості аргументу b.


2

COBOL (IBM Mainframe)

   ID DIVISION. 
   PROGRAM-ID. USELESS. 
   DATA DIVISION. 
   WORKING-STORAGE SECTION. 
   01  W-WHEN-COMPILED              PIC X(8)BX(8) VALUE SPACE.
   PROCEDURE DIVISION. 
       IF W-WHEN-COMPILED EQUAL TO SPACE 
           NEXT SENTENCE 
       END-IF 
       MOVE SPACE                   TO W-WHEN-COMPILED. 
       MOVE WHEN-COMPILED           TO W-WHEN-COMPILED 

       DISPLAY W-WHEN-COMPILED " HELLO WORLD!" 
       GOBACK 
       . 

Якщо ви запускаєте вищевказану програму (будь-який IBM Mainframe COBOL починаючи з COBOL II (перший компілятор IBM до стандарту 1985 року, можливо, також і інші IBM COBOL), вихід:

22.02.14 13.11.02 ХЕЛО СВІТ!

Однак, якщо ви видалите триразово марний рядок "ПОВЕРНУТИСЯ ПРОСТІРУ В W-КОГО-СКЛАДЕНО". (поле має початкове значення простору та має інший вміст, розміщений у ньому в наступній інструкції, і воно все одно розгалужене) програма не видає вихід і насправді відмовляється (U4038) (це означає, що воно виходить з ладу) із наступним повідомленням :

 IGZ0037S The flow of control in program USELESS proceeded beyond the 
          last line of the program.  From compile unit USELESS at entry 
          point USELESS at compile unit offset +000003AC at entry offset
          +000003AC at address 119003AC. 

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

Причиною є NEXT SENTENCE. Це Secret GO TO. Компілятор шукає наступну повну зупинку / період у джерелі та генерує гілку до наступної інструкції. Від COBOL II використання повної зупинки / періодів було зменшено. Програма повинна закінчуватися повним зупинкою / періодом. У цьому випадку філія вимикається з кінця програми.

Обидві програми складають 100% чистоту (без діагностичних повідомлень, Код повернення нуля).

Така поведінка є німим "розширенням IBM" для COBOL. Стандарт 1985 р. Не дозволяє NEXT SENTENCEв межах IF/ END-IF( CONTINUEвикористовується натомість, що є неоперативним). IBM дозволила це - час від часу викликаючи жахливі Gotchas.


2
#include <stdio.h>
#include <stdlib.h>

void strcmp_or_die(char *s, char *t) {
    if(!strcmp(s, t)) {
        printf("Success!\n");
    } else {
        int *ptr = NULL;
        *ptr = 0;
    }
}

int main(void) {
    char blah = '\0'; //segfaults without this line

    char v[2] = "ok";
    strcmp_or_die(v, "ok");
}

Проста проблема переповнення рядків.


1
Будь-який гідний компілятор збирається поставити діагностику "занадто багато ініціалізаторів".
Ben Voigt

Без яких сегментів платформи blah? Тут з OpenBSD 5.5 / amd64 та системою gcc він ніколи не налаштовується, незалежно від того, є чи ні blah. Скомпільована програма виділяє 16 байт простору стеку і копіює 16-бітове значення "ok" на перші 2 байти. Неініціалізований 3-й байт пощастило "\ 0". Якщо blahвін є, він знаходиться в 16-му байті і все ще не закінчує рядок.
kernigh

2

~ - ~!

Це, мабуть, найглупіша, найочевидніша тут.

'=|hello\|:
'=~!|Useless?\|:
@'[|y|]|n|:

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

зворотна косою рисою не є символом втечі, хе-хе.


Як ви вимовляєте назву мови?

8
@professorfish~-~!
Timtech

1
@professorfish Це було б "без коментарів".
cjfaure

1

Пакет Windows

Це пакетний файл, який друкує числа від 1 до 10 з порожнім рядком після кожного:

@echo off

setlocal EnableDelayedExpansion

set NL=^


rem Previous two lines deliberately left blank for NL to work.

for /l %%a in (1,1,10) do (
    echo %%a!NL!
)

endlocal

pause

Це ефективно використовує брудний хак для зберігання нового рядка всередині змінної (використання відкладених розширень позбавляється від страшнішого вигляду рядка NL у пов'язаній відповіді). Якщо ви видалите або іншим чином зміните два абсолютно марні порожні рядки над коментарем, ну це не спрацює.


0

троф

Troff - це найчудовіша система обробки тексту. Я використовую це для своїх документів. Для його використання потрібна макросистема, а найвідоміший - msмакропакет. Складемо наступний фрагмент коду з класичним -msваріантом.

.\" -ms macro package
.\" the following line seems to be useless
\& \" print an invisible character
.ad c
.sp |300p \" absolute vertical positionning
.ps 36p
.ft B
My title.
.PP
This is a paragraph.

Третій рядок здається марним і насправді був би марним без макропакету. Оскільки за двома рядками внизу йде абсолютне вертикальне розташування, перед цим нічого здаватися безглуздим. Але без цього невидимого символу вертикальне позиціонування не матиме ефекту, хоча я не зовсім впевнений, що міг би пояснити, чому (див. Цю тему, якщо ви хочете заглянути в дискусію). Це зводить нового користувача з розуму, але тоді фокус повинен стати звичним для більш експериментованого користувача.

Щойно перевірив мою улюблену версію troff, яка не дуже відома (heirloom troff), але я впевнений, що вона все ще працює так само і з troff GNU.


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