//
you're reading...
00 - Chủ đề chung

Đọc thêm về chương trình con

Khái niệm về chương trình con : (Sub-program)
Trong khi lập trình chúng ta thường gặp những đoạn chương trình được lặp đi lặp lại nhiều lần ở những chỗ khác nhau. Để tránh rườm rà, những đoạn chương trình này được thay thế bằng một chương trình con và khi cần ta chỉ việc gọi chương trình con đó với các tham số tương ứng cần thiết. Nếu một chương trình rất dài, sẽ khó khăn cho việc gỡ rối, hiệu chỉnh. Ta có thể phân chia bài toán thành các bài toán con, mỗi bài toán con ứng với một chương trình con và như vậy sẽ dễ dàng kiểm tra gỡ rối. Việc chia nhỏ chương trình thành các Modul nhỏ có thể ví như nguyên tắc ” Chia để trị”.
Chương trình con được dùng rất phổ biến. Vì vậy chúng ta cần nắm vững các kỹ thuật lập chương trình con.
9.2 Procedure và Function ( Thủ tục và hàm )
Có hai loại chương trình con:
Procedure ( thủ tục)
• Function ( hàm).
Sự khác nhau cơ bản của hai loại này là Function trả lại kết quả cho tên của Function, còn Procedure không trả lại kết quả thông qua tên của nó.
Cấu trúc chung của một chương trình trong đó có phần khai báo chương trình con như sau:
Program TenChuongTrinh; (*Tiêu đề *)
Label (*Khai báo các nhãn *);
…..
Const (*Khai báo các hằng *);
…..
Type (* Mô tả kiểu *);
…..
Var (* Khai báo các biến*);
……
Procedure TenThuTuc ( khai báo các tham số, nếu cần);
(*Khai báo Label, Const, Type, Var của riêng Procedure, nếu cần*).
………………..
Begin
…… (* Thân chương trình con*).
End;
Function TenHam( khai báo các tham số, nếu cần): kiểu _dữ _liệu;
(*Khai báo Label, Const, Type, Var của riêng Procedure, nếu cần*).
Begin
…… (* Thân chương trình con*).
End;
Begin
……(*Thân chương trình*)
End.
Theo qui định này, LABEL trước, rồi đến CONST, TYPE, VAR cuối cùng là các PROCEDURE, các FUNCTION. Phần nào không có thì bỏ đi, đương nhiên không thể thiếu phần thân chương trình chính.
Để minh hoạ, chúng ta xét một chương trình sau:
Ví dụ 1:
Program PhuongTrinhBacHai;
Uses Crt;
Var
A,b,c,dx,x1,x2: Real;
Procedure Vao;
Begin
Write(‘ Vào hệ số a=’); Readln(a);
Write(‘ Vào hệ số b=’); Readln(b);
Write(‘ Vào hệ số c=’); Readln(c);
End;
Procedure TinhDelta;
Begin
Dx:=b*b-4*a*c;
If dx>=0 Then DeltaKhongAm Else DeltaAm;
End;
Procedure DeltaKhongAm;
Begin
x1:=(-b+Sqrt(dx))/(2*a);
x2:=(-b-Sqrt(dx))/(2*a);
End;
Procedure DeltaAm;
Begin
Writeln(‘Phương trình vô nghiệm’);
End;
Begin
Vao;
TinhDelta;
End.
Trong chương trình trên, tất cả các biến đều được khai báo ở chương trình chính, các biến ấy được gọi là biến toàn cục, biến toàn cục có ý nghĩa trong toàn bộ chương trình (nghĩa là các chương trình con đều dùng được). Trong chương trình con cũng có phần khai báo riêng của nó, các biến đó gọi là biến cục bộ. Biến cục bộ chỉ có ý nghĩa trong chương trình con đó mà thôi.
Cấu trúc chung của procedure và function như sau:
Procedure <Tên thủ tục> ( Khai báo các tham số hình thức);
<Khai báo: Label, Const, Type, Var và thậm chí cả các procedure và function>

Begin
…. (* Thân chương trình con*)
End;
và Function như sau:
Function <Tên hàm> ( khai báo các tham số hình thức): kiểu_dữ_liệu_của _hàm;
<Khai báo: Label, Const, Type, Var và thậm chí cả các procedure và function>

Begin
…. (* Thân chương trình con*)
End;
Kết thúc chương trình con bằng dấu chấm phẩy(;) không phải là dấu chấm (.) như chương trình chính.
9.3 Chuyển tham số cho chương trình con.
Chương trình con có thể được tính toán trực tiếp với các biến toàn cục hoặc tự khai báo biến cục bộ của nó và khi khai báo cục bộ thì phải truyền tham số cho chương trình con. Có hai cách truyền tham số: truyền tham biến (variable parameter) và truyền tham trị (value parameter). Sau đây là nội dung cụ thể.
1. Không cần biến cục bộ
Ta lấy một ví dụ đơn giản là: Vào hai số, tính tổng và in kết quả.
Program TongHaiSo;
USES CRT;
Var
S,a,b :Real;
Procedure VaoHaiSo;
Begin
Write (‘ a=’); Readln(a); (*a là biến toàn cục*)
Write (‘ b=’); Readln(b); (*b là biến toàn cục*)
End;

