Печать от 1 до 1000 без петель или условных обозначений


323

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

Как бы вы сделали это, используя C или C ++?


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

433
printf («числа от 1 до 1000»);
Jondavidjohn

7
:?не условное утверждение (это выражение) ...
Крис Лутц

127
Интервью ваш шанс проявить себя. Скажите им: «Без петель или условностей? Детская игра. Я могу сделать это без компьютера!» Затем вытащите ручку и блокнот. Они могут дать вам запутанный взгляд, но просто объясните, что если вы не можете рассчитывать на встроенные языковые конструкции, вы действительно ничего не можете предположить.
JohnFx

8
Лично я думаю, что было несколько ответов, которые имели умные, интересные решения. Я также думаю, что, хотя это может быть просто ужасный вопрос для интервью, в нем может быть хорошая ценность, если интервьюер действительно ищет не столько полностью правильное решение, сколько поиск собеседника, который рассматривает подходы, которые указывают на знание TMP или использование конструкций необычными способами. Я думаю, было бы плохо, если бы этот вопрос использовался как чистый вопрос «получил-правильно-неправильно», но если бы он использовался в качестве отправной точки обсуждения, я мог бы увидеть большую ценность.
Майкл Берр

Ответы:


785

Время компиляции рекурсии! :П

#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
Может кто-нибудь объяснить мне, как это работает? довольно внушительный.
Gath

28
@Zack: Давайте получим реальное, мы печатаем 1000 строк из программы, написанной, чтобы сознательно избегать циклов. Производительность не проблема.
Dreamlax

42
Для тех, кому достаточно любопытно скомпилировать это: в g ++ установите -ftemplate-deep-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);
}


Редактировать: добавлено '&', чтобы оно учитывало адрес и, следовательно, избегало ошибок указателя.

Эта версия выше в стандартном C, так как она не полагается на арифметику указателей функций:

#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 ++, так что это нормально, только если мы отбросим требование. Тогда любой ответ может быть квалифицирован, потому что гипотетический компилятор может просто создать требуемую программу из любого ввода.
Eq-

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(). Уфф :)
Фредерик Хамиди

7
Это одно из самых удивительных нарушений CI, которые когда-либо видели. Но будет ли это работать на всех платформах?
Qwertie

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

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
@ Крис, они используют ту же логику, выраженную в макросах или шаблонах, увеличивая размер кода, верно? Вы могли бы также сгенерировать саму строку вывода вместо тысячи printfs.
Дариус Бэкон

О да, я вижу, ответ Кейта действительно генерирует всю строку, круто. :) Я пропустил это.
Дариус Бэкон

43
Что ж, приятное усилие, но довольно странно, что вы не разложили 8 на 2 * 2 * 2 и, таким образом, использовали уникальную первичную факторизацию
Дэвид Хеффернан,

298

Похоже, не нужно использовать петли

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

1
можно утверждать, что использование copy- это обман
Джон Диблинг

13
@ Йоханнес на самом деле я уверен, что printfесть петля: p
icecrime

1
@litb: заметьте, я не говорил, что «использование copy - это обман»
Джон Диблинг

2
@ Джон: копирование это обман. ты сомневаешься в этом? : 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) для x в xrange (1,1000)]) ))
Тайлер Ивз

53
Я надеюсь, что программа, которую вы написали для генерации этой строки, не содержала цикл!
Jeeyoung Ким

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."- неоднозначный вопрос о победе, неточные описания - отстой :)
сехе

Вау, в последнее время в ответах на этот вопрос было немного вандализма. Что-то подсказывает мне, что мы должны обновить этот замок до исторического.
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 () ... При сбое программы не гарантируется, что выходной буфер будет напечатан на экране.
Закк

10
@zakk: Это не является строго обязательным - по умолчанию stdout буферизуется строкой, поэтому его \nбудет достаточно для сброса вывода.
psmears

24
stdout - это буферизованная строка, если она может быть определена как интерактивное устройство , в противном случае она полностью буферизована. Если профессор перенаправит стандартный вывод в файл для автоматической проверки, у вас ничего не получится :-)
paxdiablo

опасность переполнения стека (например, во встроенной среде)
Эрнан Эче

166

Использование системных команд:

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

15
Высокий шанс /usr/bin/seqиспользует петлю внутри. :)

@jokester: вы имеете в виду, потому что Solaris / BSD не имеет seqутилиты (в настройках по умолчанию)? <ухмылка />
sehe

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

1
Какой-то яркий чувак решил изменить мой ответ, так что это не моя ошибка.
Мойнудин

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. х86-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().
Рафал Доугирд

10
Это не скучно, это просто. Если вы можете сделать то же самое с короткой функцией, как вы можете с огромным беспорядком магии шаблонов, то вы должны сделать это с помощью функции :)
amertune

21
&& является условным. Математическое И будет оценивать обе стороны (как Java и Ада «И» делает). && оценит 2-й оператор только в том случае, если (здесь он есть) первый равен true. Или другой пример: в Аде оператор коротких замыканий называется «ИЛИ ТОГДА» - используя 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-

@eq Опять же, это компилируется и работает очень хорошо ...
Марк Макдональд

72
Как запоздалая мысль: мы можем даже избежать очевидной математики. Если мы используем rand(), мы будем печатать все их числа от 1 до 1000. В конце концов =: P

5
@pooh: Не обязательно, так как rand () имеет шанс повторения после определенной последовательности, и эта последовательность может не совпадать с решением этой проблемы
dchhetri

71

Проще простого! :П

#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.
Шиннок

я изменил ++ текущий на текущий ++
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
Ummmm. Макросы. Это на ужин.
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 У большинства решений где-нибудь есть скрытый цикл?
Мойнудин

Я полагаю, если вы используете подход «циклы в компиляторе». Поскольку (вне возможного цикла по аргументам в 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 !=(). Несмотря на это, это умный подход к обработке диапазона, и именно умные подходы - это то, что я ищу в ответах на подобные вопросы.
Майкл Берр

конкретная реализация не определена
selvaiyyamperumal

@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: потому что это тайно приложение с графическим интерфейсом 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
Даже в ваших комментариях вы написали «Если да, то вызовите рекурсивную функцию для печати». Условное, написанное неочевидным способом, все еще является условным. Значение по умолчанию num также является условным.
Джерри

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: Может быть, я не очень знаком с C.
Яков Галка

Я думаю, что использование Boost подразумевает C ++. В любом случае, спасибо за решение Boost.PP.
me22

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, но я не знаю, хорошо ли это определено.
Кейтмо

Четко определенные в 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.
Bandi

2
Ему нужно только добавить volatileв декларациюj
Патрик Шлютер
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.