如何写好的程式Word文档下载推荐.docx

上传人:b****3 文档编号:16724587 上传时间:2022-11-25 格式:DOCX 页数:30 大小:72.83KB
下载 相关 举报
如何写好的程式Word文档下载推荐.docx_第1页
第1页 / 共30页
如何写好的程式Word文档下载推荐.docx_第2页
第2页 / 共30页
如何写好的程式Word文档下载推荐.docx_第3页
第3页 / 共30页
如何写好的程式Word文档下载推荐.docx_第4页
第4页 / 共30页
如何写好的程式Word文档下载推荐.docx_第5页
第5页 / 共30页
点击查看更多>>
下载资源
资源描述

如何写好的程式Word文档下载推荐.docx

《如何写好的程式Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《如何写好的程式Word文档下载推荐.docx(30页珍藏版)》请在冰豆网上搜索。

如何写好的程式Word文档下载推荐.docx

}

cout<

可讀性佳的程式風格

for(inti=1;

if(i%2==0)sum=sum+7;

elsesum=sum+i;

可讀性佳又精簡的程式風格

i++)sum+=((i%2)?

i:

7);

(3)函式的參數不要太多,參數太多代表函式可能執行太多工作,應考慮將此函式分割成數個較小的函式。

(4)使用遞迴函式化,有助於快速產生正確且可讀性高的程式,但卻必須付出執行速度緩慢的代價。

unsignedgcd(unsigneda,unsignedb)

if(b==0)returna;

//adividesaand0

elsereturngcd(b,a%b);

//recursivestep

unsignedlongfib(unsignedn)

