Bài 1. Thủ tục và hàm
Tóm tắt lý thuyết
Hiển thị
1. Cấu trúc của một chương trình con
a). Hàm
Function Tên_hàm(TS1:kiểu; TS2:kiểu; ...):kiểu; Var {khai báo các biến cục bộ}; Begin {Các lệnh tính toán}; Tên_hàm:= giá trị; {hàm kết thúc phải trả lại giá trị nào đó} End;
* Cách gọi hàm:
Tên_hàm(danh sách tham số thực sự);
b). Thủ tục
Procedure Tên_thủ_tục(TSGT1:kiểu; TSGT2:kiểu; ... ; Var TSB1:kiểu; Var TSB2:kiểu; ...); Var {khai báo các biến cục bộ của thủ tục}; Begin {Các lệnh tính toán của chương trình con}; End;
* Cách gọi thủ tục:
Tên_thủ_tục(danh sách tham số thực sự);
c). Sự khác nhau cơ bản giữa hàm và thủ tục.
- Hàm cho một giá trị thông qua tên hàm và hàm có thể tham gia vào các biểu thức tính toán, thủ tục không cho một giá trị nào. Trong thân hàm bao giờ cũng có giá trị gán cho tên hàm.
- Tham số hình thức và tham số thực sự:
+ Các tham số khác nhau sau tên hàm và thủ tục gọi là các tham số hình thức (hay còn được gọi là đối). Trong thủ tục các tham số hình thức có các loại: các tham số khai báo sau từ khoá Var gọi là các tham số biến; các tham số khai báo mà đằng trước không có từ khoá Var thì gọi là tham số giá trị. Trong hàm chỉ có tham số giá trị.
+ Tham số thực sự là các tham số dùng trong lời gọi hàm hay thủ tục. Danh sách tham số thực sự trong lời gọi phải tương ứng với các tham số hình thức trong khai báo chương trình con và chúng phải tương ứng về kiểu.
- Trong thủ tục, các tham số giá trị thường là các biến để chứa dữ liệu đưa vào thủ tục, các tham số biến là các biến mà kết quả tính toán của thủ tục sẽ chứa vào đó khi ra khỏi thủ tục, ta có thể dùng chúng để tính toán tiếp.
2. Biến toàn cục, biến cục bộ
Biến toàn cục là biến được khai báo ở đầu chương trình chính, tồn tại trong suốt thời gian chạy của chương trình. Ta có thể sử dụng và làm thay đổi giá trị của biến toàn cục nhờ các câu lệnh trong chương trình chính cũng như trong tất các chương trình con.
Biến cục bộ là biến được khai báo ở đầu một chương trình con. Chúng được cấp phát bộ nhớ khi chương trình con được gọi tới và được giải phóng khi ra khỏi chương trình con. Biến cục bộ có giá trị trong chương trình con và tất cả các chương trình con khác nằm trong chương trình con này.
Nếu tên biến cục bộ của một chương trình con trùng với tên biến toàn cục thì máy cũng không nhầm lẫn, nó sẽ dùng hai ô nhớ khác nhau để lưu trữ hai biến, khi ra khỏi chương trình con thì biến cục bộ bị xoá.
3. Cách truyền dữ liệu
Khi gặp một lời gọi tới một chương trình con, máy sẽ thực hiện các công việc sau:
- Cấp phát bộ nhớ cho các đối, các biến cục bộ.
- Truyền giá trị của các tham thực sự cho các tham số giá trị tương ứng, truyền địa chỉ của các tham số thực sự ứng với tham số biến cho các tham số biến của thủ tục.
- Thực hiện các lệnh trong chương trình con, trong khi thực hiện chương tình con, các biến cục bộ và tham số giá trị có thể bị biến đổi nhưng không ảnh hưởng tới các biến bên ngoài. Nhưng mọi thay đổi của tham số biến trong chương trình con sẽ kéo theo sự thay đổi của các tham số thực sự tương ứng (vì ở đây là truyền theo địa chỉ). Do đó, khi ra khỏi chương trình con, các tham số thực sự ứng với các tham số biến vẫn giữ được giá trị mới nhất do chương trình con tạo ra.
- Thực hiện xong các lệnh của chương trình con, máy sẽ giải phóng các đối và các biến cục bộ, trở về nơi gọi chương trình con.
Lấy kết quả thực hiện chương trình con: nếu là hàm thì lấy giá trị kết quả ở tên hàm, nếu là thủ tục thì lấy kết quả ở tham số thực sự ứng với các tham số biến. Khi cần lấy duy nhất một giá trị từ chương trình con thì ta dùng một hàm, còn nếu không cần lấy giá trị nào hoặc từ hai giá trị trở nên thì ta dùng thủ tục.
Câu hỏi, ví dụ, bài tập
Câu 1: Tìm lỗi trong các hàm số sau:
a.
Function f(a: 'a'..'z'): integer; Begin f:=ord(a)-ord('p'); if f<0 then f:=-f; End;
b.
Function g(k: integer): 0..maxint; Var i,s: 0..maxint; Begin s:=0; for i:=1 to k do s:=s+sqrt(i); End;
c.
Function h(x: integer): integer; Begin h(x):=(sqr(x)+x)/2; End;
Trả lời
Câu 2: Cho hàm số:
Function fib(n: integer): integer; Begin if n<3 then fib:=1 else fib:=fib(n-1)+fib(n-2); End;
Hãy tính nhẩm fib(2), fib(3) và fib(5).
Trả lời
Câu 3: Trong 4 hàm số sau đây có 1 hàm đúng dùng để tính n!. Bạn hãy tìm hàm số đó:
Function fac(n: integer): integer; Begin fac:=n*fac(n-1); End;
Function fac(n: integer): integer; Begin if n=0 then fac:=1 else fac:=fac(n+1)/(n+1); End;
Function fac(n: integer): integer; Begin if n=0 then fac:=1 else fac:=n*(n-1)*fac(n-2); End;
Function fac(n: integer): integer; Begin if n=0 then fac:=1 else fac:=n*fac(n-1); End;
Trả lời
Câu 4: Cho hàm số:
Function f(n: integer): integer; Begin if n>100 then f:=n-10 else f:=f(f(n+11)); End;
Hãy tính f(106), f(99) và f(85). Tìm công thức tổng quát cho f(n).
Trả lời
Câu 5: Bạn hãy viết hàm số tính C(m, n) theo công thức sau:
C(0, k) = C(k, k) = 1 với mọi 0 ≤ k ≤ n,
C(m, n) = C(m, n-1) + C(m-1, n-1) khi 0 < m < n.
Trả lời
Câu 6: Cho hàm F(n) với n tự nhiên xác định như sau:
F(0) = 0, F(1) = 1, F(2n) = F(n), F(2n+1) = F(n) + F(n+1).
Với N cho trước, hãy lập chương trình không dùng mảng độ dài N, tính F(N).
Trả lời
Câu 7: Bạn hãy kiểm tra xem các chương trình sau đây sẽ in ra kết quả gì:
Program Print; Var x,y: char; Procedure P(x: integer); Const y=true; Begin writeln(x,' ',y); End; Procedure Q; Var x: char; Begin x:=succ(y); y:='*'; writeln(x,' ',y); End; BEGIN x:='a'; y:='5'; P(8); writeln(x,' ',y); Q; writeln(x,' ',y); END.
Program Print; Type Str=String[5]; Var i: integer; t: Str; Procedure P(var s: Str); Begin i:=1; while s[i]<'9' do begin s[i]:=succ(s[i]); i:=i+1; end; End; BEGIN i:=1; t:='12945'; P(t); writeln(t[i]); END.
Trả lời
Câu 8: Bạn hãy dẫn ra một vài ví dụ trong Pascal, khi mà các biểu thức sau không thoả mãn:
y = y; y + y = 2*y.
Trả lời
Câu 9: Một file dữ liệu chứa các phân số, mỗi phân số gồm tử số và mẫu số là 2 số nguyên chứa trong 2 trường tương ứng của một record. Bạn hãy viết một chương trình tìm phân số tối giản của các phân số đó, kết quả ghi ra một file khác có cấu trúc giống file dữ liệu vào. Yêu cầu trong chương trình phải dùng một hàm tính USCLN của 2 số và một thủ tục giản ước một phân số.
Trả lời
Câu 10: Mỗi phân số gồm tử số và mẫu số là 2 số nguyên được chứa trong 2 trường tương ứng của một record. Bạn hãy viết một chương trình nhập 2 phân số và 1 dấu phép tính, sau đó tính kết quả. Yêu cầu trong chương trình phải dùng một hàm tính USCLN của 2 số và các thủ tục tính tổng, hiệu, tích, thương của 2 phân số.
Trả lời
Câu 11: Cho trước toạ độ các đỉnh của một đa giác. Bạn hãy tính chu vi và đường kính của nó. (Đường kính ở đây hiểu là khoảng cách lớn nhất giữa hai đỉnh của đa giác). Trong chương trình sử dụng hàm tính khoảng cách giữa 2 đỉnh. Dữ liệu được nhập từ tệp POLYGON.DAT có dạng: dòng đầu tiên ghi số n, n dòng tiếp theo ghi tọa độ phẳng của các đỉnh đa giác. Kết quả đưa ra màn hình.
Trả lời
Câu 12: Cho trước đa giác lồi $A_1A_2A_3...A_n$ (tức là cho toạ độ các đỉnh tương ứng của nó). Bạn hãy lập chương trình tính diện tích của nó. Trong chương trình sử dụng các hàm tính khoảng cách giữa 2 đỉnh và diện tích tam giác. Dữ liệu nhập vào giống bài trên.
Trả lời
Câu 13: Cho trước đa thức hệ số nguyên $f(x) = a_nx^n + a_{n-1}x^{n-1} + ... + a_1x + a_0$. Các nghiệm nguyên của đa thức (nếu có) phải là các ước số của a0. Bạn hãy lập chương trình tìm nghiệm nguyên của f(x). Trong chương trình sử dụng hàm tính giá trị đa thức theo sơ đồ Hoorner. Số n và dãy số $a_1, a_2, ..., a_n$ được nhập từ bàn phím.
Trả lời
Câu 14: Mỗi ma trận vuông cấp n các số thực $A = (a_{ij})$ có tương ứng một số detA gọi là định thức của nó cho bởi công thức truy hồi sau:
$\begin{array}{l} \det A = \left\{ \begin{array}{l} {a_{11}}\quad \quad \quad \quad \quad \quad \quad \quad \quad \quad \quad \quad \quad \quad \;\;khi\quad n = 1\\ {( - 1)^2}{A_{11}} + {\left( { - 1} \right)^3}{A_{12}} + ... + {\left( { - 1} \right)^{n + 1}}{A_{1n}}\quad \;khi\quad n > 1 \end{array} \right.\quad \\ \end{array}$
trong đó $A_{1i}$ là ma trận nhận được từ A bằng cách bỏ đi hàng thứ i, cột thứ 1.
Bạn hãy lập chương trình tính định thức của một ma trận cho trước. Dữ liệu ma trận cho trong tệp IN.DAT.
Trả lời
Câu 15: Mỗi ma trận vuông cấp n các số thực $A = (a_{ij})$ với detA ạ 0 có tương ứng một ma trận $B = (b_{ji})$ cùng cấp gọi là ma trận nghịch đảo của nó cho bởi công thức:
${b_{{\rm{ij}}}} = \frac{{{{\left( { - 1} \right)}^{i + j}}\det {A_{{\rm{ij}}}}}}{{\det A}}$
Trong đó $A_{ij}$ là ma trận nhận được từ A bằng cách bỏ đi hàng thứ i, cột thứ j.
Bạn hãy lập chương trình tính ma trận nghịch đảo của ma trận A. Input và Output của bài toán ghi trong các tệp có tên INPUT.DAT và OUTPUT.DAT.
Trả lời
Câu 16: Đường gấp khúc "con rồng" là đường có dạng như sau:
Hình trên vẽ 4 con rồng cấp 1, 2, 3 và 4 tương ứng. Hãy sử dụng kĩ thuật đệ qui vẽ con rồng cấp n (n nhập từ bàn phím).
Trả lời
Câu 17: Hãy lập chương trình để xếp 12 con mã lên bàn cờ tướng sao cho mỗi ô trên bàn cờ bị đúng một con mã kiểm soát.
Trả lời