You are on page 1of 95

T NG HI U QU CH NG TRÌNH VÀ PHONG CÁCH L P TRÌNH

Efficient Programs
Tr 
 

c h t là gi i thu t
Hãy dùng gi i thu t hay nh t có th Sau ó hãy ngh t i vi c t ng tính hi u qu c a code Ví d : Tính t ng c a n s t nhiên k t m
void main() { long n,m , sum ; cout << µ vào n µ ; cin << n; cout << µ vào m µ ; cin << m; sum =(m + m+ n) * n / 2; cout << µ T ng = µ <<sum; }

void main() { long n,m,i , sum ; cout << µ vào n µ ; cin << n; cout << µ vào m µ ; cin << m; sum =0; for(i = m ; i < = m+n; i++) sum += i; cout << µ T ng = µ <<sum; }

2

Dùng ch th ch

ng trình d ch

M t s compilers có vai trò r t l n trong vi c t i u ch ng trình  

Chúng phân tích sâu mã ngu n và làm m i i u ³machinely´ có th Ví d GNU g++ compiler trên Linux/Cygwin cho ch ng trình vi t = c
g++ ±O5 ±o myprog myprog.c

có th c i thi n hi u n ng t 10%

n 300%

3

Nh ng.. B n v n có th th c hi n nh ng c i ti n mà trình d ch không th B n ph i lo i b t t c nh ng ch b t h p lý trong code  Làm cho ch ng trình hi u qu nh t có th Có th ph i xem l i khi th y ch ch m  ng trình ch y V y c n t p trung vào âu t t nh t ? c i ti n nhanh nh t. 4 ..

Writing Efficient Code Xác   nh ngu n gây kém hi u qu D th a tính toán .redundant computation Ch y u Trong các procedure Các vòng l p : Loops 5 .

// «.25).Kh i t o 1 l n. dùng nhi u l n Before float f() { double value = sin(0. } After 6 .. float f() { double value = defaultValue. } double defaultValue = sin(0..25). // «.

Inline functions N u 1 hàm trong c++ ch g m nh ng l nh n gi n. không dùng stack± 4 b c khi 1 hàm cg i« 7 . Ch ng trình s l n h n chút ít Nh ng nhanh h n . không co for. Thì có th khai báo inline..    Inline code s c chèn vào b t c ch nào hàm c goi. while .

return 0. m = 9.Inline functions #include <iostream> #include <cmath> using namespace std. // 2 dòng sau th c hi n nh nhau: cout << hypothenuse (k. cout << sqrt (k * k + m * m) << endl. } 8 . double b) { return sqrt (a * a + b * b). m) << endl. } int main () { double k = 6. inline double hypothenuse (double a.

