Друк від 1 до 1000 без циклу чи умовних умов


323

Завдання : друкуйте числа від 1 до 1000, не використовуючи жодних циклів чи умовних операторів. Не пишіть заяву printf()або coutзаяву 1000 разів.

Як би ви це зробили, використовуючи C або C ++?


137
Очевидна відповідь - використовувати 500 дзвінків printfі друкувати два номери кожен раз, ні?
Джеймс Макнелл

433
printf ("числа від 1 до 1000");
jondavidjohn

7
:?це не умовне твердження (це вираз) ...
Кріс Лутц

127
Інтерв'ю ваш шанс світити. Скажіть їм "Без петель чи умовних умов? Гра дитини. Я можу це зробити без комп’ютера!" Потім витягніть ручку та блокнот. Вони можуть надати вам розгублений вигляд, але просто поясніть, що якщо ви не можете розраховувати на вбудовані мовні конструкції, ви насправді нічого не можете припустити.
JohnFx

8
Особисто я думаю, що було кілька відповідей, які мали розумні, цікаві рішення. Я також вважаю, що, хоча це може бути дуже жахливим питанням інтерв'ю, це може бути корисним для нього, якщо інтерв'ю реально шукає не стільки цілком сформоване рішення, скільки пошук того, чи розглядав респондент підходи, які вказують на знання TMP або використання конструкцій незвичними способами. Я думаю, було б погано, якби це було використано як чисте запитання "зрозумів правильно / неправильно", але якби воно було використано як вихідний пункт дискусії, я міг би бачити велику цінність.
Майкл Берр

Відповіді:


785

Складіть час рекурсії! : P

#include <iostream>
template<int N>
struct NumberGeneration{
  static void out(std::ostream& os)
  {
    NumberGeneration<N-1>::out(os);
    os << N << std::endl;
  }
};
template<>
struct NumberGeneration<1>{
  static void out(std::ostream& os)
  {
    os << 1 << std::endl;
  }
};
int main(){
   NumberGeneration<1000>::out(std::cout);
}

8
Хтось може мені пояснити, як це працює? досить вражаюче.
Гат

28
@Zack: Давайте реально, ми друкуємо 1000 рядків з програми, написаної, щоб навмисно уникати циклів. Продуктивність не проблема.
dreamlax

42
Для тих, хто цікавий, достатньо скласти це: у g ++ встановіть -ftemplate-глубина-1000. За замовчуванням максимум рекурсії шаблону - 500.
Том

6
Це все ще використовує умовні умови: відповідність шаблону прославляється, якщо.
Девід К.

10
@dreamlax: Це лише одна з тих речей, які я навчився на досвіді за ці роки: використовуйте, '\n'якщо ви дійсно не хочете промивати, використовуйте, ++iякщо вам насправді не потрібне колишнє значення i, передайте constпосилання, якщо у вас немає вагомих причин не робити ... Коли розробники перестануть думати про це (або ніколи навіть не починати), вони рано чи пізно зіткнуться з проблемою, де це має значення, тільки вони навіть не знали, що є місця, де це може мати значення.
sbi

1195

Цей фактично компілюється до збірки, яка не має жодних умов:

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

void main(int j) {
  printf("%d\n", j);
  (&main + (&exit - &main)*(j/1000))(j+1);
}


Редагувати: Додано "&", тому він буде враховувати адресу, отже, уникаючи помилок вказівника.

Ця версія вищезазначеного в стандартному С, оскільки не покладається на арифметику на функціональні покажчики:

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

void f(int j)
{
    static void (*const ft[2])(int) = { f, exit };

    printf("%d\n", j);
    ft[j/1000](j + 1);
}

int main(int argc, char *argv[])
{
    f(1);
}

17
Ну, код у цій відповіді, очевидно, не є ні C, ні C ++, тому це добре, лише якщо ми приписуємо цю вимогу. Тоді будь-яка відповідь може бути кваліфікованою, оскільки гіпотетичний компілятор може просто створити необхідну програму з будь-якого введення.
екв.-

321
@PP, це досить довго для пояснення, але в основному jце спочатку 1тому, що це насправді argc, тобто 1якщо програма викликається без аргументів. Тоді, j/1000це 0поки jне стане 1000, після чого це 1. (exit - main)це, звичайно, різниця між адресами exit()та main(). Це означає (main + (exit - main)*(j/1000)), main()поки не jстає 1000, після чого стає exit(). Кінцевим результатом є те, що main()викликається при запуску програми, потім викликає себе рекурсивно 999 разів під час збільшення j, потім викликає exit(). Whew :)
Фредерік Хаміді

7
Це одне з найдивовижніших зловживань CI, що коли-небудь траплялися. Але чи буде це працювати на всіх платформах?
Qwertie

13
@Mark: це не стандартна підпис основного, вам заборонено називати головний рекурсивно, а результат віднімання покажчиків функцій не визначений.
Яків Галка

9
Так, так, це не суто законний код C ++ з причин, які @ybungalobill дає, але я маю +1 за абсолютне божевілля і той факт, що він компілює і працює на кількох платформах. Бувають випадки, коли правильна відповідь на "Але це не стандартно!" це "Кому все одно!" :)
j_random_hacker