Procedure TinhTong;
Begin
S:=a+b; (*S là biến toàn cục*)
End;
Begin
VaoHaiSo;
TinhTong;
Writeln (‘S=’,S);
End.
Ở trên ta thấy s, a, b khai báo ở chương trình chính (toàn cục) và 3 biến đó được dùng trong cả hai thủ tục. Nghĩa là biến toàn cục có ý nghĩa trong toàn bộ chương trình. Cách thiết kế theo kiểu đó có nhược điểm là các chương trình con phải biết biến khai báo ở chương trình chính thì mới viết được chương trình con. Điều đó sẽ bất tiện khi chương trình lớn mà ta phải phân cho nhiều người viết (vì phải phụ thuộc biến ở chương trình chính)
2. Dùng biến cục bộ và truyền tham số
Ta viết lại chương trình trên theo kiểu “ít lệ thuộc” vào chương trình chính như sau:
Program TongHaiSo;
Uses Crt;
Var
S,a,b:Real; (*S,a,b là biến toàn cục*)
Procedure VaoHaiSo(Var x,y:Real);
Begin
Write (‘ x=’); Readln(x); (*x là biến cục bộ*)
Write (‘ y=’); Readln(y); (*y là biến cục bộ*)
End;
Procedure TinhTong(Var Tong:Real; P,Q:Real);
Begin
Tong:=P+Q; (*Tong,P,Q là biến cục bộ*)
End;
Begin
VaoHaiSo(a,b);
TinhTong(S,a,b);
Writeln (‘S=’,S);
End.
Giải thích:
Giả sử khi chạy chương trình gặp thủ tục VaoHaiSo(Var x,y:Real), ta gõ vào hai số 2 và 3 (nghĩa là x=2 và y=3).
Thủ tục VaoHaiSo(Var x,y:Real), điều này nói lên là x,y là tham biến (hay còn gọi là tham biến biến), vì sao vậy? Bởi vì khi ta gọi: VaoHaiSo(a,b) thì x chuyển giao giá trị cho a và y cho b. Nghĩa là trước khi gọi a và b có giá trị 0 sau khi gọi a=2 và b=3 (giá trị do x và y chuyển giao cho) tức là a,b có thay đổi giá trị (chữ Var trước x và y có ý nghĩa như vậy). Giả sử ta bỏ chữ Var và thủ tục bây giờ là VaoHaiSo(x,y:Real). Khi chạy chương trình thì trước và sau khi gọi thì a và b đều có giá trị 0, mặc dù ta vẫn gõ vào x=2 và y=3.
Thủ tục TinhTong(Var Tong:Real; P,Q:Real); thì biến Tong cũng là tham biến biến vì trước khi gọi s=0 và sau khi gọi s=5. Còn P,Q là tham biến trị, vì sao vậy? Vì khi ta gọi:TinhTong(s,a,b) thì a và b trước khi gọi có giá trị a=2, b=3 và sau khi gọi cũng vậy nghĩa là không thay đổi giá trị. Vậy là khi nào thì cần tham biến biến và khi nào thì cần tham biến trị là ở ý nghĩa trên.
3. Sự khác nhau giữa Function và Procedure
Function là một chương trình con để tính toán một giá trị nào đó, bên trong Function bắt buộc ta phải có một lệnh gán giá trị kết quả cho tên hàm:
Tên_Hàm := <biểu thức>;
Khi lập trình ta nên quyết định là sử dụng Procedure hay Function:
Chương trình con nên là Function khi các yêu cầu sau thoả mãn:
Nếu ta muốn nhận lại duy nhất một kết quả.
ã Kết quả đó phải là kiểu vô hướng.
Còn nếu không thì chương trình con nên là Procedure.
Ví dụ đơn giản là lập chương trình con tính bình phương của một số.
Nếu dùng Function, ta có:
Function BinhPhuong(x: real): Real;
Begin
BinhPhuong:= x*x;
End;
Nếu dùng Procedure, ta có
Procedure BinhPhuong(x: Real; Var y: Real);
Begin
y:= x*x;
End;
Cả hai trường hợp x đều là tham trị. Còn nếu dùng Function thì bản thân tên của Function (BinhPhuong) được dùng làm tham biến để chứa kết quả tính toán như biến y ở cách dùng Procedure. Hãy quan sát cách tính s = x3 +y3 + v3 +z3 trong hai trường hợp:
Nếu dùng Function:
S: = LapPhuong(x) + LapPhuong(y) +LapPhuong(v)+LapPhuong(z);
Program TinhTong;
Var
S,x,y,v,z:Real;
Function LapPhuong(u:Real):Real;
Begin
LapPhuong:=u*u*u;
End;
Begin
x:=3; y:=5; v:=7;z:=2;
s:=LapPhuong(x)+LapPhuong(y)+LapPhuong(v)+LapPhuong(z);
Writeln(‘s=’,s);
End.
Nếu dùng Procedure ta có:
Program TinhTong;
Var
Tong,a,b,c,d:Real;
Procedure LapPhuong(Var s:Real; x,y,v,z:Real);
Begin
S:=x*x*x+y*y*y+v*v*v+z*z*z;
End;
Begin
a:=3; b:=5; c:=7;d:=2;
LapPhuong(Tong,a,b,c,d);
Writeln(‘Tong=’,Tong);
End.
Ta thấy trong trường hợp này dùng Function ngắn hơn vì ta có thể lập Function chỉ với một biến. Ngoài ra giả sử nếu trong chương trình còn có thêm điều kiện là chỉ cộng vào khi lập phương của một số là dương:
Nếu dùng Function, ta chỉ việc viết:
If LapPhuong(x) > 0 Then s:=s+LapPhuong(x)
Còn nếu dùng Procedure thì phức tạp hơn nhiều.
4. Biến toàn cục, biến cục bộ và tầm hoạt động của biến.
Như đã nói ở trên, các biến được khai báo trong chương trình chính được gọi là các biến toàn cục. Các biến này có tầm hoạt động trong toàn bộ chương trình. Các biến được khai báo trong một chương trình con được gọi là biến cục bộ và chỉ có tầm hoạt động trong chương trình con đó hay trong các chương trình con khác chứa trong nó mà thôi. Khi chương trình con kết thúc thì các biến này cũng mất tác dụng theo. Giả sử ta có chương trình sau:
Program TamHoatDong;
Var a,b,c:Real;
Procedure ThuTucA;
Var
x,y:Real;
Procedure ThuTucB;
Var
v,z:Real;
Begin
………..
End;
Begin
………
End;
Begin
…….
End.
Ta nhận thấy:
Biến a,b,c: Có tầm hoạt động là toàn bộ chương trình
Biến x,y : Có tầm hoạt động trong ThuTucA và tất nhiên cả trong ThuTucB (vì ThuTucB nằm trong ThuTucA )
Biến v,z:Có tầm hoạt động chỉ trong ThuTucB.
5. Tính đệ quy của chương trình con.
Trong Procedure hoặc Function có thể có lời gọi đến chính nó. Tính chất này được gọi là tính đệ quy.
Ví dụ:
Function DeQuy(<Tham biến>:<Kiểu>);
Begin
…..
DeQuy(……); (*Gọi đến chính nó*)
…….
End;

Ví dụ tính giai thừa n! = 1.2.3…(n-1).n
Ta có thể định nghĩa:
Nếu n=0 thì n!=1
Nếu n>1 thì n!=(n-1)!.n
Và Function được định nghĩa đệ quy như sau.:
Function GiaiThua( n: Integer): Integer;
Begin
If n = 0 Then GiaiThua:=1 Else GiaiThua:= n * GiaiThua(n – 1);
End;

Nếu không dùng đệ quy thì:
Function GiaiThua(n: Integer): Integer;
Var
i, P: Integer;
Begin
i :=1;
P :=1 ; (*P là biến cục bộ để chứa kết quả trung gian*)
While i <= n DO
Begin
k:=k*i;
I:= i+1;
End;
GiaiThua:=P; (*gán kết quả từ biến P vào tên hàm*)
End;
Nếu không dùng đệ quy, ta chỉ cần hai ô nhớ cục bộ i và P, còn dùng đệ quy mỗi lần dùng GiaiThua(n), máy phải bố trí thêm một ô nhớ chứa kết quả GiaiThua trung gian.
Nói chung không phải lúc nào dùng đệ quy cũng có lợi.
6. Đơn vị chương trình (Unit)
Trong Turbo Pascal có nhiều đơn vị chương trình (Unit) trong đó chứa những chương trình con mà khi cần đến người lập trình chỉ cần gọi chúng bằng những tên cụ thể. Ví dụ đơn vị CRT là Unit chứa các chương trình con xử lí màn hình như thủ tục: GOTOXY, ClrScr,v.v… Printer là Unit chứa các thủ tục in như Writeln (Lst,….). DOS Là Unit chứa các hàm của DOS. SYSTEM là Unit chứa các chương trình con về hệ thống.GRAPH là Unit về đồ hoạ v.v..
Ngoài ra Unit cũng có thể do chính người lập trình tự tạo.
Một Unit do bạn tạo ra sẽ được chứa trong một file, giả sử File có tên DonVi.PAS. Cấu tạo tổng quát của Unit tự tạo như sau:
Unit DonVi; (*Tên Unit đặt trùng với tên File*)
Uses <Tên các unit cần dùng>;
Interface
(* Phần khai báo các thủ tục và hàm *)
Implementation
(*Khai báo dữ liệu và các thủ tục và hàm của Unit này*)
End. (*Kết thúc Unit bằng End có dấu chấm*)
Ví dụ ta viết lại chương trình giải phương trình bậc hai bằng Unit
Unit PTBHai;
Uses Crt;
Interface
a,b,c,dx,x1,x2: Real;
Implementation
Procedure Vao;
Begin
Write(‘ Vào hệ số a=’); Readln(a);
Write(‘ Vào hệ số b=’); Readln(b);
Write(‘ Vào hệ số c=’); Readln(c);
End;
Procedure TinhDelta;
Begin
Dx:=b*b-4*a*c;
If dx>=0 Then DeltaKhongAm Else DeltaAm;
End;
Procedure DeltaKhongAm;
Begin
x1:=(-b+Sqrt(dx))/(2*a);
x2:=(-b-Sqrt(dx))/(2*a);
ClrScr;
Writeln(‘x1=’,x1);
Writeln(‘x2=’,x2);
End;
Procedure DeltaAm;
Begin
Writeln(‘Phương trình vô nghiệm’);
End;
End.
Cách gọi Unit trong chương trình:
Program PhuongTrinhBacHai;
Uses Crt, PTBHai;
Begin
ClrScr;
Vao;
TinhDelta;
End.
7.Chương trình con là thành phần của Turbo Pascal.
Các chương trình con là thành phần của Turbo Pascal bao gồm:
Các hàm số học: ABS, ARCTAN, COS, SIN, EXP, LN, SQRT,SQR.
Các hàm vô hướng: SUCC, PRED, ODD.
Các hàm chuyển đổi: CHR, ORD, ROUND, TRUNC.
Hàm Frac(x) cho giá trị là phần thập phân của x
Hàm Int(x) cho giá trị là phần nguyên của x
Hàm Random, cho giá trị là số ngẫu nhiên nằm trong khoảng 0 và 1
Hàm Random(n), cho giá trị số thực nằm trong khoảng 0 và n (n là số nguyên)
Thủ tục Randomize, là thủ tục đảm bảo cho hàm Random chạy với một số ngẫu nhiên. Nên gọi thủ tục này trước khi gọi Random.
Hàm Upcase(ch), cho ký tự chữ lớn tương ứng với Ch.
ã Hàm KeyPressed (trong Crt), hàm cho kết quả True nếu ta gõ một ký tự, False nếu không gõ.
ã Hàm ReadKey (trong Crt), đọc một ký tự từ bàn phím.
Thủ tục GotoXY ( X, Y); ( trong Crt)
ã Hai hàm Wherex, Wherey cho toạ độ con trỏ.
ã Thủ tục ClrScr; (trong Crt), xoá toàn bộ màn hình và đặt con trỏ vào vị trí phía trên, bên trái.
ã Thủ tục ClrEof; (trong Crt), xoá toàn bộ các ký tự bên phải con trỏ màn hình, sau khi xoá con trỏ vẫn ở nguyên tại chỗ.
ã Thủ tục DelLine; (trong Crt), xoá toàn bộ dòng màn hình chứa con trỏ,sau đó dồn các dòng ở phía dưới lên.
ã Thủ tục InsLine;(trong Crt*), xen một dòng trắng vào màn hình từ vị trí con trỏ.
ã Thủ tục LowVideo và NormVideo; (trong Crt), sau khi gọi LowVideo, mọi ký tự hiện ra màn hình đều có độ sáng yếu cho tới khi gọi thủ tục NormVideo.
ã Thủ tục Delay(Time);(trong Crt), tạo ra khoảng thời gian trễ (khoảng ms).Time là một số nguyên.Delay thường được dùng để làm chậm chương trình lại cho ta quan sát, khảo sát…
ã Thủ tục Sound(F) và NoSound; tạo ra âm thanh với tần số là F ( F: số nguyên) cho đến khi ta gọi NoSound.
ã Thủ tục Halt (trong system), dừng hoạt động chương trình và trở về hệ điều hành.
ã Thủ tục Exit, khi gặp thủ tục này trong chương trình con thì kết thúc chương trình con đó và quay về chương trình gọi nó.
ã V.v..
Ví dụ 1 : Dùng Sound(F), Delay(n) và NoSound để phát âm, kéo dài và tắt âm thanh
Program AmThanh;
Uses Crt;
Var
i: Integer ;
Begin
For i:=100 To 1000 Do
Begin
Sound(i);
Delay(50);
Nosound;
End;
End.
Ví dụ 2: Dùng hàm Random để tạo các số ngẫu nhiên và dùng hàm Keypressed để điều khiển.
Program TaoSoNgauNhien;
Uses Crt;
Procedure NgauNhien;
Var
Ch: Char;
Begin
Randomize;
Repeat
Writeln(Random);
Until Keypressed;
End;
Begin
NgauNhien;
End.
Câu hỏi và bài tập:
Thế nào là biến toàn cục và biến cục bộ cho ví dụ?
Nói rõ sự khác nhau giữa tham biến biến và tham biến trị?
Khi nào thì cần tham biến biến? Cho ví dụ minh hoạ
Khi nào thì cần tham biến trị? Cho ví dụ minh hoạ
Để đỡ rắc rối trong việc truyền tham biến nhiều khi ta khai báo biến toàn cục cho mọi chương trình con, nhưng phương pháp này có hạn chế gì? hãy chỉ ra
X là biến toàn cục, trong thủ tục A cũng có khai báo biến X (cục bộ), đứng trong A nếu dùng X thì X đó là gì? (toàn cục hay cục bộ)
Cho xâu a=’0123456789′ hãy lập một chương trình con đảo thành a=’9876543210′, bạn thử viết cho cả đệ quy và không đệ quy.
Lập trình (theo kiểu thủ tục) giải phương trình bậc nhất hai ẩn sau:
ax+by=c
dx+ey=f

