bai tap pascal.doc

31 903 8
bai tap pascal.doc

Đ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

Phần 1 1 KIỂU DỮ LIỆU PROCEDURE KIỂU DỮ LIỆU PROCEDURE I. KHÁI NIỆM - ĐỊNH NGHĨA KIỂU PROCEDURE 1. KHÁI NIỆM Ngôn ngữ Pascal đã cung cấp cho chúng ta các kiểu dữ liệu từ đơn giản đến nâng cao như tập tin, con trỏ, . Bây giờ ta lại làm quen với một kiểu dữ liệu mới gọi là kiểu Procedure. Kiểu Procedure là kiểu dữ liệu mà một đối tượng (biến chẳng hạn) mang kiểu này nhận giá trị không phải là các giá trị kiểu cơ bản mà là một “chương trình con”. Chúng ta có thể xem một chương trình con như là một giá trị của một biến để rồi thực hiện các phép gán hay truyền vào một chương trình con khác thông qua các tham số kiểu Procedure này. Thật chất một biến kiểu Procedure chính là một con trỏ chứa địa chỉ segment và offset của một chương trình con thay vì địa chỉ của một vùng nhớ chứa dữ liệu. 2. ĐỊNH NGHĨA KIỂU PROCEDURE Để định nghĩa kiểu Procedure chúng ta phải dùng từ khóa PROCEDURE hay từ khóa FUNCTION và khai báo các đối số cũng như kiểu của chúng mà con trỏ trỏ đến Procedure hay Function nào đó. Cú pháp như sau TYPE <tên_kiểu> = PROCEDURE( <đối_số>: <kiểu> ); <tên_kiểu> = PROCEDURE( VAR <đối_số>: <kiểu> ); <tên_kiểu> = FUNCTION( <đối_số>: <kiểu> ): <kiểu>; Ví dụ: TYPE AnyProc = PROCEDURE; DisplayProc = PROCEDURE(S: STRING); StrProc = PROCEDURE(x,y,Attr:Byte; VAR St: STRING); StrFunc = FUNCTION(A: Real; B,C: Byte): STRING; II.KHAI BÁO BIẾN PROCEDURE Khai báo biến kiểu Procedure cũng bình thường như các biến thuộc kiểu khác, bắt đầu bằng từ khóa VAR, khai báo tên biến và tên kiểu Procedure. Ví dụ: VAR Phần 4, Đồ hoạ trong Pascal Pascal Nâng cao (Advanced Pascal) Hoàng Hữu Hạnh Proc: AnyProc; DProc: DisplayProc; SProc: StrProc; SFunc: StrFunc; Một biến kiểu Procedure là một con trỏ 4 byte (32 bit) để lưu địa chỉ CTC. Khai khai báo các biến kiểu Procedure thì kiểu Procedure mà biến đó mang nên được định nghĩa trước, điều này làm cho chương trình sáng sủa hơn và tên kiểu có thể được sử dụng nhiều lần mà tránh lặp lại không cần thiết. Chú thích cho ví dụ trên:  Proc là một biến con trỏ trỏ đến các chương trình con dạng Procedure không có đối số.  DProc là một con trỏ trỏ đến các Procedure có đối số kiểu chuỗi.  SProc là một con trỏ trỏ đến các Procedure có bốn đối số với ba đối số đầu kiểu Byte, đối số thứ tư kiểu chuỗi.  DFunc là một con trỏ trỏ đến các Function có ba đối số mà hai đối số đầu có kiểu Byte, đối số thứ ba kiểu Real. Các Function này sẽ trả về một giá trị kiểu chuỗi. Chú ý: Các biến trỏ trỏ vào Procedure sẽ hoạt động như một câu lệnh trong chương trình, tức là như một lời gọi thủ tục, trong ví dụ trên là các biến Proc, DProc, SProc. Tương tự vậy, các biến trỏ đến các Function sẽ hoạt động như một hàm, tức là chúng xuất hiện dưới dạng các lời gọi hàm. Tóm lại các biến kiểu Procedure xuất hiện trong chương trình như là các lời gọi CTC với đầy đủ các tham số mà Procedure hay Function mà nó trỏ đến có thể có. Các hàm và thủ tục sau này được xem như là các giá trị của các biến kiểu Procedure phải là các chương trình con được khai báo gọi xa với chỉ thị {$F+}. III. CÁC PHÉP TOÁN TRÊN KIỂU PROCEDURE 1. PHÉP GÁN Cú pháp phép toán: <Biến_Procedure> := <Tên_Chương_Trình_Con>; Không như phép gán đối với các biến có kiểu cơ bản, phép gán ở đây mang ý nghĩa là gán địa chỉ segment và offset của đoạn mã CTC với tên được chỉ ra ở vế phải cho biến kiểu Procedure ở vế trái. Biến này được xem như con trỏ trỏ đến CTC đó. Ví dụ: Viết chương trình thực hiện một trong bốn phép toán + - × và ÷ bằng cách dùng các hàm và sử dụng biến kiểu Procedure. TYPE FuncType = Function( x, y: Real ): Real; VAR FuncVar: FuncType; a, b: Real; Ch: Char {------- Định nghĩa hàm -------} Phần 4, Đồ hoạ trong Pascal Pascal Nâng cao (Advanced Pascal) Hoàng Hữu Hạnh {$F+} {Chỉ thị gọi xa } Function Cong(a, b: Real): Real; Begin Cong := a + b; End; Function Tru(a, b: Real): Real; Begin Tru := a - b; End; Function Nhan(a, b: Real): Real; Begin Nhan := a * b; End; Function Chia(a, b: Real): Real; Begin Chia := a / b; End; {$F-} {Bỏ gọi xa } {------- Chương trình chính -------} BEIN Write(‘A=’); ReadLn(a); Write(‘Phép toán:’); ReadLn(Ch); Write(‘B=’); ReadLn(b); {-- Gán giá trị vào biến Procedure --} Case Ch Of ‘+’: FuncVar:=Cong; ‘-’: FuncVar:=Tru; ‘*’: FuncVar:=Nhan; ‘/’: FuncVar:=Chia; End; WriteLn(‘Kết quả là: ’, FuncVar(x, y):2:2); ReadLn; END. Chú thích cho chương trình ví dụ: Trong chương trình trên, chúng ta đã định nghĩa một kiểu Procedure là FuncType là hàm có hai tham số kiểu Real và giá trị trả về cũng là kiểu Real. FuncType = Function( x, y: Real ): Real; Biến FuncVar có kiểu FuncType là một biến sẽ chứa các tên hàm có danh sách đối số và kiểu trả về của hàm như là đã khai báo. Trong ví dụ trên là bốn hàm Cong, Tru, Nhan và Chia trả về kết quả là phép toán tương ứng tác động lên hai đối số. Tiếp thao là phép gán các tên hàm cho biến FuncVar ứng với các giá trị chủa Ch. Và cuối cùng là hình thức xuất hiện của FuncVar trong câu lệnh. Phần 4, Đồ hoạ trong Pascal Pascal Nâng cao (Advanced Pascal) Hoàng Hữu Hạnh WriteLn(‘Kết quả là: ’, FuncVar(x, y):2:2);  Đối số của CTC có kiểu Procedure Kiểu dữ liệu Procedure cũng có thể dùng làm kiểu của các đối số CTC. Một đối số kiểu Procedure cũng hoạt động đúng theo các nguyên tắc mà các đối số mang kiểu khác hoạt động. Ví dụ: TYPE ProcType = Procedure; VAR p: ProcType; {$F+} Procedure ABC_Proc; Begin WriteLn('ABC'); End; Procedure DEF_Proc; Begin WriteLn('DEF'); End; {$F-} Procedure TT(pv: Proc); Begin pv; End; Procedure TB(VAR pv: Proc); Begin pv:=DEF_Proc; End; BEGIN p:=ABC_Proc; TT(p); TB(p); p; END. Phần 4, Đồ hoạ trong Pascal ABC DEF Pascal Nâng cao (Advanced Pascal) Hoàng Hữu Hạnh 2. PHÉP SO SÁNH Các phép toán so sánh không áp dụng cho các biến kiểu Procedure, do đó chúng ta không thể so sánh các biến kiểu Procedure được mà chỉ có thể so sánh địa chỉ mà các biến này mang. Lúc đó chỉ sử dụng hai phép toán só sánh bằng nhau ( = ) và khác nhau ( <> ). Kết quả là kiểu logic (Boolean). Để lấy giá trị địa chỉ của một biến chúng ta dùng toán tử @. @<Biến_Procedure_1> = hay <> @<Biến_Procedure_2> Ví dụ: Chúng ta không thể viết If TestFunc <> StrFunc then . Mà phải viết If @TestFunc <> @StrFunc then . Chú ý: Để mô tả biến Procedure không trỏ vào vùng nhớ nào, chúng ta phải gán con trỏ NIL vào con trỏ trỏ đến biến Procedure. Ví dụ: @TestFunc := NIL;  Đối số của CTC có kiểu Procedure 1. Chúng ta cần phân biệt giữa lời gọi hàm và lệnh gán giá trị là tên chương trình con cho biến Procedure. Ví dụ: Xét chương trình sau: TYPE StrFunc = Function: STRING; VAR st: STRING; pF: StrFunc; {$F+} Function TrMark: STRING; Begin WriteLn(‘Thực hiện hàm TrMark’); TrMark := ‘Advanced PASCAL’; End; {$F-} BEGIN st := TrMark; {Lời gọi hàm TrMark } pF := TrMark; {Gán đ/chỉ của TrMark cho pF } END. 2. Các và thủ tục được xem như là một kiểu dữ liệu cho biến Procedure phải có các yêu cầu sau:  Phải là hàm và thủ tục của NSD  Phải khai báo gọi xa với cặp chỉ thị {$F+} và {$F-} Phần 4, Đồ hoạ trong Pascal Pascal Nâng cao (Advanced Pascal) Hoàng Hữu Hạnh  Không có khai báo Interrupt và câu lệnh Inline.  Không có các CTC lồng bên trong. Phần 2 2 CHUYỂN ĐỔI KIỂU – UNIT NGƯỜI DÙNG CHUYỂN ĐỔI KIỂU – UNIT NGƯỜI DÙNG IV. CHUYỂN ĐỔI KIỂU (TYPE CASTING) Type Casting là một kỹ thuật dùng để biến đổi kiểu của một vùng nhớ máy tính. Pascal là một NNLT rất chặc chẽ trong trong vấn đề tổ chức dữ liệu, nhất là trong các phép gán hay trong biểu thức. Sự chặc chẽ này của Pascal đôi khi lại gây trở ngại cho lập trình viên vì phải sử dụng nhiều lệnh mới đạt được mục đích. Lấy một ví dụ như sau, St là một biến kiểu chuỗi và đang lưu giữ chuỗi ‘Turbo’, gải sử chúng ta muốn tìm mã ASCII của các ký tự trong chuỗi thì phải dùng như sau: VAR St: String[10]; . St:= ‘Turbo’; For i:=1 to Length(St) do Write(Ord(St[i],#32); trong đó chúng ta đã sử dụng đến 2 lời gọi hàm, hàm Length và Ord để xác định chiều dài chuỗi và lấy mã ASCII của ký tự trong chuỗi. Ta tiến hành xem xét vùng nhớ St, được mô hình hóa như sau 0 1 2 3 4 5 6 7 8 9 10 05 85 117 114 98 111 ‘T’ ‘u’ ‘r’ ‘b’ ‘o’ Biến St được lưu trữ như một mảng 11 phần tử ( 0 10 ) mà mỗi phần tử là một số kiểu Byte để lưu giữ mã ASCII của các ký tự trong chuỗi, trong đó mã ASCII của ký tự đầu là độ dài thực của chuỗi. Do đó chúng ta cũng có thể định nghĩa lại vùng nhớ này như sau: TYPE ByteArr = Array[0 10] of Byte; VAR A: ByteArr; Phần 4, Đồ hoạ trong Pascal Pascal Nâng cao (Advanced Pascal) Hoàng Hữu Hạnh . A[0]:=5; A[1]:=84; A[2]:=7; A[4]:=114; A[5]:=98; A[6]:=111; Vùng nhớ biến A sẽ là: 0 1 2 3 4 5 6 7 8 9 10 05 85 117 114 98 111 Nếu ta xem vùng nhớ trên là một chuối thì nó sẽ trở thành chuỗi ‘Turbo’, ngược lại với vùng nhớ của St ta có thể xem đó là một mảng các số kiểu Byte. Cách xem xét như vậy gọi là chuyển đổi kiểu (Type Casting), mà thực chất là tái định nghĩa lại kiểu dữ liệu của một vùng nhớ. Hạn chế của việc đổi kiểu mà không thể không nhắc đến là nó sẽ làm khái niệm về khả năng kiểm soát kiểu dữ liệu trong chương trình và đôi lúc xảy ra những điều đáng tiếc. 3. CÚ PHÁP ĐỔI KIỂU Cú pháp: <Kiểu> ( <Giá_trị> ) Ví dụ 1: ch := CHAR(65); Thanhtien:= (Tieuthu – 100)*LongInt(500) + 100*250; Ví dụ 2: CONST A: Array[0 10] of Byte = (05, 84, 117, 114, 98, 111, 0, 0, 0, 0, 0); TYPE St10 = STRING[10]; BEGIN WriteLn(St10(A)); ReadLn; END. 4. RECORD HÓA MỘT VÙNG NHỚ Một ví dụ thực tế: Khi muốn tạo ra một cửa sổ trong chế độ văn bản bằng thủ tục Window(x2, y1, x2, y2) tọa độ đỉnh trái trên và phải dưới phải được lưu giữ trong hai biến kiểu Word là: WindMin Tọa độ đỉnh trái trên Phần 4, Đồ hoạ trong Pascal Turbo y1 x1 y2 x2 Pascal Nâng cao (Advanced Pascal) Hoàng Hữu Hạnh WindMax Tọa độ đỉnh phải dưới Byte cao Byte thấp Để lấy các giá trị x1, y1, x2, y2 từ hai biến WindMin và WindMax, chúng ta cũng có thể dùnh hai hàm Lo và Hi của DOS, nhưng ở đây chúng ta thực hiện kỹ thuật Record hóa vùng nhớ 2 byte này bằng một kiểu Record, chẳng hạn: TYPE Toado = RECORD x, y: Byte; END; Thứ tự x, y trong record phải theo thứ tứ, trường nào đứng trước sẽ có địa chỉ thấp hơn trường đứng sau. Sau đó ta thực hiện record hóa, thực ra đó là một dạng khác của Type Casting, hai biến WindMin và WindMax và lấy các giá trị như sau: x1 := Toado(WindMin).x; y1 := Toado(WindMin).y; x2 := Toado(WindMax).x; y2 := Toado(WindMax).y; Cú pháp Record hóa vùng nhớ này có thể mở rộng cho vùng nhớ lớn hơn, các trường của Record có thể cũng là mảng. 5. ĐỐI SỐ CTC KHÔNG KIỂU Trong việc sử dụng các CTC khi viết chương trình, chúng ta đã sử dụng các đối số với các kiểu xác định. Khi gọi thực hiện các chương trình con chúng ta phải truyền các đối số thực tế đủ và đúng kiểu vào cho chúng, điều này đôi khi lại bất tiện. Turbo Pascal 5.0 trở lên cung cấp một khả năng nữa đó là có thể khai báo tham biến không kiểu, điều này thực sự là hữu ích. Ví dụ, để viết chương trình con nhập một số nguyên có kiểm tra lỗi, nhưng số nguyên thì kiểu cụ thể là Byte? hay Integer? hay Word?, . Lúc này ta phải viết nhiều CTC để nhập cho một kiểu cụ thể nếu không dùng đối sô không kiểu. Ví dụ: Chương trình con nhập số nguyên. PROCEDURE ReadInt( x, y: Byte; VAR N ); Var Temp: STRING[80]; Result: Integer; Begin Temp := #32; repeat GotoXY(x,y); Write(#32: Length(Temp)); GotoXY(x,y); ReadLn(Temp); Val(Temp, LongInt(N), Result); until Result = 0; End; Thủ tục này có sử dụng kỹ thuật Type Casting với tham biến N để sao cho nó làm việc OK với mọi trường hợp, điều này là không bắt buộc trong thủ tục này. Bây giờ chúng ta hãy thử viết chương trình để nhập các biến kiểu nguyên ShortInt, Integer, LongInt, Byte, Word sử dụng thủ tục ReadInt xem thế nào? Phần 4, Đồ hoạ trong Pascal Pascal Nâng cao (Advanced Pascal) Hoàng Hữu Hạnh V. UNIT NGƯỜI DÙNG 6. Ý NGHĨA UNIT là một thư viện chứa các chương trình con đã được cài sẵn. Trong Pascal có hai loại unit: một là unit chuẩn (cho sẵn) như SYSTEM.TPU, CRT.TPU, GRAPH.TPU, .; và một loại unit tạo ra bởi NSD. Một lý do để ta tạo các Unit của NSD là: khi chương trình quá lớn, có những nhóm chương trình con và các dữ liệu hoàn chỉnh, có thể được sử dụng bởi nhiều chương trình khác nhau. Vì vậy ta có thể nhóm những chương trình con các cấu trúc dữ liệu trên thành các Unit. Làm như thế sẽ gia tăng tối đa tốc độ chương trình, và các chương trình con đó có thể được sử dụng bởi những chương trình khác, bằng cách “USES” unit đó ra. Để sử dụng Unit trong chương trình con thì ta khai báo các Unit đó sau từ khóa USES. Ví dụ: USES Crt, Dos, Printer, NewUnit; Tóm lại, ý nghĩa khi tạo unit là như sau:  Ghi lại các CTC thường dùng vào một module tạo thư viện chương trình  Phân chương trình lớn thành các module nhỏ hơn.  Tính có thể sử dụng lại của unit 7. CÁC THÀNH PHẦN CỦA MỘT UNIT Một unit bao gồm các thành phần sau: i.Phần Khai báo (UNIT .) ii. Phần Giao tiếp (INTERFACE) iii. Phần Cài đặt (IMPLEMENTATION) iv. Phần Khởi tạo (INITIALIATION) Các phần được sắp xếp như sau trong một file nguồn: UNIT <Tên_Unit>; {Tên Unit phải đặt giống với tên file } USES <DOS_Các Unit cần dùng>; {$F+} INTERFACE (* Khai báo tên các thủ tục và hàm, tên biến, kiểu dữ liệu được viết đầy đủ trong phần Implementation sau. Tên các thủ tục: khai báo hàm trong phần này là tên các chương trình con, biến và kiểu dữ liệu mà các Unit, trong chương trình gọi Unit này cần dùng đến *). ; {khai báo tên hàm của Unit } {$F-} IMPLEMENTATION Phần 4, Đồ hoạ trong Pascal Pascal Nâng cao (Advanced Pascal) Hoàng Hữu Hạnh (* khai báo các kiểu dữ liệu, biến, . cũng đầy đủ thủ tục, hàm của Unit này *) (*Trong phần này có thể có các hàm, thủ tục mà ta không khai báo ở phần Interface, các chương trình con này gọi là chương trình con nội bộ, tức là các chương trình con chỉ sử dụng trong phạm vi Unit đó mà thôi. *) [BEGIN ] END.  Phần Khai báo Gồm tên unit viết sau từ khóa UNIT và phải trùng trên với tên file nguồn. Đây là tên mà sau này sẽ sử dụng. Ví dụ: UNIT UEXAM;  Phần Giao tiếp Còn được gọi là phần Public, là phần giao diện của unit với bên ngoài. Những gì khai báo trong phần này thì được các chương trình sử dụng unit này có thể gọi đến. Phần này bắt đầu bằng từ khóa INTERFACE Ví dụ: INTERFACE {Phần Giao tiếp } {$F+} {chỉ thị gọi xa } VAR Ini: String; PROCEDURE ThiDu1 (Var x, y: Real); PROCEDURE ThiDu2 (S: String);  Phần Cài đăt Dùng để chứa các mục riêng (private) cho các câu lệnh công cụ nằm trong unit, là phần cài đặt cụ thể các CTC đã được khai báo trong INTERFACE. Phần này bắt đầu bằng từ khóa IMPLEMENTATION sau đó là các khai báo unit sử dụng, hằng, kiểu, biến, . Phần này là “tài sản riêng” của unit, các nơi sử dụng unit này không thể dùng chúng. Ví dụ: IMPLEMENTATION {Phần Cài đặt } Var x, y: real; {các biến chỉ dụng trong Unit này } PROCEDURE ThiDu1 (Var x, y: real); Begin x:= x + y; y:= y * z + x; End;  Phần Khởi tạo Phần này như thân chương trình chính Pascal thông thường, thông thường gồm các câu lệnh gán các giá trị khởi động cho các biến public. Phần 4, Đồ hoạ trong Pascal . biến và tên kiểu Procedure. Ví dụ: VAR Phần 4, Đồ hoạ trong Pascal Pascal Nâng cao (Advanced Pascal) Hoàng Hữu Hạnh Proc: AnyProc; DProc: DisplayProc; SProc:. Char {------- Định nghĩa hàm -------} Phần 4, Đồ hoạ trong Pascal Pascal Nâng cao (Advanced Pascal) Hoàng Hữu Hạnh {$F+} {Chỉ thị gọi xa } Function Cong(a,

Ngày đăng: 26/08/2013, 00:10

Hình ảnh liên quan

Ta tiến hành xem xét vùng nhớ St, được mô hình hóa như sau - bai tap pascal.doc

a.

tiến hành xem xét vùng nhớ St, được mô hình hóa như sau Xem tại trang 6 của tài liệu.

Từ khóa liên quan

Trích đoạn

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

Tài liệu liên quan