Lập trình cấu trúc

8 1.1K 2
Lập trình cấu trúc

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

Thông tin tài liệu

Lập trình cấu trúc

Lập trình cấu trúc trên BP7Lê Minh HoàngLập trình là một công việc khó đòi hỏi phải có tư duy nhanh nhạy và sự tuân thủ kỷ luật nghiêm ngặt trong phong cách lập trình. Tư duy tốt để có thể nắm bắt được cấu trúc bài toán và tìm ra cách giải, còn phong cách tốt là để biến tất cả những cố gắng của trí não và đôi tay thành kết quả cuối cùng. Một điều rất hay thấy ở người mới học lập trình là có thể họ nắm bắt được thuật toán rất nhanh nhưng do cách làm việc thiếu hiệu quả nên tiêu tốn rất nhiều thời gian thậm chí càng làm càng bị rối trong hết lỗi này đến lỗi khác. Như vậy một phong cách lập trình tốt trước hết phải là một phong cách viết chương trình có xác suất xảy ra lỗi thấp nhất, và cho dù có xảy ra lỗi thì cũng dễ dàng chỉnh sửa. Còn việc viết các chương trình cỡ trung bình và lớn mà không có lỗi thì trừ khi sau này người ta sáng tạo ra các máy lập trình chứ nhân loại thì chẳng có ai viết chương trình máy tính mà không có lỗi cả.Ta sẽ phân tích hai vấn đề: 'Làm thế nào để hạn chế lỗí và 'nếu có lỗi thì tìm và sửa thế nàó.Hạn chế lỗi thường được quyết định bởi hai yếu tố:Môi trường lập trình và phong cách lập trình. Cách đây vài chục năm với một máy tính cỡ lớn dùng băng đục lỗ, thì rõ ràng khả năng hạn chế và tìm lỗi là rất ít bởi mọi lỗi đều dẫn tới kết quả sai hoặc treo máy, hay với một ngôn ngữ lập trình cấp thấp thì ta chỉ có thể viết những đơn vị chương trình nhỏ mà thôi, bởi tính phi cấu trúc của nó làm cho số lỗi ước tính sẽ tăng theo bình phương chiều dài chương trình. Như vậy, xét cho cùng, phải phát triển các ngôn ngữ lập trình (ADA, PASCAL, C++, BASIC) và chương trình dịch (TP, Borland C, Delphi, VB), phải sáng tạo ra các cách thiết kế (Từ trên xuống, hướng sự kiện, hướng đối tượng) chính là để giảm bớt công sức cho các lập trình viên trong việc sửa lỗi để có thể tạo ra những sản phẩm lớn hơn, hoàn thiện hơn, ít lỗi hơn. Rất may cho chúng ta là được làm việc với thế hệ máy tính nhanh, ổn định và thân thiện như ngày nay và với một trình biên dịch như BP7 có khả năng bắt lỗi rất tốt và hỗ trợ lập trình cấu trúc.Phong cách lập trình cấu trúc trên BP7 nên thế nào để hạn chế lỗi?- Viết một chương trình trên BP7 phải tuân theo các bước: Tìm hiểu yêu cầu bài toán → tìm thuật toán → xây dựng cấu trúc dữ liệu và dựng giải thuật → Viết chương trình + Thử + Sửa lỗi → Nâng cấp → Hoàn thành. Không được đảo lộn hay bỏ qua bước nào. Lưu ý riêng bước viết chương trình + thử + sửa lỗi, không phải ta viết xong cả chương trình rồi mới thử mà khi có bất kỳ cơ hội nào để thử chạy chương trình (dù là chỉ xong một phần nhỏ) ta chạy thử ngay để có thể tạm yên tâm rằng phần vừa viết không có lỗi.- Viết chương trình theo đúng thiết kế từ trên xuống, đầu tiên viết chương trình chính trước, gồm các bước rất tổng quát, tiếp theo cụ thể hoá từng bước bằng cách viết các chương trình con tương ứng, thậm chí đôi khi tại mỗi bước cụ thể hoá ta chỉ làm đến mức độ nào đó rồi lại viết tiếp các chương trình con v.v…cách làm này dựa trên nguyên tắc 'chia để trị' rất hiệu quả và đã được thực tế chứng minh. Có một vài ý kiến còn cho rằng, để tiện quan sát, tất cả các chương trình con viết theo cách trên không nên có độ dài quá một trang màn hình. Một số người có thói quen viết chương trình cứ từ đầu chí cuối, làm hết chương trình con rồi đến chương trình chính. Cách làm như vậy không logic một chút nào bởi khi chưa viết ra chương trình chính, ta đâu đã xác định được nhiệm vụ của các chương trình con, lại càng không xác định được là phải truyền cho chương trình con bao nhiêu tham số và là những tham số nào. Đối với chương trình nhỏ thì có thể không nhận thấy điều đó nhưng với những chương trình lớn thì cách làm như trên sẽ phải trả giá rất đắt bằng rất nhiều động tác xoá đi viết lại.- Viết chương trình thì khó tránh phải lỗi cú pháp (Syntax), thiếu dấu thiếu chữ trong việc soạn chương trình cũng là thường tình. Các lỗi thiếu ';', thiếu ngoặc, thiếu ':', tên chưa khai báo, v.v…thì chỉ cần trình biên dịch báo lỗi đúng chỗ đó là sửa được ngay. Cái lỗi cú pháp sửa mất nhiều thời gian nhất là lỗi sai cấu trúc khối (Có 'begin', thiếu 'end;' hay có 'repeat' thiếu 'until' v.v…). Trình biên dịch không thể chỉ ra được chỗ thiếu bởi ví dụ như có 'begin' mà không có 'end;' thì chữ 'end;' thiếu có thể cho ở nhiều nơi khác nhau mà vẫn hợp lý cả. Trình dịch chỉ thông báo lỗi chung chung là thiếu ';' mà thôi và như vậy thời gian của chúng ta lại lãng phí vào việc dò trong cả chương trình xem thiếu chỗ nào. Trong khi lỗi đó sẽ không bao giờ xảy ra nếu như khi soạn chương trình, mỗi khi gõ xong phần mở khối thì ta gõ luôn phần kết khối và lùi vào gõ đoạn giữa khối sau. Điều đó không những làm cho khối lệnh được sáng sủa, mở khối kết khối thẳng hàng mà còn làm ta không phải bận tâm gì về lỗi thiếu cấu trúc khối nữa.- Đặt tên gợi nhớ chức năng, không ngại đặt tên dài, trước khi dùng biến phải cân nhắc xem tầm hoạt động của nó là địa phương hay toàn cục, nhiệm vụ của nó để làm gì. Nên đặt tên tiếng Anh bởi nếu đặt tiếng Việt khi viết vào máy tính không có dấu dễ bị hiểu theo nghĩa khác. Còn một số việc nhỏ nữa tuy không quan trọng lắm: Từ khoá viết thường, tên thủ tục và hàm chuẩn viết hoa đầu từ tiếng Anh. Ví dụ: not, xor, and, or, mod, div, SizeOf, LongInt, Integer, Abs, Sqrt, Sin, Cos, v.v… Các tên định nghĩa trong chương trình khi khai báo viết hoa, thường thế nào thì thống nhất trong cả chương trình viết hoa, thường như thế. Sau dấu phân cách từ (phẩy hoặc chấm, chấm phẩy…) nên có 1 dấu cách, trước và sau dấu gán := đều có dấu cách. Đọc thêm các chương trình mẫu của Borland để rõ điều này.- Hạn chế tối đa việc viết các thủ tục và hàm lồng nhau quá nhiều cấp, gây rối trong việc đọc chương trình.Nếu ta viết chương trình mà bị lỗi thì sửa như thế nào?Như đã nói ở trên, ta nói sửa lỗi ở đây là sửa lỗi sai trong cài đặt thuật toán chứ không nói đến lỗi syntax nữa. Muốn sửa lỗi cài đặt giải thuật thì về cơ bản các kỹ thuật gỡ rối là khoanh vùng xác định lỗi tức là thu hẹp phạm vi dò tìm tới khi xác định chính xác lỗi và sửa.Lỗi chương trình xảy ra khi ta có một bộ dữ liệu cho vào chương trình chạy được kết quả không theo ý muốn. Khi đó ta sử dụng trình gỡ rối Debugger của BP7 như sau: Bước 1: Mở cửa số Watches theo dõi giá trị bằng cách bấm Ctrl + F7 hay chọn menu Debug/Ađ Watch. Gõ tên biến hay biểu thức cần theo dõi, tên biến sẽ hiện ra trong cửa sổ Watches. Dùng phím F6 để luân chuyển hoạt động giữa cửa sổ soạn thảo và cửa sổ Watches. Bấm Ctrl + F5 hay chọn menu Window/Size/Move sau đó điều chỉnh vị trí và kích thước hai cửa sổ sao cho phù hợp nhất, tốt nhất không nên che nhau. Bước 2: Bấm F8 (Run/ Step over) để thực hiện chương trình từng bước, khi đó trên cửa sổ soạn thảo sẽ có một vạch ngang cho biết chương trình đã chạy tới dòng nào. Mỗi lần bấm F8 thì chương trình chạy đúng 1 dòng và dừng lại, thông báo giá trị các biến được theo dõi trong cửa số Watches. Nhớ rằng mỗi lần chạy qua 1 bước, ta phải tự tính xem, nếu đúng thì giá trị biến theo dõi phải là bao nhiêu và so sánh với kết quả trong cửa sổ Watches, nếu giống thì dò tiếp, nếu sai thì chắc chắn dòng lệnh vừa chạy qua là dòng lệnh gây lỗi, ta đã khoanh vùng được một lần.Bước 3: Nếu dòng lệnh gây lỗi chỉ là một dòng lệnh tương đối đơn giản: như biểu thức số học chẳng hạn thì nhiều khả năng do ta gõ sai hoặc gõ thừa thiếu một yếu tố gì đó, ta xem kỹ lại biểu thức đó và sửa. Nhưng nếu dòng lệnh gây lỗi lại là lời gọi chương trình con thì sao. Ta dừng việc gỡ rối bằng cách bấm Ctrl + F2 (Run/ Program reset) và bắt đầu lại từ đầu, chỉ có điều khi đến dòng lệnh gây lỗi ta không bấm F8 chạy qua nữa mà ấn F7 (Run/ Trace into) để trình gỡ rối truy vết vào chương trình con và lại thực hiện chạy từng bước (Step over − F8) hay truy vết (Trace into − F7) tiếp tục thu hẹp phạm vi tìm lỗi.Lưu ý:1. Cửa sổ Watches có thể theo dõi cùng lúc nhiều biến2. Để tiết kiệm thao tác cho đỡ phải bấm F8 quá nhiều ta có thể di chuyển con trỏ tới một dòng và bấm F4 (Run/ Go to cursor) để cho chương trình sẽ chạy tới dòng đó thì dừng lại, hiện ra vạch ngang và từ đó gỡ rối tiếp.3. Khi gỡ rối ta phải dùng khá nhiều cửa sổ, chính vì vậy mà những cửa sổ nào không cần nhất thiết nên đóng lại để khỏi tốn bộ nhớ và che lấp các cửa sổ có ích. 4. Ta cần phải kết hợp cả kỹ thuật đưa giá trị trung gian ra màn hình và tạo điểm dừng theo điều kiện để tiện gỡ rối vòng lặp, ví dụ:Xét đoạn chương trìnhfor i := 1 to 1000 dofor j := 1 to 1000 dobeginS1;S2; end;Giả sử ta biết được lệnh S1 là lệnh gây lỗi, nhưng không phải lúc nào cũng lỗi, nó chỉ gây lỗi khi i = 501 và j =1000 (điều này có thể biết được bằng cách đưa giá trị trung gian của i và j ra màn hình). Nếu ta sử dụng lệnh chạy từng bước F8 thì không ổn bởi như vậy ta sẽ phải bấm 500x1000 lần. Khi đó ta làm như sau, di chuyển con trỏ đến dòng chứa lệnh S1. Chọn Debug/ Ađ breakpoint. Gõ vào ô Condition điều kiện: (i = 501) and (j = 1000) sau đó bấm Enter để máy nhận. Cuối cùng chỉ việc bấm Ctrl+F9 để chạy, khi chạy đến dòng chứa lệnh S1 mà có i = 501 và j = 1000 thì máy sẽ dừng và hiện vạch ngang cho gỡ rối tiếp (gỡ theo vết vào chương trình con S1 chẳng hạn).5. Cuối cùng, rất quan trọng trong gỡ rối là phải xác định chính xác lỗi, đi sửa lung tung theo kiểu 'có bệnh vái bốn phương' là điều tối kỵ, bởi sửa không đúng chỗ thì lỗi ngày càng tai hại.I. Một vài kỹ thuật nhỏ trong BP7 1. Break, Continue, Exit, Halt và Goto.Trong một vòng lặp, nếu gặp lệnh Break thì vòng lặp đó sẽ bị ngừng vô điều kiện.Ví dụ: Nhập vào hai số x và y, tính thương của x/y. Quá trình cứ tiếp tục cho tới khi nhập y = 0:repeatReadln(x, y);if y = 0 then Break;Writeln(x / y);until False; {Không cần điều kiện thoát}Trong một vòng lặp, nếu gặp lệnh Continue thì toàn bộ lệnh của vòng lặp nằm phía sau continue sẽ bị bỏ qua, máy kiểm tra ngay điều kiện xem còn lặp tiếp không, nếu còn lặp tiếp thì làm lần lặp kế tiếp luôn.Ví dụ:Nhập vào số x kiểu LongInt và kiểm tra dữ liệu Abs(x)≤ 46340; nếu đúng, in ra x2, nếu không bắt nhập lại. (Bởi 463412 tràn phạm vi LongInt)repeatReadln(x);if Abs(x) > 46340 then Continue;Writeln(Sqr(x));until Abs(x) <= 46340; Trong một chương trình con, nếu chạy tới lệnh Exit thì chương trình con sẽ thoát ra ngay.Chạy tới lệnh Halt ở bất cứ nơi đâu, chương trình sẽ dừng vô điều kiện. (Điều này tương đương với lệnh Exit nằm ở thân chương trình chính}Bốn lệnh kể trên không có ở mọi thế hệ PASCAL. Nói chung cũng có những cấu trúc tương đương để thay, nhưng dùng được các lệnh này một cách uyển chuyển và hợp lý sẽ làm cho đỡ tốn công sức nhiều, (đặc biệt là Break và Exit).Để dễ nhớ công dụng, ta có thể quan niệm như sau: Break là Goto tới một nhãn ngay phía dưới bên ngoài vòng lặp. Continue là Goto đến điểm kiểm tra điều kiện lặp. Exit là Goto tới cuối chương trình con (chữ End;). Còn Halt thực sự không phải lệnh Goto.Nói chung, Goto là lệnh phi cấu trúc nên ta cố gắng sử dụng càng hạn chế càng tốt, bằng cách thay nó bằng các lệnh kể trên và các lệnh có cấu trúc. Tuy nhiên, cũng không nên quá cứng nhắc, nếu muốn thoát vô điều kiện cùng một lúc 7, 8 vòng lặp For thì nếu không dùng Goto, ta sẽ phải thay bằng các cấu trúc lặp với số lần không biết trước (Repeat, While) hay sử dụng 7, 8 lệnh Break, chương trình sẽ trở nên khó đọc hơn và chạy chậm hơn. Hạn chế không có nghĩa là cấm dùng (cũng như đệ quy vậy thôi), ta phải xác định được nhược điểm của Goto để viết các chú thích đúng chỗ giúp cho chương trình sáng sủa và dễ bảo trì.2. Hệ cơ số 16 (hexa)Trong hệ cơ số 16, có 16 chữ số, ký hiệu như sau: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F. Về mặt giá trị các chữ số từ A tới F mang giá trị từ mười đến mười lăm.Để chuyển đổi từ hệ thập phân sang hệ 16 ta có thể dùng phép chia liên tiếp với số chia là 16.Ví dụ: Đổi số 43982 sang hệ 16- 43982/16 = 2748 dư 14 (dư E)- 2748 /16 = 171 dư 12 (dư C)- 171/16 = 10 dư 11 (dư B)- 10/16 = 0 dư 10 (dư A).Vậy số 43982 sẽ bằng ABCE trong hệ 16, trong BP7, viết $ABCE cũng như là viết 43982. Đổi số từ hệ hexa sang hệ thập phân có thể đổi bằng cách nhân từng chữ số Hexa với các luỹ thừa tương ứng của 16.$ABCE = 10*163 + 11 * 162 + 12 * 16 + 14 = 43982.Để đổi một số trong hệ nhị phân ra hệ Hexa, ta xét từ hàng đơn vị lên, đổi từng nhóm 4 chữ số nhị phân được một chữ số hệ 16.10 1010 1011 1100 1110(2) = 2ABCE(16)Phép chuyển ngược lại, ta đổi một chữ số Hexa thành nhóm 4 chữ số nhị phân. Chứng minh điều trên khá dễ dàng.Xét hai lệnh gán sau với I là biến Integer:I := $0000FFFFI := $FFFFFFFFMới trông thì tưởng như $0000FFFF < $FFFFFFFF, nên lẹnh gán thứ nhất tràn số $FFFF = 65535) thì lệnh gán thứ hai sai là tất nhiên, nhưng thực ra không phải như vậy.Các hằng số hexa 16 bít (≤ 4 chữ số hexa) được BP7 coi như các giá trị LongInt 32 bit$0000FFFF = 0000 0000 0000 0000 1111 1111 1111 1111 = 65535 thì tràn Integer$FFFFFFFF = 1111 1111 1111 1111 1111 1111 1111 1111 = -1. (Không tràn)Ta nhớ lại cách lưu trữ giá trị LongInt trong máy tính, bít đầu tiên = 1 tức là số âm và giá trị số âm đó sẽ bằng giá trị dãy 31 chữ số tiếp theo trừ đi 231. nên kết quả sẽ bằng -1. Viết số -1 trong hệ Hexa là viết như vậy đấy, nếu như không muốn dùng ký pháp không chính tắc -$1.3. Tổ chức bộ nhớ trong chế độ thựcMọi byte nhớ trong chế độ thực đều được đánh địa chỉ (như đánh số nhà vậy). Hệ thống địa chỉ được đánh số từ 0 cho tới $FFFFF (Từ 0 tới 1048575, có 220 = 1MB ô nhớ) bộ nhớ này được chia làm 16 đoạn (Segments)Đoạn 0: Từ $00000 tới $0FFFFĐoạn 1: Từ $10000 tới $1FFFFĐoạn 2: Từ $20000 tới $2FFFF…Đoạn F: Từ $F0000 tới $FFFFF.Mỗi đoạn có $10000 = 65536 = 64KB ô nhớ được đánh địa chỉ, các biến toàn cục trong Pascal được tổ chức trong một đoạn, các biến địa phương được đặt vào một đoạn, mã lệnh đặt vào một đoạn. (Ta tạm hình dung như vậy chứ thực ra các đoạn có thể đặt chồng chéo, không nhất thiết phải bắt đầu và kết thúc ở các địa chỉ nói trên và có nhiều cách viết tương đương cho địa chỉ của một ô nhớ). Mỗi biến chiếm một đoạn liên tục các ô nhớ và địa chỉ của ô nhớ đầu tiên là địa chỉ của biến đó. Vì mỗi đoạn giới hạn ở dung lượng 64KB nên tổng kích thước các biến toàn cục cũng như tổng kích thước biến địa phương của một chương trình con không thể vượt quá giới hạn này. Nếu muốn dùng các đoạn nhớ còn trống khác thì ta phải sử dụng biến cấp phát động và con trỏ.Khi không có thiết lập về bộ nhớ (Tự tra cứu dẫn hướng biên dịch $M), thì ngoài vùng nhớ bị hệ thống chiếm giữ, chương trình của chúng ta độc chiếm hoàn toàn vùng nhớ còn lại.4. SizeOf, FillChar và MoveBây giờ ta tạm quên đi kiểu của các biến mà chỉ quan tâm đến độ lớn của biến. Mặc dù PASCAL là ngôn ngữ định kiểu rất mạnh, nhưng suy cho cùng, khi dịch chương trình ra mã máy thì mỗi biến chỉ đơn giản là một dãy ô nhớ chứa các giá trị số mà thôi. Chẳng hạn như cùng một ô nhớ chứa số 65, nếu ô nhớ đó do một biến kiểu Byte chiếm thì khi truy xuất biến đó ta có giá trị 65, nhưng nếu là biến kiểu Char chiếm thì khi truy xuất ta có chữ A, là biến kiểu Boolean chiếm thì khi truy xuất ta có giá trị TRUE. Vì vậy ta gọi chung kiểu Boolean, Char, Byte, ShortInt là các biến 1 Byte; Integer, Word là các biến 2 Byte; v.v…a) Hàm SizeOf cho ta độ lớn đo bằng Byte của một biến hay một kiểu.Ví dụ:Nếuvara: Integer;b: Char;c: array[1 10] of LongIntThì SizeOf(a) = SizeOf(Integer) = 2SizeOf(b) = SizeOf(Char) = 1SizeOf(c[1]) = SizeOf(LongInt) = 4SizeOf(c) = 10 * 4 = 40.b) Thủ tục FillChar(X , S, V). Điền giá trị V (1 byte) vào bộ nhớ, bắt đầu từ địa chỉ biến X, điền liên tiếp S byte. (V phải là một giá trị 1 Byte).Ví dụ:Nếuvara: array[1 10] of Boolean;b: array[1 10] of Byte;c: array[1 10] of Char; Thì:- FillChar(a, 10, 65) tương đương với FillChar(a, SizeOf(a), 65); sẽ cho ta một mảng a toàn giá trị TRUE. Lưu ý rằng số 65 ở đây có thể thay bằng một số kiểu Byte khác 0 bởi Pascal coi Byte khác 0 là giá trị True còn Byte bằng 0 là giá trị False- FillChar(b, 10, ’B’) tương đương với FillChar(b, SizeOf(b), ’B’); sẽ cho ta một mảng b toàn các số 66- FillChar(c, 10, 67) tương đương với FillChar(c, SizeOf(c), 67); sẽ cho ta một mảng c toàn các chữ C.Đặc biệt lưu ý:Nếu x là mảng các phần tử lớn hơn 1 Byte :x: array[1 100] of Integer;Muốn khởi tạo tất cả các giá trị trong mảng x thành 0, ta có thể viết:FillChar(x, SizeOf(x), 0)Nhưng muốn khởi tạo tất cả các giá trị trong mảng x thành 1, ta không thể viết:FillChar(x, SizeOf(x), 1)Bởi FillChar là điền giá trị vào từng Byte một, nên do mỗi biến Integer là 2 Byte nên cả hai Byte này đều sẽ bị điền giá trị 1.x[1] = 00000001 00000001 = 257.Nếu điền giá trị 0 thì cả hai Byte đều bị điền 0, nên giá trị Integer chiếm 2 Byte đó cũng sẽ là 0, mọi chuyện vẫn ổn, nhưng giá trị khác 0 thì không thể cho kết quả như ý được.FillChar là một công cụ mạnh, ngoài chuyện khó chịu kể trên, nó nhanh hơn hàng ngàn lần cách dùng vòng lặp để điền từng giá trị một, nên tận dụng đúng lúc đúng chỗ.c) Thủ tục Move(A, B, S): Copy S byte từ vùng nhớ bắt đầu ở địa chỉ biến A sang vùng nhớ bắt đầu bằng địa chỉ biến B.Ví dụ:Nếuvara, b: array[1 1000] of Word;Thì:Move(a, b, 2000) sẽ copy giá trị toàn mảng a sang mảng bMove(a[501], b[1], 1000) sẽ copy nửa cuối của mảng a sang nửa đầu của mảng bThông thường, để an toàn và dễ sửa đổi, lệnh Move(a[501], b[1], 1000) nên thay bằng:Move(a[501], b[1], 500 * SizeOf(a[1]));Nói chung, chỉ nên copy bộ nhớ giữa hai biến chiếm có kiểu chiếm cùng một số Byte, nếu a là mảng Byte và b là mảng Word thì ta lại gặp vấn đề khó chịu như FillChar.Xét ví dụ sau:vara: array[1 1000] of Word;Nếu muốn dồn các phần tử từ a[2] tới a[999] lên trước một vị trí ta có thể dùng vòng lặp:for i := 2 to 999 do a[i - 1] := a[i];Nếu muốn dồn các phần tử từ a[2] tới a[999] về sau một vị trí ta có thể dùng vòng lặp:for i := 999 downto 2 do a[i + 1] := a[i];Nhưng nếu dùng lệnh Move, ta có thể tự do copy ô nhớ mà không phải bận tâm to với downto gì cả. Move(a[2], a[1], 998 * 2) và Move(a[2], a[3], 998 * 2);Đặc biệt lưu ý: Dùng Move thì số Byte di chuyển không được phép là số âm,5. Biến ở địa chỉ tuyệt đối.Như đã nói ở trên, bộ nhớ được chia làm các đoạn, như vậy một ô nhớ sẽ có địa chỉ xác định xem nó nằm ở đoạn nào (địa chỉ đoạn − Segment) và trong đoạn đó nó là ô nhớ thứ mấy (địa chỉ Offset).Để khai báo một biến bắt buộc chiếm giữ ở địa chỉ nào đó, ta dùng cách khai báo biến nằm ở địa chỉ tuyệt đối;Ví dụ:varTime: LongInt absolute 0:$46C;Có nghĩa là: Khai báo biến Time nằm ở một ô nhớ của phân đoạn 0 và địa chỉ Offset $46C; absolute là từ khoá của BP7. Biến Time khai báo như vậy sẽ không chiếm bộ nhớ của chương trình mà sẽ được dùng để truy xuất vào ô nhớ chỉ ra bởi địa chỉ nói trên.Các biến của BIOS (Basic Input Output System − Hệ thống vào ra cơ sở) có sẵn trong máy tính được đặt ở đầu phân đoạn 0 của bộ nhớ. Địa chỉ Offset $46C chứa một biến LongInt là đồng hồ xung nhịp của máy tính. Đồng hồ này chứa bộ đếm thời gian bắt đầu với giá trị 0 từ 0 giờ và với tần suất 18.2 lần trong một giây, biến LongInt này được tăng lên 1*. Vì vậy cứ 18.2 lần trong một giây, biến Time của ta sẽ tự động tăng lên 1 mà chẳng cần lệnh gì cả nên không hề ảnh hưởng gì đến tốc độ. Ta có thể lợi dụng tính chất đó để đo xem chương trình của ta chạy mất bao nhiêu giây.program TimeCount;varTime: LongInt absolute 0:$46C;Start: LongInt;…beginStart := Time; {Lưu thời điểm lúc bắt đầu chạy chương trình vào biến Start}…{Mã lệnh chương trình}Writeln(’Thời gian: ’, (Time - Start) / 18.2:1:2, ’ (giây)’);end. . như ngày nay và với một trình biên dịch như BP7 có khả năng bắt lỗi rất tốt và hỗ trợ lập trình cấu trúc. Phong cách lập trình cấu trúc trên BP7 nên thế nào. Lập trình cấu trúc trên BP7Lê Minh HoàngLập trình là một công việc khó đòi hỏi phải có tư duy nhanh

Ngày đăng: 10/09/2012, 15:26

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan