Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 19 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
19
Dung lượng
127,87 KB
Nội dung
CHƯƠNG TRÌNH CON CHƯƠNG TRÌNH CON Bởi: Võ Thanh Ân Chương IV: CHƯƠNG TRÌNH CON KHÁI NIỆM VỀ CHƯƠNG TRÌNH CON Trong chương trình, có đoạn cần phải lập đi, lập lại nhiều lần chỗ khác Để tránh phải viết lại đoạn người ta thường phân chương trình thành nhiều module, module giải công việc đó, module chương trình (subprogram) Một tiện lợi khác việc sử dụng module ta dễ dàng kiểm tra tính đắn trước ráp nối vào chương trình Do việc xác định sai sót tiến hành điều chỉnh chương trình thuận lợi Trong Pascal chương trình viết dạng hàm (FUNCTION) thủ tục (PROCEDURE) Hàm thủ tục chương trình con, hàm khác thủ tục chỗ hàm trả giá trị cho lệnh gọi thông qua tên hàm thủ tục không Do ta dùng hàm Đối với Borland Pascal 7.0 điều không bắt buộc ta gọi hàm gọi thủ tục Không thiết phải lấy giá trị trả Để thực điều menu Options >Compiler cần khai báo cú pháp mở rộng (eXtended syntax), chương trình cần có dẫn hướng biên dịch {$ X+} Nếu không, biên dịch (gõ F9) Pascal thông báo lỗi “Error 122: Invalid variable reference” Tuy vậy, dù dẫn hướng biên dịch {$ X+}, gõ CTRL+F9 chương trình chạy thường! Ví dụ:{$X+}Program TestExtendSyntax;uses crt;var i,j:byte;{ -}Function DoiViTri(i,j: byte):byte;Var Tam:byte;BEGINTam:=i; i:=j; j:=tam;Gotoxy(i,j); write('*')END;{ }BEGINi:=5; j:=20;Gotoxy(i,j); write('*');Doivitri(i,j);readln;END thoả mãn yêu cầu sau • Ta muốn nhận kết mà • Ta cần dùng tên chương trình (chứa kết đó) để viết biểu thức Nếu không thỏa hai yêu cầu ta dùng thủ tục 1/19 CHƯƠNG TRÌNH CON Borland Pascal thiết kế cài đặt sẵn Unit gèm theo gói phần mềm nhiều thủ tục hàm tiện dùng Muốn sử dụng thủ tục hàm Unit ta cần khai báo tên Unit câu lệnh USES Tuy nhiên phần lớn thủ tục hàm dùng chương trình người dùng phải tự viết HÀM (FUNCTION) Hàm chương trình tính toán trả cho ta giá trị kiểu vô hướng Cấu trúc hàm sau: FUNCTION [(:[;: ])]: ; (Header) [VAR :[;: ]] Khai báo biến cục có BEGIN END; Thân hàm • Tên hàm danh biểu, phải tuân thủ theo qui tắc đặt danh biểu đề cập chương I • Một hàm có nhiều tham số Trong trường hợp có nhiều tham số có kiểu liệu ta viết chúng cách dấu , (phẩy) Ngược lại, tham số hình thức khác kiểu phải cách dấu ; (chấm phẩy) • KiểuKQ kiểu vô hướng, phản ảnh kiểu giá trị mà hàm trả lại sau chạy xong Ví dụ, ta khai báo hàm sau: FUNCTION TEST(x,y:Integer; z:Real): Real; Đây hàm có tên TEST, với tham số, x y thuộc kiểu Integer, z thuộc kiểu real, hàm trả kết kiểu real • Trong hàm, ta sử dụng hằng, kiểu, biến dùng riêng nội hàm • Thông thường mục đích sử dụng hàm để lấy trị trả cần lưu ý gán kết cho tên hàm thân hàm Ví dụ 1: Ta xây dựng hàm DT truyền tham số vào bán kính hình tròn, hàm trả diện tích hình tròn Program TinhDienTich; Uses Crt; VAR BanKinh: real; Phép gán để trả giá trị cho tên hàm Ch: Char; 2/19 CHƯƠNG TRÌNH CON { } Function DT(Radius:Real):Real; Begin DT := PI * Radius* Radius; End; { } Begin Clrscr; Repeat Write(‘Nhập bán kính: ’); Readln(BanKinh); Writeln(‘Diện tích hinh tron tuong ung: ‘ ,DT(Bankinh):0:2); Writeln; Write(‘Tiếp tục (C/K)? ’); Repeat ch:=readkey; Until Upcase(ch) in [‘C’,’K’]; Until UpCase(Ch) = ‘K’; {Lưu ý: ‘K’ in hoa} End Ví dụ 2: Program TinhGiaithua; USES CRT; Var Num:longint; Ch:char; X,Y:byte; 3/19 CHƯƠNG TRÌNH CON { -} Function GiaiThua(m: longint): longint; Var Tam, Dem:Longint; BEGIN IF (M=0); Writeln(M,’! = ’,GiaiThua(Num)); REPEAT Write(‘Tinh nua khong ? (C/K) :’); CH:=READKEY; UNTIL Upcase(Ch) in [‘C’,’K’]; Writeln(Ch); UNTIL Upcase(Ch)=’K’; Readln END THỦ TỤC (PROCEDURE) Cấu trúc thủ tục sau: PROCEDURE (:[;: ]): ; (Header) [VAR :[;: ] Khai báo biến cục có BEGIN END; Thân thủ tục Như cấu trúc thủ tục tương tự cấu trúc hàm Chỉ có hai điều khác: • Header khóa Procedure thay Function • Không có câu lệnh gán thân Procedure Ví dụ: Thủ tục INSO sau in số từ đến giá trị biến truyền vào Với n tham số thực tế, So tham số hình thức Program TEST; 5/19 CHƯƠNG TRÌNH CON Var n: Integer; { -} Procedure INSO( So : Integer); Var i: Integer; Begin For i := to So Write( i:10 ); End; { Chương trình } Begin Write(‘Nhập số lớn không: ’); Readln(n); INSO( n ); Readln; End LỜI GỌI CHƯƠNG TRÌNH CON VÀ VẤN ĐỀ TRUYỀN THAM SỐ Một chương trình gồm chương trình nhiều chương trình Kèm theo biến, tham số khai báo vị trí khác chương trình Khả từ vị trí chương trình “nhìn thấy” chương trình con, biến khai báo quan trọng Mặt khác làm việc theo nhóm, chương trình con, modune khác chương trình nhiều người, nhiều nhóm lập trình khác thực Khi khả xảy nhóm khác dùng tên biến, tên hàm, tên thủ tục cho mục đích khác lớn Vì khả “nhìn thấy”, chương trình cần có chế cấu trúc cho “che khuất” biến cần thiết Phần sau đây, nhằm mục đích đó, nghiên cứu khái niệm liên quan đến “tầm vực “ biến chương trình (con) hiệu ứng lề (side effect) xảy 6/19 CHƯƠNG TRÌNH CON KHỐI (block): Một khối Header (PROGRAM | FUNCTION | PROCEDURE) khối từ khóa END (END END;) thân chương trình/chương trình tương ứng Minh họa: PROGRAM ProgName;VAR a,b: type1; x:type2BEGIN…….…….END.PROCEDURE Proc1(t,h:type1; Var k:type2);VAR x,yBegin…….…….End;PROCEDURE Proc2Var qBEGIN…….…….END;FUNCTION func1(r:type): type;Var xBegin…….…….End; Trong minh họa ta có khối ứng với chương trình chính, khối ứng với Procedure Proc1, Procedure Proc2, Function func1, Proc1 Proc2 hai khối cấp, func1 khối khối Proc2 TẦM VỰC: Tầm vực biến hay chương trình phạm vi mà biến chương trình nhìn thấy chương trình (ie: gọi biến chương trình đó) Tầm vực biến hay chương trình chỗ khai báo khối hết khối mà khai báo đó, kể khối trừ khối có khai báo lại biến chương trình Qui định tầm vực qui định riêng ngôn ngữ Mỗi học ngôn ngữ sinh viên cần tham khảo qui định vê tầm vực riêng ngôn ngữ Theo qui định trên, Và áp dụng cho hình minh họa trước ta thấy: • Các biến a,b biến toàn cục gọi nới đâu chương trình • Biến x chương trình gọi đâu chương trình trừ PROCEDURE Proc1 FUNCTION func1vì procedure/ function có khai báo lại biến x Trong thân procedure/function gọi x ta gọi đến biến x cục biến x toàn cục • Các biến t,h,k y gọi Proc1 mà • Biến x gọi Proc1 biến cục riêng mà • Biến q gọi Proc2 func1 mà Biến r gọi Func1 mà Biến x gọi func1 biến cục riêng func1, không liên quan đến biến x khai báo chương trình Proc1 • Procedure Proc1 gọi Proc2, Func1 chương trình Trong Procedure Proc1 dĩ nhiên, theo qui định này, gọi (Đây trường hợp gọi đệ qui mà ta nghiên cứu sau) 7/19 CHƯƠNG TRÌNH CON • Proc2 gọi chương trình chính, Func1 Proc1 gọi Proc2 • Func1 gọi bới Proc2 • Proc1 chương trình gọi Func1 • Có ngoại lệ: Chương trình gọi • HOẠT ĐỘNG CỦA CHƯƠNG TRÌNH CON KHI ĐƯỢC GỌI VÀ SỰ BỐ TRÍ BIẾN • Khi chương trình chương trình gọi biến, “tên” chương trình bố trí vùng nhớ gọi STACK Khi chương trình gọi biến toàn cục bố trí vào stack tồn lúc chấm dứt chương trình Khi chương trình gọi biến khai báo tham số sau từ khóa VAR (của nó) bố trí vào stack giải phóng chương trình chấm dứt Điều có lợi cho phép ta sử dụng vùng nhớ hợp lí Người ta dùng biến toàn cục tốt để tránh lỗi (trong thời gian chạy) làm tràn stack (Stack overflow error) • VẤN ĐỀ TRUYỀN THAM SỐ KHI GỌI CHƯƠNG TRÌNH CON Khi gọi chương trình (thủ tục hay hàm) ta phải theo qui định sau đây: • - Nếu chương trình có qui định tham số phải truyền giá trị biến cho tham số • - Phải truyền đủ số tham số Có điều khó chịu Pascal cho phép “quá tải” tham số thủ tục “bản thân” thủ tục Write, Writeln Chúng ta gọi Writeln(‘Mot tham so’) hay Writeln(‘Tham so thu nhat’,’Tham so thu hai’) điều lại không cho phép chương trình viết bới người dùng! • - Phải truyền kiểu liệu theo thứ tự tham số khai báo Để hiểu rõ cách Pascal xử lí việc truyền tham số cần xem qua ví dụ sau đây: Program ParameterPassing; Var a,b:byte; c:integer; { } Procedure TestVar (x,y,z: byte; Var t: integer); Var d: byte; Begin 8/19 CHƯƠNG TRÌNH CON D:=4; {1} X:=X+D; B:=B+X; T:=T+D; {2} Writeln(‘Ben thu tuc:’); Writeln(‘A=’,a, ‘B=’,b,’C=’,c,’D=’,d,’X=’,x,’Y=’,y,’Z=’,z,’T=’,t); End; { } BEGIN A:=3; B:=5; C:=8; Writeln(‘Truoc goi thu tuc:’); Writeln(‘A=’,a, ‘ B=’,b,’ C=’,c); TestVar(a,5,c,c); Writeln(‘Sau goi thu tuc:’); Writeln(‘A=’,a, ‘ B=’,b,’ C=’,c); Readln; END • Quá trình chạy chương trình diễn biến nhớ sau: • * Trước gọi thủ tục: • Cấp vùng nhớ cho biến toàn cục a,b,c STACK A=3 B=5 C=8 Kết xuất chương trình: Truoc goi thu tuc: A=3 B=5 C=8 9/19 CHƯƠNG TRÌNH CON * Trong thực thủ tục: • Cấp vùng nhớ cho biến cục x,y,z,t,d • Chuyển giao tham số: TestVar(a,5,c,c); Các tham số x,y,z gọi tham trị Việc chuyển giao giá trị cho tham số thực trị biến, giá trị chuyển giao COPY vào ô nhớ tương ứng biến Các ô nhớ ứng với x,y,z có giá trị 3,5,8 Tham số T khai báo sau từ khóa VAR gọi tham biến Việc chuyển giao tham số thực biến Ở ta chuyển giao biến C cho vị trí tham số T Pascal không copy giá trị biến C vào ô nhớ ứng với T mà tạo “con trỏ” để trỏ C, thao tác T thực ô nhớ C Biến D khởi tạo (lần đầu) STACK A=3 B=5 C=8 x=3 y=5 z=8 T= (Trỏ C) d=0 Sau dòng lệnh {1} {2} thủ tục nhớ là: STACK A=3 B=5+(3+4) C=8+4 x=3+4 Y=5 z=8 T= (Trỏ C) d=4 Kết xuất chương trình chạy đến câu lệnh cuối thủ tục là: Truoc goi thu tuc: A=3 B=5 C=8 10/19 CHƯƠNG TRÌNH CON Ben thu tuc: A=3 B=12 C=12 D=4 X=7 Y=5 Z=8 T=12 • * Sau thực thủ tục: • Thu hồi vùng nhớ cấp cho thủ tục: STACK A=3 B=5+(3+4) C=8+4 Kết xuất chương trình chạy đến câu lệnh cuối là: Truoc goi thu tuc: A=3 B=5 C=8 Ben thu tuc: A=3 B=12 C=12 D=4 X=7 Y=5 Z=8 T=12 Sau goi thu tuc: A=3 B=12 C=12 • Mấy vấn đề cần nhớ: Đối với tham trị chuyển giao trị biến Giá trị chuyển giao COPY vào nội dung ô nhớ biến tham trị Đối với tham biến chuyển giao biến Một trỏ trỏ biến chuyển giao, thao tác thực biến chuyển giao • Và kết luận quan trọng: Sự thay đổi tham biến bên thủ tục làm thay đổi giá trị biến chuyển giao (Trường hợp biến C) Điều không xảy tham trị (Trường hợp biến A, thay đổi biến X không ảnh hưởng đến nội dung ô nhớ A) Sự thay đổi biến chuyển giao trường hợp tham biến gọi hiệu ứng lề (Side effect) Người lập trình phải lưu ý để phòng ngừa hiệu ứng lề mong muốn 11/19 CHƯƠNG TRÌNH CON TÍNH ĐỆ QUI CỦA CHƯƠNG TRÌNH CON Như nói chương trình Pascal gọi Một lời gọi gọi lời gọi đệ qui (recursion) Gọi đệ qui kỹ thuật lập trình quan trọng thường ngắn gọn thường … phù hợp với suy nghĩ tự nhiên nhiều cách giải toán Thậm chí nhiều toán dùng đệ qui Tuy nhiên xét tốc độ giải thuật tối ưu không gian nhớ đệ qui thường giải pháp tốt Người ta thường cố gắng khắc phục đệ qui cách dùng vòng lặp sử dụng stack công việc không dễ dàng Ví dụ 1: Định nghĩa giai thừa số nguyên không âm m sau: Lập trình để tính giai thừa số nguyên không âm nhập từ bàn phím Cách 1: Dùng đệ qui Function GT(m: Integer): Longint; Begin If ( m = ) or ( m = ) then GT := Else GT := m * GT( m-1 ); End; Rõ ràng cách viết đệ qui “phù hợp cách tự nhiên” với định nghĩa giai thừa Việc thực thi lời gọi đệ qui diễn tương tự sau: Ví dụ ta truyền vào giá trị m = 4, tức gọi GT(4) GT(4) m = → Tính * GT(4-1) → gọi GT(3) GT(3) m = → Tính * GT(3-1) → gọi GT(2) 12/19 CHƯƠNG TRÌNH CON GT(2) m = → Tính * GT(2-1) → gọi GT(1) GT(1) m = → Gán GT(1):=1 Cuối trình “tính ngược” cho phép trả giá trị GT(4): GT(4) ? * (3 * (2 * GT(1))) Cách 2: Dùng vòng lặp Function GiaiThua(m: longint): longint; Var Tam, Dem:Longint; BEGIN IF (M ‘,Y); END; 16/19 CHƯƠNG TRÌNH CON { } Procedure Doi(N:byte; A,B,C:Cot); {Dời N đĩa từ cọc A sang cọc C lấy cọc B làm trung gian} BEGIN IF (N>0) THEN Begin Doi(N-1,A,C,B); {Dời N-1 đĩa từ cọc A sang cọc B lấy cọc C làm trung gian} Chuyen(A,C); Doi(N-1,B,A,C); {Dời N-1 đĩa từ cọc B sang cọc C lấy cọc A làm trung gian} End; END; { } BEGIN Clrscr; Write(‘Cho biet so dia :’); Readln(Sodia); Writeln(‘Cac buoc thuc hien:’); Doi(Sodia,’A’,’B’,’C’); Writeln; Writeln(‘Thuc hien xong!’); READLN; END Nếu áp dụng chương trình cho trường hợp N=3 ta có trình gọi đệ qui sau: Doi(1,A,B,C) Doi(0,A,C,B) 17/19 CHƯƠNG TRÌNH CON Chuyen(A,C) Doi(0,B,A,C) Doi(3,A,B,C) Doi(2,A,C,B) Chuyen(A,B) Doi(1,C,A,B) Doi(0,C,B,A) Chuyen(C,B) Doi(0,A,C,B) Chuyen(A,C) Doi(1,B,C,A) Doi(0,B,A,C) Chuyen(B,A) Doi(0,C,B,A) Doi(2,B,A,C) Chuyen(B,C) Doi(1,A,B,C) Doi(0,A,C,B) Chuyen(A,C) Doi(0,B,A,C) Ví dụ cho thấy việc kết xuất câu lệnh Chuyen(X,Y) xảy toàn lời gọi đệ qui thực cho thấy thứ tự lời gọi đệ qui lần cuối 18/19 CHƯƠNG TRÌNH CON Nhận xét quan trọng bạn viết thủ tục đệ qui lẽ bạn cần phải hình dung trước thứ tự kết xuất lời gọi đệ qui có nhiều nhánh 19/19 [...]... tham biến được gọi là hiệu ứng lề (Side effect) Người lập trình phải hết sức lưu ý để phòng ngừa hiệu ứng lề ngoài mong muốn 11/19 CHƯƠNG TRÌNH CON 1 TÍNH ĐỆ QUI CỦA CHƯƠNG TRÌNH CON Như đã nói trên một chương trình con trong Pascal có thể gọi về chính nó Một lời gọi như thế gọi là một lời gọi đệ qui (recursion) Gọi đệ qui là một kỹ thuật lập trình rất quan trọng vì nó thường ngắn gọn và thường … phù... End; END; Lưu ý: Một chương trình con đệ qui bao giờ cũng có ít nhất hai phần: • Phần gọi đệ qui Trong ví dụ trên là GT:=m*GT(m-1) • Phần “neo” Trong ví dụ trên là IF (m=0) or (m=1) THEN GT:=1 Phần này rất quan trọng vì nó đảm bảo quá trình đệ qui phải dừng sau một số hữu hạn bước 13/19 CHƯƠNG TRÌNH CON Quên phần này sẽ xảy ra lỗi làm tràn bộ nhớ stack (stack overflow) khi xảy ra quá trình đệ qui Ví dụ... với N đĩa như vậy được “đệ qui” về hai bài toán (N-1) đĩa và bài toán 1 đĩa Quá trình đệ qui sẽ dừng lại khi N=0 (không còn đĩa để dời hoặc chuyển) Chương trình sẽ như sau: PROGRAM ThapHanoi; Uses crt; TYPE Cot = Char; { } Procedure Chuyen(X,Y:Cot); BEGIN Writeln(X,’ -> ‘,Y); END; 16/19 CHƯƠNG TRÌNH CON { } Procedure Doi(N:byte; A,B,C:Cot); {Dời N đĩa... so dia :’); Readln(Sodia); Writeln(‘Cac buoc thuc hien:’); Doi(Sodia,’A’,’B’,’C’); Writeln; Writeln(‘Thuc hien xong!’); READLN; END Nếu áp dụng chương trình này cho trường hợp N=3 ta có quá trình gọi đệ qui như sau: Doi(1,A,B,C) Doi(0,A,C,B) 17/19 CHƯƠNG TRÌNH CON Chuyen(A,C) Doi(0,B,A,C) Doi(3,A,B,C) Doi(2,A,C,B) Chuyen(A,B) Doi(1,C,A,B) Doi(0,C,B,A) Chuyen(C,B) Doi(0,A,C,B) Chuyen(A,C) Doi(1,B,C,A)...CHƯƠNG TRÌNH CON Ben trong thu tuc: A=3 B=12 C=12 D=4 X=7 Y=5 Z=8 T=12 • * Sau khi thực hiện thủ tục: • Thu hồi các vùng nhớ đã được cấp cho thủ tục: STACK A=3 B=5+(3+4) C=8+4 Kết xuất của chương trình khi chạy đến câu lệnh cuối là: Truoc khi goi thu tuc: A=3 B=5 C=8 Ben trong thu tuc: A=3 B=12 C=12... như sau: Ví dụ ta truyền vào giá trị m = 4, tức gọi GT(4) GT(4) m = 4 → Tính 4 * GT(4-1) → gọi GT(3) GT(3) m = 3 → Tính 3 * GT(3-1) → gọi GT(2) 12/19 CHƯƠNG TRÌNH CON GT(2) m = 2 → Tính 2 * GT(2-1) → gọi GT(1) GT(1) m = 1 → Gán GT(1):=1 Cuối cùng một quá trình “tính ngược” sẽ cho phép trả về giá trị của GT(4): GT(4) ? 4 * (3 * (2 * GT(1))) Cách 2: Dùng vòng lặp Function GiaiThua(m: longint): longint;... hơn ví dụ thứ nhất vì lời gọi đệ qui chia làm hai nhánh Cách 2: (Dùng chỗ lưu trữ tạm) FUNCTION FIBO(n:word):word; Var Counter,F1,F2:word; BEGIN F1:=1; F2:=1; Fibo:=1; FOR Counter:=3 TO n DO 14/19 CHƯƠNG TRÌNH CON Begin Fibo:=F1+F2; F1:=F2; F2:=Fibo; End; END; Trong cách 2 này việc khử đệ qui không còn dễ dàng nữa vì cách đó không chứa rõ ràng một qui tắc tổng quát cho phép xử lí Ví dụ 3: Bài toán tháp... Chuyển tiếp đĩa còn lại từ cọc A qua cọc C Chuyển tiếp đĩa đang ở cọc B sang cọc C N=3 Ta phải thực hiện 7 bước như sau: Trạng thái ban dầu Bước 1: Chuyển một đĩa từ A qua C 15/19 CHƯƠNG TRÌNH CON Bước 2: Chuyển một đĩa từ A qua B Bước 3: Chuyển một đĩa từ C qua B Bước 4: Chuyển một đĩa từ A qua C Bước 5: Chuyển một đĩa từ B qua A Bước 6: Chuyển một đĩa... Doi(0,B,A,C) Ví dụ này cho thấy việc kết xuất ở các câu lệnh Chuyen(X,Y) chỉ xảy ra khi toàn bộ các lời gọi đệ qui đã được thực hiện và cũng cho thấy thứ tự các lời gọi đệ qui lần cuối cùng 18/19 CHƯƠNG TRÌNH CON Nhận xét này rất quan trọng khi bạn viết thủ tục đệ qui vì lẽ bạn cần phải hình dung trước thứ tự các kết xuất nhất là khi lời gọi đệ qui có rất nhiều nhánh 19/19 ... pháp tốt Người ta thường cố gắng khắc phục đệ qui bằng cách dùng vòng lặp và sử dụng stack nhưng đó là công việc không mấy dễ dàng Ví dụ 1: Định nghĩa giai thừa của một số nguyên không âm m như sau: Lập trình để tính giai thừa của một số nguyên không âm nhập từ bàn phím Cách 1: Dùng đệ qui Function GT(m: Integer): Longint; Begin If ( m = 0 ) or ( m = 1 ) then GT := 1 Else GT := m * GT( m-1 ); End; Rõ ... End LỜI GỌI CHƯƠNG TRÌNH CON VÀ VẤN ĐỀ TRUYỀN THAM SỐ Một chương trình gồm chương trình nhiều chương trình Kèm theo biến, tham số khai báo vị trí khác chương trình Khả từ vị trí chương trình “nhìn... BIẾN • Khi chương trình chương trình gọi biến, “tên” chương trình bố trí vùng nhớ gọi STACK Khi chương trình gọi biến toàn cục bố trí vào stack tồn lúc chấm dứt chương trình Khi chương trình gọi... chương trình nhìn thấy chương trình (ie: gọi biến chương trình đó) Tầm vực biến hay chương trình chỗ khai báo khối hết khối mà khai báo đó, kể khối trừ khối có khai báo lại biến chương trình Qui