544
#include <stdio.h>
int i = 0;
p()    { printf("%d\n", ++i); }
a()    { p();p();p();p();p(); }
b()    { a();a();a();a();a(); }
c()    { b();b();b();b();b(); }
main() { c();c();c();c();c();c();c();c(); return 0; }

Я здивований, здається, ніхто цього не розміщував - я вважав, що це найбільш очевидний спосіб. 1000 = 5*5*5*8.


Люди опублікували це. Інші версії передають номер для друку замість глобальної, але це, по суті, те саме рішення.
Кріс Лутц

1
@Chris, вони використовують ту саму логіку, виражену в макросах або шаблонах, підірвавши розмір коду, правда? Ви також можете створити сам вихідний рядок замість тисячі printf.
Дарій Бекон

О так, я бачу, що відповідь Кіта все-таки породжує всю струну, класно. :) Я пропустив це.
Дарій Бекон

43
Ну, приємні зусилля, але досить дивно, що ви не розкладали 8 на 2 * 2 * 2 і таким чином використовуєте унікальну основну факторизацію
Девід Геффернан,

298

Схоже, не потрібно використовувати петлі

printf("1 10 11 100 101 110 111 1000\n");

1
можна стверджувати, що використання copyобману
Джон Діблінг

13
@Johannes насправді я впевнений, що printfце цикл: p
icecrime

1
@litb: Примітка Я не говорив , що «використовуючи copy це обман»
Джон Dibling

2
@John: копіювання - це обман. ти сумніваєшся в цьому? : P
Наваз

1
за шкалою від 1 до 10, який шанс я використовую двійковим?
Йорданія

270

Ось три рішення, які я знаю. З другою, можливо, можна стверджувати.

// compile time recursion
template<int N> void f1()
{ 
    f1<N-1>(); 
    cout << N << '\n'; 
}

template<> void f1<1>() 
{ 
    cout << 1 << '\n'; 
}

// short circuiting (not a conditional statement)
void f2(int N)
{ 
    N && (f2(N-1), cout << N << '\n');
}

// constructors!
struct A {
    A() {
        static int N = 1;
        cout << N++ << '\n';
    }
};

int main()
{
    f1<1000>();
    f2(1000);
    delete[] new A[1000]; // (3)
    A data[1000]; // (4) added by Martin York
}

[ Редагувати: (1) і (4) можна використовувати лише для констант часу компіляції, (2) і (3) можуть бути використані і для виразів часу виконання - в кінці редагування. ]


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

5
Питання, яке вразило мене, читаючи конструктор один: Чи стандартний мандат, щоб кожен елемент у масиві будувався послідовно? Було б важливо, чи мали конструктор побічні ефекти. Я впевнений, що кожен здоровий компілятор реалізує це як цикл 0-> 1000, але мені цікаво, чи можете ви все-таки бути поступливими та циклічними назад?
Джозеф Гарвін

6
@Joseph - Конструктор не повинен впливати на те, яким порядком ініціюються окремі об'єкти, але це хороше питання.
Кріс Лутц

12
@ Джозеф це визначено 12,6 / 3 (C ++ 03). Ініціалізація проводиться в порядку передплати.
Йоханнес Шауб - запалений

2
@Joseph: І вони також зруйновані в зворотному порядку, тому ви можете так само легко використовувати деструктор :)
j_random_hacker

263

Я не пишу заяву printf 1000 разів!

printf("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\n32\n33\n34\n35\n36\n37\n38\n39\n40\n41\n42\n43\n44\n45\n46\n47\n48\n49\n50\n51\n52\n53\n54\n55\n56\n57\n58\n59\n60\n61\n62\n63\n64\n65\n66\n67\n68\n69\n70\n71\n72\n73\n74\n75\n76\n77\n78\n79\n80\n81\n82\n83\n84\n85\n86\n87\n88\n89\n90\n91\n92\n93\n94\n95\n96\n97\n98\n99\n100\n101\n102\n103\n104\n105\n106\n107\n108\n109\n110\n111\n112\n113\n114\n115\n116\n117\n118\n119\n120\n121\n122\n123\n124\n125\n126\n127\n128\n129\n130\n131\n132\n133\n134\n135\n136\n137\n138\n139\n140\n141\n142\n143\n144\n145\n146\n147\n148\n149\n150\n151\n152\n153\n154\n155\n156\n157\n158\n159\n160\n161\n162\n163\n164\n165\n166\n167\n168\n169\n170\n171\n172\n173\n174\n175\n176\n177\n178\n179\n180\n181\n182\n183\n184\n185\n186\n187\n188\n189\n190\n191\n192\n193\n194\n195\n196\n197\n198\n199\n200\n201\n202\n203\n204\n205\n206\n207\n208\n209\n210\n211\n212\n213\n214\n215\n216\n217\n218\n219\n220\n221\n222\n223\n224\n225\n226\n227\n228\n229\n230\n231\n232\n233\n234\n235\n236\n237\n238\n239\n240\n241\n242\n243\n244\n245\n246\n247\n248\n249\n250\n251\n252\n253\n254\n255\n256\n257\n258\n259\n260\n261\n262\n263\n264\n265\n266\n267\n268\n269\n270\n271\n272\n273\n274\n275\n276\n277\n278\n279\n280\n281\n282\n283\n284\n285\n286\n287\n288\n289\n290\n291\n292\n293\n294\n295\n296\n297\n298\n299\n300\n301\n302\n303\n304\n305\n306\n307\n308\n309\n310\n311\n312\n313\n314\n315\n316\n317\n318\n319\n320\n321\n322\n323\n324\n325\n326\n327\n328\n329\n330\n331\n332\n333\n334\n335\n336\n337\n338\n339\n340\n341\n342\n343\n344\n345\n346\n347\n348\n349\n350\n351\n352\n353\n354\n355\n356\n357\n358\n359\n360\n361\n362\n363\n364\n365\n366\n367\n368\n369\n370\n371\n372\n373\n374\n375\n376\n377\n378\n379\n380\n381\n382\n383\n384\n385\n386\n387\n388\n389\n390\n391\n392\n393\n394\n395\n396\n397\n398\n399\n400\n401\n402\n403\n404\n405\n406\n407\n408\n409\n410\n411\n412\n413\n414\n415\n416\n417\n418\n419\n420\n421\n422\n423\n424\n425\n426\n427\n428\n429\n430\n431\n432\n433\n434\n435\n436\n437\n438\n439\n440\n441\n442\n443\n444\n445\n446\n447\n448\n449\n450\n451\n452\n453\n454\n455\n456\n457\n458\n459\n460\n461\n462\n463\n464\n465\n466\n467\n468\n469\n470\n471\n472\n473\n474\n475\n476\n477\n478\n479\n480\n481\n482\n483\n484\n485\n486\n487\n488\n489\n490\n491\n492\n493\n494\n495\n496\n497\n498\n499\n500\n501\n502\n503\n504\n505\n506\n507\n508\n509\n510\n511\n512\n513\n514\n515\n516\n517\n518\n519\n520\n521\n522\n523\n524\n525\n526\n527\n528\n529\n530\n531\n532\n533\n534\n535\n536\n537\n538\n539\n540\n541\n542\n543\n544\n545\n546\n547\n548\n549\n550\n551\n552\n553\n554\n555\n556\n557\n558\n559\n560\n561\n562\n563\n564\n565\n566\n567\n568\n569\n570\n571\n572\n573\n574\n575\n576\n577\n578\n579\n580\n581\n582\n583\n584\n585\n586\n587\n588\n589\n590\n591\n592\n593\n594\n595\n596\n597\n598\n599\n600\n601\n602\n603\n604\n605\n606\n607\n608\n609\n610\n611\n612\n613\n614\n615\n616\n617\n618\n619\n620\n621\n622\n623\n624\n625\n626\n627\n628\n629\n630\n631\n632\n633\n634\n635\n636\n637\n638\n639\n640\n641\n642\n643\n644\n645\n646\n647\n648\n649\n650\n651\n652\n653\n654\n655\n656\n657\n658\n659\n660\n661\n662\n663\n664\n665\n666\n667\n668\n669\n670\n671\n672\n673\n674\n675\n676\n677\n678\n679\n680\n681\n682\n683\n684\n685\n686\n687\n688\n689\n690\n691\n692\n693\n694\n695\n696\n697\n698\n699\n700\n701\n702\n703\n704\n705\n706\n707\n708\n709\n710\n711\n712\n713\n714\n715\n716\n717\n718\n719\n720\n721\n722\n723\n724\n725\n726\n727\n728\n729\n730\n731\n732\n733\n734\n735\n736\n737\n738\n739\n740\n741\n742\n743\n744\n745\n746\n747\n748\n749\n750\n751\n752\n753\n754\n755\n756\n757\n758\n759\n760\n761\n762\n763\n764\n765\n766\n767\n768\n769\n770\n771\n772\n773\n774\n775\n776\n777\n778\n779\n780\n781\n782\n783\n784\n785\n786\n787\n788\n789\n790\n791\n792\n793\n794\n795\n796\n797\n798\n799\n800\n801\n802\n803\n804\n805\n806\n807\n808\n809\n810\n811\n812\n813\n814\n815\n816\n817\n818\n819\n820\n821\n822\n823\n824\n825\n826\n827\n828\n829\n830\n831\n832\n833\n834\n835\n836\n837\n838\n839\n840\n841\n842\n843\n844\n845\n846\n847\n848\n849\n850\n851\n852\n853\n854\n855\n856\n857\n858\n859\n860\n861\n862\n863\n864\n865\n866\n867\n868\n869\n870\n871\n872\n873\n874\n875\n876\n877\n878\n879\n880\n881\n882\n883\n884\n885\n886\n887\n888\n889\n890\n891\n892\n893\n894\n895\n896\n897\n898\n899\n900\n901\n902\n903\n904\n905\n906\n907\n908\n909\n910\n911\n912\n913\n914\n915\n916\n917\n918\n919\n920\n921\n922\n923\n924\n925\n926\n927\n928\n929\n930\n931\n932\n933\n934\n935\n936\n937\n938\n939\n940\n941\n942\n943\n944\n945\n946\n947\n948\n949\n950\n951\n952\n953\n954\n955\n956\n957\n958\n959\n960\n961\n962\n963\n964\n965\n966\n967\n968\n969\n970\n971\n972\n973\n974\n975\n976\n977\n978\n979\n980\n981\n982\n983\n984\n985\n986\n987\n988\n989\n990\n991\n992\n993\n994\n995\n996\n997\n998\n999\n1000\n");

