zoukankan      html  css  js  c++  java
  • 混乱是怎样炼成的——《C解毒》试读

    4.有一个已排好序的数组,要求输入一个数后,按原来排序的规律将它插入数组中。

    #include <stdio.h>
    int main( )
    { int a[11]={1,4,6,9,13,15,19,18,40,100};
      int temp1,temp2,number,end,i,j;
      printf("array a:\n");
      for(i=0;i<10;i++)
        printf("%5d",a[ i ]);
      printf("\n");
      printf("insert data:");
      scanf("%d",&number);
      end=a[9];
      if(number>end)
        a[10]=number;
      else
         {for(i=0;i<10;i++)
           {if(a[ i ]>number)
              {temp1=a[ i ];
               a[ i ]=number; 
               for(j=i+1;j<11;j++)
                  {temp2=a[j];
                   a[j]=temp1;
                   temp1=temp2;
                  }
              break;    
              }
           }
         }     
      printf("Now array a:\n");
      for(i=0;i<11;i++)
        printf("%5d",a[ i ]);
      printf("\n");
      return 0;
    }
    

    ——谭浩强 ,《C程序设计(第四版)学习辅导》,清华大学出版社,2010年7月,p57~58


    这个题目很简单,但代码却混乱无比,堪称混乱之集大成者。如果想学习怎样把代码写的混乱无比,从中可以品悟出很多独家秘诀。

    秘诀一、无聊

    int end ;
      end=a[9];
      if(number>end)
    //……
    

    这段代码堪称无聊之代表作。方法很简单,就是定义一个并不需要的变量(end),毫无意义地对它赋值(end=a[9]),再用这个克隆的变量(end)做“>”运算而不是用原来的数据对象(a[9])进行运算。而使用原来的数据对象做运算,除了可以提高程序效率、使得代码可读性更好之外,实在是一点也不够无聊啊。不无聊的代码写起来很容易很简单,通常酱紫地:

      if ( number > a[9] )
    //……
    

    秘诀二、忽左忽右,前后不一

    把一个数插入到一个有序的数组中,通常有两种考虑:或者从前往后先找到待插入数的位置再做打算,或者从后向前逐步调整。但这绝对达不到混乱的目的。样本代码中先是把数据放在了最后

        a[10]=number;
    

    貌似要从后向前,然而这只是一个虚招。紧接着又

    for(i=0;i<10;i++)
           {if(a[ i ]>number)
    

    这又是前向后的招数了。

    这里,制造混乱的要诀在于忽前忽后,忽左忽右,任何一个招数都不使老,任何一个思路都不贯彻始终,这样才能让人捉摸不透,制造混乱,之后方可在乱中取胜。
    而寻常的招数则是无条件地先把待插入的数放在数组的最后,例如

    scanf("%d",&a[10]);
    

    然后再对数组元素的次序逐步调整以到达有序的状态。

    或者,先从前面找到待插入数据的正确位置,例如

    int insert_pos ;
    scanf("%d",&number);
    for(insert_pos=0; insert_pos < 10 && number > a[insert_pos]; insert_pos++)
        ;
    

    待找到应该插入的位置之后再做进一步的处理。
    寻常的招数固然思路清晰且简洁易懂,然而主要的缺点就是达不到天下大乱之奇功。

    秘诀三、颠三倒四,手忙脚乱

    如果按照从前向后的思路,在找到待插入的位置后,首先考虑的应该是把这个位置上和以后位置上的数组元素向后移动,空出待插入元素的位置,然后插入:

    for( i = 11 – 1 ; i > insert_pos ; i--)
      a[i]=a[i-1];
    a[insert_pos]= number;
    

    之后数组成为新的有序状态。然而,这种简单的做法实在是属于乱而无术。究竟怎样才能达到乱而有术的境界呢?样本代码给我们做出了极出色的示范。
    首先,在找到待插入的位置后,并不等安排好其他数组元素的位置再插入,而是迫不及待,把数据插入进去

         {for(i=0;i<10;i++)
           {if(a[ i ]>number)
              {temp1=a[ i ];
               a[ i ]=number; 
    

    这样,temp1这样多余的变量就必不可少,总不能把被排挤出的原来的a[i]给摔掉啊。紧接着

               for(j=i+1;j<11;j++)
                  {temp2=a[j];
                   a[j]=temp1;
                   temp1=temp2;
                  }
    
    

    就如同马戏团小丑表演的抛球杂耍一样——不停地把球抛起(temp2=a[j];)、接住(a[j]=temp1;),同时忙里抽闲地还要不停地从一只手倒入另一只手中(temp1=temp2;),颠三倒四手忙脚乱得让人眼花缭乱目不暇接。这种把几件事搅和在一起忙活的方法实乃制造混乱秘笈中之秘笈。

    忙完之后,发现寻找插入位置的循环竟然还没结束,于是,赶紧刹车——

              break;    
    

    仿佛马戏表演进入高潮之后戛然而止。幸好制动及时,没有照成追尾。后面再像没事人一样按平常的方式输出——大乱之后的大治。实在是乱出了风格乱出了水平,乱的让人高山仰止。相比之下,下面这种写法

    #include <stdio.h>

    int main( )
    {
    int a[11] = {1,4,6,9,13,15,19,18,40,100};
    int number , i , insert_pos ;

    printf(
    "array a:\n");
    for( i =0 ; i <11-1 ;i++)
    printf(
    "%d ",a[i]);
    putchar(
    '\n');

    printf(
    "insert data:");
    scanf(
    "%d",&number);

    //寻找正确的插入位置
    for( insert_pos =0 ;
    ( insert_pos
    <11-1 ) && (number > a[insert_pos]) ;
    insert_pos
    ++ )
    ;

    //插入位置及后面的元素后移
    for( i =11-1 ; i > insert_pos ; i-- )
    a[i]
    =a[i-1];

    //插入
    a[insert_pos]= number;

    //输出
    printf("Now array a:\n");
    for( i =0 ; i <11 ; i++ )
    printf(
    "%d " , a[i] );
    putchar(
    '\n');

    return0;
    }

    就显得太过于井井有条昆乱不挡了。貌似一副怎么也乱不起来的样子。更有甚者

    #include <stdio.h>

    int main( )
    {
    int a[11] = {1,4,6,9,13,15,19,18,40,100};
    int i ;

    printf(
    "array a:\n");
    for( i =0 ; i <11-1 ;i++)
    printf(
    "%d ",a[i]);
    putchar(
    '\n');

    printf(
    "insert data:");
    scanf(
    "%d",&a[ 11-1 ] );

    for( i =11-1 ; (i >0) && ( a[i] < a[i-1] ) ; i-- )
    {
    int temp ;
    temp
    = a[ i ] ;
    a[ i ]
    = a[ i -1] ;
    a[ i
    -1 ] = temp ;
    }

    //输出
    printf("Now array a:\n");
    for( i =0 ; i <11 ; i++ )
    printf(
    "%d " , a[i] );
    putchar(
    '\n');

    return0;
    }

    则非但不忙不乱,简直称得上是有些游手好闲了。

  • 相关阅读:
    mac 命令大全
    GAME OF THRONES 2
    GAME OF THRONES 1
    软件工程-作业一
    猜数字游戏
    摘自-角田光代《对岸的她》
    java复习总结
    艾米莉-狄金森
    初次接触软件工程
    Environment/reflection mapping & bump mapping
  • 原文地址:https://www.cnblogs.com/pmer/p/2130032.html
Copyright © 2011-2022 走看看