偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

從刻舟求劍的故事評(píng)析劣質(zhì)代碼

開(kāi)發(fā) 架構(gòu)
我們今天將從一個(gè)習(xí)題出發(fā),講講不會(huì)寫(xiě)代碼的人毛病,就是急著先把能寫(xiě)的內(nèi)容一下子寫(xiě)完。

 【題目】

  將一個(gè)5*5的矩陣中***的元素中***的元素放在中心,4個(gè)角分別放4個(gè)最小的元素(順序?yàn)閺淖蟮接遥瑥纳系较乱来螐男〉酱蟠娣牛?,?xiě)一函數(shù)實(shí)現(xiàn)之,用main函數(shù)調(diào)用。

    ——譚浩強(qiáng) ,《C程序設(shè)計(jì)(第四版)學(xué)習(xí)輔導(dǎo)》,清華大學(xué)出版社,2010年7月,p108

【評(píng)析】

  這其實(shí)是一個(gè)相當(dāng)復(fù)雜的問(wèn)題,題目作者自己大概根本沒(méi)意識(shí)到,更沒(méi)有真正想清楚這個(gè)問(wèn)題的解決,拍拍腦袋就出題了。

題目中明顯的問(wèn)題是語(yǔ)義不清,比如什么是“***”?什么是“最小”?什么是倒數(shù)第二???這些含義都不明確。所以如果不進(jìn)一步對(duì)問(wèn)題進(jìn)行補(bǔ)充說(shuō)明,題目的解并不能保證唯一。客氣點(diǎn)說(shuō)題目不嚴(yán)格,如果事實(shí)求是說(shuō),題目本身就是錯(cuò)誤的。

  例如,1、1、2、2、3、3這6個(gè)數(shù)中,究竟1是這組整數(shù)中第二小的數(shù),還是2是第二小的整數(shù)?這個(gè)問(wèn)題的答案很可能有歧義,更有歧義的是究竟哪個(gè)位置上的數(shù)是第2小的數(shù)?

  “寫(xiě)一函數(shù)實(shí)現(xiàn)之”完全是一個(gè)過(guò)分的要求,也是一個(gè)外行的要求,就跟要求別人用腳指頭敲鍵盤(pán)一樣。

【原代碼】

  1. . #include <stdio.h> 
  2. int main() 
  3. . {void change(int *p); 
  4. .  int a[5][5],*p,i,j; 
  5. .  printf("input matrix:\n"); 
  6. .  for(i=0;i<5;i++) 
  7. .    for(j=0;j<5;j++) 
  8. .      scanf("%d",&a[i][j]); 
  9. .  p=&a[0][0]; 
  10. .  change(p); 
  11. .  printf("Now matrix:\n"); 
  12. .  for(i=0;i<5;i++) 
  13. .    {for(j=0;j<5;j++) 
  14. .       printf("%d ",a[i][j]); 
  15. .     printf("\n"); 
  16. .    } 
  17. .  return 0; 
  18. . } 
  19. void change(int *p) 
  20. .  {int i,j,temp; 
  21. .   int *pmax,*pmin; 
  22. .   pmax=p; 
  23. .   pmin=p; 
  24. .   for(i=0;i<5;i++) 
  25. .     for(j=i;j<5;j++) 
  26. .      {if(*pmax<*(p+5*i+j))pmax=p+5*i+j; 
  27. .       if(*pmin>*(p+5*i+j))pmin=p+5*i+j; 
  28. .      } 
  29. .   temp=*(p+12); 
  30. .   *(p+12)=*pmax; 
  31. .   *pmax=temp; 
  32. .   temp=*p; 
  33. .   *p=*pmin; 
  34. .   *pmin=temp; 
  35. .   pmin=p+1; 
  36. .   for(i=0;i<5;i++) 
  37. .     for(j=0;j<5;j++) 
  38. .       if(((p+5*i+j)!=p)&&(*pmin>*(p+5*i+j)))pmin=p+5*i+j; 
  39. .   temp=*pmin; 
  40. .   *pmin=*(p+4); 
  41. .   *(p+4)=temp; 
  42. .   pmin=p+1; 
  43. .   for(i=0;i<5;i++) 
  44. .     for(j=0;j<5;j++) 
  45. .       if(((p+5*i+j)!=(p+4))&&((p+5*i+j)!=p)&&(*pmin>*(p+5*i+j))) 
  46. .            pmin=p+5*i+j; 
  47. .   temp=*pmin; 
  48. .   *pmin=*(p+20); 
  49. .   *(p+20)=temp; 
  50. .   pmin=p+1; 
  51. .   for(i=0;i<5;i++) 
  52. .      for(j=0;j<5;j++) 
  53. .        if(((p+5*i+j)!=p)&&((p+5*i+j)!=(p+4))&&((p+5*i+j)!=(p+20))&& 
  54. .             (*pmin>*(p+5*i+j))) pmin=p+5*i+j; 
  55. .   temp=*pmin; 
  56. .   *pmin=*(p+24); 
  57. .   *(p+24)=temp; 
  58. . } 

  ——譚浩強(qiáng) ,《C程序設(shè)計(jì)(第四版)學(xué)習(xí)輔導(dǎo)》,清華大學(xué)出版社,2010年7月,p109~110