Ласкаво просимо ;)


223
Я сподіваюся, що ви написали програму для створення цього рядка.
Мартін Йорк

32
open ("1000.c", 'w "). write (' printf ("% s "); '% (" \ n ".join ([str (x) for x in xrange (1,1000)]) ))
Тайлер Евз

53
Я сподіваюся, що програма, яку ви написали для створення цього рядка, не містила циклу!
Jeeyoung Kim

20
Макрос Vim зробив би цю роботу швидко.
StackedCrooked

2
Трохи Perl породжує це у вигадливій формі:$r='printf("'; for (1..1000) { $r.="$_\\n" } $r.='");'; print $r;
sidyll

213
printf("%d\n", 2);
printf("%d\n", 3);

Він друкує не всі цифри, але робить "Друк чисел від 1 до 1000". Неоднозначне запитання про перемогу! :)


77
мій улюблений після 'printf (' числа від 1 до 1000 ')' - на дурні запитання потрібні нерозумні відповіді.
SEngstrom

Це круто. +1 за те, щоб скористатися двозначністю питання. ха-ха
Наваз

2
Відредаговано; жодним чином, формою чи формою не робив цей код print "Print numbers from 1 to 1000."- неоднозначне запитання про перемогу, неточні описи смоктати :)
1111

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

172

Спустіть фатальну помилку! Ось файл countup.c:

#include <stdio.h>
#define MAX 1000
int boom;
int foo(n) {
    boom = 1 / (MAX-n+1);
    printf("%d\n", n);
    foo(n+1);
}
int main() {
    foo(1);
}

Скомпілюйте та виконайте у запиті оболонки:

$ ./countup
1
2
3
...
996
997
998
999
1000
Floating point exception
$

Це дійсно друкує числа від 1 до 1000, без певних циклів і умов.


43
вам слід зателефонувати fflush (stdout); після кожного printf () ... При збої програми не гарантується, що вихідний буфер буде надрукований на екрані.
zakk

10
@zakk: Це не суворо необхідно - за замовчуванням stdout буферизується, тому \nволі буде достатньо, щоб вимити вихід.
psmears

24
stdout - це буферний рядок, якщо його можна визначити інтерактивним пристроєм , інакше він повністю буферний. Якщо професор перенаправить stdout до файлу для автоматизованої перевірки, ви не зможете :-)
paxdiablo

небезпека
потоку потоку

166

Використання системних команд:

system("/usr/bin/seq 1000");

15
Високий шанс /usr/bin/seqвикористовує цикл внутрішньо. :)

@jokester: ти маєш на увазі, тому що Solaris / BSD не має seqутиліти (у налаштуваннях за замовчуванням)? <grin />
sehe

Я ненавиджу це говорити (ну, ні, я не знаю), але у вашому рішенні є помилка. Він не виводить правильний набір чисел. :) Ось виправлення: system("/bin/echo {1..1000}"); Якби ви спочатку написали одиничний тест ...
Дон Бренсон

1
Якийсь яскравий чувак вирішив змінити мою відповідь, тож це не моя помилка.
moinudin

100

Неперевірений, але має бути стандарт ванілі C:

void yesprint(int i);
void noprint(int i);

typedef void(*fnPtr)(int);
fnPtr dispatch[] = { noprint, yesprint };

void yesprint(int i) {
    printf("%d\n", i);
    dispatch[i < 1000](i + 1);
}

void noprint(int i) { /* do nothing. */ }

int main() {
    yesprint(1);
}

29
@Prasoon: Це стосунки.
Яків Галка

28
вимога "немає умов" (якщо, перемикач тощо). не "немає умов"
jon_darkstar

32
<не є умовою. Це реляційний оператор. if/ else- умовна заява. ?:є умовним оператором. <це просто оператор, який повертає булеве значення. Це, мабуть, одна машинна інструкція без стрибків чи нічого.
Кріс Лутц

12
@ Кріс Lutz: На x86, це 3 інструкції: cmpl, setleі movzbl. x86-64 - це плюс плюс cltq. PowerPC - це 2 інструкції: cmpwiі crnot.
Адам Розенфілд

4
1 - i / 1000. Ніяких порівнянь!
Тайська

96

Трохи нудно в порівнянні з іншими тут, але, напевно, те, що вони шукають.

#include <stdio.h>

int f(int val) {
    --val && f(val);
    return printf( "%d\n", val+1);
}

void main(void) {
    f(1000);
}

Зробили це коротше. встановити i = 1 поза головним, а потім всередині основного: printf ("% d \ n", 11 - i) && --i && main (i);
jftuga

3
@Jens Schauder: Користуючись лінивою &&оцінкою в першому рядку f().
Rafał Dowgird

10
Це не нудно, це просто. Якщо ви можете зробити те ж саме за допомогою короткої функції, як ви можете, з величезним безладом магічних шаблонів, тоді вам слід зробити це за допомогою функції :)
amertune

21
&& - умовний. Математичний AND оцінить обидві сторони (як, наприклад, Java & та Ada). && оцінить 2-го оператора, лише якщо (ось він) перший істинний. Або інший приклад: в Ada це оператор короткого замикання називається "АБО ТОМ" - використовуючи THEN для позначення умовного аспекту. Вибачте, ви могли б так само добре використати? : оператор.
Мартін