{return(n<

=1?

n:

fib(n-1)+fib(n-2);

(5)盡量保持程式的單純化,即以簡單直接的方法寫程式。

U[k++]=(S[i]<

S[j]?

S[i++]:

S[j++]);

上一行程式太過複雜,若改寫如下,則容易理解

if(S[i]<

S[j]){U[k]=S[i];

i++;

else{U[k]=S[j];

j++;

k++;

*x+=(*xp=(2*k<

(n-m)?

c[k+1]:

d[k--]));

if(2*k<

n-m)*xp=c[k+1];

else*xp=d[k--];

*x+=*xp;

下列程式可用來複製字元陣列:

intlength=strlen(q);

for(inti=0;

=length;

i++)p[i]=q[i];

此程式可改寫如下:

inti;

for(i=0;

q[i]!

=0;

p[i]=0;

可進一步改寫如下:

while(*q!

=0)*p++=*q++;

*p=0;

while((*p++=*q++)!

=0);

while(*p++=*q++);

//對不熟悉的人會覺得難以理解

注意:

*p++相當於*(p++);

所以*p++=*q++;

相當於

*p=*q;

p++;

q++;

(6)使用正確的資料型態,能減少程式錯誤且加快程式執行速度。

(7)使用有意義的函式與變數名稱,有助於程式自我說明。

(8)變數的使用範圍越小越不容易誤用,因此應該避免使用整體參數,區域變數的宣告盡量延後到給初值的地方再宣告。

(9)結構:

儘量使用結構以減少變數的個數。

//For3Dgeometry

typedefstructPoint3Struct{doublex,y,z;

}Point3;

typedefPoint3Vector3;

typedefstructMatrix4Struct{doubleelement[4][4];

}Matrix4;

typedefstructBox3dStruct{Point3min,max;

}Box3;

(10)盡量使用函式或巨集減少程式的行數,函式或巨集命名要有意義。

巨集命名採用全大寫以便區別。

(11)使用const和inline取代#define。

(12)利用自訂資料型態,資料型態的名稱要有意義,以幫助程式自我說明,資料型態的名稱採用首字大寫以便區別。

typedefunsignedIndex;

typedeflongNumber;

typedeffloatForce;

typedeffloatTorque;

typedeffloatSize;

typedeffloatThickness;

typedeffloatTemperature;

typedeffloatPower;

typedeffloatAngle;

(13)使用命名有意義的符號常數或常數變數代替不變的常數,有助於閱讀。

命名採用全大寫以便區別

常見的符號常數

對應之常數變數

#defineD2R0.0174533

#defineR2D57.29578

#definePI3.1415926536

#defineEXP2.718282

#defineGOLDEN1.618034

#defineZERO1.0E-20

#defineBIG1.e30

constfloatD2R=0.0174533

constfloatR2D=57.29578

constfloatPI=3.1415926536

constfloatEXP=2.718282

constfloatGOLDEN=1.618034

constfloatZERO=1.0E-20

constfloatBIG=1.e30

(14)識別字的命名要有意義,但不要以底線或雙底線開頭,以免與C++內定的識別字衝突。

在程式中應避免對不同的目的使用相同的變數名稱,以避免混淆。

(15)使用全域變數容易發生與區域變數發生重複命名的問題,因此命名時應特別規定以便與其他變數區別,或根本避免採用。

(16)藉由列舉型態的宣告,可以用有意義的名稱取代整數常數,從而提高程式的可讀性。

(17)在二元運算子的前後都置空白字元,有助於閱讀;

但單元運算子與運算元間不可以有空白字元。

(18)逗號後面加入空白字元,有助於閱讀。

(19)運算式中加入冗餘括弧,有助於閱讀。

(20)作“==”運算時,將常數置於運算子左邊比置於右邊好。

這樣的好處是萬一誤將“==”寫成“=”,編譯器就會指出此項錯誤。

例如if(x==5)應寫成if(5==x)。

(21)使用最小開放權限原則可以使程式比較容易修改及維護。

(22)如果傳入函式的數值在函式內為定值,則該參數應宣告為const,以確保他不會無意間被修改。

修飾詞const可加強最小開放權限原則。

(23)由於捨入誤差的影響,算數式的運算順序會影響計算的誤差,應仔細考慮下列情況以避免誤差產生:

(1)兩個相近的數相減,會嚴重丟失有效數字。

Ex:

,當

時,y容易產生捨入誤差,此時應改為

時,x容易產生捨入誤差,此時應改為

,當x很大時容易產生捨入誤差,此時應改為

(2)分母越小,商的絕對誤差越大,因此運算過程要合理的安排計算順序,以降低誤差的產生,分母出現0或趨近0的情況要完全避免。

10000/0.01/500應改為10000/(0.01×

500)

(3)注意計算步驟的簡化,以減少計算的次數。

(4)避免數字太大,造成overflow。

可改為

_

3.有效率的程式:

3.1簡單而直覺的程式往往也是效率最差的程式,但好處是容易撰寫、測試和除錯;

此外,也可以用來驗證其他寫法之程式的正確性與效率。

因此寫一個簡單而直覺的程式是寫程式的一個不錯的起點。

3.2完成簡單而直覺的程式後,思考是否有更好的資料結構與演算法。

3.3如果可能盡量使用陣列而不要使用鏈結串列,因為使用陣列的演算法通常較有效率。

3.4如果使用到stack或queue,則應進一步思考改用heap是否更好。

3.5如果是靜態的資料即應使用陣列,事先對陣列排序通常有助於發展較簡單而且快速的方法。

3.6加(+)、減(-)、乘法(*)、位元運算(&

、|)需要的時間差不多;

rand()約2倍加/減法的時間;

除法(/)及模數(%)運算約為5倍加/減法的時間;

開根號(sqrt)約10倍加/減法的時間;

簡單三角運算(sin)約20倍加/減法的時間;

反三角運算(asin)約50倍加/減法的時間;

進階三角運算(sinh)約100倍加/減法的時間,記憶體的配置(malloc、free)約200倍加/減法的時間。

所以除法應該考慮改為乘法,模數(%)可考慮用減法取代,避免使用三角函數:

sin(a)用y/r、cos(a)用x/r取代。

記憶體的配置非常浪費時間,應盡量避免。

如果記憶體不是問題,就不需要使用動態記憶體。

範例:

使用減法求餘數

intmod(unsignedm,unsignedn)

{while(m>

=n)m-=n;

returnm;

#defineMOD(m,n){while(m>

3.7對於恆正的變數應宣告unsigned,宣告unsigned可以使編譯器最佳化的編譯此程式,從而加速執行速度。

針對下列程式:

intmiddle(inta,intb)

{return(a+b)/2;

若middle(即回傳值)恆正,應修改為

{returnunsigned(a+b)/2;

3.8迴圈內的程序往往對執行時間有決定性的影響,因此應該仔細撰寫,不需要在迴圈內的步驟,就應該移出廻圈。

求f=1+t0+m0t1+m0m1t2+…+m0m1…mi-1ti+…=

//直覺的程式

f=1+t[0];

mprod=1;

=n;

{

mprod=1;

for(j=0;

j<

=i-1;

j++)mprod*=m[j];

f+=t[i]*mprod;

//較佳之程式

i++){mprod*=m[i-1];

3.9利用矩陣儲存相同的資料,去除資料的重複計算

for(j=0;

r;

j++)

for(i=0;

c;

{

CL[j][i].x=bx+(i+0.5)*px;

CL[j][i].y=by+(j+0.5)*py;

}

較快的程式:

floattempx[c],tempy[r];

i++)tempx[i]=bx+(i+0.5)*px;

j++)tempy[j]=by+(j+0.5)*py;

CL[j][i].x=tempx[i];

CL[j][i].y=tempy[j];

上述程式可以進一步改進:

floattempx[c],tempy;

tempy=by+(j+0.5)*py;

{CL[j][i].x=tempx[i];

CL[j][i].y=tempy;

此程式將重複的步驟合併,不但加快速度也減少記憶體的使用。

3.10迴路裡面避免使用函數

C是堆疊導向的語言,函式的局部變數及參數均使用堆疊做為暫時的儲存所。

當函式被呼叫時,返回位址也被放入堆疊以備程式執行完後可以返回,把這些資料壓入堆疊的過程稱為callingsequence,而將這些資料自堆疊中取出的過程稱為returningsequence,這些過程都會耗用許多時間。

Example:

voidexchangesort(intn,keytypeS[])

for(indexi=1;

=n-1;

for(indexj=i+1;

j++)if(S[j]<

S[i])exchange(S[i],S[j]);

去除函數:

keytypetemp;

j++)

if(S[j]<

S[i]){temp=S[i];

S[i]=S[j];

S[j]=temp:

3.11使用條件運算子取代ifelse結構

k++;

可改為下列較快的程式:

3.12去除不必要的ifelse結構

考慮下列程式

voidf(inta,intb)

boolb1;

if(a==b)b1=true;

elseb1=false;

上述程式實際上可簡化為:

boolb1=a==b;

將上式表為連乘形式

floatx[n],y,L;

for(unsigni=0;

i++)if(i!

=k)L*=(y-x[i])/(x[k]-x[i]);

for(inti=0,L=1;

k;

i++)L*=(y-x[i])/(x[k]-x[i]);

for(i=k+1;

此程式少了i與k的比較,所以速度較快。

其中

for(i=1,sum=0;

=max;

for(j=1;

if(i==1&

&

j==1)continue;

elseif(i==1)sum+=A[j];

elseif(j==1)sum+=B[i];

elsesum+=C[i][j];

改進:

(去除不必要的判斷)

sum=0;

for(j=2;

j++)sum+=A[j];

for(i=2;

i++)sum+=B[i];

for(j=2;

j++)sum+=C[i][j];

3.13巢狀的if/else結構,要將為true機率較大判斷式置於前面

二元搜尋法Binarysearch

(1)常見的寫法:

indexlocation(indexlow,indexhigh)

{indexmid;

if(low>

high)return0;

else{

mid=(unsigned)(low+high)/2;

if(x==S[mid])returnmid;

//Findx.

elseif(x<

S[mid])returnlocation(low,mid-1);

//Searchleftsublist

elsereturnlocation(mid+1,high);

//Searchrightsublist.

(2)改進:

indexmid;

//xS

if(x<

elseif(x>

S[mid])returnlocation(mid+1,high);

elsereturnmid;

3.14去除遞迴:

遞迴演算法比起非遞廻程式耗費更多的執行時間與記憶體。

雖然遞迴函式功能很強,但使用上要小心。

採用遞迴方式的常式會比使用迭代的常式執行速度較慢,需要更多的資源負擔。

遞迴呼叫某個函式可能造成堆疊發生溢位。

因為函式的參數和局部變數是存放在堆疊區,而且每次函式呼叫都會把這些變數複製一份,堆疊空間將會耗盡。

如堆疊空間耗盡,將會發生堆疊溢位。

如果發生在已經除錯的遞迴函式,可以嘗試配置更多的堆疊空間給程式,當撰寫遞迴函式時,必須在所有的遞迴呼叫還沒有執行完畢之前,增加條件敘述句使函式強制返回。

假如沒有加入條件敘述句,函式將自我呼叫直到堆疊耗盡。

發展遞迴函式時,這是常見的錯誤。

當發展遞迴式時,使用大量的輸出敘述句,可觀察函式在執行期間的行為,發現錯誤時,就可以略過執行程序。

求費氏數列之遞迴演算法:

fib(n-1)+fib(n-2));

去除遞迴之費氏數列演算法:

unsignedlongfib2(unsignedn)

Indexi;

unsignedlongf[n];

for(f[0]=0,f[1]=1,i=2;

i++)f[i]=f[i-1]+f[i-2];

returnf[n];

3.15使用環狀移動取代一系列的對調

Insertionsort

voidinsertionsort(unsignedn,keytypeS[])

indexi,j;

keytypex,temp;

for(i=2;

x=S[i];

j=i–1;

while(S[j]>

x&

j>

0)

{

temp=S[j+1];

S[j+1]=S[j];

S[j]=temp;

//SwapS[j]andS[j+1]

j--;

}

keytypex;

0)S[j+1]=S[j--];

S[j+1]=x;

3.16使用sentinel減少比較次數

S[0]=-∞//Sentinal

x)S[j+1]=S[j--];

Binarysearch

voidseqsearch1(indexn,constkeytypeS[],keytypex,index&

location)

{//index&

denotelocationisanoutputparameter.

location=0;

while(++location<

=n&

S[location]!

=x);

if(location>

n)location=0;

加入sentinel

voidseqsearch2(indexn,constkeytypeS[],keytypex,index&

S[n+1]=x;

//SetasentinelattheendofS.

while(S[

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 工作计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1