7.3.6 Ví dụ về bản ghi
Ví dụ 7.52: Nhập một danh sách N (1<= N<= 50) sinh viên gồm các trường: Họ tên, Mã số, các điểm Toán, Lý.
Đối với mỗi sinh viên, hãy tính điểm trung bình :
DTB=(Toan + Ly)/2 , và phân loại như sau:
Loại= Giỏi nếu DTB <= 9,
Khá nếu 7<= DTB < 9,
Bình nếu 5<= DTB < 7,
Kém nếu DTB < 5.
Sắp xếp danh sách theo trật tự giảm của DTB, in danh sách lên màn hình, mỗi người trên một dòng gồm các mục: Số thứ tự, Họ tên, Mã số, điểm Toán, Lý, DTB và phân loại.
Cho biết điểm Toán cao nhất là mấy ?. Có bao nhiêu người được điểm cao nhất đó?
Điểm trung bình môn Toán cho cả danh sách là bao nhiêu ?.
Bài giải :
Trong chương trình dưới đây, chỗ nào có ký hiệu ' ' thì hãy thay bằng một ký tự trắng.
PROGRAM VIDU_7_52;
Uses CRT;
Type KSVIEN = RECORD
Hoten:String[18];
Maso, Loai : String[8];
Toan, Ly, DTB : Real;
End;
Var DS : Array[1..50] of KSVIEN;
Z : KSVIEN;
N, i, j, Dem : Integer;
Max, TBToan: Real;
BEGIN
CLRSCR;
Repeat
Write(‘ Nhập số sinh viên N= ‘) ;
Readln(N);
Until ( N>0) and ( N < 51);
{ Nhập danh sach, tính DTB va phân loại }
For i:=1 to N do WITH DS[i] DO
begin
Write(‘Nhap ho ten sinh vien thu ‘,i,’ : ‘);
Readln(Hoten);
Write(‘Nhap ma so sinh vien thu ‘,i,’ : ‘);
Readln(Maso);
Write(‘Nhap điểm Toan, Ly sinh vien thu ‘,i,’ : ‘);
Readln(Toan, Ly);
DTB:=( Toan + Ly)/2;
If DTB >=9 then Loai:=‘Gioi’
else
if DTB >=7 then Loai:=‘Kha’
else
if DTB >=5 then Loai:=‘Binh’
else
Loai:=‘Kem’;
end;
{ Sắp xếp giảm theo DTB }
For i:=1 to N-1 do
For j:=i+1 to N do
If DS[i].DTB < DS[j].DTB then
begin
Z:=DS[i]; DS[i]:=DS[j]; DS[j]:=Z;
end;
Writeln(‘ In danh sach len man hinh ‘ );
Writeln(‘STT HO VA TEN MA SO TOAN LY DTB LOAI’);
For i:=1 to N do
WITH DS[i] DO
Writeln(i:2,#32,Hoten,#32:19-Length(Hoten), Maso:8,Toan:4:1,Ly:4:1,DTB:4:1,Loai:5);
{ Tìm điểm Toán cao nhất }
Max:=DS[1].Toan;
For i:=1 to N do
if Max< DS[i].Toan then
Max:=DS[i].Toan;
Writeln(‘Diem Toan cao nhat = ‘, Max:4:1);
{ Đếm số em có điểm Toán =Max}
Dem:=0;
For i:=1 to N do
if DS[i].Toan =Max then
Dem:=Dem+1;
Writeln(‘ Có ‘, Dem, ‘ em có điểm Toán= ‘, Max:4:1);
{ Tính điểm trung bình môn Toán cho cả danh sach }
TBToan:=0; { Lấy tổng điểm môn Toán}
For i:=1 to N do
TBToan := TBToan + DS[i].Toan;
TBToan:=TBToan/N ;
Writeln(‘Diem trung binh mon Toan= ‘ , TBToan:6:2);
Readln;
END.
Ví dụ 7.53 Nhập một danh sách N (1<= N<= 50) đầu sách gồm các thông tin về Tên sách, Số lượng (SL) và Đơn giá (DG).
Với mỗi đầu sách, tính Giá tiền như sau:
GT = SL * DG nếu SL<10
= SL*DG - 5%*SL*DG nếu 10 Ê SL<30
= SL*DG - 8%* SL*DG nếu 30 Ê SL <50
= SL*DG - 10%* SL*DG nếu SL ³ 50
(Tức là nếu mua từ 10 đến 29 cuốn thì được giảm 5% đơn giá, mua từ 30 đến 49 cuốn thì được giảm 8% đơn giá, mua từ 50 cuốn trở lên thì được giảm 10% đơn giá).
Tính Tổng số tiền phải chi cho việc mua sách, kể cả 10% thuế giá trị gia tăng đánh vào tổng giá tiền.
Tìm xem trong danh sách đó có cuốn "TIN HOC DAI CUONG" không. Nếu có thì cho biết có bao nhiêu cuốn và đơn giá của nó.
Bài giải:
PROGRAM VIDU_7_53;
Uses CRT;
Type KSACH = RECORD
Tensach : String[20];
SL : Integer;
DG, GT: Real;
End;
Mang = Array[1..50] of KSACH;
Var S : Mang;
Z : KSACH;
N, i : Integer;
Tongtien : Real;
BEGIN
Repeat
Write(‘ Nhập N: ‘); Readln( N );
Until (N>0) and ( N<51);
{ Nhập N sách và tính tiền}
For i:=1 to N do
With S[i] do
begin
Write(‘Nhap ten sach thu: ‘,i,’:‘); Readln(Tensach);
Repeat
Write(‘Nhập Số lượng : ‘); Readln(SL);
Until SL>0;
Write(‘Nhập đơn giá : ‘); Readln(DG);
Case SL of
1..9 : GT:=SL*DG;
10..29 : GT:=SL*DG*(1-0.05);
30..49 : GT:=SL*DG*(1-0.08);
else GT:=SL*DG*(1-0.1);
end; { Hết Case}
end; { Hết For}
{Tính tổng giá thành các đầu sách}
Tongtien:=0;
For i:=1 to N do
Tongtien:=Tongtien+S[i].GT;
{Cộng thêm thuế 10% giá tri gia tăng}
Tongtien:=Tongtien + 0.1*Tongtien ;
Writeln(‘Tổng tiền phải chi là: ‘, Tongtien :6:2);
{Tìm cuốn ‘TIN HOC DAI CUONG’}
i:=1;
While (i<=N) and (S[i].Tensach<> ‘TIN HOC DAI CUONG’) do
i:=i+1;
If i> N then
writeln (‘ Không có cuốn TIN HOC DAI CUONG!‘)
else
WITH S[i] DO
writeln(‘ Co ‘, SL:4,‘ cuon, don gia= ‘,DG:6:2);
Readln;
END.
7.4. Kiểu tập hợp (Set of) 7.4.1. Khái niệm
Kiểu tập hợp là một kiểu dữ liệu có cấu trúc nhằm thể hiện mô hình dữ liệu tập hợp trong toán học. Nó thể hiện loại dữ liệu có thể xác nhận giá trị không phải chỉ là một phần tử đơn lẻ trong miền xác định không phải chỉ là một phần tử đơn lẻ trong miền xác định mà là một tập hợp nhiều phần tử cùng thuộc một kiểu dữ liệu vô hướng đếm được nào đó.
7.4.2. Cú pháp
Phần mô tả khai báo kiểu tập hợp có cú pháp như sau:
TYPE tên_kiểu_tập_hợp = SET OF tên_kiểu_dữ_liệu_cơ_sở;
Var tên_biến : tên_kiểu_tập_hợp;
Trong đó: tên_kiểu_dữ_liệu_cơ_sở có thể là một kiểu dữ liệu vô hướng đếm được bất kỳ, kể cả kiểu đoạn con, kiểu liệt kê.
Chú ý: Turbo Pascal hạn chế số phần tử có thể của mỗi giá trị kiểu tập hợp là 256
7.4.3. Một số tính chất
- Một giá trị của dữ liệu kiểu tập hợp được thể hiện bằng cách liệt kê mọi phần tử của tập, cách nhau bởi dấu phẩy, đóng trong hai dấu ngoặc vuông.
- Thứ tự liệt kê các phần tử không quan trọng.
- Có thể gán giá trị cho biến tập hợp như thông thường.
- Tập rỗng ký hiệu là [].
7.4.4. Các phép toán trên tập hợp
7.4.4.1. Phép toán quan hệ
Để thực hiện các phép toán quan hệ thì các toán hạng toán hạng phải cùng kiểu. và thực hiện như sau:
- So sánh bằng nhau:
A = B cho kết quả là TRUE nếu A và B hoàn toàn như nhau,
- So sánh khác nhau:
A <> B cho kết quả là FALSE nếu A và B hoàn toàn như nhau
- So sánh nhỏ hơn hay bằng:
A<=B là TRUE nếu A là tập con của B
- So sánh lớn hơn hay bằng:
A>= B là TRUE nếu B là tập con của A.
* Chú ý: không có so sánh nhở hơn chặt (<), lớn hơn chặt (>) đối với kiểu tập hợp. Muốn thể hiện quan hệ “là tập con thực sự” ta phải kết hợp hai điều kiện:
(A<=B) and (A<>B)
7.4.4.2. Phép tìm kiếm (thuộc về)
Để diễn tả một phần tử x có thuộc một tập hợp A hay không ta sử dụng cú pháp:
x in A cho kết quả là TRUE nếu x là một phần tử của A
ngược lại cho kết quả là FALSE
7.4.4.3.Phép hợp, Giao, Hiệu
Để thực hiện các phép hợp, giao, hiệu thì hai toán hạng cũng phải cùng kiểu.
- Phép hợp được ký hiệu bằng dấu +:
A+B = {xi | (xi in A) or (xi in B)}
- Phép giao được ký hiệu bằng dấu *
A* B = {xi | (xi in A) and (xi in B)}
- Phép lấy hiệu được ký hiệu bằng dấu -:
A - B = {xi | (xi in A) and not(xi in B)}
7.4.5. Viết và đọc dữ liệu kiểu tập hợp
Nói chung ta không thể dùng các thủ tục WRITE (WRITELN) và READ (READLN) để viết ra và đọc vào các dữ liệu kiểu tập hợp. Tuy nhiên chúng ta có thể lập trình để thực hiện các thao tác này khi mà các phần tử của tập hợp là các số nguyên hoặc ký tự.
Ví dụ 7.54: Nhập vào n ký tự rồi lựa chọn trong đó các chữ hoa để thành lập một tập hợp và cuối cùng là in ra các ký tự trong tập vừa tạo.
Program vidu_7_54;
VAR Tap_chu_hoa : SET OF 'A'..'Z' ;
i, n :Integer;
Ch :Char;
BEGIN
WRITE(' Nhap so n = '); READLN(n);
Tap_Chu_Hoa :=[]; {Khoi tao Tap_chu_hoa la tap rong }
{Để đọc vào n ký tự bất kỳ }
FOR i :=1 TO n DO
BEGIN
WRITE('Nhập Ký tự thứ ', i , ' : ' ); READLN(Ch);
{Neu ch la ky tu hoa thi cho no vao Tap_Chu_Hoa}
IF ch=UPCASE(ch) THEN
Tap_Chu_hoa :=Tap_Chu_hoa + [Ch];
END;
{in cac ky tu trong Tap_Chu_hoa ra man hinh }
FOR Ch :='A' TO 'Z' DO
IF Ch IN Tap_Chu_Hoa THEN
WRITE(ch : 4) ;
WRITELN;
READLN;
END.
Ví dụ 7.55: Đếm số kí tự là nguyên âm, là phụ âm trong một dãy kí tự. Để đơn giản ta dùng kí tự số 0 để đánh dấu kết thúc dãy.
Dễ thấy rằng cần phải có hai tập hợp chữ cái là các nguyên âm và các phụ âm để phục vụ cho việc kiểm tra từng kí tự đọc vào. Chương trình cần phải định nghĩa kiểu dữ liệu TapKiTu và hai biến NguyenAm, PhuAm có kiểu là tập hợp bộ chữ cái như đã nêu trên.
Program vidu_7.55;
Type TapKiTu = Set of Char;
Var NguyenAm, PhuAm: TapKiTu;
ch: char;
So_NguyenAm, So_PhuAm: byte;
Begin
So_NguyenAm:= 0; So_PhuAm:= 0;
NguyenAm:= ['a','e','i','o','u'];
PhuAm:= ['a'..'z'] - NguyenAm;
Write(' cho day ki tu, ket thuc bang so 0: ');
read(ch);
while ch <> '0' do
begin
if ch in NguyenAm then
So_NguyenAm:= So_NguyenAm + 1;
if ch in PhuAm then
So_PhuAm:= So_PhuAm + 1;
read(ch);
end;
Writeln('So nguyen am la: ', So_NguyenAm);
Writeln('So phu am la: ', So_PhuAm);
end.
Ví dụ 7.56: Tìm các số nguyên tố trong khoảng 1..N
Thuật toán sàng Eratosthene.
Phân tích:
Sàng ban đầu chứa toàn bộ dãy số 2 .. N. Bắt đầu từ số nhỏ nhất là 2, ta loại bỏ khỏi sàng tất cả các số là bội số của 2. Số nhỏ nhất còn lại trên sàng sẽ là số nguyên tố thứ nhất là 3. Bỏ số này ra khỏi sàng, ghi nó vào tập số nguyên tố.
Tiếp tục loại bỏ khỏi sàng các số là bội số của các số nguyên tố vừa chọn được. Số nhỏ nhất còn lại trên sàng sẽ là số nguyên tố tiếp theo.
Lặp lại việc này ta sàng dần được hết các số nguyên tố.
Program Sang_Eratosthene ;
Const N=100;
Type Nguyen = 1.. N;
Var NguyenTo, Sang: Set of Nguyen ;
Number: Nguyen ;
I: Integer ;
BEGIN
NguyenTo:= [ ] ;
Sang:= [ 2..N] ;
Number:= 2;
Repeat
While not (Number IN Sang) do
Number:= Number + 1;
NguyenTo:= NguyenTo + [Number] ;
Write ( Number , ' ' );
i:= Number ;
While i <= N do
Begin
Sang:= sang - [i] ;
I:= i + Number ;
End.
Until Sang = [] ;
END.
50>30>
Chia sẻ với bạn bè của bạn: |