. double double_array[100]. */ return (0). } 9 .. /* . char *pchar. chúng compile-time. pchar = (char *)malloc(100). int int_array[100].. int main() { static float float_array[100].Static Variables Ki u d li u Static tham chi u t i global hay 'static' c c p phát b nh khi d ch variables .

Khi b n g i l i CT con. N u b n mu n 1 giá tr v n c l u l i cho n khi k t thúc toàn ch ng trình.  B ng cách này 1 ct con có th ³nh ´ m t vài m u tin sau m i l n c g i. 10 . b n c n khai báo bi n c c b c a CT con ó là static và kh i t o cho nó 1 giá tr . Dùng bi n Static thay vì Global :  Cái hay c a 1 bi n static là nó là local c a CT con.  Vi c kh i t o s ch th c hi n l n àu tiên ch ng trình c g i và giá tr sau khi bi n i s cl u cho các l n g i sau. các bi n c c b l i c c p phát và kh i t o l i.Static Variables Các bi n khai báo trong CT con c c p phát b nh khi ct con c g i và s b lo i b khi k t thúc ct con. => tránh c các side efects.

các bi n c c b c a ct con . stack. 11 Heap data:   .D li u này s còn cho n khi ta gi i phóng ho c khi k t thúc CT. heap Khi th c hi n . . . và heap data.Stack. pchar trong ví d trên). vùng d li u data segment c a 1 ch trình c chia làm 3 ph n :  ng . Static: global hay static variables Stack data:  .static.ví d double_array trong ví d trên.D li u c c p phát ng (vd.

nh ng v i inline functions thì có th .  Các bi u th c truy n nh là i s cho inline functions c tính 1 l n.  Inline functions có cùng syntax nh các hàm khác. còn inline functions c truy n b i compiler. 12 .  B n không th g r i cho macros. bi u th c truy n nh tham s cho macros có th c tính l i nhi u h n 1 l n.Macros  #define max(a.b) (a>b?a:b) Các hàm Inline c ng gi ng nh macros vì c 2 c khai tri n khi d ch compile time  macros c khai tri n b i preprocessor. ch có i u là có thêm t khóa inline khi khai báo hàm. Trong 1 s tr ng h p. Tuy nhiên có nhi u i m khác bi t:  Inline functions tuân th các th t c nh 1 hàm binh th ng.

. } } 13 . { return values[i]. } } return 0..3*3-3. . if (i < 10 && i >= 0) int f(int i) { { if (i < 10 && i >= 0) return i * i . thì nên tính tr c 1 l n và l u l i giá tr . 9*9-9}.Tính toán tr c các giá tr N u b n ph i tính i tính l i 1 bi u th c.i. 0.. r i dùng giá tr y sau này static int[] values = int f(int i) { {0. return 0. 2.

Y = 15 + strlen(str). i<=10.i<=10. Y = 15 + len. 14 . for (i = 1. len = strlen(str).Lo i b nh ng bi u th c thông th ng ng tính cùng m t bi u th c nhi u l n! M t s compilers có th nh n bi t và x lý.i++) x += len.i++) x += strlen(str). for (i = 1.

15 .S d ng các bi n Trình d ch không th t i s h c! ng x lý if (a > sqrt(b)) x = a*a + 3*a + 2. if (a *a > b) x = (a+1)*(a+2).

Dùng ³lính canh´ -Tránh nh ng ki m tra không c n thi t Tr c char s[100].tim.. «. pos = 0. 16 . int pos. size . searchValue. If (pos >= size) tim =0 else tim = 1. searchValue « size = strlen(s). Gán giá tr cho s. while (pos < size) && (s[pos] != searchValue) do pos++.

searchValue). while ( s[pos] != searchValue) do pos++. Ýt    ng chung t giá tr c n tìm vào cu i xâu Luôn tìm th y ! Nh ng n u v trí > size => khong tim thay ! size = strlen(s). If (pos >= size) tim =0 else tim = 1. Có th làm t ng t v i m ng. strcat(s.Dùng ³lính canh´ «. pos = 0. danh sách « 17 .

i*M). i<100.i++) plot(i.i++) plot(i. i<100. M = sin(d). 18 . for (i =0.D ch chuy n nh ng bi u th c b t bi n ra kh i vòng l p ng l p các bi u th c tính toán không c n thi t M t s Compilers có th t x lý! for (i =0. i*sin(d)).

i ++. sum += q*i -i*7.i++) sum += q*i -i*7. i<= j+3.Không dùng các vòng l p ng n for (i =j. sum += q*i -i*7. 19 . i = j. i ++. sum += q*i-i*7.

Gi m th i gian tính toán Trong mô ph ng Neural Network ng i ta th ng dùng hàm có tên sigmoid V i X d ng l n ta có sigmoid(x) $ 1 V i x âm ³l n´ sigmoid (x) $ 0 1 sigmoid ( x) ! 1  e  kx 20 .

0 + exp(-x)) }. 21 .0 / (1.Tính Sigmoid float sigmoid (float x ) { return 1.

Chính vì v y .Tính Sigmoid Hàm exp(-x) m t r t nhi u th i gian  tính! Nh ng hàm ki u này ng i ta ph i dùng khai tri n chu i Chu i Taylor /Maclaurin Tính t ng các s h ng d ng ((-x)n / n!) M i s h ng l i dùng các phép toán v i s ch m ng Nói chung các mô ph ng neural network g i hàm này tr m tri u l n trong m i l n th c hi n. sigmoid(x) chi m ph n l n th i gian (kho ng 70-80%) 22 .

. Trong m i l n g i sigmoid Tìm giá tr g n nh t c a x và k t qu ng v i giá tr y Th c hi n n i suy tuy n tính . x99 sigmoid(x99) 23 Tính hàm t i N i m và xây d ng 1 m ng. .Tính Sigmoid ± Gi i pháp Thay vì tính hàm m i lúc   x0 sigmoid(x0) x1 sigmoid(x0) x2 sigmoid(x0) x3 sigmoid(x0) x4 sigmoid(x0) x5 sigmoid(x0) x6 sigmoid(x0) .linear interpolation .

0). . 24 .Tính Sigmoid if (x <x0) return (0. x0 sigmoid(x0) x1 sigmoid(x0) x2 sigmoid(x0) x3 sigmoid(x0) x4 sigmoid(x0) x5 sigmoid(x0) x6 sigmoid(x0) . x99 sigmoid(x99) if (x > x99) return (1. .0).

) tùy theo chính xác mà b n mu n  T n k m thêm không gian b nh cho m i i m là 2 float hay double t c là 8 ± 16 bytes/ i m Kh i t o giá tr cho m ng khi b t u th c hi n 25 .Tính Sigmoid Ch n s các i m (N = 1000.v. 10000. v.

Tính Sigmoid
B n ã bi t X0 


Tính Delta = X1-X0 Tính Xmax = X0 + N * Delta; Tính i = (X ± X0)/Delta;
1 phép tr s th c và 1 phép chia s th c

V i X ã cho  

Tính sigmoid(x)
1 phép nhân float và 1 phép c ng float

26

Results
N u dùng exp(x) : 

M i l n g i m t kho ng 300 nanoseconds v i 1 máy Pentium 4 t c 2 Ghz.

Dùng tìm ki m trên m ng và n i suy tuy n tính : 

M i l n g i m t kho ng 30 nanoseconds

T c 

t ng g p 10 l n
64K to 640 K b
27

i l i ph i t n k m thêm t nh .

Luu y !
V i i a s các ch ng trình, vi c t ng t c th c hi n là c n thi t Tuy nhiên, c t ng t c cho nh ng o n code không s d ng th ng xuyên là vô ích !

28

Không ng ng nghi ng .Early Binding: Hãy th c hi n ngay công vi c tránh th c hi n nhi u l n sau này.Relentless Suspicion: t d u h i v s c n thi t c a m i m u code và m i tr ng . n gi n hóa van . 29 . Liên k t s m . m i thu c tính trong c u trúc d li u.Nh ng quy t c c b n Fundamental Rules n gi n hóa Code ± Code Simplification : H u h t các ch ng trình ch y nhanh là n gi n. hay don gi n hóa ch ng trình nó ch y nhanh h n.Problem Simplification: t ng hi u qu c a ch ng trình. hãy n gi n hóa v n mà nó gi i quy t. Vì v y.

Quy t c t ng t c Có th t ng t c b ng cách s d ng thêm b nh ( m ng ). 30 . nh ng yêu c u sau này s c x lý b ng cách tìm ki m t m ng hay danh sách k t qu thay vì tính l i hàm. Dùng thêm các d li u có c u trúc: Th i gian cho các phép toán thông d ng có th gi m b ng cách s d ng thêm các c u trúc d li u v i các d li u b xung ho c b ng cách thay i các d li u trong c u trúc sao cho d ti p c n h n. L u các k t qu c tính tr c: Th i gian tính toán l i các hàm có th gi m b t b ng cách tính toán hàm ch 1 l n và l u k t qu ... .

ng dùng c n ph i d ti p c n nh t. luôn Lazy Evaluation: Không bao gi tính 1 ph n t cho n khi c n nh ng s tính toán không c n thi t. Caching: D li u th hi n h u.Quy t c t ng t c : cont. tránh 31 .

K t h p các vòng l p ± loop fusion: N u 2 vòng l p g n nhau cùng thao tác trên cùng 1 t p h p các ph n t thì c n k t h p chung vào 1 vòng l p.Hot spots trong ph n l n các ch ng trình n t các vòng l p: a Code ra kh i các vòng l p: Thay vì th c hi n vi c tính toán trong m i l n l p.Quy t c l p : Loop Rules Nh ng i m nóng . t t nh t th c hi n nó ch m t l n bên ngoài vòng l p.n u c. 32 .

³Lính gác´ hay ³V s ´ là m t ví d cho quy t c này. LTV có th ph i thay i i u ki n k t thúc vòng l p. Lo i b Loop : V i nh ng vòng l p ng n thì c n lo i b vòng l p.Quy t c l p : Loop Rules K t h p các phép th .Combining Tests: Trong vòng l p càng ít ki m tra càng t t và t t nh t ch m t phép th . tránh ph i thay i và ki m tra i u ki n l p 33 .

Procedure Rules Khai báo nh ng hàm ng n và n gi n (th ng ch 1 dòng) là inline   Tránh ph i th c hi n 4 b c khi hàm g i. Tránh dùng b nh stack c 34 .

u m i CT. Tuy nhiên khi 1 quy t c b vi ph m. Nói chung s là t t n u ta tuân th các quy tác sau ây : M t quy t c quan tr ng trong phong cách l p trình là ³Tính nh t quán´. thì th ng c bù l i b ng m t cái gì ó. C n l u ý r ng các quy t c c a ³programming style´ . ôi khi b vi ph m. th m trí b i nh ng nhà v n hay nh t. ch c n ng Hãy dùng t i thi u s các tham s c a CT con. h ng thì hãy tuân th nó trong toàn b ch ng trình. N u b n ch p nh n m t cách th c t tên hàm hay bi n. M t CT con ph i ng n ng i c có th n m b t nh m t n v .GOOD PROGRAMMING STYLE Sau ây là các quy t c v ³programming style ³ rút ra t cu n ³The Elements of Programming Style" cuiar tác gi Kernighan and Plauger. áng ta m o hi m. nên có m t o n chú thích « M i CT con ph i có m t nhi m v rõ ràng. gi ng nh quy t c v n ph m English. > 6 tham s cho 1 CT con là quá nhi u 35 .

i++) i++.giá tr tr v c a hàm Không nên thay i giá tr c a bi n ch y trong thân c a vòng l p for. N u ³i'' c dùng làm bi n ch y cho vòng l p trong 1 CT con. Nên nh t quán trong vi c dùng các bi n local có cùng tên.i<=10. for(i=1. ví d không nên làm nh sau : for i = 1 to 10 do i := i + 1. Functions ch nên tác ng t i duy nh t 1 giá tr .GOOD PROGRAMMING STYLE Có 2 lo i Ct con : functions và procedures. thì ng dùng nó cho vi c khác trong các CT con khác 36 .

± S d ng th vi n m i khi có th 4. Say what you mean.GOOD PROGRAMMING STYLE 1. Avoid too many temporary variables ± Tránh dùng nhi u bi n trung gian 5. Use library functions whenever feasible. tr c ti p 3. simply and directly ± Trình bày v n 1 cách n gi n. Write clearly / don't be too clever ± Vi t rõ ràng ± ng quá thông minh (k bí) 2. Write clearly / don't sacrifice clarity for efficiency ± Vi t rõ rang / ng hy sinh s rõ rang cho hi u qu 37 .

If a logical expression is hard to understand. Choose variable names that won't be confused ± Ch n tên bi n sao cho tránh cl nl n 10. Choose a data representation that makes the program simple ± Hãy l a ch n c u trúc d li u ch ng trình thành n gi n 38 . ± Tránh các nhánh không c n thi t 11. Replace repetitive expressions by calls to common functions. Avoid unnecessary branches. try transforming it ± N u 1 bi u th c logic khó hi u. Parenthesize to avoid ambiguity. ± Dùng () tránh r c r i 9. ± Hãy thay nh ng bi u th c l p i l p l i b ng cách g i các hàm 8.GOOD PROGRAMMING STYLE 6. ( tính toán «) 7. Let the machine do the dirty work ± Hãy máy tính làm nh ng vi c n ng nh c c a nó. c g ng chuy n i cho n gi n 12.

± Mô ul hóa. Modularize. ± Tr c tiên hãy vi t ct b ng gi ng d hi u.GOOD PROGRAMMING STYLE 13. Dùng các hàm và th t c 15. ± Vi t và ki m tra 1 CT l n thành t ng CT con 39 . Don't patch bad code /{ rewrite it. ± Tránh hoàn toàn vi c dùng goto 16. Write first in easy-to-understand pseudo language. Write and test a big program in small pieces. Use procedures and functions. r i hãy chuy n sang ngôn ng c n thi t. Avoid gotos completely if you can keep the program readable. ± Không ch p vá mã x u ± Vi t l i o n code ó 17. then translate into whatever language you have to use. 14.

Use recursive procedures for recursively-defined data structures.GOOD PROGRAMMING STYLE 18. không dùng phép m 22. not by count. ± Hãy dùng các th t c quy cho các c u trúc d li u quy 19. Test input for plausibility and validity. recover if possible. Make input easy to prepare and output self-explanatory. Make sure input doesn't violate the limits of the program. d chu n b và u ra d hi u 40 . ± Hãy m b o u vào không quá gi i h n cho phép c a CT 21. Terminate input by end-of-file marker. Identify bad input. ± Hãy k t thúc dòng nh p b ng ký hi u EOF. khôi ph c n u có th 23. ± Ki m tra u vào m b o tính chính xác và h p l 20. ± Xác nh u vào x u. ± Hãy làm cho u vào n gi n.

Hãy m b o các bi n c kh i t o tr c khi s d ng 26. Make it right before you make it faster. 25. ± Hãy làm cho CT ch y úng.0 28. Test programs at their boundary values. Use uniform input formats.1 is hardly ever 1.0 is not zero. 7/8 =0 nh ng 7. ± Ki m tra 1 s câu tr l i b ng tay 27.0 times 0.. Make sure all variable are initialized before use.0/8. ± Hãy dùng các u vào theo các nh d ng chu n.GOOD PROGRAMMING STYLE 24.0/8. 10.0 <> 0 29. 7/8 is zero while 7. Check some answers by hand.0.1 không ch c ã = 1. tr c khi làm nó ch y nhanh 41 . ± Hãy ki m tra CT t i các c n 26. ± 10 nhân 0.

hãy t ch c l i mã 33. tr c khi làm nó ch y nhanh 31. Make it clear before you make it faster. Keep it simple to make it faster. ± Hãy m b o các tr ng h p c bi t là th c s c bi t 34. ± ng chú thích nh ng o n mã x u. ± Hãy trình d ch th c hi n các vi c tôi u hóa n gi n 32. ± ng c tái s d ng mã. Make sure comments and code agree. reorganize instead. thay vì v y. Don't comment bad code | rewrite it. h y vi t l i 37.. ± ng chú thích quá nhi u 42 . ± Hãy gi nó n gi n làm cho nó nhanh h n 35.Hãy nh d ng CT giúp ng i c hi u c CT 39. Format a program to help the reader understand it. ± Hãy vi t code rõ ràng. Don't strain to re-use code. sát code 36. ± Hãy dùng các tên bi n có ngh a 38. Make sure special cases are truly special.GOOD PROGRAMMING STYLE 30. Don't over-comment. Let your compiler do the simple optimizations. Use variable names that mean something. ± Chú thích ph i rõ ràng.

black)..return B. color.u=b-u1e-7?b-u:b+u.P..-6.}vec trace(level...y*B.yx.y+=a*A..eta.D.5.-3...D.*l.N.if(d<0)N=vcomb(-1.3.{return A.kl.B.1.black)..5.1.0.y+A.s-cen)).D)vec P.D)vec P.1.kt.y.U=vcomb(-1..black.color.s-cen )))..z.u=u0?sqrt(u):1e31.0f %.1.B.vcomb(s-ks.P.y*=U..if(!level--)return black./sqrt( vdot(A.02.0.P=vcomb(tmin.d= -vdot(D.B)double a.*best.while(yx<32*32) U..8.5.D)).vcomb(eta*d-sqrt (e).1..lcolor. ..N.vcomb(2*d.return best.1.color=amb..B..1.Program Style  Who reads your code? The compiler Other programmers typedef struct{double x.s= sph+5..double u.}vec vunit(A)vec A...while(l--sph)if((e=l kl*vdot(N.1.D)).2.6..0.color.printf("%.} This is a working ray tracer! (courtesy of Paul Heckbert)43 .5915590261).1.y.3.1.color)...vunit(U))..0.U=s-color.0..1.D.0.}struct sphere*intersect(P.05.z..while(s--sph)b=vdot(D..P.z}vec.x.color.5.x=yx%32-32/2..ks.}.else return amb.02..amb={.black)))).-.5..d= -d.x.0.9.U.if(s=intersect(P.2.U)==l)color=vcomb(e .color.15.vcomb(s-kl..U.-1.b..0f %.8..A.e=1-eta* eta*(1d*d).P.N..tmin..7.05.x+=a* A.u=b*b-vdot(U..z+=a*A.e.U).0f\n".e0?trace(level.vec N.8.vcomb(eta.N=vunit(vcomb(-1.85.y.black.12..{return vcomb(1..trace(level.U.2.....x*=U.32.{double d.u: tmin.color.-3.eta=s-ir.02}.5. struct sphere*s..5.B...A.z.z=32/2-yx++/32.eta=1/eta. trace(3.return vcomb(s-kt.1.1.l=sph+5.D.U)+s-rad*s rad.}main(){printf("%d %d\n".B)vec A .1.U=vcomb(255.{best=0.5..-.z*=U.kd..7.P)..sph[]={0.y=32/2/tan(25/114. 1..3.2.8. 1.32).vec U..0.black))):black...double vdot(A.0.tan().7...8.A)).double rad.{B.tmin=u=1e-7&&u<tmin?best=s.x*B..z*B..ir}*s.black).struct sphere{ vec cen.1.8.U=vunit(vcomb(-1.6.vcomb(s-kd.l-cen))))0&&intersect(P.7.}vec vcomb(a...0.tmin=1e30.sqrt().vec A.x+A.P...

Program Style  Vì sao program style l i quan tr ng? L i th ng x y ra do s nh m l n c a LTV  Bi n này c dùng làm gì?  Hàm này c g i nh th nào? Good code = code d c  Làm th nào code thành d c? C u trúc ch ng trình rõ ràng. d hi u. g i nh Vi t chú thích rõ ràng S d ng môdul 44 . khúc tri t S d ng thành ng ph bi n Ch n tên phù h p.

Structure: Spacing 
Use

readable/consistent spacing

VD: Gán m i ph n t m ng a[j] = j. Bad code
for (j=0;j<100;j++) a[j]=j;

Good code
for (j=0; j<100; j++) a[j] = j;

Th ng có th d a vào auto-indenting, tính n ng trong trình so n th o
45

Structure: Indentation (cont.) 
Use

readable/consistent indentation
if (month == FEB) { if (year % 4 == 0) { if (day > 29) legal = FALSE; } else { if (day > 28) legal = FALSE; } }

VD:
if (month == FEB) { if (year % 4 == 0) if (day > 29) legal = FALSE; else if (day > 28) legal = FALSE; }

Wrong code (else matches ´if day > 29µ)

Right code

46

Structure: Indentation (cont.) 
Use

³else-if´ cho c u trúc a l a ch n
v 2 4 5 7 8 10 17 x 10
47

VD: B c so sánh trong tìm ki m low=0 nh phân - binary search. Bad code if (x < v[mid])
high = mid ± 1; else if (x > v[mid]) low = mid + 1; else return mid;

mid=3

high=6

Good code

if (x < v[mid]) high = mid ± 1; else if (x > v[mid]) low = mid + 1; else return mid;

*/ } « 48 . */ { const double PI = 3. if (scanf("%d".Structure: ´Paragraphsµ  Dùng chính dòng tr ng chia code thành các ph n #include <stdio.h> int main(void) /* Read a circle's radius from stdin. and compute and write its diameter and circumference to stdout. printf("Enter the circle's radius:\n"). /* or: return EXIT_FAILURE. double circum. Return 0 if successful. "Error: Not a number\n"). &radius) != 1) { fprintf(stderr.14159.h> #include <stdlib. int radius. int diam. exit(EXIT_FAILURE).

diam).Structure: ´Paragraphsµ  Dùng chính dòng tr ng chia code thành các ph n diam = 2 * radius. printf("and circumference %f. printf("A circle with radius %d has diameter %d\n". radius. return 0. circum). } 49 . circum = PI * (double)diam.\n".

Structure: Expressions  Dùng các bi u th c d ng nguyên b n VD: Ki m tra n u n th a mãn j < n < k Bad code if (!(n >= k) && !(n <= j)) Good code if ((j < n) && (n < k)) BT i u ki n có th thông th ng  c nh cách th c b n vi t ng vi t BT i u ki n theo ki u mà b n không bao gi s d ng 50 .

nh ng ai nh u tiên cao h n các toán i u ó? 51 .Structure: Expressions (cont.)  Dùng () tránh nh m l n VD: Ki m tra n u n th a mãn j < n < k Moderately bad code if (j < n && n < k) Moderately better code if ((j < n) && (n < k)) Nên nhóm các nhóm m t cách rõ ràng  Toán t quan h (vd ³>´) có t logic (vd ³&&´).

Right code while ((c = getchar()) != EOF) putchar(c).Structure: Expressions (cont.)  Dùng () tránh nh m l n (cont. Nên nhóm các nhóm m t cách rõ ràng :explicit  Toán t Logic (³!=³) có u tiên cao h n toán t gán (³=³) 52 .) VD: c và in các ký t cho n cu i t p. Wrong code ( i u gì x y ra ???) while (c = getchar() != EOF) putchar(c).

)  n gi n hóa các bi u th c ph c t p ng ng v i các tháng VD: Xác nh các ký t t c an m Bad code if ((c == 'J') || (c == 'F') || (c == 'M') || (c == 'A') || (c == 'S') || (c == 'O') || (c == 'N') || (c == 'D')) Good code if ((c (c (c (c == == == == 'J') 'M') 'S') 'N') || || || || (c (c (c (c == == == == 'F') || 'A') || 'O') || 'D')) Nên x p x p các c c u song song ! 53 .Structure: Expressions (cont.

0. i<n.0. -- VD: Set each array element to 1. i++) array[i] = 1.0. 54 . perhaps just ³so-so´ code) i = 0. while (i <= n-1) array[i++] = 1. Chú C Idioms ý khi dùng ++. Good code for (i=0. Bad code (or.

Check_Octal(). CONTROL. Buffer_Insert (Tên hàm) (h ng s ) (bi n c c b )  Dùng  Dùng phong cách nh t quánkhi ghép t ng t cho tên hàm 55 VD.... « .Naming  Dùng tên g i nh . front_size VD. inkq(). có tính miêu t cho các bi n và hàm VD : hovaten. frontSize. CAPACITY  Dùng  Dùng tên nh t quán cho các bi n c c b ch hoa. frontsize. docsolieu(). ch th CAPACITY buf VD. i (not arrayIndex) cho bi n ch y vòng l p ng nh t quán VD.

. t chú thích t Và thay i khi b n thân code changes. «. . structure type definitions. Làm Comments Hãy ch R i« ch ngôn ng ng trình t di n t b n thân  Vi t chú thích i++. chú thích t ng dòng vd. thêm thông tin ng /* add one to i */  Chú thích các o n (³paragraphs´) code. ³Sort array in ascending order´  Chú  Vi thích d li u t ng th ng ng v i code!!! 56 Global variables.

*/ printf("Enter the circle's radius:\n"). exit(EXIT_FAILURE).h> #include <stdlib. if (scanf("%d". int diam.14159. /* or: return EXIT_FAILURE. */ } « 57 . &radius) != 1) { fprintf(stderr. */ { const double PI = 3.) #include <stdio. "Error: Not a number\n"). ng chú thích t ng dòng code /* Read a circle's radius from stdin.h> int main(void) thích các o n (³paragraphs´) code. and compute and write its diameter and circumference to stdout. double circum. Chú Comments (cont. int radius. /* Read the circle¶s radius. Return 0 if successful.

return 0. */ diam = 2 * radius. circum = PI * (double)diam.) /* Compute the diameter and circumference. diam). printf("and circumference %f. } 58 .Comments (cont. /* Print the results. circum).\n". radius. */ printf("A circle with radius %d has diameter %d\n".

c file gì. d hi u bi t cách nó làm vi c« N u không. ch không ph i nó làm nh th nào B n thân Code ph i rõ ràng. các bi n t ng th mà nó tác ng t i 59 . bi n t ng th c dùng  Mô t outputs: giá tr tr v .Function Comments  Mô t nh ng gì c n thi t chính xác g i hàm 1 cách Mô t Hàm làm gì. tham s truy n ra. ghi ra files gì. hãy vi t chú thích bên trong nh ngh a hàm  Mô t u vào: Tham s truy n vào.

*/ « } Describes how the function works 60 . D a trên ký t y và tr ng thái DFA hi n th i. g i hàm x lý tr ng thái t ng ng. L p cho n h t t p end-of-file.)  Bad function comment /* decomment.Function Comments (cont.c */ int main(void) { /* c 1 ký t .

Tr v 0 n u thành công.c */ int main(void) { /* c 1 CT C qua stdin. */ « } Describes what the function does 61 .)  Good function comment /* decomment.Function Comments (cont. EXIT_FAILURE n u không thành công. Ghi ra stdout v i m i chú thích thay b ng 1 d u cách.

Modularity  Ch ng trình l n vi t khó h n Ct nh  Tr u t ng hóa là chìa khóa x lý s ph c t p Abstraction cho phép LTV bi t code làm cái gì. mà không c n bi t làm nh th nào  Ví d : hàm m c tr u t ng Hàm s p x p 1 m ng các s nguyên Character I/O functions : getchar() and putchar() Mathematical functions : sin(x) and sqrt(x) 62 .

Bottom-Up Design is Bad  Bottom-up design 1 2 Thi t k chi ti t 1 ph n Thi t k chi ti t 1 ph n khác L p l i cho n h t  Bottom-up design in programming n h« t nh t 1 2 3 4 Vi t ph n u tiên c a CT 1 cách chi ti t cho Vi t ph n ti p theo c a CT 1 cách chi ti t cho L p l i cho n h t « 63 .

c th .Top-Down Design is Good  Top-down design design in programming Thi t k toàn b s n ph m m t cách s b . chi ti t h n K t qu : S n ph m c modul hóa 1 cách t nhiên 2 4 5 1 3 « 64 . t ng th Tinh ch nh cho n khi hoàn thi n  Top-down Xây d ng s l c hàm main() b ng pseudocode Tinh ch nh t ng l nh gi ng  Công vi c n gi n => thay b ng real code  Công vi c ph c t p => thay b ng l i g i hàm L p l i sâu h n.

và ti p t c L p l i (mostly) m c sâu h n. c th h n. và« Quay l i tinh ch nh pseudocode ã có. cho n khi các hàm c nh ngh a xong 1 2 Oops 2· 1· 3 4 2· Oops 1· 3 4· 2·· 5 1·· 3· « 65 .Top-Down Design in Reality  Thi t k CT Top-down trong th c ti n : nh ngh a hàm main() = pseudocode Tinh ch nh t ng l nh pseudocode   N u g p s c Oops! Xem l i thi t k .

nh ng c n trái và c n ph i  D n các t t i a có th trên 1 dòng 50 ký t  Thêm các d u cách c n thi t gi a các t c n ph i  Không c n c n ph i dòng cu i cùng n gi n hóa. tab.Ví d : Text Formatting  M c tiêu : Minh h a good program và programming style  c bi t là modul hóa m c hàm và top-down design Minh h a cách i t v n n vi t code  Ôn l i và mô t cách xây d ng CT C Text formatting u vào: ASCII text. ho c end-of-file  Không có t nào quá 20 ký t  66 . v i hàng lo t d u cách và phân dòng u ra: Cùng n i dung. gi nh r ng :  1 t k t thúc b ng d u cách space. newline.

In funding Old Nassau we spend more money every year. Let's all with our accounts rejoice. Our banks shall give. Tune every heart and every voice. Bid every bank withdrawal. Bid every bank withdrawal.Ví d v Input and Output I N P U T O U T P U T Tune every heart and every voice. In funding Old Nassau we spend more money every year. while we shall live. while we shall live. Our banks shall give. In funding Old Nassau. Let's all with our accounts rejoice. We're funding Old Nassau. 67 . We're funding Old Nassau. In funding Old Nassau.

ho c EOF T t c các ký t trong 1 t ph i c in trên cùng 1 dòng  Làm sao c và in c các t c các ký t t stdin cho n khi g p space. tab xu ng dòng. tab. newline. or EOF In các ký t ra stdout ti p theo b i các d u space(s) or newline N u u vào l n x n thì th nào ? C n lo i b các d u spaces th a. và newlines t input  Làm sao có th c n ph i ? Ta không bi t c s d u spaces c n thi t cho n khi c h t các t C n ph i l u l i các t cho n khi có th in c tr n v n 1 dòng  Nh ng. Khái Thinking About the Problem niêm ³t ´ Chu i các ký t không có kho ng tr ng. các d u tabs. Bao nhiêu space c n ph i thêm vào gi a các t ? C n ít nh t 1 d u space gi a các t riêng bi t trên 1 dòng Có th thêm 1 vài d u spaces ph kín 1 dòng 68 .

nhi u backtracking s x y ra 69 .Word Dòng .Writing the Program   Key constructs T .Line Các b c ti p theo Vi t pseudocode cho hàm main() Tinh ch nh L uý: Chú thích hàm và m t s dòng tr ng vì nh ng h n ch không gian Trình t thi t k là lý t ng c b qua Trong th c t .

) { < c 1 t > if (<H t t >) { <In dòng không c n c n ph i> return 0.. } 70 .The Top Level  pseudocode hàm main()« int main(void) { <Xóa dòng> for (. } if (<T không v a dòng hi n t i>) { <In dòng có c n l ph i> <Xóa dòng> } <Thêm t vào dòng> } return 0.

) { wordLen = ReadWord(word). } if (< T không v a dòng hi n t i >) { < In dòng có c n l ph i > < Xóa dòng > } < Thêm t vào dòng > int ReadWord(char *word) { } <B qua whitespace> return 0.. <L u các ký t cho n MAX_WORD_LEN c a t > } <Tr v dài t > } < c 1 t > ngh a là gì? Vi c này khá ph c t p nên c n tách thành 1 hàm riêng « 71 . if (<H t t >) { < In dòng không c n c n ph i > return 0. < Xóa dòng > for (. int wordLen.Reading a Word #include <stdio.h>  enum {MAX_WORD_LEN = 20}. int main(void) { char word[MAX_WORD_LEN + 1].

while ((ch == ' ') || (ch == '\n') || (ch == '\t')) ch = getchar(). */ return pos.) function int ReadWord(char *word) { int ch. } ch = getchar(). /* B qua whitespace. /* L u các ký t vào t cho n MAX_WORD_LEN . pos++. } 72 . */ while ((ch != ' ') && (ch != '\n') && (ch != '\t') && (ch != EOF)) { if (pos < MAX_WORD_LEN) { word[pos] = (char)ch. pos = 0. ReadWord() Reading a Word (cont. */ ch = getchar(). /* Tr v dài t . } word[pos] = '\0'.

/* B qua whitespace. pos++. while (IsWhitespace(ch)) ch = getchar().  /* L u các ký t vào t cho n MAX_WORD_LEN . */ while (!IsWhitespace(ch) && (ch != EOF)) { if (pos < MAX_WORD_LEN) { word[pos] = (char)ch. } word[pos] = '\0'. } ch = getchar(). pos = 0.Reading a Word (cont. } Hmmm. ReadWord() ch a 1 vài o n code l p l i => tách thành 1 hàm riêng : IsWhitespace(ch) 73 . int IsWhitespace(int ch) { return (ch == ' ') || (ch == '\n') || (ch == '\t'). */ ch = getchar(). /* tr v dài t .) int ReadWord(char *word) { int ch. */ } return pos.

int lineLen = 0. line. int *lineLen) { <N u dòng ã ch a 1 s t . } if (<T không v a (*lineLen) += strlen(word). char *line. &lineLen) . enum {MAX_LINE_LEN = 50}.. char line[MAX_LINE_LEN + 1]. line. word). &lineLen).Saving a Word  Quay #include <stdio. 74 } l i main(). thêm 1 d u tr ng> return 0.h> enum {MAX_WORD_LEN = 20}. strcat(line. <Thêm t vào dòng> có ngh a là gì ?  T o 1 hàm riêng cho vi c ó : AddWord(word. <Xóa dòng> for (.) { wordLen = ReadWord(word). int wordLen. } return 0. dòng) { < In dòng có c } l > n <Xóa dòng> } AddWord(word. if (<H t t >) { void l > <In dòng không c nAddWord(const char *word. int main(void) { char word[MAX_WORD_LEN + 1].h> #include <string.

} strcat(line. thêm 1 d u tr ng. } 75 . AddWord() Saving a Word (cont. line[*lineLen + 1] = '\0'. (*lineLen)++. int *lineLen) { /* N u dòng ã ch a 1 s t .) void AddWord(const char *word. char *line. word). */ if (*lineLen > 0) { line[*lineLen] = ' '. (*lineLen) += strlen(word).

} if (<T không v a dòng>) { <In dòng có c n l > <Xóa dòng> } AddWord(word. /* N u h t t . } <H t t > và <In dòng không c n l > ngh a là gì ?  T o các hàm th c hi n  76 . */ if ((wordLen == 0) && (lineLen > 0)) { puts(line).Printing the Last Line « int main(void) { char word[MAX_WORD_LEN + 1].) { wordLen = ReadWord(word). } return 0. int lineLen = 0. in dòng không c n l . int wordLen. <Xóa dòng> for (.. char line[MAX_LINE_LEN + 1]. line. return 0. &lineLen).

line. int wordLen. /* If no more words. }  <T không v a dòng> Ngh a là gì? 77 . } return 0.) { wordLen = ReadWord(word). } /* N u t không v a dòng. */ if ((wordLen == 0) && (lineLen > 0)) { puts(line).. char line[MAX_LINE_LEN + 1]. &lineLen). <Xóa dòng> for (. return 0. int lineLen = 0. thì « */ if ((wordLen + 1 + lineLen) > MAX_LINE_LEN) { <In dòng có c n l > < Xóa dòng > } AddWord(word. print line with no justification.Deciding When to Print « int main(void) { char word[MAX_WORD_LEN + 1].

) { « /* N u t không v a dòng. numWords++.Bây gi . <In dòng có c n l > ngh a là gì ?  Rõ ràng hàm này c n bi t trong dòng hi n t i có bao nhiêu t . thì« */ if ((wordLen + 1 + lineLen) > MAX_LINE_LEN) { WriteLine(line. n trong tâm c a CT. line. <Xóa dòng> for (. <Xóa dòng> } AddWord(word. numWords).. } 78 Printing with Justification . } return 0. &lineLen). Vì v y ta thêm numWords vào hàm main «  « int main(void) { « int numWords = 0. lineLen.

i < lineLen. int lineLen.Printing with Justification (cont. int numWords) { <Tính s kho ng tr ng d th a cho dòng> for (i = 0. i++) { if (<line[i] is not a space>) <Print the character> else { <Tính s kho ng tr ng c n bù thêm> <In 1 space.)  Vi t pseudocode cho WriteLine()« void WriteLine(const char *line. c ng thêm các spaces c n bù> } <Gi m thêm không gian và m s t > } } 79 .

numWords--. i < lineLen. 2. }  Hoàn t t hàm WriteLine() « S l ng các kho ng tr ng VD: N u extraSpaces = 10 và numWords = 5.lineLen.) void WriteLine(const char *line. int lineLen. */ extraSpaces = MAX_LINE_LEN . */ for (j = 1. and 3 t ng ng 80 . else { /* Tính s kho ng tr ng c n thêm. /* Tính s kho ng tr ng d th a cho dòng.Printing with Justification (cont. */ spacesToInsert = extraSpaces / (numWords . c ng thêm các spaces ph . spacesToInsert. j. i. int numWords) { int extraSpaces. /* Gi m b t spaces và m t . 3. */ extraSpaces -= spacesToInsert. j++) putchar(' '). j <= spacesToInsert + 1. } } putchar('\n'). i++) { if (line[i] != ' ') putchar(line[i]). /* In 1 space. thì space bù s là 2. for (i = 0.1).

*lineLen = 0. *numWords = 0.. <Xóa dòng> ngh a là gì ?  Tuy n gi n. &lineLen. numWords++. } void ClearLine(char *line. } 81 . int *lineLen. &lineLen. int *numWords) { line[0] = '\0'. } } return 0. lineLen.Cu i cùng. numWords). for (. then« */ if ((wordLen + 1 + lineLen) > MAX_LINE_LEN) { WriteLine(line. addWord(word. ClearLine(line. ClearLine(line. &numWords). nh ng ta c ng xd thành 1 hàm  Clearing the Line « int main(void) { « int numWords = 0. line. &lineLen).) { « /* If word doesn't fit on this line. &numWords).

qua cac m u nh .Modularity: Tóm t t ví d V i ng i s d ng CT Input: V n b n v i khuôn d ng l n x n Output: Cùng n i dung. riêng bi t Testing : Test t ng hàm riêng bi t T ng t c : Ch t p trung vào các haanf ch m M r ng: Ch thay i các ph n liên quan  82 . nh ng trình bày c n l trái. rõ ràng. ph i. sáng s a  Gi a các ph n c a CT Các hàm x lý t : Word-handling functions Các hàm x lý dòng : Line-handling functions main() function  L i ích c a modularity c code: d ràng.

enum {MAX_LINE_LEN = 50}. } ch = getchar(). } word[pos] = '\0'. int IsWhitespace(int ch) { return (ch == ' ') || (ch == '\n') || (ch == '\t'). ch = getchar().h> enum {MAX_WORD_LEN = 20}. while (!IsWhitespace(ch) && (ch != EOF)) { if (pos < MAX_WORD_LEN) { word[pos] = (char)ch.h> #include <string. pos++. return pos. } 83 .The ´justifyµ Program #include <stdio. } int ReadWord(char *word) { int ch. pos = 0. while (IsWhitespace(ch)) ch = getchar().

line[*lineLen + 1] = '\0'. for (i = 0. extraSpaces = MAX_LINE_LEN . int lineLen. j <= spacesToInsert + 1. int *numWords) { line[0] = '\0'.1). *numWords = 0. i. (*lineLen)++. *lineLen = 0. char *line. int *lineLen. } void AddWord(const char *word. (*lineLen) += strlen(word). word). for (j = 1. } strcat(line. j. i++) { if (line[i] != ' ') putchar(line[i]). int *lineLen) { if (*lineLen > 0) { line[*lineLen] = ' '. else { spacesToInsert = extraSpaces / (numWords . spacesToInsert. } } putchar('\n'). i < lineLen. } 84 .lineLen. } void WriteLine(const char *line. int numWords) { int extraSpaces. extraSpaces -= spacesToInsert. j++) putchar(' ').void ClearLine(char *line. numWords--.

. &lineLen. &lineLen). line. for (. } 85 . } AddWord(word. int wordLen.) { wordLen = ReadWord(word). if ((wordLen == 0) && (lineLen > 0)) { puts(line). numWords).int main(void) { char word[MAX_WORD_LEN + 1]. } if ((wordLen + 1 + lineLen) > MAX_LINE_LEN) { WriteLine(line. int numWords = 0. &numWords). int lineLen = 0. } return 0. &numWords). numWords++. ClearLine(line. break. &lineLen. lineLen. char line[MAX_LINE_LEN + 1]. ClearLine(line.

Optimizing C and C++ Code  t kích th c m ng = b i c a 2 V i m ng. khi t o ch s . trình d ch s bi n l nh switch thành các nhóm if ± else ±if l ng nhau. hãy ch ng chia chúng thành các switch l ng nhau. nhóm 1 g m nh ng cases th ng g p. và nhóm 2 g m nh ng cases ít g p=> k t qu là các phép th s ít h n. trình d ch th c hi n các phép nhân.if l ng nhau. nh v y thao tác s nhanh h n t các tr ng h p th ng g p trong l nh switch lên u Khi s các tr ng h p tuy n ch n là nhi u và tách bi t. vi c th c hi n s nhanh h n Tái t o các switch l n thành các switches l ng nhau Khi s cases nhi u. N u b trí các case th ng g p lên trên. mà t o thành 1 b ng các ch s . vì v y. t c nhanh h n 86 . hãy t kích th c m ng b ng bôi s c a 2 phép nhân có th c chuy n thành phép toán d ch chuy n nhanh chóng    t các case labels trong ph m vi h p N u s case label trong câu l nh switch n m trong ph m vi h p. trình d ch s bi n i thành if ± else .

n u không s d ng ( void) L u ý ví trí c a tham chi u t i code và data Các b x lý d li u ho c mã gi c tham chi u trong b nh cache tham kh o v sau. V i C ? ( Không dùng bi n t ng th . n u c nó t b nh cache. dùng bi n c c b «) 87 .Optimizing C and C++ Code (tt)       Minimize local variables Các bi n c c b c c p phát và kh i t o khi hàm c g i. vì v y m t th i gian Khai báo các bi n c c b trong ph m vi nh nh t H n ch s tham s c a hàm V i các tham s và giá tr tr v > 4 bytes. và gi i phóng khi hàm k t thúc. Do ó nó nên mã và d li u ang c s d ng cùng nhau th c s nên c t v i nhau . Nh ng tài li u tham kh o b nh cache c nhanh h n. i u này v i object trong C + + là ng nhiên. hãy dùng tham chi u ng nh ngh a giá tr tr v .

Optimizing C and C++ Code (tt)       Nên dùng int thay vì char hay short ( m t th i gian convert ). n u bi t int không âm. String designation): m_name(name). m_destignation (designation) { } ng nh ngh a các hàm o tùy h ng : "just in case" virtual functions Các hàm g m 1 n 3 dòng l nh nên nh ngh a inline 88 . String designation) { m_name = name. m_designation = designation. } /* === Optimized Version === */ Employee::Employee(String name. hãy kh i t o giá tr cho bi n Hãy dùng danh sách kh i t o trong hàm kh i t o Employee::Employee(String name. hãy dùng unsigned int Hãy nh ngh a các hàm kh i t o n gi n Thay vì gán.

C++ typedef unsigned int uint. } 89 . } int div32s (int a){ return a / 32.M t vài ví d t i u mã C. uint div32u (uint a) { return a / 32.

break. letter = classes[queue]. else if ( queue == 1 ) letter = 'S'.switch ( queue ) { case 0 : letter = 'W'. break. else letter = 'U'. } Ho c có th là : if ( queue == 0 ) letter = 'W'. case 2 : letter = 'U'. break. 90 . static char *classes="WSU". case 1 : letter = 'S'.

min) int fact1_func (int n) { int i. fact = 1. i <= n. for (i = 1.(x >= min && x < max) có th chuy n thành (unsigned)(x . for (i = n. return (fact).min) < (max . i++) fact *= i. i--) fact *= i. vi phép th != n gi n h n <= 91 . } Fact2_func nhanh h n. i != 0. } int fact2_func(int n) { int i. fact = 1. return (fact).

i++) { if( list[i] == -99 ) { found = TRUE. !\n").T i u o n code sau : found = FALSE. for(i=0. } } if( found ) printf("Yes.i<10000. there is a -99. 92 .

0.Floating_point So sánh : x = x / 3. exp và log (ch m g p 10 l n * ) L u ý : n u x là float hay double thì : 3 * (x / 3) <> x. Th m chí th t tính toán c ng quan tr ng: (a + b) + c <> a + (b + c). Và x = x * (1. 93 . ? (bi u th c h ng c th c hi n ngay khi d ch) Hãy dùng float thay vì double Tránh dùng sin.0) .0/3.

5 thay vì x / 2.     Tránh dùng ++. x+x+x thay vì x*3 M ng 1 chi u nhanh h n m ng nhi u chi u Tránh dùng quy 94 . -.0. vd while ( n--) {«} Dùng x * 0.trong bi u th c l p .

95 .