1. Trang chủ
  2. » Công Nghệ Thông Tin

Kỹ năng lập trình part 2 pot

39 172 0
Tài liệu được quét OCR, nội dung có thể không chính xác

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 39
Dung lượng 677,73 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Việc thực thi một macro ở mọi vị trí xuất hiện của nó sẽ làm cho chương trình đã dịch trở nên lớn ra, Các hàm inline cla C++ cũng có trở ngại này.. vì cần phải thay đổi chương trình ít

Trang 1

biết vị trí kết thúc tập tin một cách tường minh:

getchar (})} != EGF š& isupper(c}

? size = ROUND TO INT(sqrt (dx*ax + dy*dy);

Đoạn chương trình trên thực hiện phép tính lấy căn bậc hai một số gấp đôi số lần cần thiết Ngay cả khi được cho các đối số đơn giản, một biểu thức phức tạp như phần thân của macro ROUN3_=O TNT sẽ được dịch thành nhiều chỉ thị, mà lẽ ra nên được đặt trong chỉ một hàm để gọi ra khi cần

Việc thực thi một macro ở mọi vị trí xuất hiện của nó sẽ làm cho chương

trình đã dịch trở nên lớn ra, (Các hàm inline cla C++ cũng có trở ngại này)

Đồng ngoặc phần than cia macro và các đối số

Nếu bạn vẫn muốn dùng macro, hãy cần thận Maero làm việc theo cách thay thế nguyên văn: các tham số trong định nghĩa được thay thế bằng các đối số của lời gọi và biểu thức của macro thay thế nguyên văn lời gọi macro Đây là điều khác biệt khó chịu so với hàm Biểu thức

Trang 2

#define square(x; ((xi*(x}) Tắt cả các đầu ngoặc đơn trên đều cần thiết Và việc dùng dấu ngoặc cho đúng bên trong macro cũng vẫn còn chưa giải quyết dược van dé tinh toán nhiều lần Nếu một thao tác thông dụng trong chương trình, ta hãy ding ham cho thao tác đó

Trong C++, các hàm iae tránh được vấn đẻ về cú pháp trong khi vẫn có thể cho được ưu thé € tốc độ thực thi như macro Chúng thích hợp

cho các hàm ngắn đùng để gán hoặc lấy một giá trị đơn lẻ

Bài tập 1-9 Xác định lỗi trong định nghĩa macro sau:

? #define ISDIGIT{c) { SO’) && (a <- 19873) 2 1: 6

1.5, Cae sé téi nghĩa

SỐ tối nghĩa là các hằng số, kích thước mảng, vị trí ký tự, hệ số chuyển đối và những giá trị số khác xuất hiện trong chương trình

Đặt tên cho các số tỗi nghĩa

Nguyên tắc chung là tất cả giá trị số trừ 0 và 1 đều có thế xem là tôi

nghĩa và nên được đặt tên cho nó, Một con số trong mã nguồn của chương trình sẽ không thể cho biết gì về tầm quan trọng cũng như xuất xứ của nó, làm cho chương trình trở nên khó hiểu và khó sửa đổi Doạn trích sau được trích ra từ một chương trình xuất ra một biểu đề về tần số của kỹ tự trên một

màn hình văn bản 24x80 thật sự khó hiểu một cách không cần thiết vì sự

xuất hiện của một loại các số tối nghĩa:

Trang 3

số chữ trong bảng chữ cái Nhưng không có một con sô nào trong 3 số trên xuất hiện trong doạn mã nguồn điều này cảng làm cho những piá trị số kia trở nên kỳ bí

+ — 4 /* height of bars */

WIDTHS = (MAXCOL - 2} /NLET/* width of pars */

Trang 4

giờ những gì vòng lặp chính thực hiện đã trơ nên rõ ràng hon:

đó là một vòng lặp rất thích hợp chạy từ 0 đến xzz?-:, cho biết rằng vòng lặp chạy trên các phần tử của đữ liệu Cũng vậy, lời gọi đến hàm araw cũng

dễ hiểu hơn vì các từ như MAXROM và MĩwCor nhắc ta nhớ thứ tự các đối số Điều quan trọng nhất là đoạn mã nguồn trên đã có thể chạy được với kích

thước mân hình hoặc kiểu dữ liệu khác Các giá trị số đã không còn kỳ bí

nữa, và cả chương trình cũng vậ

Định nghĩa các con số dưới dạng hằng số, không ding macro

quản lý các giá trị của số tôi nghĩa Tuy bộ xử lý trước của C là một công cụ

Các lập trình viên C thường dùng theo truyền thing der

mạnh nhưng lại kém thông minh và dùng macro là một cách lập trình nguy hiểm vì macro thay đổi cấu trúc của chương trình Hãy dùng ngôn ngữ đúng đắn để thực hiện công việc Trong C và C++, các hằng số nguyên có thể được định nghĩa bằng phát biểu enum, như ta thấy trong ví dụ trước, Hang sé mọi loại có thể được định nghia bang const trong C++:

Trang 5

const int MAXROW = 24, MAXCOI BO;

hoac bang fina! trong Java:

static final int MAXROW - 24, MAXKCOL = 80;

€ cũng có các giá trị const nhưng không dùng được làm phần tử biên của mảng, do đó phát biểu sauø vẫn là phương pháp được chọn trong

dé hiểu vai trò của chúng Ví dụ, dùng (void+)0 hay wưru cho một con trỏ

rỗng trong C, và dùng *\2⁄ thay vì 0 cho byte rỗng ở cuối một chuỗi Nói

44

Trang 6

cách khác, đừng viết:

? sure e

mà hãy viết:

Chúng tôi thích dùng những hằng số tường minh khác nhau, va ding

số 0 để chỉ giá trị số nguyên, vì mỗi hằng số như vậy biểu thị từng công dụng của giá trị 0 và vì vậy cung cấp được thêm chút ít thông tin về số 0 dé Tuy nhiên, trong C++, ky hiệu được chấp nhận cho một con trỏ rỗng lại là ø hơn là RULL Còn Java giải quyết vấn để này tốt hơn cả bằng cách định nghĩa từ khóa nu1: cho một tham chiếu đối tượng không trỏ đến một cái gì

ca

Dùng chính ngôn ngữ đó để tính toán kích thước của đối tượng

Đừng đùng một giá trị kích thước tưởng minh cho bất kỳ kiểu dữ

liệu nào; ví dụ, hãy dùng s¡zeof;¡at) thay vì giá trị 2 hay 4 Cũng lý do