【評(píng)析】

  1. .  printf("input matrix:\n"); 
  2. .  for(i=0;i<5;i++) 
  3. .    for(j=0;j<5;j++) 
  4. .      scanf("%d",&a[i][j]); 
  5. .  p=&a[0][0]; 
  6. .  change(p); 
  7. .  printf("Now matrix:\n"); 
  8. .  for(i=0;i<5;i++) 
  9. .    {for(j=0;j<5;j++) 
  10. .       printf("%d ",a[i][j]); 
  11. .     printf("\n"); 
  12. .    } 

 

不會(huì)寫(xiě)代碼的人毛病,就是急著先把能寫(xiě)的內(nèi)容一下子寫(xiě)完。在這段代碼中可以看到change(p)像是掉進(jìn)了一堆亂麻里的一只牙簽一樣,整個(gè)代碼的結(jié)構(gòu)亂作一團(tuán)。這是一只很拙劣的風(fēng)格,對(duì)比一下下面的寫(xiě)法就知道這段代碼有多糟糕了。

 

  1. #include <stdio.h> 
  2.   
  3. int main( void ) 
  4.    int a[5][5] ; 
  5.   
  6.    input(a,5); 
  7.    change(*a); 
  8.    output(a,5); 
  9.   
  10.    return 0; 

 

  哪個(gè)寫(xiě)法清晰明了是一目了然的吧?

  結(jié)構(gòu)化程序設(shè)計(jì)中有一條著名的原則,這就是自頂向下(Top Down),這個(gè)原則說(shuō)的是先從大處著眼,把問(wèn)題分解為若干小問(wèn)題,然后再把這些小問(wèn)題進(jìn)一步分解為更小的問(wèn)題,直到無(wú)法再分解為止。這叫逐步細(xì)化。

每一層分解都是一種抽象,抽象的目的是為了概括,概括的目的是為了有一個(gè)簡(jiǎn)單的表現(xiàn)形式,從而把不必要的細(xì)節(jié)隱藏在這種簡(jiǎn)單的表現(xiàn)形式的后面。函數(shù)是實(shí)現(xiàn)這種思想的利器。在每次的分解過(guò)程中,問(wèn)題總是被分解為同一層次上的問(wèn)題。這樣的代碼才可能具有優(yōu)雅的均衡感和良好的可讀性。

  1. p=&a[0][0]; 
  2. change(p); 

  是典型的多此一舉。因?yàn)閜這個(gè)變量多余。這兩句話(huà)無(wú)非就是

  1. change(*a);   //或change(a[0]);  //或change(&a[0][0]); 

 

而已。需要注意的是,change()函數(shù)要操作的是整個(gè)數(shù)組,而這里的實(shí)參僅僅是一個(gè)指向a[0][0]的指針。很顯然,change()得到的信息并不充分,它不可能知道它要操作的是一個(gè)int [5][5]類(lèi)型的數(shù)組。換言之,chang()函數(shù)不可能完成任務(wù),除非它再通過(guò)別的歪門(mén)邪道獲得其他必要的信息。

  下面考察chang()函數(shù)定義。

  從沒(méi)見(jiàn)過(guò)這么丑的函數(shù)!居然能把函數(shù)寫(xiě)得如此之丑,不禁嘆為奇跡。

  1. void change(int *p) 

前面提到過(guò),參數(shù)不完整。這注定后面要走歪門(mén)邪道(比如許多無(wú)厘頭的Magic Number)。

  1. for(i=0;i<5;i++) 
  2.   for(j=i;j<5;j++) 
  3.   {if(*pmax<*(p+5*i+j))pmax=p+5*i+j; 
  4.    if(*pmin>*(p+5*i+j))pmin=p+5*i+j; 
  5.    } 

  這段代碼試圖尋找***值與最小值的位置。但是正如前面討論過(guò)的那樣,***、最小值的位置可能不是唯一的。那么究竟要找的是哪一個(gè)呢?其實(shí)代碼作者自己也不知道,找到哪個(gè)算哪個(gè),無(wú)頭蒼蠅撞大運(yùn)。

  這其中有一個(gè)明顯的錯(cuò)誤,就是內(nèi)層for語(yǔ)句中的j=i。這表明它并不是在整個(gè)數(shù)組中尋找***最小值的位置,而只是在數(shù)組中的一個(gè)局部尋找***最小值的位置。這樣的代碼顯然是錯(cuò)誤的。

  即使改正了這個(gè)錯(cuò)誤,從C語(yǔ)言的語(yǔ)法角度講,這段代碼也還是錯(cuò)誤的。因?yàn)閜是指向main()中a[0][0]的指針,而a[0][0]是一維數(shù)組a[0]的一個(gè)元素。根據(jù)C語(yǔ)言的規(guī)則,這個(gè)p做加減法得到的結(jié)果必須依然指向a[0]中的元素或者a[0]中***一個(gè)元素的下一個(gè)位置,否則代碼行為是未定義的。而在p+5*i+j這個(gè)表達(dá)式中,由于5*i+j的值可能大于5,所以是未定義行為。所謂未定義行為通俗地來(lái)說(shuō)就是,C語(yǔ)言并沒(méi)有承諾這樣寫(xiě)會(huì)得到什么,這樣的代碼可能得到任何結(jié)果。就像瘋子的胡言亂語(yǔ)可以隨意解釋一樣。

  即使拋開(kāi)前面一系列錯(cuò)誤不談,后面的代碼依然是錯(cuò)誤的:

  1. temp=*(p+12); 
  2.  *(p+12)=*pmax; 
  3.  *pmax=temp; 
  4.  temp=*p; 
  5. *p=*pmin; 
  6. *pmin=temp; 

  這里,代碼把pmax所指向的數(shù)據(jù)對(duì)象與p+12(這個(gè)表達(dá)式本身就不靠譜)所指向的數(shù)據(jù)對(duì)象交換,然后又把pmin所指向的數(shù)據(jù)對(duì)象與p所指向的數(shù)據(jù)對(duì)象交換。但是代碼作者忘記了,pmin所指向的位置可能恰恰是p+12所指向的位置,在這種情況下,第二次交換就是***元素與p指向的元素的交換,而非所期待的最小元素與*p的交換,這樣得到的結(jié)果顯然是錯(cuò)誤的。在這里代碼作者犯了中國(guó)古代寓言“刻舟求劍”中一模一樣的錯(cuò)誤。古希臘哲學(xué)家說(shuō)人不能兩次走入同一條河,說(shuō)的也是同樣的道理。

  這個(gè)錯(cuò)誤從另一個(gè)方面提示我們,寫(xiě)代碼應(yīng)該一個(gè)問(wèn)題一個(gè)問(wèn)題地解決,不要眉毛胡子一把抓,把幾個(gè)問(wèn)題攪和在一塊。

  好了。從內(nèi)容到形式,從算法到語(yǔ)法,代碼已經(jīng)是錯(cuò)得一塌糊涂了,差不多要亮瞎我的雙眼了。沒(méi)有任何理由再繼續(xù)看下去了。就此打住。

 

原文鏈接:http://www.cnblogs.com/pmer/archive/2012/07/22/2604229.html

【編輯推薦】

 

 

責(zé)任編輯:彭凡 來(lái)源: 博客園
相關(guān)推薦

2011-06-03 08:58:14

2018-01-31 07:47:10

線纜電線電纜

2021-04-14 10:05:04

中國(guó)聯(lián)通薪資員工

2011-06-15 13:20:33

2013-08-22 10:56:34

大數(shù)據(jù)

2010-03-10 17:09:09

交換機(jī)

2009-08-01 15:47:04

網(wǎng)線故障

2017-07-05 15:09:52

密碼token瀏覽器

2010-12-24 09:36:37

2011-06-19 18:35:14

打印機(jī)常見(jiàn)問(wèn)題

2021-07-12 05:01:11

云原生軟件架構(gòu)

2011-06-20 09:31:20

項(xiàng)目經(jīng)理

2012-06-13 11:48:34

國(guó)雙科技軟件外包大數(shù)據(jù)

2016-12-02 14:15:52

2013-10-15 09:56:54

大數(shù)據(jù)

2012-10-17 13:50:25

2012-03-12 09:46:21

Solaris2.5illumos

2012-04-01 14:41:10

Solarisillumos

2009-06-16 10:33:26

華為任正非創(chuàng)業(yè)故事

2021-05-29 08:07:29

數(shù)據(jù)庫(kù)用戶(hù)OS
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)