Не потрібно вибачатися. && - оператор порівняння. Потрійний оператор - умовний.
Аарон

71

Завдання ніколи не вказувало, що програма повинна припинятися після 1000.

void f(int n){
   printf("%d\n",n);
   f(n+1);
}

int main(){
   f(1);
}

( Можна скоротити до цього, якщо ви запустите ./a.out без зайвих параметрів )

void main(int n) {
   printf("%d\n", n);
   main(n+1);
}

Це не зупиняється на 1000, хоча. Це просто продовжує.
Ремі Лебо

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

@eq Знову ж таки, це збирається і працює чудово…
Марк Макдональд

72
Як задумка: ми можемо навіть ухилитися від явної математики. Якщо ми будемо використовувати rand(), ми надрукуємо всі їх числа від 1 до 1000. Зрештою =: P

5
@pooh: Не обов'язково, оскільки rand () має шанс повторитись після певної послідовності, і ця послідовність може не входити до набору рішень для цієї проблеми
dchhetri

71

Легкий як пиріг! : P

#include <iostream>

static int current = 1;

struct print
{
    print() { std::cout << current++ << std::endl; }
};

int main()
{
    print numbers [1000];
}

ви можете зробити "static int current = 0", інакше буде надруковано від 2 до 1001.
Shinnok

я змінив ++ поточний на поточний ++
Zelix

65
#include <stdio.h>
#define Out(i)       printf("%d\n", i++);
#define REP(N)       N N N N N N N N N N
#define Out1000(i)   REP(REP(REP(Out(i))));
void main()
{
 int i = 1;
 Out1000(i);
}

3
Умммм. Макроси Що на вечерю.
EvilTeach

42

Ми можемо запустити 1000 ниток, кожна з яких друкує одне з номерів. Встановіть OpenMPI , компілюйте за допомогою mpicxx -o 1000 1000.cppта запустіть mpirun -np 1000 ./1000. Можливо, вам буде потрібно збільшити ліміт дескриптора за допомогоюlimit або ulimit. Зауважте, що це буде досить повільно, якщо у вас немає навантажень ядер!

#include <cstdio>
#include <mpi.h>
using namespace std;

int main(int argc, char **argv) {
  MPI::Init(argc, argv);
  cout << MPI::COMM_WORLD.Get_rank() + 1 << endl;
  MPI::Finalize();
}

Звичайно, номери не обов'язково друкуються в порядку, але питання не вимагає їх замовлення.


1
Неявний цикл у бібліотеці? Але +1 все одно для нового підходу.
Кріс Луц

11
@Chris У більшості рішень десь є прихований цикл?
moinudin

Я гадаю, якщо ви скористаєтеся підходом "циклів у компіляторі". Оскільки (за межами можливого циклу над аргументами в MPI::Init()) я не можу уявити жодних циклів у фактичній бінарній частині вашої програми 1000.cpp, я дав вам +1, навіть якщо під час його виконання, безумовно, виконується цикл.
Кріс Лутц

40

З простим C:

#include<stdio.h>

/* prints number  i */ 
void print1(int i) {
    printf("%d\n",i);
}

/* prints 10 numbers starting from i */ 
void print10(int i) {
    print1(i);
    print1(i+1);
    print1(i+2);
    print1(i+3);
    print1(i+4);
    print1(i+5);
    print1(i+6);
    print1(i+7);
    print1(i+8);
    print1(i+9);
}

/* prints 100 numbers starting from i */ 
void print100(int i) {
    print10(i);
    print10(i+10);
    print10(i+20);
    print10(i+30);
    print10(i+40);
    print10(i+50);
    print10(i+60);
    print10(i+70);
    print10(i+80);
    print10(i+90);
}

/* prints 1000 numbers starting from i */ 
void print1000(int i) {
    print100(i);
    print100(i+100);
    print100(i+200);
    print100(i+300);
    print100(i+400);
    print100(i+500);
    print100(i+600);
    print100(i+700);
    print100(i+800);
    print100(i+900);
}


int main() {
        print1000(1);
        return 0;
}

Звичайно, ви можете реалізувати ту саму ідею для інших баз (2: print2 print4 print8 ...), але число 1000 тут запропонувало базу 10. Ви також можете трохи зменшити кількість рядків, додавши проміжні функції: print2() print10() print20() print100() print200() print1000()та інші еквівалентні альтернативи.


Чому число 1000 пропонує підставу 10? У будь-якій позиційній нотації з базою B1000 є цілком дійсним числом і завжди дорівнює B^3.
Філіп

Я просто мав на увазі, що, враховуючи те, як число представлено в базі 10, факторизація "10x10x10" запропонувала себе, але можливі й інші варіанти. Напевно, я мав би сказати "факторизація" замість "бази"
leonbloy

34

Просто використовуйте std :: copy () зі спеціальним ітератором.

#include <algorithm>
#include <iostream>
#include <iterator>

struct number_iterator
{
    typedef std::input_iterator_tag iterator_category;
    typedef int                     value_type;
    typedef std::size_t             difference_type;
    typedef int*                    pointer;
    typedef int&                    reference;

    number_iterator(int v): value(v)                {}
    bool operator != (number_iterator const& rhs)   { return value != rhs.value;}
    number_iterator operator++()                    { ++value; return *this;}
    int operator*()                                 { return value; }
    int value;
};



int main()
{
    std::copy(number_iterator(1), 
              number_iterator(1001), 
              std::ostream_iterator<int>(std::cout, " "));
}

Я думаю, що ваш код починається з 0. Також згоден з Крісом, питання, яке я бачив років тому, було зазначено як "без бібліотек, крім IO". ще +1 :)
Яків Галка

3
@Chris Lutz: Реалізація копії не визначена. Я навіть можу використовувати шаблон шаблону, як зазначено вище (ви просто не знаєте). Тому ви не можете сказати, що він використовує цикл, тому що ми не знаємо.
Мартін Йорк

7
Насправді, мій вибір ниткою не був би неявним циклом std::copyнастільки, скільки неявний умовний у operator !=(). Незважаючи на те, що я сприймаю розумну обробку діапазону, і розумні підходи - це те, що я шукаю у відповідь на подібні питання.
Майкл Берр

Конкретність реалізації не визначена
selvaiyamperumal

@selvaiyyamperumal: Не впевнений, про що ти саме говориш. Але якщо ви говорите про поведінку, то стандарт не погоджується з вами. "Поведінка, визначена реалізацією" означає, що вона чітко визначена, але повинна бути чітко задокументована реалізацією. "Не визначена поведінка" означає, що все може статися.
Мартін Йорк

33

Використання функції вказівника (ab). Ніякої препроцесорної магії для збільшення випуску. ANSI C.

#include <stdio.h>

int i=1;

void x10( void (*f)() ){
    f(); f(); f(); f(); f();
    f(); f(); f(); f(); f();
}

void I(){printf("%i ", i++);}
void D(){ x10( I ); }
void C(){ x10( D ); }
void M(){ x10( C ); }

int main(){
    M();
}

3
Це те, про що я думав. Попередня людина сказала, що 5 * 5 * 5 * 8 = 1000. Я подумав, що це смішно, йому не вистачало очевидних 10 ^ 3. Приємне рішення!
Еван Моран

32
#include <iostream>
#include <iterator>
using namespace std;

int num() { static int i = 1; return i++; }
int main() { generate_n(ostream_iterator<int>(cout, "\n"), 1000, num); }

30

Некрасива відповідь C (розкручується лише для одного кадру стека на потужність 10):

#define f5(i) f(i);f(i+j);f(i+j*2);f(i+j*3);f(i+j*4)
void f10(void(*f)(int), int i, int j){f5(i);f5(i+j*5);}
void p1(int i){printf("%d,",i);}
#define px(x) void p##x##0(int i){f10(p##x, i, x);}
px(1); px(10); px(100);

void main()
{
  p1000(1);
}

3
все гаразд, але чому "void main ()"? шкідливі звички рідко йдуть? : P
Наваз

30
@Nawaz: Оскільки це таємно додаток GUI для Windows, тому це не має значення. Я назвав це лише "головним", бо думав про омарів і маю жахливий правопис.
Мартін

29

Переповнення стека:

#include <stdio.h>

static void print_line(int i)
{   
 printf("%d\n", i); 
 print_line(i+1);
}   

int main(int argc, char* argv[])
{   
 //get up near the stack limit
 char tmp[ 8388608 - 32 * 1000 - 196 * 32 ];
 print_line(1);
} 

Це для стека 8МБ. Здається, що виклик кожної функції займає приблизно 32 байти (звідси 32 * 1000). Але тоді, коли я запустив його, я дістався лише до 804 (отже, 196 * 32; можливо, час виконання C має інші частини в стеку, які ви також повинні вирахувати).


25

Весело з функціональними вказівниками (не потрібно нічого із цього новомодного TMP):

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


#define MSB(typ) ((sizeof(typ) * CHAR_BIT) - 1)

void done(int x, int y);
void display(int x, int y);

void (*funcs[])(int,int)  = {
    done,
    display
};

void done(int x, int y)
{
    exit(0);
}

void display(int x, int limit)
{
    printf( "%d\n", x);
    funcs[(((unsigned int)(x-limit)) >> MSB(int)) & 1](x+1, limit);
}


int main()
{
    display(1, 1000);
    return 0;
}

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

funcs[!!(limit-1)](x+1, limit-1);

мені подобається, як ти це отримав зі зміщенням біт. але з вашим спрощенням задумавшись, що робить подвійний удар? його побитові або логічні? я загубився, і Google змусив мене гуляти по колахfuncs[!!(limit-1)](x+1, limit-1);
jon_darkstar

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

@Chris: Я повністю погоджуюся - але я не розглядав питання використання операторів логічного відношення до моменту публікації, і я вважав, що однорядний патч буде більш доцільним. Крім того, вона трохи краще вписується у все затуманене відчуття проблеми.
Майкл Берр

24

Я думаю, що ця відповідь буде дуже простою і зрозумілою.

int print1000(int num=1)
{
    printf("%d\n", num);

    // it will check first the num is less than 1000. 
    // If yes then call recursive function to print
    return num<1000 && print1000(++num); 
}

int main()
{
    print1000();
    return 0;        
}

3
У вашій відповіді використовуються умовні висловлювання, які заборонено відповідно до питання.
stevelove

4
умовні висловлювання, якщо інше і т. д. Я просто використав логічну операцію !! Надію це зрозуміло!
Паппу

2
Навіть у своїх коментарях ви написали "Якщо так, то викликайте рекурсивну функцію для друку". Умовне, написане невиразним способом, все ще є умовним. За замовчуванням число також є умовним.
Геррі

23

Я пропустив все задоволення, всі хороші відповіді на C ++ вже розміщені!

Це найдивніша річ, яку я міг придумати, але я не ставлю на те, що це законний C99: p

#include <stdio.h>

int i = 1;
int main(int argc, char *argv[printf("%d\n", i++)])
{
  return (i <= 1000) && main(argc, argv);
}

Ще один, з невеликим обманом:

#include <stdio.h>
#include <boost/preprocessor.hpp>

#define ECHO_COUNT(z, n, unused) n+1
#define FORMAT_STRING(z, n, unused) "%d\n"

int main()
{
    printf(BOOST_PP_REPEAT(1000, FORMAT_STRING, ~), BOOST_PP_ENUM(LOOP_CNT, ECHO_COUNT, ~));
}

Остання ідея, така ж накрутка:

#include <boost/preprocessor.hpp>
#include <iostream>

int main()
{
#define ECHO_COUNT(z, n, unused) BOOST_PP_STRINGIZE(BOOST_PP_INC(n))"\n"
    std::cout << BOOST_PP_REPEAT(1000, ECHO_COUNT, ~) << std::endl;
}

mainЯк я пам’ятаю, виклик призводить до невизначеної поведінки.
Яків Галка

4
Це абсолютно законно C. @ybungalobill: Ви повинні думати про C ++, де виклик main () спеціально заборонено.
Майкл Фукаракіс

@Michael: Можливо, я не дуже знайомий із С.
Яків Галка

Я думаю, що використання Boost означає C ++. Незалежно від цього, кудо для рішення Boost.PP.
мені22

6
Логічні оператори &&і ||, швидше за все , підпадають під «умовними» , оскільки вони коротке замикання (як би ?:).
чудовий

22

Легкий як пиріг:

int main(int argc, char* argv[])
{
    printf(argv[0]);
}

спосіб виконання:

printer.exe "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;26;27;28;29;30;31;32;33;34;35;36;37;38;39;40;41;42;43;44;45;46;47;48;49;50;51;52;53;54;55;56;57;58;59;60;61;62;63;64;65;66;67;68;69;70;71;72;73;74;75;76;77;78;79;80;81;82;83;84;85;86;87;88;89;90;91;92;93;94;95;96;97;98;99;100;101;102;103;104;105;106;107;108;109;110;111;112;113;114;115;116;117;118;119;120;121;122;123;124;125;126;127;128;129;130;131;132;133;134;135;136;137;138;139;140;141;142;143;144;145;146;147;148;149;150;151;152;153;154;155;156;157;158;159;160;161;162;163;164;165;166;167;168;169;170;171;172;173;174;175;176;177;178;179;180;181;182;183;184;185;186;187;188;189;190;191;192;193;194;195;196;197;198;199;200;201;202;203;204;205;206;207;208;209;210;211;212;213;214;215;216;217;218;219;220;221;222;223;224;225;226;227;228;229;230;231;232;233;234;235;236;237;238;239;240;241;242;243;244;245;246;247;248;249;250;251;252;253;254;255;256;257;258;259;260;261;262;263;264;265;266;267;268;269;270;271;272;273;274;275;276;277;278;279;280;281;282;283;284;285;286;287;288;289;290;291;292;293;294;295;296;297;298;299;300;301;302;303;304;305;306;307;308;309;310;311;312;313;314;315;316;317;318;319;320;321;322;323;324;325;326;327;328;329;330;331;332;333;334;335;336;337;338;339;340;341;342;343;344;345;346;347;348;349;350;351;352;353;354;355;356;357;358;359;360;361;362;363;364;365;366;367;368;369;370;371;372;373;374;375;376;377;378;379;380;381;382;383;384;385;386;387;388;389;390;391;392;393;394;395;396;397;398;399;400;401;402;403;404;405;406;407;408;409;410;411;412;413;414;415;416;417;418;419;420;421;422;423;424;425;426;427;428;429;430;431;432;433;434;435;436;437;438;439;440;441;442;443;444;445;446;447;448;449;450;451;452;453;454;455;456;457;458;459;460;461;462;463;464;465;466;467;468;469;470;471;472;473;474;475;476;477;478;479;480;481;482;483;484;485;486;487;488;489;490;491;492;493;494;495;496;497;498;499;500;501;502;503;504;505;506;507;508;509;510;511;512;513;514;515;516;517;518;519;520;521;522;523;524;525;526;527;528;529;530;531;532;533;534;535;536;537;538;539;540;541;542;543;544;545;546;547;548;549;550;551;552;553;554;555;556;557;558;559;560;561;562;563;564;565;566;567;568;569;570;571;572;573;574;575;576;577;578;579;580;581;582;583;584;585;586;587;588;589;590;591;592;593;594;595;596;597;598;599;600;601;602;603;604;605;606;607;608;609;610;611;612;613;614;615;616;617;618;619;620;621;622;623;624;625;626;627;628;629;630;631;632;633;634;635;636;637;638;639;640;641;642;643;644;645;646;647;648;649;650;651;652;653;654;655;656;657;658;659;660;661;662;663;664;665;666;667;668;669;670;671;672;673;674;675;676;677;678;679;680;681;682;683;684;685;686;687;688;689;690;691;692;693;694;695;696;697;698;699;700;701;702;703;704;705;706;707;708;709;710;711;712;713;714;715;716;717;718;719;720;721;722;723;724;725;726;727;728;729;730;731;732;733;734;735;736;737;738;739;740;741;742;743;744;745;746;747;748;749;750;751;752;753;754;755;756;757;758;759;760;761;762;763;764;765;766;767;768;769;770;771;772;773;774;775;776;777;778;779;780;781;782;783;784;785;786;787;788;789;790;791;792;793;794;795;796;797;798;799;800;801;802;803;804;805;806;807;808;809;810;811;812;813;814;815;816;817;818;819;820;821;822;823;824;825;826;827;828;829;830;831;832;833;834;835;836;837;838;839;840;841;842;843;844;845;846;847;848;849;850;851;852;853;854;855;856;857;858;859;860;861;862;863;864;865;866;867;868;869;870;871;872;873;874;875;876;877;878;879;880;881;882;883;884;885;886;887;888;889;890;891;892;893;894;895;896;897;898;899;900;901;902;903;904;905;906;907;908;909;910;911;912;913;914;915;916;917;918;919;920;921;922;923;924;925;926;927;928;929;930;931;932;933;934;935;936;937;938;939;940;941;942;943;944;945;946;947;948;949;950;951;952;953;954;955;956;957;958;959;960;961;962;963;964;965;966;967;968;969;970;971;972;973;974;975;976;977;978;979;980;981;982;983;984;985;986;987;988;989;990;991;992;993;994;995;996;997;998;999;1000"

У специфікації не сказано, що послідовність повинна бути створена всередині коду :)


18
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;

class Printer
{
public:
 Printer() { cout << ++i_ << "\n"; }
private:
 static unsigned i_;
};

unsigned Printer::i_ = 0;

int main()
{
 Printer p[1000];
}

15
#include <stdio.h>

void nothing(int);
void next(int);
void (*dispatch[2])(int) = {next, nothing};

void nothing(int x) { }
void next(int x)
{
    printf("%i\n", x);
    dispatch[x/1000](x+1);
}

int main()
{
    next(1);
    return 0;
}

15

Більше зловживання препроцесорами:

#include <stdio.h>

#define A1(x,y) #x #y "0\n" #x #y "1\n" #x #y "2\n" #x #y "3\n" #x #y "4\n" #x #y "5\n" #x #y "6\n" #x #y "7\n" #x #y "8\n" #x #y "9\n"
#define A2(x) A1(x,1) A1(x,2) A1(x,3) A1(x,4) A1(x,5) A1(x,6) A1(x,7) A1(x,8) A1(x,9)
#define A3(x) A1(x,0) A2(x)
#define A4 A3(1) A3(2) A3(3) A3(4) A3(5) A3(6) A3(7) A3(8) A3(9)
#define A5 "1\n2\n3\n4\n5\n6\n7\n8\n9\n" A2() A4 "1000\n"

int main(int argc, char *argv[]) {
    printf(A5);
    return 0;
}

Я відчуваю себе так брудно; Я думаю, зараз піду душ.


2
Чи можете ви зателефонувати A2()без такого аргументу?
Кріс Лутц

Мені самому було цікаво про це. Він добре працює з GCC, але я не знаю, чи це чітко визначена поведінка.
keithmo

Добре визначений у C99, не пам'ятайте, що сказав C89, створює проблеми хоча б з деякими версіями MSVC, якщо пам'ять служить.
zwol

15

Якщо рішення POSIX прийняті:

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/time.h>
#include <pthread.h>

static void die(int sig) {
    exit(0);
}

static void wakeup(int sig) {
    static int counter = 1;
    struct itimerval timer;
    float i = 1000 / (1000 - counter);

    printf("%d\n", counter++);

    timer.it_interval.tv_sec = 0;
    timer.it_interval.tv_usec = 0;
    timer.it_value.tv_sec = 0;
    timer.it_value.tv_usec = i; /* Avoid code elimination */
    setitimer(ITIMER_REAL, &timer, 0);
}

int main() {
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    signal(SIGFPE, die);
    signal(SIGALRM, wakeup);
    wakeup(0);
    pthread_mutex_lock(&mutex);
    pthread_mutex_lock(&mutex); /* Deadlock, YAY! */
    return 0;
}

13

Оскільки про помилки немає обмежень ..

int i=1; int main() { int j=i/(i-1001); printf("%d\n", i++); main(); }

Або ще краще (?),

#include <stdlib.h>
#include <signal.h>

int i=1;
int foo() { int j=i/(i-1001); printf("%d\n", i++); foo(); }

int main()
{
        signal(SIGFPE, exit);
        foo();
}

2
Тоді вам слід уникати оптимізацій компілятора, щоб уникнути невикористаного j.
банді

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