CHƯƠNG 10: KIỂU DỮ LIỆU CÓ CẤU TRÚC- KIỂU MẢNG
Chúng ta đã làm quen với các kiểu dữ liệu: Integer, Char, Boolean, Real, Liệt kê và Khoảng con. Trong Pascal tồn tại các kiểu dữ liệu khác được tạo ra từ các phần tử có kiểu dữ liệu đơn giản trên. Dữ liệu đó được gọi là dữ liệu có cấu trúc (vì nó có tính cấu trúc).
Trong Pascal có 4 kiểu dữ liệu có cấu trúc đó là: Mảng (array), tập hợp(set), bản ghi (record) và tệp (file).
10.1 Mảng (array)
Mảng là một dữ liệu có cấu trúc bao gồm một số hữu hạn phần tử có cùng kiểu. Số phần tử của mảng được xác định khi định nghĩa mảng. Mỗi phần tử của mảng được biểu diễn thông qua tên mảng cùng với chỉ số nằm trong mở và đóng ngoặc vuông[].
Giả sử ta có 1 mảng 10 phần tử nguyên ta định nghĩa kiểu mảng như sau:
Type
A = ARRAY [1..10] Of Integer;
Việc khai báo một biến mảng B được viết như sau:
Var
B:A;
Chú ý:1..10 là một khoảng con, ý muốn nói các phần tử của mảng dựa theo chỉ dẫn đó.
Ta cũng có thể khai báo trực tiếp biến B như sau:
Var
B: ARRAY [ 1..10] Of Integer;
Một số ví dụ về định nghĩa mảng như sau.
Ví dụ 1:
Type
A=Array[1…5] of integer;
B=Array[1…5] of char;
Color = (Do, Vang, Xanh, Den);
Var
X,Y: A;
M,N: B ;
K: Array[ ‘A’ …’F’] Of Integer;
P: Array[Color] Of Boolean;
A, B là hai kiểu mảng gồm 5 phần tử được đánh số thứ tự từ 1 đến 5 thông qua kiểu chỉ dẫn là một khoảng con: 1..5. Các phần tử của A có kiểu nguyên, còn các phần tử của B có kiểu ký tự. X, Y là các biến có kiểu A v.v…
K là một biến mảng gồm 6 số nguyên được đánh số qua chỉ dẫn là các chữ cái từ ‘A’ cho đến ‘F’.
P là một mảng gồm 4 phần tử kiểu Boolean, các phần tử được đánh dấu qua chỉ dẫn là tên của 4 mầu sắc.
Khi khai báo mảng, kiểu chỉ dẫn chỉ có thể là kiểu đơn giản như: ký tự, khoảng con, liệt kê và Boolean. Kiểu chỉ dẫn không được là Real hoặc Integer. Nghĩa là sai nếu viết.
Type
A= Array[Real] of integer;
Phần tử của mảng được xác định qua biến mảng và giá trị chỉ dẫn để trong ngoặc vuông. Ví dụ: K[‘A’]:=12; X[2]:=3; P[Do]:=False; v.v..
Sau đây la một số ví dụ.
Ví dụ 1: Vào 5 giá trị cho mảng nguyên
Program VaoMangNguyen;
Uses Crt;
Type
A=Array[1..5] of Integer;
Var
I: Integer;
X:A;
Begin
For I:=1 To 5 Do
Begin
Write( ‘ X [‘,I, ‘] = ‘ ); (* Tạo chỉ dẫn để biết mà gõ vào*).
Readln (X[I] ); (* Vào số nguyên qua bàn phím *).
End;
End.
Khi chương trình chạy, máy sẽ hiện ra tên phần tử và chờ ta gõ vào:
X [1] = 1
X [2] = 2
X [3] = 4
X [4] = 3
X [5] = 2
Ví dụ 2: Tổng hai mảng
Program TongHaiMang;
Uses Crt;
Type
A=Array[1..5] of Integer;
Var
I: Integer;
Z, X, Y:A;
Begin
ClrScr;
Writeln(‘Vào mảng X’);
For I:=1 To 5 Do
Begin
Write( ‘ X [‘,I, ‘] = ‘ ); (* Tạo chỉ dẫn để biết mà gõ vào*)
Readln (X[I] ); (* Vào số nguyên qua bàn phím *)
End;
Writeln(‘Vào mảng Y’);
For I:=1 To 5 Do
Begin
Write( ‘ Y [‘,I, ‘] = ‘ ); (* Tạo chỉ dẫn để biết mà gõ vào*)
Readln (Y[I] ); (* Vào số nguyên qua bàn phím *)
End;
Writeln(‘Tính tổng Z:=X+Y’);
For I:=1 To 5 Do Z[i]:=X[i]+Y[i]; (*Tính tổng hai mảng*)
End.
Ví dụ 3:
Giả sử ta muốn biết trong 50 lần gõ vào phím chữ cái trên bàn phím (ở chế độ chữ nhỏ), có bao nhiêu lần gõ vào mỗi loại chữ cái nhỏ từ ‘a’ đến ‘z’.

Program ChuongTrinhDem;
Uses Crt;
Var
I : integer;
Chr : Char
A: Array[ ‘a’… ‘z’] Of Integer;
Begin
For Chr := ‘a’ To ‘ z’ Do A[Chr] :=0; (*Xoá mảng A *)
For I:=1 To 50 Do
Begin
Readln (Chr);
A[Chr] :=A[Chr] + 1;(*đếm số lần xuất hiện *)
End;
For Chr:= ‘a’ To ‘z’ Do
If A[Chr] > 0 Then
Writeln (‘Chu ‘, Chr, ‘ = ‘ , A[Chr] : 3);
End.
10.2 Xếp mảng.
Việc sắp xếp các phần tử của mảng tăng hoặc giảm dần là một việc hay xảy ra trong cuộc sống. Sau đây sẽ trình bày một số phương pháp sắp xếp mảng qua các ví dụ.
Sau đây là ví dụ về việc xếp mảng.
Đầu tiên đem phần tử thứ nhất lần lượt so sánh với các phần tử tiếp theo, nếu nó lớn hơn thì đem đổi chỗ giá trị của hai phần tử so sánh. Kết quả sau lượt đầu, phần tử đầu tiên giữ giá trị nhỏ nhất. Tiếp tục vòng hai , đem phần tử thứ hai so sánh với các phần tử tiếp theo ….
Program XepMang;
Uses Crt;
Const
N=10 ;
Var
a: Array[1..N] Of Integer;
tg: Integer ; (*tg là biến trung gian*)
i,j: Integer;
Begin
ClrScr;
(*Vào mảng*)
For i:=1 To n Do Begin
Write (‘ Vào a[‘ ,i ,’ ] = ‘);
Readln (a[i]);
End;
(* xếp mảng lớn dần*)
For i:=1 To n-1 Do
For j:=i+1 To n Do
Begin
If a[i] >a[j] Then
Begin
(* đổi chỗ phần tử cho nhau*)
tg:=a[i];
a[i]: = a[j];
a[j]:= tg;
End;
End;
(* In ra kết quả *)
For i:=1 To n Do Writeln (a[i]:5);
End.
Ví dụ 2: Cộng hai ma trận cùng số dòng và cùng số cột: c(m,n) = a(m,n)+b(m,n)
Program TongHaiMaTran;
Const
m =3; n=4;
Var
a, b, c: Array [1…m, 1…n ] Of Integer;
i, j, k: Integer;
Begin
(* Vào dữ liệu cho ma trận a*)
For i:= 1 To m Do
For j:= 1 To n Do
Begin
Write( ‘a[‘, i, ‘,’ , j, ‘] =’ );
Readln (a[i, j] );
End;
(* Vào dữ liệu cho ma trận b*)
For i:= 1 To m Do
For j := 1 To n Do
Begin
Write( ‘b[‘, i, ‘,’ , j, ‘] =’ );
Readln (b[i,j] );
End; (* Cộng hai ma trận*)
For i:=1 To m Do
For j:= 1 To n Do
c[i,j]:=a[i,j]+b[i,j];
(* Hiển thị ma trận C*)
For i:=1 To m Do
Begin
For j:= 1 To n Do Write (C [I, J] : 5 ); (*In một hàng*)
Writeln;
End;
End.
Trong chương trình trên, việc vào dữ liệu cho ma trận được tiến hành theo từng dòng.
Ví dụ 3: Ví dụ 2 được viết lại theo kiểu thủ tục:
Program TongHaiMaTran;
Const
m =3; n=4;
Type
Mang= Array [1..m, 1..n] Of Real;
Var
a,b,c: Mang;
Procedure VaoMang(Var x, y: Mang);
Var
i, j : Integer;
Begin
(* Vào dữ liệu cho ma trận x*)
For i:= 1 To m Do
For j:= 1 To n Do
Begin
Write( ‘x[‘, i, ‘,’ , j, ‘] =’ );
Readln (x[i, j] );
End;
(* Vào dữ liệu cho ma trận y*)
For i:= 1 To m Do
For j := 1 To n Do
Begin
Write( ‘y[‘, i, ‘,’ , j, ‘] =’ );
Readln (y[i,j] );
End;
End;
Procedure TongHaiMaTran(x,y:Mang; Var Tong:Mang);
Var I,j: Integer;
Begin
For i:=1 To m Do
For j:= 1 To n Do
Tong[i,j]:=x[i,j]+y[i,j];
End;
Begin
VaoMang(a,b);
TongHaiMaTran(a,b,c);
For i:=1 To m Do
Begin
For j:=1 To n Do Write(c[i,j]; Writeln;
End;
End.
Câu hỏi và bài tâp:
1. Vào lương của 10 người sau đó tính tổng lương?
2. Vào tên củ 10 sinh viên sau đó xếp tên theo A,B,C..
3. Vào dữ liệu cho ma trận có dạng sau:
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
Sau đó chuyển thành :
0 1 1 1
1 0 1 1
1 1 0 1
1 1 1 0
Nghĩa là nếu a[i,j]=1 thì a[i,j]:=0 và ngược lại.
4. Tìm Max của mảng một chiều có 10 phần tử
5. Tìm Max của mảng A(10,12)
6. Cho hai mảng một chiều A và B hãy xếp hai mảng đó tăng dần sau đó trộn hai mảng đó thành mảng C theo trật tự sau: a[1],b[1],a[2],b[2] v.v.
7. Cho ma trận thực dạng A[1..10,1..10] hãy đưa vào 100 thành phần của nó là các số ngẫu nhiên (Random), sau đó tính tổng hai đường chéo chính. Tính tổng tất cả các phần tử, trừ các thành phần của hai đường chéo chính.
8. Giải phương trình bậc nhất hai ẩn bằng khai báo mảng
CHƯƠNG 11: XÂU KÝ TỰ (STRING)
11.1 Định nghĩa xâu ký tự
Một xâu ký tự được định nghĩa bằng từ khoá String, theo sau là số ký tự cực đại có thể có của xâu ký tự, được đặt trong ngoặc vuông.
String[n]; với n là độ dài cực đại của xâu.
Ví dụ 1:
Type
Xau1= String [10];
Xau2= String [40];
Var
A:Xau1;
B: Xau2;
Hay cũng có thể khai báo trực tiếp:
Var
A:String[10];
B:String[40];
Xâu ký tự chiếm số byte bằng số ký tự cực đại khi khai báo, cộng với một byte đầu tiên chứa số ký tự hiện có của xâu.
Ví dụ 2:
Var
a,b:String[15];
Begin
a:=’Tin hoc’;
…..
End.
Biến a khai báo ở trên được gán giá trị : a:=’Tin hoc’;
a trong trường hợp này chỉ có độ dài 7 ký tự, mặc dù độ dài cực đại cho phép của biến a là 15. Như đã nói ở trên, byte đầu tiên để biểu diễn độ dài xâu ký tự. Vì độ dài xâu ký tự được biểu diễn bằng một byte nên ta thấy ngay rằng độ dài xâu ký tự chỉ nằm trong khoảng từ 1 đến 255.
Người ta có thể hiểu String như là một mảng ký tự có chỉ số chạy từ 0 đến độ dài cực đại, phần tử thứ 0 chứa độ dài thực của xâu. Song mảng ký tự có độ dài luôn luôn không đổi.
Ta có thể truy nhập vào từng ký tự của một xâu ký tự với tên biến và chỉ số đặt trong ngoặc vuông như khi truy nhập vào phần tử của mảng. Chỉ số này có thể chạy từ 1 tới độ dài cực đại của xâu ký tự. Ví dụ:
Writeln(a[3]) sẽ cho chữ ‘n’ (*vì a:=’Tin hoc’*)
Nếu vị trí ký tự đó nằm ngoài độ dài thực của xâu thì phần tử đó của xâu không xác định. Vì vậy khi truy nhập vào từng phần tử của xâu ta cần phải kiểm tra xem vị trí đó có nằm trong khoảng độ dài thực của xâu hay không.
11.2 Các thao tác với xâu ký tự
1. Phép cộng xâu
Ta dùng dấu cộng (+) để ghép hai xâu lại với nhau. Ví dụ:
A:= ‘Tin hoc’+’ van phong’ ;
Trong biến a sẽ có: a:=’Tin hoc van phong’.
2. So sánh xâu ký tự
Xâu ký tự có thể được dùng trong các biểu thức so sánh:
ã Khi so sánh hai xâu ký tự, các ký tự của hai xâu được so sánh từng cặp một từ trái qua phải theo giá trị của bảng mã ASCII.
Nếu hai xâu có độ dài khác nhau nhưng số ký tự đều giống nhau thì xâu có độ dài ngắn hơn được coi là bé hơn. Ví dụ:
‘Tin hoc van phong'<‘Tin hoc van phong trinh do A’; Cho giá trị True
Hai xâu ký tự bằng nhau nếu như cả về nội dung lẫn độ dài của chúng là giống nhau.
‘Tin hoc van phong’=’Tin hoc van phong’; có giá trị True.
3. Khai báo String làm tham số cho chương trình con.
Tương tự như Array, String có thể dùng làm tham số cho chương trình con.
Ví dụ:
Type
a= String[10];
b=String[20];
Var
x: a;
y: b;
Function HamXau:a;
Procedure ThuTucXau(St: b);
……
Khi dùng String làm tham số cho chương trình con, về nguyên tắc độ dài của tham số thực phải bằng độ dài của tham số hình thức. Ví dụ lời gọi sau là đúng:
ThuTucXau(b); vì b ( tham số thực sự) có kiểu là a trùng với tham số hình thức là St cũng có kiểu là a.
4. Các thủ tục và hàm chuẩn xử lý xâu ký tự
Trong Turbo Pascal có một số thủ tục và hàm để xử lý xâu ký tự như sau:
ã Length (St) là hàm cho ta độ dài của xâu ký tự St.
Ví dụ: với St := ‘Tin hoc’; thì length(St) có giá trị bằng 7.
ã Delete (St, Pos,Num)
Là thủ tục xoá đi Num ký tự từ vị trí Pos trong xâu St.
Ví dụ với St :=’Tin hoc’;
Sau khi gọi Delete(St, 2, 3);
St sẽ còn lại: Thoc.
Insert (Obj, St, Pos)
Là thủ tục xen xâu ký tự Obj vào xâu St tại vị trí Pos.
Ví dụ với St = ‘Tin hoc’; Obj = ‘ 23’;
Sau khi gọi Insert(obj, St, 6); St sẽ thành ‘ Tin h23oc’.
ã Str (Value, St)
Là thủ tục biến đổi giá trị bằng số nguyên hoặc thực Value thành một dãy ký tự biểu diễn số đó. Cách biểu diễn của St sẽ được qui định do qui cách của Value.
Ví dụ: I là một số nguyên bằng 52 với qui cách viết là 5 ký tự.
Str (I:5, St) sẽ cho ra St = ‘ 52’; ( *5 ký tự*)
giả sử X là số thực và bằng 123.5678901. Ta muốn biểu diễn X dưới dạng 10 ký tự với 5 số thập phân.
Str(X :10:5, St) sẽ cho kết quả St = ‘ 123.56789’;
Val(St, Value, Code )
Là thủ tục biến đổi xâu ký tự St (biểu diễn một số nguyên hoặc thực) thành một số nguyên hoặc thực chứa trong value. Code là số nguyên để phát hiện lỗi: nếu phép biến đổi mà đúng thì Code có giá trị 0, nếu sai do St không biểu diễn đúng số nguyên hoặc số thực, Code sẽ nhận giá trị bằng vị trí của ký tự sai trong xâu chữ St.
Ví dụ X là biến thực, St = ‘123.56’, Z là biến nguyên.
Val (St, X, Z) cho ta X = 123.56 và Z = 0
thí dụ I là biến nguyên, St = ‘123’, Z là biến nguyên.
Val (St, I, Z ) cho ta I = 123 và Z =0;
nếu St = ‘ 123X’ tức là St không biểu diễn đúng số nguyên do có chữ X thì Val (St, I, Z ) cho ta I không xác định và Z = 4;
Ví dụ:
Var
St : String [4];
K,I : Integer;
Begin
Repeat
Write(‘Vào xâu ký tự số nguyên St=’);
Readln (St); (* Vào xâu ký tự số nguyên*)
Val (St, I, K); (* Chuyển St thành số nguyên I*)
If K <> 0 Then writeln (# 7, ‘Lỗi!’ );
Until z = 0;
End;
ã Copy (St, Pos, n)
Hàm Copy sẽ nhận n ký tự trong St từ vị trí Pos.
Ví dụ:
St :=’123456789 ‘; St1 là một xâu ký tự khác.
St1: = Copy (St, 3, 2); sẽ cho St1 = ’34’;
ã Concat (St1, St2,…, StN);
Là hàm ghép nối tất cả các xâu ký tự St1, St2, …, StN thành một xâu ký tự theo thứ tự đã viết. Tất nhiên nếu tổng số chiều dài của các xâu ký tự lớn hơn 255 thì máy sẽ báo lỗi. chúng ta cũng có thể dùng phép + để ghép nối xâu ký tự.
ã Pos(Obj , Target)
Là hàm cho ta vị trí đầu tiên của xâu Obj gặp trong xâu Target.
Nếu không tìm thấy , Pos có giá trị bằng 0.
Ví dụ: Nếu St = ‘123454545’ và Obj =’45’ thì
Pos(obj,St) cho giá trị bằng 4
Pos(‘4X’, St) cho giá trị bằng 0 vì không tìm thấy.
CHƯƠNG 12: KIỂU BẢN GHI (RECORD)
12.1 Record là gì?
Chúng ta đã biết về dữ liệu có cấu trúc như mảng (array). Dữ liệu này đều được tạo ra bằng một tập hợp các phần tử có cùng kiểu. Ví dụ các phần tử của một Array[ 1..10] of Real là các số thực hay Array [1..10] of String[12]là các xâu ký tự.
Một dữ liệu có cấu trúc mới với các phần tử có kiểu khác nhau được gọi là bản ghi (tiếng Anh gọi là Record). Như vậy Record là một dữ liệu có cấu trúc mà các phần tử có kiểu khác nhau, điều đó nói lên tính linh hoạt của nó trong việc thiết lập các dữ liệu phong phú trong cuộc sống.
12.2 Mô tả Record
Để mô tả A có kiểu Record với các biến trường có tên là t1, t2,..,tn và kiểu của biến trường tương ứng là: k1, k2,…kn, ta có cách viết tổng quát như sau:
Type
A = Record
t1 : k1;
t2 : k2;
………..
tn : kn;
End;
Ví dụ 1:
Một sơ yếu lý lịch bao gồm: Họ tên, Ngày sinh, Chức vụ, Văn hoá, Lương v.v.. Ta mô tả như sau:
Type
A = Record
HoTen : String[25];
NgaySinh : String[8];
VanHoa : String[10];
Luong : Real;
SoCon : Byte;
End;
Ta có 5 trường với kiểu: String, Real, Byte để mô tả một nhân sự nào đó.
Ví dụ 2:
Để mô tả thời gian (ngày/Tháng/năm) ta mô tả một Record như sau:
Type
ThoiGian= Record
Ngay : 1..31;
Thang: 1..12;
Nam : Integer;
End;
Và ví dụ 1 có thể viết lại như sau:
Type
ThoiGian= Record
Ngay : 1..31;
Thang: 1..12;
Nam : Integer;
End;

Type
A = Record
HoTen : String[25];
NgaySinh : ThoiGian;
VanHoa : String[10];
Luong : Real;
SoCon : Byte;
End;
Hay cũng có thể viết lồng nhau như sau:
Type
A = Record
HoTen : String[25];
NgaySinh : Record
Ngay : 1..31;
Thang: 1..12;
Nam : Integer;
End;
VanHoa : String[10];
Luong : Real;
SoCon : Byte;
End;
12.3 Vào- Ra Record
Để xác định một trường của Record, ta cần phải dùng tên biến Record,dấu chấm và tên trường của Record. Ví dụ BanGhi.NgaySinh (BanGhi là biến Record, NgaySinh là biến trường của Record đó)
Ví dụ 1:
Vào dữ liệu cho bản ghi có tên NhanSu sau:
Program VaoRaBanGhi;
Uses Crt;
Type
A=Record
HoTen : String[25];
NgaySinh : String[8];
VanHoa : String[10];
Luong : Real;
SoCon : Byte;
End;

Var
NhanSu: A;
Begin
ClrScr;
Write ( ‘Vào họ tên ? ‘);
Readln ( NhanSu.HoTen);
Write ( ‘Vào ngày sinh ? ‘);
Readln ( NhanSu. NgaySinh);
Write ( ‘Vào văn hoá ? ‘);
Readln ( NhanSu. VanHoa);
Write ( ‘Vào lương ?’);
Readln ( NhanSu.Luong);
Write ( ‘Vào số con ?’);
Readln( NhanSu. SoCon);
(*……………….Hiển thị dữ liệu trên màn hình……………… *)
Writeln ( ‘Họ tên: ‘,NhanSu.HoTen);
Writeln ( ‘Ngày sinh: ‘,NhanSu.NgaySinh);
Writeln ( ‘Trinh độ văn hoá:’,NhanSu.VanHoa);
Writeln ( ‘Bậc lương:’,NhanSu.Luong);
Writeln ( ‘Số con:’,NhanSu.SoCon);
End.
Ở trên ta thấy biến NhanSu được viết lặp quá nhiều lần, do đó trong Turbo Pascal có sử dụng lệnh With…. Do…để rút gọn quá trình đó, chương trình trên được viết lại như sau:
Program VaoRaBanGhi;
Uses Crt;
Type
A=Record
HoTen : String[25];
NgaySinh : String[8];
VanHoa : String[10];
Luong : Real;
SoCon : Byte;
End;

Var
NhanSu: A;
Begin
ClrScr;
With NhanSu Do
Begin
Write ( ‘Vào họ tên ? ‘);
Readln (HoTen);
Write ( ‘Vào ngày sinh ? ‘);
Readln ( NgaySinh);
Write ( ‘Vào văn hoá ? ‘);
Readln (VanHoa);
Write ( ‘Vào lương ?’);
Readln (Luong);
Write ( ‘Vào số con ?’);
Readln ( Con);
(*………………… Hiển thị dữ liệu trên màn hình………….. *)
Writeln ( ‘Họ tên: ‘,HoTen);
Writeln ( ‘Ngày sinh: ‘,NgaySinh);
Writeln ( ‘Trinh độ văn hoá:’,VanHoa);
Writeln ( ‘Bậc lương:’,Luong);
Writeln ( ‘Số con:’,SoCon);
End;
End.
12.4 Mảng các Record
Ta thấy biến NhanSu ở trên chỉ “chứa” được một người, vậy trong một tổ chức có nhiều người thì xử lý thế nào? Tất nhiên ta phải dùng mảng.
Ví dụ 1:
Program VaoRaBanGhi;
Uses Crt;
Const n=10;
Type
A=Record
HoTen : String[25];
NgaySinh : String[8];
VanHoa : String[10];
Luong : Real;
SoCon : Byte;
End;
B=Array[1..n] Of A;
Var
NhanSu: B;
I: Integer;
Begin
ClrScr;
For I:=1 To n Do
With NhanSu[i] Do
Begin
Write ( ‘Vào họ tên ? ‘);
Readln (HoTen);
Write ( ‘Vào ngày sinh ? ‘);
Readln ( NgaySinh);
Write ( ‘Vào văn hoá ? ‘);
Readln (VanHoa);
Write ( ‘Vào lương ?’);
Readln (Luong);
Write ( ‘Vào số con ?’);
Readln ( SoCon);
(*…….. Hiển thị dữ liệu trên màn hình………. *)
Writeln ( ‘Họ tên: ‘,HoTen);
Writeln ( ‘Ngày sinh: ‘,NgaySinh);
Writeln ( ‘Trinh độ văn hoá:’,VanHoa);
Writeln ( ‘Bậc lương:’,Luong);
Writeln ( ‘Số con:’,SoCon);
End;
End.
Ví dụ 2: Tính tổng số con và tổng lương của mảng NhanSu trên:
Program VaoRaBanGhi;
Uses Crt;
Const n=10;
Type
A=Record
HoTen : String[25];
NgaySinh : String[8];
VanHoa : String[10];
Luong : Real;
SoCon : Byte;
End;
B=Array[1..n] Of A;
Var
NhanSu: B;
I: Integer;
TongCon, TongLuong: Integer;
Begin
ClrScr;
For I:=1 To n Do
With NhanSu[i] Do
Begin
Write ( ‘Vào họ tên ? ‘);
Readln (HoTen);
Write ( ‘Vào ngày sinh ? ‘);
Readln ( NgaySinh);
Write ( ‘Vào văn hoá ? ‘);
Readln (VanHoa);
Write ( ‘Vào lương ?’);
Readln (Luong);
Write ( ‘Vào số con ?’);
Readln ( SoCon);
End;
TongCon:=0; TongLuong:=0;
For I:=1 To n Do
With NhanSu[i] Do
Begin
TongCon:=TongCon+SoCon;
TongLuong:=TongLuong+Luong;
End;
Writeln(‘Tổng con:’,TongCon);
Writeln(‘Tổng lương:’,TongLuong);
End.

Advertisements

About pascalteacher

Trang thông tin Toán học và Tin học

Thảo luận

Không có bình luận

Trả lời

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Đăng xuất / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Đăng xuất / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Đăng xuất / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Đăng xuất / Thay đổi )

Connecting to %s

Các tác giả

Categories

Tháng Mười 2016
H B T N S B C
« Th9   Th11 »
 12
3456789
10111213141516
17181920212223
24252627282930
31  

NCT Computer

Flickr Photos

Thống kê

  • 181,058 lượt xem

pascalteacher.nct@gmail.com


Trang huấn luyện học sinh giỏi Tin học

%d bloggers like this: