C: Циклирование без использования циклов или рекурсии

Я хочу написать функцию C, которая будет печатать от 1 до N по одной в каждой строке на stdout, где N является параметром int для функции. Функция не должна использоваться во время циклов do-while, инструкции goto, рекурсии и оператора switch. Является ли это возможным?

С блокировкой чтения, сигналов и сигналов тревоги. Я думал, что мне придется использовать sigaction и SA_RESTART, но, похоже, он работал достаточно хорошо.

Обратите внимание, что setitimer / alarm, вероятно, специфичен для unix / -like.

 #include  #include  #include  #include  #include  volatile sig_atomic_t counter; volatile sig_atomic_t stop; void alarm_handler(int signal) { printf("%d\n", counter++); if ( counter > stop ) { exit(0); } } int main(int argc, char **argv) { struct itimerval v; v.it_value.tv_sec = 0; v.it_value.tv_usec = 5000; v.it_interval.tv_sec = 0; v.it_interval.tv_usec = 5000; int pipefds[2]; char b; stop = 10; counter = 1; pipe(pipefds); signal(SIGALRM, alarm_handler); setitimer(ITIMER_REAL, &v, NULL); read(pipefds[0], &b, 1); } 
 #include  int callback(const void *a, const void *b) { static int n = 1; if (n <= N) printf("%d\n", n++); return 0; } int main(int argc, char *argv) { char *buf; /* get N value here */ buf = malloc(N); // could be less than N, but N is definitely sufficient qsort(buf, N, 1, callback); } 

Я думаю, что это не считается рекурсией.

N не фиксирован, поэтому вы не можете развязать цикл. Насколько я знаю, у C нет iteratorов.

Вы должны найти что-то, что имитирует цикл.

Или думать вне коробки:

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

 int f(int N) { if (N >= 900) f100(100); if (N >= 800) f100(100); if (N >= 700) f100(100); ... f100(n % 100); } int f100(int N) { if (N >= 90) f10(10); if (N >= 80) f10(10); if (N >= 70) f10(10); ... f(n % 10); } int f10(int N) { if (N >= 9) func(); if (N >= 8) func(); if (N >= 7) func(); ... } 

Я бы использовал longjmp()

 #include  #include  void do_loop(int n) { int val; jmp_buf env; val = 0; setjmp(env); printf("%d\n", ++val); if (val != n) longjmp(env, 0); } int main() { do_loop(7); return 0; } 

Вы можете сделать это, вложив macros.

 int i = 1; #define PRINT_1(N) if( i < N ) printf("%d\n", i++ ); #define PRINT_2(N) PRINT_1(N) PRINT_1(N) #define PRINT_3(N) PRINT_2(N) PRINT_2(N) #define PRINT_4(N) PRINT_3(N) PRINT_3(N) : : #define PRINT_32(N) PRINT_31(N) PRINT_31(N) 

Всего будет 32 макроса. Предполагая размер int как 4 байта. Теперь вызовите PRINT_32(N) из любой функции.

Изменить: добавление примера для ясности.

 void Foo( int n ) { i = 1; PRINT_32( n ); } void main() { Foo( 5 ); Foo( 55 ); Foo( 555 ); Foo( 5555 ); } 

Вы можете использовать функции setjmp и logjmp для этого, как показано в этом C FAQ

Для тех, кому интересно, почему у кого-то есть такой вопрос, это один из часто задаваемых вопросов в Индии по набору свежих сортов.

Это делает это:

 int main () { printf ("1 to N one per each line\n"); return 0; } 

Вот еще один:

 #include  #include  int main (int c, char ** v) { char b[100]; sprintf (b, "perl -e 'map {print \"$_\\n\"} (1..%s)'", v[1]); system (b); return 0; } 

сначала напишите весь возможный вывод в строку, а null завершите его, где выход должен остановиться.
это довольно грязное решение, но, учитывая ограничения, все, что я могу придумать,
за исключением использования ассемблера, вне курса.

 char a[]="1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n"/*...*/; main(n,v)char**v;{n=atoi(v[1]); #define c(x)(n>x?nx:0) a[n+c(1)+c(9)+c(99)+c(999)+c(9999)+c(99999)+c(999999)+c(9999999)/*+...*/]=0; puts(a);} 

Учитывая, что MAX_INT==2147483647 на популярных архитектурах, нам нужно только перейти на +c(999999999) . Вывод этой начальной строки может занять некоторое время, хотя …

Вы не запретили fork() .

Если вы знаете верхний предел N, вы можете попробовать что-то вроде этого;)

 void func(int N) { char *data = " 1\n 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9\n10\n11\n12\n"; if (N > 0 && N < 12) printf("%.*s", N*3, data); else printf("Not enough data. Need to reticulate some more splines\n"); } 

Шутка в сторону, я действительно не вижу, как вы можете это сделать без рекурсии или всех указаний, которые вы там упомянули. Это заставляет меня больше интересоваться решением.

Edit : Просто заметил, что я предложил такое же решение, как grombeestje 🙂

Другое дело (по linux) было бы сделать так, как показано ниже, где 7 равно N

 int main() { return system("seq 7"); } 

Это берет целое число N из командной строки и печатает от 1 до N

 #include  #include  int total; int N; int print16(int n) { printf("%d\n",n+0x01); total++; if (total >= N) exit(0); printf("%d\n",n+0x02); total++; if (total >= N) exit(0); printf("%d\n",n+0x03); total++; if (total >= N) exit(0); printf("%d\n",n+0x04); total++; if (total >= N) exit(0); printf("%d\n",n+0x05); total++; if (total >= N) exit(0); printf("%d\n",n+0x06); total++; if (total >= N) exit(0); printf("%d\n",n+0x07); total++; if (total >= N) exit(0); printf("%d\n",n+0x08); total++; if (total >= N) exit(0); printf("%d\n",n+0x09); total++; if (total >= N) exit(0); printf("%d\n",n+0x0A); total++; if (total >= N) exit(0); printf("%d\n",n+0x0B); total++; if (total >= N) exit(0); printf("%d\n",n+0x0C); total++; if (total >= N) exit(0); printf("%d\n",n+0x0D); total++; if (total >= N) exit(0); printf("%d\n",n+0x0E); total++; if (total >= N) exit(0); printf("%d\n",n+0x0F); total++; if (total >= N) exit(0); printf("%d\n",n+0x10); total++; if (total >= N) exit(0); } int print256(int n) { print16(n); print16(n+0x10); print16(n+0x20); print16(n+0x30); print16(n+0x40); print16(n+0x50); print16(n+0x60); print16(n+0x70); print16(n+0x80); print16(n+0x90); print16(n+0xA0); print16(n+0xB0); print16(n+0xC0); print16(n+0xD0); print16(n+0xE0); print16(n+0xF0); } int print4096(int n) { print256(n); print256(n+0x100); print256(n+0x200); print256(n+0x300); print256(n+0x400); print256(n+0x500); print256(n+0x600); print256(n+0x700); print256(n+0x800); print256(n+0x900); print256(n+0xA00); print256(n+0xB00); print256(n+0xC00); print256(n+0xD00); print256(n+0xE00); print256(n+0xF00); } int print65536(int n) { print4096(n); print4096(n+0x1000); print4096(n+0x2000); print4096(n+0x3000); print4096(n+0x4000); print4096(n+0x5000); print4096(n+0x6000); print4096(n+0x7000); print4096(n+0x8000); print4096(n+0x9000); print4096(n+0xA000); print4096(n+0xB000); print4096(n+0xC000); print4096(n+0xD000); print4096(n+0xE000); print4096(n+0xF000); } int print1048576(int n) { print65536(n); print65536(n+0x10000); print65536(n+0x20000); print65536(n+0x30000); print65536(n+0x40000); print65536(n+0x50000); print65536(n+0x60000); print65536(n+0x70000); print65536(n+0x80000); print65536(n+0x90000); print65536(n+0xA0000); print65536(n+0xB0000); print65536(n+0xC0000); print65536(n+0xD0000); print65536(n+0xE0000); print65536(n+0xF0000); } int print16777216(int n) { print1048576(n); print1048576(n+0x100000); print1048576(n+0x200000); print1048576(n+0x300000); print1048576(n+0x400000); print1048576(n+0x500000); print1048576(n+0x600000); print1048576(n+0x700000); print1048576(n+0x800000); print1048576(n+0x900000); print1048576(n+0xA00000); print1048576(n+0xB00000); print1048576(n+0xC00000); print1048576(n+0xD00000); print1048576(n+0xE00000); print1048576(n+0xF00000); } int print268435456(int n) { print16777216(n); print16777216(n+0x1000000); print16777216(n+0x2000000); print16777216(n+0x3000000); print16777216(n+0x4000000); print16777216(n+0x5000000); print16777216(n+0x6000000); print16777216(n+0x7000000); print16777216(n+0x8000000); print16777216(n+0x9000000); print16777216(n+0xA000000); print16777216(n+0xB000000); print16777216(n+0xC000000); print16777216(n+0xD000000); print16777216(n+0xE000000); print16777216(n+0xF000000); } int print2147483648(int n) { /* * Only goes up to n+0x70000000 since we * deal only with postive 32 bit integers */ print268435456(n); print268435456(n+0x10000000); print268435456(n+0x20000000); print268435456(n+0x30000000); print268435456(n+0x40000000); print268435456(n+0x50000000); print268435456(n+0x60000000); print268435456(n+0x70000000); } int main(int argc, char *argv[]) { int i; if (argc > 1) { N = strtol(argv[1], NULL, 0); } if (N >=1) { printf("listing 1 to %d\n",N); print2147483648(0); } else { printf("Must enter a postive integer N\n"); } } 
 int x=1; void PRINT_2(int); void PRINT_1(int n) { if(x>n) return; printf("%d\n",x++); PRINT_2(n); } void PRINT_2(int n) { if(x>n) return; printf("%d\n",x++); PRINT_1(n); } int main() { int n; scanf("%d",&n); if(n>0) PRINT_1(n); system("pause"); } 
  #include "stdio.h" #include "stdlib.h" #include "signal.h" int g_num; int iterator; void signal_print() { if(iterator>g_num-1) exit(0); printf("%d\n",++iterator); } void myprintf(int n) { g_num=n; int *p=NULL; int x= *(p); // the instruction is reexecuted after handling the signal } int main() { signal(SIGSEGV,signal_print); int n; scanf("%d",&n); myprintf(n); return 0; } 

Я очень разочарован тем, что это не работает. Для меня фраза «функция вызывается после того, как какие-либо ранее зарегистрированные функции, которые уже были вызваны в момент ее регистрации», предполагает, что после того, как они начали вызываться, можно зарегистрировать обработчики atexit. То есть, обработчик может зарегистрировать другой обработчик. В противном случае, как вообще возможно существование функции, которая была вызвана во время регистрации другой функции? Но для меня вызов atexit возвращает 0 успеха, но фактически не приводит к другому вызову. Кто-нибудь знает, почему я сделал какую-то глупую ошибку?

 #include "stdio.h" #include "stdlib.h" int count = 0; int limit = 10; void handler() { printf("%d of %d\n", ++count, limit); if (count < limit) atexit(handler); } int main(int argc, char **argv) { if (argc > 1) limit = atoi(argv[1]); atexit(handler); } 

Кстати, не recursion, потому что atexit не вызывает его параметр, он ставит их в очередь, чтобы их называть позже. Очевидно, что среда выполнения C содержит цикл для вызова обработчиков atexit, но этот цикл существует независимо от того, зарегистрируете ли вы какие-либо обработчики atexit или нет. Так что если эта программа содержит цикл, то и каждая программа C 😉

  ///  /// Print one to Hundred without using any loop/condition. ///  int count = 100; public void PrintOneToHundred() { try { int[] hey = new int[count]; Console.WriteLine(hey.Length); count--; PrintOneToHundred(); } catch { Console.WriteLine("Done Printing"); } }