tương tự, sizeof(array[0]) tốt hơn of:in:! vì cần phải thay đổi

chương trình ít hơn khi kiểu mảng thay đ

Ham sizeof déi khi là một cách thuận tiện giúp tránh phải dùng thêm tên cho giá trị kích thước mảng, Ví dụ, nếu ta viết:

char buf (10247;

fgets(buf, sizeof(buf}, stdin };

thì kích thước của bộ đệm vẫn còn là một số tối nghĩa, nhưng chỉ xuất hiện

có một lần trong phần khai báo Có thẻ không cần thiết phải đặt tên cho kích

thước của một mảng cục bộ, nhưng rất cần thiết viết mã nguồn sao cho không phải sửa đổi lại nếu kích thước hay kiểu mang thay đôi

45

Trang 7

Bài tập 1-10 Hãy viết lại các định nghĩa sau đây để giám thiểu nguy

Trang 8

1.6 Cha thich

Chú thích đảnh cho việc giúp người dọc chương trình, Chú thích giúp người đọc không phải bằng cách nhắc những điều mã nguồn đã nêu, hay bằng cách phủ nhận mã nguồn cũng như không phải bằng cách làm rồi trí người đọc với cách trình bày phức tạp mà còn mắc lỗi Chú thích tốt nhất trợ giúp cho sự thấu hiệu một chương trình bằng cách chị ru một cách ngăn

gọn những chí tiệt đáng chú ý hoặ

bằng cách cung cấp một vải nhìn chỉ tiết

hơn về tiên trình của chương trình

Đừng cô găng chủ thích những diều hiển nhiên

Chú thích không nên trình bày lại những thông tín tự nó đã rõ, Dưới

47

Trang 9

nhung néu hành động đã hiển hiện rõ ràng, nhắc lại thành lời văn là vô

Những chú thích trên cũng nên xóa đi, vì tên dược chọn cần thận đã

tự truyền tải thông tín

Chủ thích cho hàm và dữ liệu toàn cục

Chú thích rõ ràng là có thể có ích Ta chú thích cho các hàm, các

biến toàn cục, các định nghĩa hằng, các trường trong các cầu trúc và lớp, và tất cả những gì mà một lời tóm tất ngắn gọn có thể giúp cho việc nắm bất chương trình

Các biển toàn cục có xu hướng làm thành từng cụm nằm rải rác

struct State ( /* tiếp đầu ngũtdanh sách tiếp vì ngữ */

chay *pref[NPREF); /* tù tiếp đầu ngữ */ 48

Trang 10

Đôi khi mã nguồn khó thực sự có thể vì thuật toán phức tạp hoặc vì cấu trúc đữ liệu rắc rối khó hiểu Trong trường hợp đó một lời,chú thích giúp cho người đọc hiểu được bản chất của vấn đề Cũng rất có giá trị khi gợi ý lý do vì sao đã thực hiện một rẽ nhánh, Chú thích dưới đây giới thiệu một sự thi hành rất hiệu quả một khai triển hàm eos rời rạc dùng trong một

* 32 - bit integer arithmeric (8 - bic coefficients)

* 12 multiplies, 29 adds per DCT

49

Trang 11

}

Chú thích hữu ích này cho biết ra tài liệu tham khảo, mô tả ngắn gọn

dữ liệu sử dụng trình bảy ngắn gọn khả năng thực thí của thuật toán, và cho biết bằng cách nào vả tại sao thuật toán gốc được sứa chữa

Đừng chủ thích cho những doạn mã nguằn thở mà hãy viết lại nó Hãy chú thích những gì bất thường hay có khả năng pây nhằm lẫn nhưng khi chú thích trở nên lấn át mã nguồn chương trình thì cần xem xét sửa chữa mã nguồn Ví dụ sau đây đùng một chủ thích dài rối ram va ding

một phát biểu điều kiện biên dich cho phát biểu pzint£ để giải thích cho

Trang 12

là ở tên biến rc t khó hiểu Một tên có tính gợi nhớ hơn như

hfoungd, sẽ làm cho chú thích trở nên không cân thiết, cũng không cân luén phat biéu prince

Cho dù nguồn gốc của sự thiểu nhất quán là gì di nữa, một chú thích mâu thuẫn với mã nguồn chương trình sẽ gây nhằm lẫn và rồi phải tốn một khoảng thời gian dài để sứa lỗi một cách vô ích vì nhằm tưởng một chú thích sai là đúng, Khi thay đổi mã nguồn hãy luôn chắc chắn rằng chú thích

vẫn luôn được chính xác

Chủ thích không phái chỉ nên khớp với mã nguồn mà còn nên trực tiếp giải thích cho mã nguồn Chú thích trong ví dụ sau là đúng - nhằm giải thích cho mục đích của hai dòng kế tiếp - nhưng có vẻ như mâu thuẫn với

mã nguồn: vì chú thích giái thích về ký tự xuống, dong con ma nguồn lại nói

về khoảng trăng:

2 TỶT€ (&ÁPOW)7

? srrcpy(date, ctime [&now};;

? ⁄* bộ ký bự xuống động đã được copy tx ctime */

Trang 13

Ma nguồn và chủ thích bây giờ đã khớp với nhau, nhưng vẫn có thể

cải tiễn thêm cả hai bằng cách viết cho trực tiếp hơn Vấn đề là phải

Biểu thức sau cùng trên phù hợp với đặc tính của C dùng để xóa ký

tự cuối cùng trong một chuỗi Mã nguồn bây giờ đã ở nên ngắn gọn, phù

hợp với đặc tính của ngôn ngữ, sáng sủa, và chú thích đã trực tiếp giải thích

được lý do vì sao đưa vào chú thích như vậy

Rõ ràng, không gây nhằm lan

Chủ thích được coi là để giúp cho người đọc ở những chỗ khó chứ không phải để gây thêm khó khăn cho ho Vi dụ sau day theo đúng nguyên

tắc đưa chú thích cho các hàm và giải thích các đặc tính bất thường; nhưng

ngược lại, hàm được dùng là hàm scremp va dac tính bất thường nằm ngoài công việc cần thực hiện, cài đặt theo giao tiếp chuẩn thông thường:

52

Trang 14

2 int strempichar *sl, char 7s2 }

trước và sau trong phần chú thích trên chưa đúng Ở đây ta đã quá thôi

phông để nói lên rằng thủ tục này rất khó biểu, nhưng vì nó cài đặt một hàm chuẩn, lời chú thích có thể giúp ích theo cách tóm tắt các hành động và cho biết các định nghĩa bắt đầu ở đâu; đó là tất cả những gì cần thiết:

/* Hăm strcme; trả về < Ô nếu s!<s2 „ > 0 nếu $1

Trang 15

Các sinh viên thường được dạy rằng cần chú thích mọi thứ Những lập trình viên chuyên nghiệp thường được yêu cầu phải chú thích tất cả mã nguồn của họ, Nhưng mục đích của chú thích có thể không giữ được nếu cứ tuân theo những nguyên tắc đó một cách mù quáng Chú thích là phương tiện để giúp cho người đọc Hiểu những phần chương trình không dé hiểu nêu chỉ có mã nguẫn chương trình Hãy viết mã nguồn cảng để hiểu cảng tốt; làm được điều này tốt chừng nảo thì cảng cần ít chủ thích chừng đó Mã nguồn viết tốt cần ít chủ thích hơn là mã nguồn viết do,

Bài tập 1-11 Hãy bình luận những lời chú thích sau:

line namber = line nuMer + 1;

f £ (fout, do ots\n$d as\n"%,

// tăng biến line nuber

? line mueber = lìr

‹4

Trang 16

1.7 Vi sao phải lo lắng về phong cách lập trình?

Trong chương này ta đã nói về những điều quan tâm chủ yếu trong, phong cách lập trình: tên có tính gợi nhớ sự sáng sùa trong các biêu thức, dòng điều khiển rõ ràng: mã nguồn và chú thích đễ hiểu và tầm quan trọng của việc dùng một cách nhất quán các cách viết được quy ước cũng như các cách viết phù hợp với đặc tính của ngôn ngữ trong việc đạt được những điều

trên Không thể chối cãi rằng những điều này là vô ích

Nhưng vì sao lại phải lo lắng về phong cách? Có ai quan tâm đến hình thức bên ngoài của chương trình một khi nó chạy tốt? Không phải là sẽ mất nhiều thời gian hơn để làm cho chương trình trông đẹp mắt hơn sao? Không phải là các quy tắc dù sao cũng đều là tùy ý sao?

Câu trả lời là mã nguồn chương trình được viết tốt sẽ dé đọc và dễ

hiểu hơn, và hầu như chắc chắn là ít lỗi hơn, và có khả năng có kích thước

nhỏ hơn so với mã nguồn được chấp vá cầu thả và không hề trau chuốt Trong tình huống cấp bách cần hoàn thành chương trình cho kịp với một thời hạn nào đó, thường vấn đề phong cách đễ bị gác sang một bên đề giải quyết sau Quyết định này có thể sẽ phải trả giá đất

Quan điểm cơ bản là phong cách tốt phải là vẫn để thói quen, Nếu ngay từ ban đầu khi viết mã nguồn bạn đã nghĩ đến vấn đề phong cách, và nếu bạn dành thời gian để duyệt lại và cải tiễn bạn sẽ tập cho mình một thói quen tốt Một khi đã trở nên quen, tiềm thức của bạn sé trợ giúp cho bạn trong nhiều chỉ tiết vụn vặt, và ngay cả khi bạn phải viết mã nguồn trong trạng thái chịu áp lực công việc cao, mã nguôn của bạn cũng sẽ tốt hơn

55

Trang 17

Chuong 2

CAU TRÚC DỮ LIỆU VÀ GIẢI THUẬT

Nghiên cứu về thuật toán và cầu trúc dữ liệu là nên táng của ngành

khoa học máy tính, nó bao gồm nhiều kỹ thuật tinh tế và phân tích toán học phức tạp Một thuật toán hay một cầu trúc dữ liệu tốt sẽ giúp giái quyết một bài toán chỉ trong vài giây, ngược lại sẽ phải mắt nhiều năm mới giái được

Trong các lĩnh vực chuyên biệt như đỗ họa, cơ sớ dữ liệu, phân tích

cú pháp, phân tích số học, và mô phỏng, khả năng giải các bài toán này phụ thuộc rất nhiều vào thuật toán và cấu trúc dữ liệu có tốt hay không Nếu bạn cài đặt các chương trình mà mình chưa thực hiện bao giờ, thì bạn phải tìm được những vấn để liên quan đã được giải quyết rồi Đừng lãng phí thời gian cho những vấn đề phức tạp mà đã được làm tốt rồi

Mọi chương trình đều phụ thuộc vào thuật toán và cấu trúc dữ liệu,

nhưng có một số lại cần đến sự sáng tạo ra các phương pháp mới hoàn toản Ngay cả đối với một chương trình khá phức tạp như trình biên dịch hay trình

duyệt Web, đều dùng hầu hết các cấu trúc đữ liệu là mảng, danh sách liên kết, cây, và bảng băm Một chương trình đòi hỏi sự tối ưu nó sẽ phải dựa trên những cái đơn giản Do đó, đối với các lập trình viên nhiệm vụ là phải biết cách áp dụng những thuật toán và cấu trúc đữ liệu nào sẵn có phù hợp với bài toán của mình

Tóm lại, chỉ có một vải thuật toán cơ bản được dùng trong hầu hết các chương trình tìm kiếm và sắp xếp cơ bản thậm chí còn thường được đưa vào thư viện dùng chung Tương tự, mọi cấu trúc dữ liệu cũng dẫn xuất

từ các cầu trúc dữ liệu cơ bản VÌ vậy, nội dụng trong chương này cũng sẽ quen thuộc với hau hết các lập trình viên Chúng tôi đã dưa ra vải phiên bản sẵn có để thảo luận và bạn có thể cài đặt cụ thể nếu cần thiết, nhưng bạn nên

56

Trang 18

tìm hiểu những gì ngôn ngữ lập trình và các thư viện đã cung cấp trước khi

2.1 Tìm kiếm

Cấu trúc mảng là lựa chọn tốt nhất đề lưu trữ dữ liệu dạng bảng tĩnh

Việc khởi tạo các máng lúc biên địch sẽ rất dễ và ít tốn kém (Trong Java, quá trình khởi tạo dién ra tại thời điểm thực thi chương trình, nhưng điều này không quan trọng lắm trong việc cài đặt chỉ tiết trừ khi kích thước mảng khả lớn) Ví dụ chương trình phát hiện ra các từ được dùng khá nhiều trong

một đoạn văn rườm rà, ta có thể viết như sau:

Thủ tục tìm kiếm phải cần biết có bao nhiêu phần tử có trong mảng,

Ta có thể đưa kích thước của mảng làm tham số đầu vào; hoặc cach ta dùng

ở đây là đánh đấu cuối mang bang NULL:

/* Hàm lookup : tìm kiêm tuần tụ các hàm trong mảng */ int lookup(char *word , char *array(]]

for (i= 6¿ arrayl[i] != NULL; i++}

if (strcmp(word, arrayli]) == 0)

return ij;

return -1;

Trang 19

Trong C va C++, ta co thé khai béo mang kiéu chudi nhu sau: char

y[- hay chay “*arrsy Mặc dù 2 cách này là tương đương, nhưng

ch thứ nhất cho ta thấy cách sứ dụng tham số rõ ràng hơn

Thuật toán tìm kiêm trên được gọi là (ừm kiếm mẫn tự vì nó sẽ tìm

lần lượt từng phần tử để tìm ra phần tử mong muốn Khi số lượng các phần

tử tương đối nhỏ, phương pháp tìm kiếm tuần tự thực hiện đủ nhanh Các thư viện chuẩn cũng hỗ trợ cdc ham tim kiếm tuần tự cho các kiểu đữ liệu khác nhau chẳng hạn như hàm s:reh+ và scrstr: tìm ra ký tự hay chuỗi con đầu tiên trong mét chudi C hay C++, trong Java lớp s

zing cũng có hàm tương tự indexo?, và thuật loắn tìm kiểm tổng quát trong C++ được

ứng dụng với mọi kiểu đữ liệu Do đó nêu một hàm nào đó có thể dùng được với kiêu đữ liệu của bạn, thì bạn có thể dùng hàm đó

Phương pháp tìm kiếm tuần tự rất đễ, tuy nhiên số phép thực hiện tỷ

lệ với số lượng dữ liệu được tìm kiểm; nếu gấp đôi số lượng phần tứ thì thời gian tìm kiểm cũng sẽ nhân đôi trong trường hợp phản tử cần tìm không xuất hiện trong mảng Do thời gian thực hiện tuyến tính với kích thước đữ liệu nên phương pháp này còn được gọi la far kiểm tuyển tỉnh,

Sau đây là đoạn chương trình mỉnh họa kiêu đữ liệu máng được trích

từ chương trình phân tích từ loại HFML trong đó định nghĩa các từ dựa trên hơn 100 ký tự đơn:

58

Ngày đăng: 10/08/2014, 06:23