stackoverflow | C/C++ | 如何不使用循環和判斷語句實現“打印從1到100之間的數字”


原文鏈接:http://www.keepsimply.org/2012/08/11/printing-1-to-1000-without-loop-or-conditionals/

作者:獨酌逸醉
時間:2012.08.11

聲明:翻譯僅以技術學習和交流為目的,如需轉載請務必標明原帖鏈接。
來源:http://stackoverflow.com/questions/4568645/printing-1-to-1000-without-loop-or-conditionals
水平有限,如有翻譯不當,歡迎探討、批評與指正。

 


任務:
不使用循環和條件判斷語句“打印從1到100之間的數字”。不要使用 1000 個printf 或者 cout 哦,O(∩_∩)O~。
如果是你,你將怎么用 C 或者 C++ 語言實現呢?

方法一:

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

 

譯者注:這是利用模板編譯時的遞歸來實現的,會消耗編譯時間。存在一個問題就是,不同的編譯器對模板遞歸編譯的層數有限制。這個問題,有人跟帖也說了。默認情況下 g++ 的遞歸深度是 500. 我用 Code::blocks 10.05 和 visual studio 2010 分別進行測試,CB 編譯失敗,VS2010可成功編譯和運行。把參數改成 501 之后(也就是說遞歸編譯層數是500),CB也可以成功編譯和運行。

方法二:

#include<stdio.h>

int b = 1;

int printS()
{
    printf("%d\n", b);
    b++;
    return (1001-b) && printS();
}

int main()
{
    printS();
}

 

方法三:
OpenMP 版(非命令行方式):

#include <iostream>
#include <omp.h>

int main(int argc, char** argv)
{
#pragma omp parallel num_threads(1000)
    {           
#pragma omp critical
        {
            std::cout << omp_get_thread_num() << std::endl;
        }
    }

    return 0;
}

 

(在VS2010 OpenMP 運行時庫下無法執行(64個線程的限制),在linux下可以運行,比如 Inter 編譯器)。
下面是一個命令行方式的版本:

#include <stdio.h>
#include <omp.h>

int main(int argc, char *argv[])
{
  int i = 1;
  #pragma omp parallel num_threads(1000)
  #pragma omp critical
    printf("%d ", i++);
  return 0;
}

 

譯者注:我沒有接觸過 OpenMP ,不敢妄加揣測。如果有熟悉的朋友可以幫忙測試一下,測試完把結果告訴我一下,不勝感激。

方法四:

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

int numbers[501] = {0};

int comp(const void * a, const void * b){
    numbers[0]++;
    printf("%i\n", numbers[0]);
    return 0;
}

int main()
{
    qsort(numbers+1,500,sizeof(int),comp);
    comp(NULL, NULL);
    return 0;
}

 

譯者注:原帖參數是 51,我想應該是 501。
想搞懂原因,就要去分析這里面的 qsort 是怎么執行的,
假設我們要打印1~5,numbers初始序列應該是:0,0,0,0,0,0,程序中實現的是第一個元素的遞增,每次比較的時候,打印第一個元素。也就是說其實打印到那個值,取決於調用 comp 的次數。假設qsort選取第一個元素為軸,那么比較次數應該是 4+3+2=9,加上 main 函數中,qsort執行后的一次 comp 調用,4+3+2+1=10。假如軸的選取不是第一個元素,那么比較次數應該是多少呢?讀者自己分析吧。

方法五:

printf("打印從1到100之間的數字");

 

譯者注:這個答案亮,但是誰能說它是錯的呢?!

方法六:

#include <iostream>
#include <stdexcept>
#include <cstdio>

using namespace std;

int main(int arg)
{
    try
    {

        printf("%d\n",arg);
        int j=1/(arg-1000);
        main(arg+1);
    }

    catch(...)
    {
        exit(1);
    }
}

 

譯者注:code::blocks 10.05 不能通過編譯(VS2010可以),很顯然是因為 exit 的緣故,去掉就可以了。這種方法靠除 0 錯引起異常,結束遞歸,以程序的崩潰而告終,^_^。

方法七:

#include <iostream>

static int n = 1;
class number
{
public:
    number ()
    {
        std::cout << n++ << std::endl;
    }
};

int main(int argc, char* argv[])
{
    number X[1000];
    return 0;
}

 

方法八:

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

static int x(/*@unused@*/ const char * format, ...)
{
    exit(0);
}

static void p(int v, int e) {
    static int (*a[])(const char *, ...) = { printf, x };
    (void)a[v/(e+1)]("%d\n", v);
    p(v+1, e);
}

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

 

譯者注:看似復雜,其實非常簡單。a[] 是一個函數指針數組,a[0] = printf ; a[1] = x 。當 v/(e+1) = 0 時,調用 printf 打印數字。當 v/(e+1) = 1 時,調用 x ,跳出遞歸。

方法九:

#include <iostream>

using namespace std;

template<int N>
void func()
{
    func<N-1>();
    cout << N << "\t";
}

template<>
void func<1>()
{
    cout << 1 << "\t";
}

int main()
{
    func<1000>();
    cout << endl;
    return 0;
}

 

譯者注:和方法一有點像是吧?嗯,原理一樣,只不過方法一是類模板,方法九是函數模板。

方法十:

#include <stdio.h>
#define sign(x) (( x >> 31 ) | ( (unsigned int)( -x ) >> 31 ))

void (*actions[3])(int);

void Action0(int n)
{
    printf("%d", n);
}

void Action1(int n)
{
    int index;
    printf("%d\n", n);
    index = sign(998-n)+1;
    actions[index](++n);
}

int main()
{
    actions[0] = &Action0;
    actions[1] = 0; //Not used
    actions[2] = &Action1;

    actions[2](0);

    return 0;
}

 

方法十一:

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

 

譯者注:此方法和方法八有異曲同工一秒。

方法十二:
C++:

#include <iostream>
using namespace std;

static int i = 1;
struct a
{
    a(){cout<<i++<<endl;}
    ~a(){cout<<i++<<endl;}
}obj[500];

int main()
{
    return 0;
}

 

C:

#include <stdio.h>

#define c1000(x) c5(c5(c5(c4(c2(x)))))
#define c5(x) c4(x) c1(x) //or x x x x x
#define c4(x) c2(c2(x))   //or x x x x
#define c2(x) c1(x) c1(x) //or x x
#define c1(x) x

int main(int i)
{
    c1000(printf("%d\n",i++);)
    return 0;
}

 

一個更簡單的版本:

#include <stdio.h>
#define p10(x) x x x x x x x x x x
int main(int i)
{
    p10(p10(p10(printf("%d\n",i++);)))
    return 0;
} 

 

方法十三:

#include <process.h>
int main()
{
    system("cmd.exe /c for /l %x in (1, 1, 1000) do echo %x" );
}

 

譯者注:依賴於 Windows 平台,CB不能通過編譯,VS2010可正常編譯和運行。

方法十四:

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

 

方法十五:

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

typedef void(*word)(int);

word words[1024];

void print(int i) {
    printf("%d\n", i);
    words[i+1](i+1);
}

void bye(int i) {
    exit(0);
}

int main(int argc, char *argv[])
{
    words[0] = print;
    words[1] = print;
    memcpy(&words[2], &words[0], sizeof(word) * 2); // 0-3
    memcpy(&words[4], &words[0], sizeof(word) * 4); // 0-7
    memcpy(&words[8], &words[0], sizeof(word) * 8); // 0-15
    memcpy(&words[16], &words[0], sizeof(word) * 16); // 0-31
    memcpy(&words[32], &words[0], sizeof(word) * 32); // 0-63
    memcpy(&words[64], &words[0], sizeof(word) * 64); // 0-127
    memcpy(&words[128], &words[0], sizeof(word) * 128); // 0-255
    memcpy(&words[256], &words[0], sizeof(word) * 256); // 0-511
    memcpy(&words[512], &words[0], sizeof(word) * 512); // 0-1023
    words[1001] = bye;
    words[1](1);
}

 

方法十六:

#include <stdio.h>

int printN(int n) {
  printf("%d\n", n);
  return 1;
}

int print_range(int low, int high) {
  return ((low+1==high) && (printN(low)) ||
      (print_range(low,(low+high)/2) && print_range((low+high)/2, high)));
}

int main() {
  print_range(1,1001);
}

 

方法十七:

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

 


方法十八:

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

 

譯者注:亮,你們都懂的!

方法十九:

#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))));
int main()
{
    int i = 1;
    Out1000(i);
    return 0;
}

 


譯者注:
1.上文上所有代碼測試環境為 Windows 7 下 Code::blocks 10.05 和 Visual Studio 2010 ,如果沒有備注說明的話,代表兩個環境都可通過編譯,正常運行。
2.想一探具體的朋友可以去看原帖。有一些得分較低的答案我沒有發上來;討論部分我也沒有發過來。畢竟帖子整理成文章是要有所取舍的,否則文章太過雜亂。這一點希望讀者見諒。
3.這篇帖子我翻譯的帖子中最滿意的,因為我覺得很有意思。涵蓋的C/C++知識面很廣。有些答案很BT,但是回望那些BT的答案,又是否會思索這其中巧的地方呢?也許有人會說,開發過程中,幾乎沒人會這么用,研究沒有多大意義。我個人認為,這些奇淫技巧的確在開發過程中,是很少用,但是這玩技術的過程,是一件很快樂的事情,而且我相信每個回帖人都會認為自己的答案是最好的,這是屬於我們自己這個行業的快樂。也正因為這樣,也許有人的工資不高,待遇不好,依然可以快樂的工作着。(哎,廢話又多了,^_^)
好了,本文結束,感謝閱讀!

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM