Tải bản đầy đủ

HƯỚNG DẪN DẠY BỒI DƯỠNG HỌC SINH GIỎI MÔN TIN HỌC

PHÒNG GD & ĐT VĨNH TƯỜNG
TRƯỜNG THCS VĨNH TƯỜNG

Chuyên đề:

HƯỚNG DẪN
DẠY BỒI DƯỠNG HỌC SINH GIỎI MÔN TIN HỌC

Vĩnh Tường, tháng 02 năm 2019
1


Trước khi đi vào nội dung chính của chuyên đề, xin nói ngắn gọn về ngôn ngữ lập trình
Pascal:
Pascal là một ngôn ngữ lập trình bậc cao
do Niklaus Wirth, giáo sư điện toán
trường Đại học kỹ thuật Zurich (Thụy Sĩ)
đề xuất năm 1970. Ông lấy tên Pascal để
kỷ niệm nhà toán học và nhà triết học
người Pháp nổi tiếng Blaise Pascal.


Pascal là một ngôn ngữ lập trình bậc cao có các từ khóa bằng tiếng Anh, tính logic Toán học chặt
chẽ, đặc trưng bởi thuật toán và khả năng trừu tượng hóa cao. Điều này lí giải vì sao những học sinh
học Toán tốt, thông minh lại dễ dàng tiếp thu dạng kiến thức này.
Do tính chất và nội dung của môn học mà chuyên đề t ập trung ch ủ y ếu vào thuật toán và
chất toán khi dạy học lập trình cho học sinh giỏi.

Phần A. Hướng dẫn dạy bồi dưỡng học sinh giỏi (HSG) môn Tin học lớp 8.
A.1 Lí thuyết cần nắm vững:
 Câu lệnh gán: Cú pháp: a:= b; (Gán giá trị của b cho a)
 Câu lệnh điều kiện
Cú pháp:
Câu lệnh điều kiện dạng thiếu

If <điều kiện> then ;

Câu lệnh điều kiện dạng đủ

If <điều kiện> then
Else ;

Hoặc: Lệnh CASE Cú pháp:
Dạng 1

Dạng 2

CASE B OF
Const 1: S1;
Const 2: S2;
...
Const n: Sn;
END;

CASE B OF
Const 1: S1;
Const 2: S2;
...
Const n: Sn;
ELSE Sn+1;
END;


 Câu lệnh lặp
3.1 Lặp với số lần biết trước :
Cú pháp:
For := to do ;

(dạng tiến – duyệt từ nhỏ đến

lớn)

For := downto do ;

(dạng lùi – duyệt từ lớn đến

nhỏ)

2


3.1 Lặp với số lần chưa biết trước :
Cú pháp:

While <điều kiện> do ;

Hoặc:
Repeat
;
;
....
;

Until <điều kiện>;
 Các phép toán và hàm số học
* Các phép toán trên kiểu số nguyên:
+ Phép chia lấy phần nguyên : Div
+ Phép chia lấy phần dư :

Mod

+ Các hàm số học sử dụng cho kiểu số nguyên và số thực:









Abs(n): Giá trị tuyệt đối của số n
Sqr(x): bình phương của số x.
Sqrt(x): cho kết quả là căn bậc hai của x.
Odd(x): cho kết quả là true nếu x số lẻ, ngược lại là false.
Round(n): Làm tròn số thực n tới số nguyên gần n nhất.
Trunc(n): Làm tròn số thực n tới số nguyên có giá trị tuyệt đối bé hơn n.
Inc(n): Tăng n thêm 1 đơn vị (n:=n+1).
Dec(n): Giảm n đi 1 đơn vị (n:=n-1).

 Các phép toán logic
Giả sử A và B là hai giá trị kiểu Boolean. K ết quả của các phép toán đ ược th ể hi ện qua
bảng dưới đây:
A

B

A AND B

A OR B

A XOR B

NOT A

TRUE

TRUE

TRUE

TRUE

FALSE

FALSE

TRUE

FALSE

FALSE

TRUE

TRUE

FALSE

FALSE

TRUE

FALSE

TRUE

TRUE

TRUE

FALSE

FALSE

FALSE

FALSE

FALSE

TRUE

A.2 Yêu cầu về kiến thức và phương pháp giảng dạy
(1) Hiểu sâu sắc lí thuyết
Muốn dạy bất cứ nội dung nào, trước hết bạn phải nắm vững và hi ểu sâu s ắc lí thuy ết
của vấn đề đó. Tin học lập trình không phải là môn h ọc có tính ch ất h ọc thu ộc nh ư các môn
khoa học xã hội (Văn, Sử, Địa); cũng không có sẵn định lí, tính chất nh ư các môn khoa h ọc t ự
nhiên (Toán, Lí, Hóa) để cứ thế áp dụng. Học lập trình là h ọc cách s ử d ụng m ột ngôn ng ữ đ ể
3


diễn đạt giao tiếp với máy tính và đặc biệt là gi ải quy ết được các bài toán đ ặt ra nh ờ s ức
mạnh tính toán, tính logic, công cụ hỗ trợ mà ngôn ngữ lập trình đó cung cấp.
Khi học lí thuyết về ngôn ngữ lập trình, có thể hi ểu là ta đang đ ược cung c ấp công c ụ đ ể làm
việc với môi trường giao tiếp người – máy tính; phải hiểu n ếu không n ắm ch ắc các công c ụ
này thì không thể giao tiếp thành công tức là ta không chuy ển tải thành công đ ể máy tính
hiểu.
(2) Truyền đạt rõ ràng, dễ hiểu
Bạn không thể dạy học sinh trở nên lập trình gi ỏi mà không truy ền đ ạt rõ ràng, d ễ hi ểu
những nội dung lí thuyết của ngôn ngữ lập trình đó - điều này không d ễ vì ngôn ng ữ l ập
trình sử dụng bộ kí tự riêng, tuân theo một cú pháp, quy tắc dùng nh ất đ ịnh và đ ặc bi ệt là đòi
hỏi nhiều chất Toán, sự thông minh, tư duy linh hoạt, khả năng sáng tạo.
Khi truyền đạt rõ ràng, dễ hiểu lí thuyết lập trình, các thầy cô có thể khơi gợi sự hứng thú,
tìm tòi, muốn khám phá và cả sự sáng tạo ban đầu ở người học.
(3) Dạy thuật toán như thế nào?
Dạy lí thuyết sẽ có nhiều điểm tương đồng giữa các thầy cô (vì lí thuyết chung, có sẵn trong
sách và phần lớn thầy cô sẽ không gia công thêm trình tự SGK hướng dẫn) nhưng dạy thuật
toán thì phải thực tế (và càng thực tế càng tốt). Lưu ý rằng đặc trưng của thuật toán là tính
tuần tự logic đảm bảo khi thực hiện đúng thứ tự các bước đó thì ta có được kết quả.
Thầy, cô có thể lấy ví dụ về dạy một thuật toán trong chương trình Tin học lớp 8 không ?
(4) Minh họa cụ thể các đoạn code mẫu
Trong quá trình học lập trình, học sinh cần có khả năng đọc và hiểu code của người khác (lời
giải của bạn khác, của sách, sự chia sẻ code trên mạng) và chỉ khi đọc và hiểu được code mới
tự bổ sung cho mình cách giải tham khảo:
Ví dụ với đoạn code sau, thầy cô sẽ minh họa như thế nào ?
------------------------------------------------uses crt;
var N,n1,n2,S,i,j:Longint;
dem:integer;
begin
clrscr;
writeln('******BA NGUOI CAU CA******');
for i:=2 to 1000 do
begin
n:=i;
if (n mod 3=1) then
//neu so ca ban dau chia 3 du 1
begin
n1:=((n-1) div 3)*2;
//so ca con lai sau khi nguoi thu 1 lay
if (n1 mod 3=1) then
begin
4


n2:=((n1-1) div 3)*2; //so ca con lai sau khi nguoi thu 2 lay
if (n2 mod 3=1) then
begin
write(i:5);
inc(dem);
if (dem mod 10=0) then writeln;
end;
end;
end;
end;
readln;
end.
Kết quả chạy chương trình:

Đây là đề bài của code giải trên:
Ba người đi câu được một số lượng không lớn hơn N con cá. Mệt m ỏi và tr ời đã t ối, m ỗi
người tìm một nơi để ngủ. Khi trời gần sáng, người thứ nhất th ức d ậy, đ ếm s ố cá th ấy n ếu
chia 3 thì dư một con bèn vứt một con cá xuống sông và đem v ề m ột ph ần ba s ố cá. Ng ười
thứ hai thức dậy tưởng hai người kia còn ngủ, đếm số cá thấy chia ba d ư m ột nên v ứt xu ống
sông một con rồi đem về một phần ba số cá. Người thứ ba th ức d ậy t ưởng mình d ậy s ớm
hơn cả anh ta đếm cá thấy chia ba dư một nên cũng vứt m ột con xuống sông và đem v ề m ột
phần ba số cá.
Với một số N nhập từ bàn phím ( N<1000 ), hãy thông báo trên màn hình
những
khả năng có thể xảy ra về số lượng cá mà ba người câu được tho ả mãn nh ững gi ả thi ết đã
cho.
Khi các thầy cô đã làm tốt yêu cầu về kiến thức và phương pháp giảng d ạy thì m ột h ệ th ống
bài tập nâng cao trọng tâm, tổng hợp kỹ năng, có yêu cầu sáng t ạo và tích h ợp nhi ều ch ất
Toán là phần quan trọng nhất trong việc bồi dưỡng học sinh giỏi Tin học
A.3 Bài tập chọn lọc:
Lưu ý:
+ Phần lời giải, thuật toán, chất toán, dẫn dắt cho m ỗi bài sẽ đ ược trình bày ở bu ổi chuyên đ ề
phần báo cáo, thực hành, thảo luận.
+ Để có kết quả tốt nhất khi tiếp thu chuyên đề này, các thầy cô c ần gi ải quy ết đ ược các bài
tập đưa ra ít nhất theo cách riêng của bản thân hoặc c ố g ắng làm đ ược càng nhi ều càng t ốt
các yêu cầu kèm theo mỗi bài.
+ Nếu đề bài chưa chính xác hoặc thiếu trường hợp, hoặc có thể có thuật toán t ốt h ơn đ ể gi ải
thì các thầy cô có thể trao đổi khi tham gia chuyên đề.
5


Bài 1. (cách sử dụng biến, lệnh gán)
Nhập vào hai số nguyên a và b, hãy hoán đổi giá trị của chúng cho nhau : a nhận giá trị b; b
nhận giá trị a bằng 2 cách:
Cách 1: dùng thêm biến c
Cách 2: không dùng thêm biến.
Bài 2. (cách sử dụng biến, hàm div, mod)
Nhập vào một số nguyên dương n có 4 chữ số. Hãy in ra tổng các chữ số của nó mà không
dùng thêm biến nào khác.
Ví dụ:
Nhập
N = 2019

In ra
12

Bài 3. (cách sử dụng biến, hàm div, mod)
Viết chương trình đổi số tiền là a (đơn vị trăm đồng) ra các tờ tiền là 500 đ, 200 đ và 100 đ
sao cho số tờ tiền là ít nhất.
Yêu cầu: chỉ dùng câu lệnh gán không dùng thêm biến, không dùng câu lệnh if then, for, while
do,
Ví dụ:
Nhập
2300

In ra
6

Bài 4. (lệnh if )
Nhập vào một số nguyên dương chỉ năm dương lịch.
a) Hãy kiểm tra xem đó có phải là năm nhuận hay không ? n ếu có ghi ‘la nam nhuan’, ng ược
lại ghi ‘khong la nam nhuan’
b) nếu không là năm nhuận thì cần thêm ít nhất mấy năm nữa để trở thành năm nhuận ?
Ví dụ:
Nhập
2020
2019

In ra
la nam nhuan
khong la nam nhuan
+1

Bài 5. (chỉ dùng lệnh if, không dùng div, mod, while … do)
Nhập vào một số nguyên dương nhỏ hơn 100000.
In ra số lượng các chữ số của nó.
Ví dụ:
Nhập

In ra
6


100
3
Bài 6. Nhập vào một số nguyên dương N. In ra số nhỏ nhất l ớn h ơn N thỏa mãn chia h ết cho
3 bằng 2 cách:
a) dùng lệnh if
b) không dùng lệnh if (ghi thẳng kết quả)
Bài 7. (lệnh for, lệnh if)
a. In ra các số tự nhiên từ 1đến 100, mỗi hàng k số cách đ ều nhau (k nguyên d ương nh ỏ h ơn
20).
Ví dụ:
Nhập

In ra

K=13

b. In ra các số tự nhiên từ m đến n , mỗi hàng k số cách đều nhau (n > m+ 100; k nguyên
dương nhỏ hơn 20)
Bài 8. (lệnh for, chất Toán)
Cho các hình chữ nhật có số đo các cạnh là các số nguyên dương và chu vi bằng P.
Hãy in ra diện tích lớn nhất có thể của hình chữ nhật
Ví dụ:
Nhập
V = 20

In ra
25

Bài 9. (chất Toán)
Nhập vào tuổi cha, tuổi con hiện tại.
In ra số năm chưa tới hoặc số năm đã qua mà tuổi cha gấp đôi tuổi con (phân bi ệt + hoặc -)
Nhập
In ra
24 2
+ 20
Bài 10. (lệnh While … do)
Viết chương trình nhập vào một số nguyên dương N từ bàn phím ( N < 109 ).
Hãy in ra số nhỏ nhất lớn hơn N thỏa mãn chia 9 dư 8, chia 8 d ư 7, chia 7 d ư 6, chia 6 d ư 5,
chia 5 dư 4, chia 4 dư 3, chia 3 dư 2 và chia 2 dư 1.
Ví dụ :
Nhập

In ra
7


N = 100

2519

Bài 11. Tổ Ong (chất Toán)
Tổ ong bao gồm nhiều ô giống nhau hình lục bát. Các ô này để ở, ch ứa m ật, sáp, ong
non, . . . Ban đầu ong xây một ô. Sau đó xây ti ếp các ô k ề cạnh v ới ô ban đ ầu, làm thành l ớp
thứ hai, sau đó xây tiếp các ô kề cạnh với ô ở lớp thứ hai, làm thành l ớp thứ 3, . . .

Người ta tìm thấy một tổ ong lớn có tới n lớp.
Hãy xác định số ô của tổ ong tìm thấy. (1 ≤ n ≤ 109).
Ví dụ :
Nhập
N=2

In ra
7

Bài 12. (Thuật toán Đếm, chất Toán)
Nhập vào một số nguyên n kiểu longint.
Hãy kiểm tra xem n có là số nguyên tố hay không ? nếu có ghi ‘yes’, ngược lại ghi ‘no’.
Ví dụ :
Nhập
N = 41

In ra
yes

Bài 13. (Thuật toán Đếm)
Nhập vào số nguyên dương N. in ra N số nguyên tố đầu tiên (N < 1000).
Ví dụ :
Nhập
N=5
Bài 14. (Thuật toán Euclid, chất Toán)

In ra
2 3 5 7 11

Nhập vào hai số nguyên dương a và b (a , b nhỏ hơn 109).
a) hãy in ra UCLN(a,b) bằng 2 cách khác nhau.
b) hãy in ra BCNN(a,b)
Ví dụ :
8


Nhập
A= 4
B=6

In ra
UCLN(4,6) = 2
BCNN(4,6) = 12

Bài 15. (chất Toán)
Cho hình chữ nhật với hai kích thước a và b (a, b là các s ố nguyên d ương nh ỏ h ơn 10 9). Hỏi
cần ít nhất bao nhiêu nhát cắt (mỗi nhát cắt song song với một trong hai c ạnh c ủa hình ch ữ
nhật) để chia hình chữ nhật thành các hình vuông có cạnh bằng nhau.
Nhập vào hai số nguyên dương a, b là hai kích thước của hình chữ nhật.
In ra số nguyên dương K là số nhát cắt ít nhất cần dùng.
Ví dụ :
Nhập
A=4
B=6

In ra
3

Bài 16. (chất Toán, dùng hàm có sẵn)
Nhập vào một dãy số nguyên gồm N số Ai ( n < 100, −1000 ≤ Ai ≤ 1000 ) .
Hãy in ra các số chính phương có trong dãy số trên. Có tất cả bao nhiêu số chính phương ?
Ví dụ :
Nhập
N = 10
-8 0 1 49 -25 5 7 9 4 0

In ra
6
0 1 49 9 4 0

Bài 17. (thuật Toán sắp xếp, thuật toán đánh dấu, tạo mảng phụ)
Nhập vào một dãy số nguyên gồm N số Ai ( n < 100, −1000 ≤ Ai ≤ 1000 ) khác nhau đôi một.
Hỏi sau khi sắp xếp dãy số trên tăng dần, thì số ở vị trí thứ k của dãy ban đầu trong dãy đã
sắp xếp ở vị trí bao nhiêu ?
Ví dụ :
Nhập
N=7
K=3
-8 0 2019 49 -25 5 7

In ra
7

Bài 18. (từ trong ra ngoài)
Viết chương trình nhập vào từ bàn phím một số nguyên dương n (n<= 1000). Sau đó tính và
in ra màn hình giá trị của của biểu thức T (lấy 8 chữ số thập phân sau dấu phảy)
T = 1 + 2 + 3 + ... + n (có n dấu căn bậc hai)

9


Phần B. Hướng dẫn dạy bồi dưỡng học sinh giỏi (HSG) môn Tin học lớp 9.

PHẦN LÍ THUYẾT BÁO CÁO
Hướng dẫn dạy bồi dưỡng học sinh giỏi (HSG) môn Tin học lớp 9.
1. KIỂU KÝ TỰ (CHAR)
1.1. Ký tự và biến kiểu ký tự:

tự


ASCII


tự


ASCII


tự


ASCII

32

A

65

a

97

0

48

B

66

b

98

1

49

C

67

c

99

2

50

D

68

d

100

3

51

E

69

f

101

4

52

F

70

e

102

5

53

G

71

g

103

6

54

H

72

h

104

7

55

I

73

i

105

8

56

J

74

j

106

9

57

K

75

k

107

L

76

l

108

M

77

m

109

N

78

n

110

O

79

o

111

P

80

p

112

Q

81

q

113

R

82

r

114
10


S

83

s

115

T

84

t

116

U

85

u

117

V

86

v

118

W

87

w

119

X

88

x

120

Y

89

y

121

Z

90

z

122

Các ký tự dùng trong máy tính điện tử được liệt kê đầy đủ trong bảng mã ASCII gồm
256 ký tự khác nhau và được đánh số thứ tự từ 0 đến 255. Số thứ tự của mỗi ký tự còn gọi là
mã ASCII của ký tự đó. Biểu 6.5 liệt kê một phần của bảng mã ASCII gồm các chữ số và
chữ cái kèm theo mã của chúng.
Trong bảng, ký tự có mã bằng 32 là ký tự trắng (space).
Tuy có 256 ký tự khác nhau song chỉ có 128 ký tự đầu tiên là hay dùng, còn lại là các
ký tự mở rộng. Các ký tự có mã từ 0 đến 31 gọi là các ký tự điều khiển, không in ra được,
được dùng để điều khiển các thiết bị ngoại vi, chẳng hạn ký tự có mã là 7 dùng để tạo một
tiếng kêu bip, ký tự có mã là 13 dùng để chuyển con trỏ màn hình xuống đầu dòng dưới...
Mỗi ký tự trong bảng mã ASCII gọi là một hằng ký tự, chiếm độ dài 1 byte, và khi viết
trong Pascal phải được đặt trong cặp nháy đơn: ‘0’, ‘1’, ‘A’, ‘B’, ‘$’,...
Giữa các ký tự, có một thứ tự mặc nhiên theo nguyên tắc : ký tự có mã nhỏ hơn thì nhỏ
hơn. Tức là:
Ký tự trắng < ‘0’< ‘1’< ...< ‘9’< ‘A’< ‘B’< ...’Z’< ‘a’< ‘b’< ...< ‘z’
Biến nhận gía trị là các hằng ký tự gọi là biến kiểu ký tự, chúng được khai báo nhờ từ
khóa CHAR, chẳng hạn như khai báo hai biến ch và ch1 dưới đây:
Var
ch, ch1: Char ;
Khi đó có thể gán:
ch:=‘A’;
ch1:=‘$’;
Ký tự ‘A’ gọi là gía trị của biến ch, còn ‘$’ là gía trị của biến ch1.
11


INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin%20Hoc%20Dai
%20Cuong%20A25_files/Bai06_4_files/bullet2.gif" \* MERGEFORMAT Nhận xét: Từ
bảng mã của các chữ cái ta suy ra:
Mã chữ thường = Mã chữ hoa tương ứng + 32. (1)
1.2. Các hàm liên quan đến ký tự :
INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin%20Hoc%20Dai
%20Cuong%20A25_files/Bai06_4_files/bullet_dia_blue.gif" \* MERGEFORMAT Hàm
PRED(ch): cho ký tự đứng ngay trước ký tự ch trong bảng mã. Ví dụ: Pred(‘B’)=‘A’
INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin%20Hoc%20Dai
%20Cuong%20A25_files/Bai06_4_files/bullet_dia_blue.gif" \* MERGEFORMAT Hàm
SUCC(ch): cho ký tự đứng ngay sau ký tự ch trong bảng mã. Ví dụ: Succ(‘A’)=‘B’.
INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin%20Hoc%20Dai
%20Cuong%20A25_files/Bai06_4_files/bullet_dia_blue.gif" \* MERGEFORMAT Hàm
UpCase(ch): đổi ký tự ch thành chữ hoa. Ví dụ:
Upcase( ‘a’ ) = ‘A’, Upcase( ‘b’ ) = ‘B’, Upcase( ‘A’ ) = ‘A’ .
INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin%20Hoc%20Dai
%20Cuong%20A25_files/Bai06_4_files/bullet_dia_blue.gif" \* MERGEFORMAT Hàm
ORD(ch) : cho mã của ký tự ch. Ví dụ: Ord (‘A’) = 65, Ord (‘a’) = 97 .
INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin%20Hoc%20Dai
%20Cuong%20A25_files/Bai06_4_files/bullet_dia_blue.gif" \* MERGEFORMAT Hàm
CHR(k) : đối số k nguyên, 0< k < 256, cho ký tự có mã bằng k. Ví dụ:
Chr (65)= ‘A’ ,
Chr (97)= ‘a’,
Chr(32) là ký tự trắng.
Có một số ký tự không có trên bàn phím, để viết chúng lên màn hình ta phải dùng lệnh
Write và hàm CHR. Ví dụ:
Lệnh Writeln(Chr(201)) ; in ra ký tự : +
Lệnh Writeln(Chr(187)) ; in ra ký tự : +
Ký tự có mã là 7 gọi là ký tự BEL (chuông), và lệnh:
Write( Chr(7) ) ; hay Write(#7) ;
có tác dụng phát ra một tiếng kêu bip.
Chú ý:
12


INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin%20Hoc%20Dai
%20Cuong%20A25_files/Bai06_4_files/bullet_dia_green.gif" \* MERGEFORMAT Turbo
Pascal ( TP ) cho phép viết gọn Chr(k) thành #k nếu k là hằng số. Ví dụ, hai lệnh sau cùng
in lên màn hình chữ A :
Write(#65);
Write(Chr(65));
INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin%20Hoc%20Dai
%20Cuong%20A25_files/Bai06_4_files/bullet_dia_green.gif" \* MERGEFORMAT Trong
TP không có hàm đổi chữ hoa ra chữ thường, nhưng có thể làm việc này nhờ công thức (1)
và hai hàm Ord và Chr :
Chữ thường := Chr ( Ord(chữ hoa) + 32 )
INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin
%20Hoc%20Dai%20Cuong%20A25_files/Bai06_4_files/bullet2.gif" \*
MERGEFORMAT Ví dụ 1: Nhập vào một số nguyên k, 0< k < 256, in ra ký tự có mã là
k. Chương trình kết thúc khi nhập vào số 0 :
PROGRAM VIDU1 ;
Uses CRT;
Var
k : Byte;
Begin
CLRSCR;
Writeln(‘ Nhập số 0 để kết thúc :’);
Repeat
Write(‘ Nhập mã của ký tự : ‘); Readln(k);
Writeln(‘ Ký tự có mã ‘, k, ‘ là ‘ , Chr(k) );
Until k=0;
End.
Chạy
Chép tập tin nguồn

13


INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin
%20Hoc%20Dai%20Cuong%20A25_files/Bai06_4_files/bullet2.gif" \*
MERGEFORMAT Ví dụ 2: Nhập một ký tự, nếu là chữ hoa thì đổi ra chữ thường, nếu
là chữ thường thì đổi ra chữ hoa.
PROGRAM VIDU2;
{ Ðổi chữ hoa ra thường và ngược lại}
Var
ch, ch1 : Char;
Begin
Write(‘ Nhập một ký tự :’); Readln(ch);
If (ch>=‘A’) and ( ch<=‘Z’) then ch1:=Chr( Ord (ch)+32)
else
ch1:= Upcase(ch);
Writeln(ch, ‘ đã đổi ra: ‘ , ch1);
Readln;
End.
Chạy
Chép tập tin nguồn
2. MẢNG MỘT CHIỀU
2.1. Mảng và cách khai báo mảng :
INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin%20Hoc
%20Dai%20Cuong%20A61_files/Bai10_1_files/bullet4.gif" \* MERGEFORMAT
Khái niệm :
Mảng là một tập gồm nhiều phần tử có cùng chung một kiểu dữ liệu. Mỗi phần tử của
mảng có một đại lượng xác định vị trí tương đối của phần tử đó so với các phần tử khác
trong mảng, gọi là chỉ số Các yếu tố để xác định một mảng gồm có:
INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin%20Hoc
%20Dai%20Cuong%20A61_files/Bai10_1_files/bullet_dia_blue.gif" \* MERGEFORMAT
Tên mảng

14


INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin%20Hoc
%20Dai%20Cuong%20A61_files/Bai10_1_files/bullet_dia_blue.gif" \* MERGEFORMAT
Kiểu dữ liệu chung của các phần tử trong mảng
INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin%20Hoc
%20Dai%20Cuong%20A61_files/Bai10_1_files/bullet_dia_blue.gif" \* MERGEFORMAT
Kiểu dữ liệu của chỉ số và phạm vi của chỉ số.
Kiểu dữ liệu của các phần tử mảng là mọi kiểu dữ liệu mà một biến có thể có. Tuy nhiên,
kiểu dữ liệu của chỉ số thì không được là kiểu thực hay kiểu chuỗi, nó chỉ có thể là kiểu đếm
được : nguyên, ký tự, lôgic, liệt kê hay đoạn con.
INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin
%20Hoc%20Dai%20Cuong%20A61_files/Bai10_1_files/bullet4.gif" \*
MERGEFORMAT Khai báo mảng một chiều :
Mảng một chiều, còn gọi là dãy, hay đơn giản là mảng, có thể khai báo theo một trong hai
cách :
INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin%20Hoc
%20Dai%20Cuong%20A61_files/Bai10_1_files/bullet5.gif" \* MERGEFORMAT Cách
1: Khai báo trực tiếp theo cách sau :
VAR
Tênmảng : Array[m1 . . m2] of Tênkiểudữliệu ;
Ở đây m1, m2 là hai hằng xác định phạm vi của chỉ số, chúng có chung một kiểu dữ
liệu,và m1 < m2.
Ví dụ: Cho khai báo dưới đây:
Var
A : Array[0..10] of Real;
Hten: Array[1..5] of String[18];
B: Array[‘a’..’d’] of Integer;
Theo khai báo trên, ta có ba mảng:
INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin%20Hoc
%20Dai%20Cuong%20A61_files/Bai10_1_files/bullet_dia_blue.gif" \* MERGEFORMAT
Mảng thứ nhất tên là A, gồm 11 phần tử cùng kiểu Real, ứng với các chỉ số 0, 1, 2, ..., 10,
đó là:
A[0], A[1], A[2], ..., A[10]

15


INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin%20Hoc
%20Dai%20Cuong%20A61_files/Bai10_1_files/bullet_dia_blue.gif" \* MERGEFORMAT
Mảng thứ hai tên là HTen gồm 5 phần tử cùng kiểu dữ liệu là String[18] ứng với các chỉ số
từ 1 đến 5:
Hten[1], Hten[2], Hten[3], Hten[4], Hten[5]
INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin%20Hoc
%20Dai%20Cuong%20A61_files/Bai10_1_files/bullet_dia_blue.gif" \* MERGEFORMAT
Mảng thứ ba tên là B, gồm 4 phần tử cùng kiểu Integer ứng với các chỉ số ‘a’, ‘b’, ‘c’, ‘d’:
B[‘a’], B[‘b’], B[‘c’], B[‘d’]
Ðể có một hình ảnh về mảng, đối với mảng A, ta hình dung có một dãy nhà một tầng, tên
gọi là dãy A, gồm 11 phòng liên tiếp giống hệt nhau được đánh số thứ tự từ 0,1, 2, ..., đến 10
:
A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10
Tương tự, mảng B cũng giống như dãy nhà B một tầng có 4 phòng được đánh số thứ tự là
các chữ a, b, c, d :
Ba

Bb

Bc

Bd

INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin%20Hoc%20Dai
%20Cuong%20A61_files/Bai10_1_files/bullet5.gif" \* MERGEFORMAT Cách 2 : Khai
báo qua một kiểu dữ liệu mới, gồm hai bước:
Bước 1: Ðịnh nghĩa kiểu dữ liệu mảng :
TYPE
Tênkiểumảng = Array[m1 . . m2] of Tênkiểudữliệu;
Bước 2: Khai báo biến có kiểu dữ liệu là kiểu mảng:
VAR
Tênmảng : Tênkiểumảng ;
Ví dụ, đối với các mảng A, B và Hten ở trên ta có thể khai báo theo cách 2, như sau:
Type
Mang1 = array[0..10] of Real;
Mang2 = array[1..5] of String[18];
16


Mang3 = array[‘a’..’d’] of Integer;
Var
A : Mang1;
Hten: Mang2;
B: Mang3;
INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin
%20Hoc%20Dai%20Cuong%20A61_files/Bai10_1_files/bullet4.gif" \*
MERGEFORMAT Khai báo mảng có gán trị ban đầu:
Pascal cho phép vừa khai báo mảng vừa gán gía trị ban đầu cho các phần tử mảng, chẳng
hạn như dưới đây:
Const
X : array[1..5] of Integer = (12, 14, 16, 18, 20) ;
Khi đó X là một mảng gồm 5 phần tử cùng kiểu nguyên và có giá trị X[1]=12, X[2]=14,
X[3]=16, X?4]=18, X[5]=20.
Mặc dù từ khóa ở đây là Const song X lại được dùng như là một biến mảng, tức là các
phần tử của X có thể thay đổi gía trị được. Ví dụ, trong chương trình ta có thể gán:
X[1]:= 2;
X[2]:=5+20;

2.2. Truy xuất các phần tử mảng:
Các xử lý trên mảng được quy về xử lý từng phần tử mảng. Ðể xác định một phần tử của
mảng, ta dùng cách viết :
Tênmảng[ chỉ số của phầ? tử ]
Ví du : có thể gán :
A[0]:= 15.8;
A[1]:= 2*A[0];
Hten[3]:= ‘Nguyen Thi Loan’;
B[‘a’]:=100;
17


Chỉ số của một phần tử có thể là một biến, một hằng, hay một biểu thức. Ví dụ, cho i là
biến kiểu nguyên, khi đó ta có thể dùng các lệnh:
i:=6;
A[i]:=100.25;
Hai lệnh trên tương đương với một lệnh:
A[6]:=100.25;
Nếu biến i có giá trị là 6 thì lệnh :
A[ i div 2 +1] := 4.5; tương đương với lệnh:
A[4]:=4.5; vì biểu thức i div 2 +1 có gía trị là 4.
Khi nhập dữ liệu cho các phần tử của một mảng , ta có thể dùng câu lệnh For, While hay
Repeat.
Ví dụ, nhập dữ liệu cho các phần tử của mảng A:
For i:=0 to 10 do
begin
Write(‘Nhập phần tử thứ ‘ , i , ‘: ‘);
Readln(A[i]);
end;
hoặc (dùng While) :
i:=0;
While i<= 10 do
begin
Write(‘Nhap phần tử thứ ‘, i, ‘: ‘);
Readln(A[i]);
i:=i+1;
end;
Tương tự để nhập dữ liệu cho các phần tử của mảng B, ta viết:
For ch:=‘a’ to ‘d’ do
18


begin
Write(‘Nhap phần tử thứ ‘, ch, ‘: ‘);
Readln(B[ch]);
end;
Ðể in các gía trị của mảng A lên màn hình, ta viết :
For i:=0 to 10 do Write(A[i]:6:2);
Các gía trị của mảng A sẽ được in liên tiếp nhau trên cùng một dòng. Còn nếu muốn in
mỗi phần tử trên một dòng, ta thay lệnh Write bằ?g Writeln.
Tương tự, mảng B được in lên màn hình bằng lệnh :
For ch:=‘a’ to ‘d’ do Write(B[ch]);
Chú ý : Turbo Pascal cho phép gán một mảng này cho một mảng khác.
Nếu X, Y là hai biến mảng cùng một kiểu mảng thì lệnh:
X := Y;
có nghĩa là lấy gía trị của từng phần tử của mảng Y gán cho phần tử tương ứng trong mảng
X. Ví dụ, cho khai báo:
Var
X, Y : Array[1..10] of Real;
Khi đó, lệnh:

X := Y;

tương đương với lệnh :
For i:=1 to 10 do X[i] :=Y[i];
2.3. Các bài toán cơ bản về mảng :
INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin%20Hoc%20Dai
%20Cuong%20A61_files/Bai10_1_files/bullet4.gif" \* MERGEFORMAT Ví dụ 1: Ðếm
số lần xuất hiện của gía trị x trong dãy A1, A2, ..., An .
Ví dụ gía trị x=6 xuất hiện 3 lần trong dãy 6 7 1 2 6 0 6 1.
Ta dùng biến Dem kiểu nguyên để đếm số lần xuất hiện của x. Ðầu tiên ta gán Dem:=0,
sau đó duyệt từng phần tử A1, A2, ..., An, mỗi khi có một phần tử bằng x thì tăng biến Dem
lên một đơn vị. Kết qủa là biến Dem có gía trị đúng bằng số phần tử bằng x. Hai lệnh chính
của thuật toán là:
19


Dem:=0;
For i:=1 to N do If A[i]=x then Dem:=Dem+1;
Ví dụ, đếm trong dãy số A có bao nhiêu số 0, ta viết:
Dem:=0;
For i:=1 to N do if A[i]=0 then Dem:=Dem+1;
Writeln(‘ Có ‘, Dem , ‘ số không ‘);
Nhận xét: Ðẳng thức A[i]=x ( hay A[i]=0 ) là điều kiện để biến Dem được tăng thêm 1,
vậy bài toán trên có thể mở rộng là: hãy đếm số phần tử của mảng A thỏa mãn một điều kiện
cho trước. Trong lệnh For ở trên, khi thay đẳng thức A[i]=x bằng A[i] thỏa điều kiện , ta
được thuật toán tổng quát hơn :
Dem:=0;
For i:=1 to N do If A[i] thỏa điều kiện then Dem:=Dem+1;
Chương trình sau nhập một mảng A có N phần tử, in mảng A lên màn hình, và đếm xem
mảng A có bao nhiêu số dương :
PROGRAM VIDU3;
{ Ðếm số dương trong mảng}
Type
Kmang = Array[1..20] of Real;
Var
A: Kmang;
i, N, Dem : Integer;
Begin
Repeat
Write(‘ Nhập số phần tử N : ‘);
Readln(N);
Until (N>0) and ( N<21);
{ nhập mảng }
For i:=1 to N do
20


begin
Write(‘Nhập A[‘ , i , ‘ ]: ‘);
Readln( A[i] );
end;
{ In mảng A}
Writeln(‘ Mảng A là : ’);
For i:=1 to N do Write(A[i]:3:0);
Writeln;
{ đếm số dương }
Dem:=0;
For i:=1 to N do If A[i]>0 then Dem:=Dem+1;
Writeln(‘ Số số dương = ‘ , Dem );
Readln;
End.
Chạy
Chép tập tin nguồn
INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin%20Hoc
%20Dai%20Cuong%20A61_files/Bai10_1_files/bullet4.gif" \* MERGEFORMAT Ví dụ
4: Tìm số lớn nhất của dãy A1, A2, ..., An.
Gọi Max là biến chứa số lớn nhất phải tìm, thế thì :
Bước 1: Gán Max:=A[1];
Bước 2: Nếu MaxBước 3: Nếu Max...
Bước n: Nếu MaxKhởi đầu, Max được gán giá trị A[1]. Sang bước 2, Max được so sánh với A[2] để chọn
ra số lớn nhất giữa A[1], A[2] và lưu vào biến Max. Sang bước 3, Max được tiếp tục so sánh
21


với A[3] để tìm ra số lớn nhất giữa A[1], A[2], A[3], .v.v. Kết qủa, sau bước n, biến Max sẽ
chứa số lớn nhất của dãy A[1], A[2], ..., A[n].
Quá trình trên được mô tả bằng hai lệnh:
Max:=A[1];
For i:=2 to n do if MaxNhận xét:
INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin%20Hoc
%20Dai%20Cuong%20A61_files/Bai10_1_files/bullet_dia_green.gif" \* MERGEFORMAT
Trong lệnh For trên, biến i chạy bắt đầu từ 2, nhưng kết qủa vẫn đúng nếu cho i chạy bắt
đầu từ 1.
INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin%20Hoc
%20Dai%20Cuong%20A61_files/Bai10_1_files/bullet_dia_green.gif" \* MERGEFORMAT
Không nhất thiết phải gán giá trị ban đầu cho Max là A[1], mà có thể gán cho Max một
phần tử tùy ý trong mảng, ví dụ phần tử A[n] chẳng hạn, nhưng khi đó biến i trong lệnh For
phải chạy bắt đầu từ 1.
INCLUDEPICTURE "Giao%20tinh%20Turbo%20pascal%207.0html/Tin%20Hoc
%20Dai%20Cuong%20A61_files/Bai10_1_files/bullet4.gif" \* MERGEFORMAT Ví dụ
5: Bài toán sắp xếp mảng tăng dần (hay giảm dần)
Cho dãy A[1], A[2],..., A[n], nói rằng A là một dãy tăng nếu A[1] < A[2]< ...< A[n], tương
tự, A là dãy giảm nếu A[1] > A[2] > ... >A[n]. Dãy đồng nhất A[1]=A[2]= ... =A[n] là
trường hợp đặc biệt, vừa là dãy tăng, vừa là dãy giảm.
Ví dụ:
Dãy 1 3 3 5 5 6 6 6 là dãy tăng
Dãy 9 9 8 5 5 4 0 0 là dãy giảm
Dãy 1 3 3 2 5 4 6 6 là dãy không tăng không giảm.
Bài toán đặt ra là: cho một dãy A[1], A[2], ..., A[n] bất kỳ, hãy thực hiện các hoán đổi các
gía trị của các phần tử trong mảng A để A lập thành một dãy tăng.
Ví dụ, cho dãy A có 5 phần tử A[1]=9, A[2]=7, A[3]=5, A[4]=8, và A[5]= 2, cần thực hiện
các hoán đổi như thế nào để có A[1]=2, A[2]=5, A[3]=7, A[4]=8 và A[5]=9.
Có những phương pháp sắp xếp mảng khác nhau, ở đây chỉ xin giới thiệu một phương
pháp, tuy chưa phải là hay nhưng đơn giản và dễ hiểu cho những người mới lập trình, đó là
phương pháp lựa chọn trực tiếp (Straight selection sort).
Ý tưởng của phương pháp là như sau:
22


Bước 1: Tìm số nhỏ nhất trong các phần tử A[1], A[2],.., A[n] và để vào vị trí đầu tiên
A[1].
Bước 2: Tìm số nhỏ nhất trong các phần tử A[2], A[3],.., A[n] và để vào vị trí thứ hai
A[2].
.v.v.
Bước n-1: Tìm số nhỏ nhất trong hai phần tử A[n-1], A[n] và để vào vị trí n-1. Sau bước
này thì A[n] sẽ là gía trị lớn nhất.
Chẳng hạn, xét dãy A có 4 phần tử: {5,3,4,1}:
Bước 1:

Nếu A[1]>A[2] thì đổi A[1] với A[2], được: {3,5,4,1}
Nếu A[1]>A[3] thì đổi A[1] với A[3]: không đổi
Nếu A[1]>A[4] thì đổi A[1] với A[4], được: {1,5,4,3}

Bước 2:

Nếu A[2]>A[3] thì đổi A[2] với A[3], được: {1,4,5,3}
Nếu A[2]>A[4] thì đổi A[2] với A[4], được: {1,3,5,4}

Bước 3:

Nếu A[3]>A[4] thì đổi A[3] với A[4], được: {1,3,4,5}

Sau ba bước, dãy A đã được sắp xếp xong.
Tại bước thứ i (i chạy từ 1 đến 3 ), ta phải so sánh A[i] lần lượt với A[j] (j chạy từ i+1 đến
4), nếu A[i]>A[j] thì hoán đổi các gía trị của A[i] và A[j], nói cho gọn là đổi chỗ A[i] với
A[j]. Qúa trình trên được thể hiện bằng hai vòng lặp For :
For i:=1 to 3 do
For j:=i+1 to 4 do
if A[i]>A[j] then Ðổi chỗ A[i] và A[j] ;
Mảng A ở trên chỉ có 4 phần tử, trong trường hợp tổng quát khi mảng A có N phần tử thì
lệnh For thứ nhất sẽ có biến i chạy từ 1 đến N-1, và lệnh For thứ hai sẽ có biến j chạy từ i+1
đến N, tức là :
For i:=1 to N-1 do
For j:=i+1 to N do
if A[i]>A[j] then Ðổi chỗ A[i] và A[j] ;
Việc đổi chỗ các gía trị trong A[i] và A[j] được tiến hành bằng cách dùng một biến Z
trung gian cùng kiểu dữ liệu với A[i] và A[j]. Ðầu tiên gởi tạm gía trị của A[i] vào biến Z,
23


sau đó đưa gía trị của A[j] vào A[i], và cuối cùng đưa gía trị trong Z vào A[j], tức là phải
làm ba lệnh :
Z:=A[i];
A[i]:=A[j];
A[j]:=Z;
Tóm lại, thuật toán sắp xếp dãy A tăng được viết như sau:
For i:=1 to N-1 do
For j:=i+1 to N do
if A[i]>A[j] then
begin { Ðổi chỗ A[i] và A[j] }
Z:=A[i];
A[i]:=A[j];
A[j]:=Z;
end;
Trong đó N là số phần tử của dãy A còn Z là một biến trung gian có cùng kiểu dữ liệu với
các phần tử của mảng A.
Chương trình dưới đây tìm số lớn nhất của mảng A và sắp dãy A tăng dần:
PROGRAM VIDU6;
{ Tìm Max và sắp dãy A tăng dần }
Uses CRT;
Type
Kmang = array[1..20] of Real;
Var
i, j, N : Integer;
A: Kmang;
z, Max : Real;
Begin
24


Clrscr;
Repeat
Write(‘ Nhập số phần tử N : ‘);
Readln(N);
Until (N>0) and ( N<21);
For i:=1 to N do

{ nhập mảng }

begin
Write(‘Nhập A[‘, i, ‘]: ‘);
Readln(A[i]);
end;
{ Tìm số lớn nhất }
Max :=A[1];
For i :=1 to N do if Max< A[i] then Max:=A[i];
Writeln(‘ Số lớn nhất là: ’ , Max : 4:1);
{ sắp xếp dãy tăng }
For i:=1 to N-1 do
For j:=i+1 to N do
If A[i]>A[j] then
begin

{23}

{ đổi chỗ A[i] và A[j] }

z:=A[i];
A[i]:=A[j];
A[j]:=z;
end;
Writeln(‘ Dãy đã sắp xep tăng là : ‘);
For i:=1 to N do Write(A[i]:3:0);
Readln;
25


Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay

×
x