You are on page 1of 6

Bài 9.

Làm việc với dãy số


1. Mục đích, yêu cầu
• Biết được khái niệm mảng một chiều
• Biết cách khai báo mảng, nhập, in, truy cập các phần tử của mảng
• Hiểu thuật toán tìm số lớn nhất, số nhỏ nhất của một dãy số
2. Những điểm cần lưu ý và gợi ý dạy học
Tương tự với câu lệnh điều kiện, câu lệnh lặp, vào đầu bài này cần giới thiệu một số ví dụ nhằm đưa
đến nhu cầu cần có biến mảng trong ngôn ngữ lập trình.
Ví dụ 1, trong SGK dẫn đến nhu cầu biến mảng, sau khi đã phân tích sự bất tiện nếu chỉ sử
dụng cách khai báo biến đã biết (khai báo biến đơn). Pascal cung cấp một công cụ hiệu quả để hỗ
trợ người lập trình đó là biến mảng.
Mục 1 có hai nội dung quan trọng đó là nhu cầu của biến mảng trong ngôn ngữ lập trình và
thuật toán tìm số lớn nhất của một dãy số. Thuật toán tìm số lớn nhất của dãy số (học sinh đã được
tìm hiểu ở bài 5). Trong mục 1 chỉ giới thiệu việc tìm số lớn nhất của dãy số như một nhiệm vụ cần
thực hiện mà không đề cập đến việc giải quyết nhiệm vụ này như thế nào. Mục tiêu của các ví dụ ở
mục 1 là dẫn đến nhu cầu cần có biến mảng.
Trong phần 2 cần cho HS biết cách khai báo, truy cập, nhập (gán) giá trị, viết giá trị của biến
mảng ra màn hình.
a) Khai báo biến mảng:
Có hai cách khai báo biến mảng
Cách 1: Khai báo trực tiếp biến mảng một chiều:
var <tên biến mảng> : array [kiểu chỉ số] of [kiểu phần tử];
Cách 2: Khai báo gián tiếp biến mảng qua kiểu mảng một chiều:
type <tên kiểu mảng> = array [kiểu chỉ số] of <kiểu phần tử>;
var <tên biến mảng>:<tên kiểu mảng>;
trong đó:
- kiểu chỉ số là một dãy số nguyên liên tục n1..n2 với n1, n2 là các hằng (hoặc biểu thức cho
kết quả là số nguyên) xác định chỉ số đầu tiên và chỉ số cuối cùng (n1≤ n2).
- kiểu phần tử là kiểu của các phần tử mảng.
Tuy nhiên, GV chỉ cần giới thiệu với HS cách 1. Kiểu chỉ số cũng chỉ cần giới thiệu thật đơn giản là
dãy số nguyên dương bắt đầu từ n1=1 (không nhất thiết phải giới thiệu những trường hợp còn lại).
Kiểu phần tử có thể là số nguyên, thực.
GV cần sử dụng một số ví dụ để luyện tập về khai báo mảng một chiều và giải thích số lượng phần
tử, kiểu phần tử của từng biến mảng tương ứng với mỗi ví dụ.
b) Truy cập mảng:
Sau khi đã cho HS luyện tập với khai báo biến mảng, có thể sử dụng các khai báo vừa thực hiện để
giới thiệu về các truy cập vào biến mảng. Ví dụ, với khai báo
var Diem: array[1..50] of real;
khai báo này đã tạo ra một biến mảng có 50 phần tử từ phần tử 1 đến phần tử 50. Các phần tử này
được "đặt tên" như thế nào? Để "gọi đích danh" từng phần tử cụ thể Pascal sử dụng cách: Tên biến
mảng[chỉ số phần tử]. Ví dụ, Diem[1] là phần tử thứ nhất; Diem[5] là phần tử thứ 5. Có thể thực
hiện các thao tác như gán giá trị, so sánh, viết giá trị ra màn hình... với Diem[1],
Diem[2]...Diem[50] như với biến đã học (biến đơn).
c) Nhập giá trị cho biến mảng:
Để nhập giá trị cho biến mảng thì cần nhập giá trị cho từng phần tử của mảng. Giống như với việc
gán giá trị cho biến đơn, có hai cách để gán giá trị cho phần tử của mảng:
Gán trực tiếp bằng lệnh gán: ví dụ: Diem[1] := 8, Diem[2] := 9.5.
Gán giá trị bằng cách nhập từ bàn phím, sử dụng lệnh read(), readln().
Có thể viết một đoạn chương trình với 50 lệnh readln() để thực hiện việc nhập giá trị cho 50
phần từ của mảng từ bàn phím:
readln(Diem[1]; readln(Diem[2]);... readln(Diem[50]);
Tuy nhiên, việc kết hợp vòng lặp for...do với câu lệnh readln() là một cách lập trình hiệu quả,
hay được sử dụng để nhập dữ liệu cho mảng.
For i:=1 to 50 do readln(Diem[i]);
Tương tự như vậy, để viết giá trị của các phần tử của mảng ra màn hình người ta kết hợp giữa
for...do với lệnh writeln() hoặc write().
For i:=1 to 50 do writeln(Diem[i]);
Giả sử chỉ muốn viết ra màn hình những điểm số lớn hơn hoặc bằng 9 chẳng hạn, câu lệnh như sau:
For i:=1 to 50 do
if Diem[i] >= 9 then writeln(Diem[i]);
Việc đưa ra yêu cầu này có hai mục đích: thứ nhất là để HS làm quen trước với so sánh phần tử của
biến mảng sẽ được sử dụng trong phần sau. Làm như vậy HS sẽ không bị bỡ ngỡ khi gặp phép so
sánh này trong chương trình. Thứ hai, HS thấy được sự kết hợp giữa các câu lệnh mà cụ thể là câu
lệnh for...do và câu lệnh if-then trong chương trình.
Trong các ví dụ trên, khi duyệt các phần tử của biến mảng hoàn toàn có thể sử dụng cấu trúc
while...do, tuy nhiên ở đây cấu trúc for...do phù hợp hơn vì trong trường hợp biết trước số lần lặp.
Mặt khác, sử dụng cấu trúc for...do ở đây nói chung là dễ hiểu hơn, gần với cách nghĩ tự nhiên của
HS hơn. GV cũng có thể nhắc lại về tầm quan trọng của việc lựa chọn cấu trúc điều khiển phù hợp
khi lập trình.
Mục 3 là ví dụ về một chương trình cụ thể sử dụng biến mảng và thuật toán tìm giá trị lớn nhất, nhỏ
nhất của dãy số nguyên. Trước khi giới thiệu chương trình cụ thể GV nên hướng dẫn HS tìm hiểu
lại thuật toán này (đã học trong Bài 5).
Giải thích về thuật toán tìm giá trị lớn nhất của dãy số nguyên:
+ Đầu tiên gán giá trị số thứ 1 của dãy số cho Max (Ban đầu tạm thời coi số thứ nhất là số
lớn nhất -số lớn nhất tạm thời)
+ So sánh số lớn nhất tạm thời này với số thứ 2, nếu số thứ 2 lớn hơn số lớn nhất tạm thời-
Max thì gán giá trị của số thứ 2 cho Max. Như vậy đến thời điểm này Max là số lớn nhất của
số thứ 1 và số thứ 2.
+ Cứ tiếp tục như vậy, đem so sánh Max với tất cả các số còn lại, găp số nào lớn hơn Max thì
gán giá trị của số đó cho Max. Sau khi so sánh đến số cuối cùng của dãy số thì Max chính là
giá trị lớn nhất của dãy số.
Do học sinh đã được tìm hiểu thuật toán này ở bài 5, cho nên giáo viên có thể yêu cầu học sinh trình
bày lại thuật toán tìm số lớn nhất của dãy số hoặc thực hiện lại việc mô phỏng thuật toán trên một
dãy số cụ thể để các em nhớ lại thuật toán. Ví dụ về mô phỏng thuật toán này đã có ở bài 5.
Sau đó yêu cầu học sinh thảo luận chỉnh sửa thuật toán trên để tìm ra số nhỏ nhất của dãy số. Ví dụ,
mô phỏng thuật toán tìm giá trị nhỏ nhất của dãy số có thể như bảng dưới đây:
Dãy số 5 4 4 7 6 3 15 6 8

i 1 2 3 4 5 6 7 8 9

ai < SMIN Đúng Sai Sai Sai Đúng Sai Sai Sai

SMIN 5 4 4 4 4 3 3 3 3

Thuật toán tìm giá trị lớn nhất, nhỏ nhất trong dãy số nguyên rất đơn giản, không khó hiểu với HS.
Nhưng HS lại có thể khó hiểu là do các em chưa biết tại sao máy tính lại phải sử dụng thuật toán
này mới tìm ra được số lớn nhất. Thực tế, nếu GV viết một dãy số nguyên lên bảng (ví dụ, 1, 4, 23,
6, 8, 9) HS có thể thấy ngay được 23 là giá trị lớn nhất mà không nhận thấy sự cần thiết phải thực
hiện thuật toán nêu trên.
Trong trường hợp này, có sự khác biệt giữa con người và máy tính khi giải quyết công việc.
Con người có thể đã nhìn nhiều số đồng thời, với dãy số ngắn như trên con người có thể nhìn cả dãy
số cùng một lúc. Con người có thể nhận diện ra số lớn nhất không chỉ dựa vào giá trị mà có thể còn
qua một số dấu hiệu bổ trợ khác, ví dụ như: độ dài của số (có một số duy nhất có hai chữ số) chẳng
hạn. Với những dấu hiệu bổ trợ, khả năng quan sát và tư duy, con người nhanh chóng "khoanh
vùng" được đáp án và nhanh chóng tìm ra đáp án. Tức là phương án giải của con người không tuần
tự mà có thể bỏ qua một số bước khi cần thiết. Do vậy, trong trong nhiều tình huống con người giải
các bài toán hiệu quả hơn nhiều máy tính.
Tuy nhiên, khả năng này con người lại bị hạn chế trong tình huống dãy số rất lớn (hàng ngàn, hàng
triệu, hàng tỉ số chẳng hạn). Khi đó máy tính lại thể hiện được sức mạnh của mình bởi ưu thế về tốc
độ xử lí.
Để HS hiểu được máy tính làm việc như thế nào, GV có thể yêu cầu các em thực hiện như sau: Viết
10 số nguyên, mỗi số vào một mảnh giấy. Gấp 10 mảnh giấy này lại và bỏ vào một hộp A. Đặt một
hộp B rỗng bên cạnh. Yêu cầu HS chuyển lần lượt đến hết từng mảnh giấy ở hộp A sang hộp B. Sau
khi chuyển xong HS cho biết số số lớn nhất trong các số được ghi trên các mảnh giấy. HS được
phép xem số trên mảnh giấy khi chuyển mảnh giấy đó từ hộp A sang hộp B. Yêu cầu HS không ghi
chép ra giấy. Mục đích của việc không cho học sinh ghi chép là để HS mô phỏng hoạt động của
máy tính: Chỉ cần nhớ số lớn nhất tại thời điểm hiện tại, so sánh với số vừa lấy ra từ hộp A (đang
cầm trên tay) và nhớ lấy số lớn hơn và cứ tiếp tục như vậy đến khi hết các số trong hộp, số được
nhớ cuối cùng là số lớn nhất.
Để thực hiện công việc này cần hướng dẫn HS thực hiện mô phỏng theo giải thuật tìm dãy số
lớn nhất của dãy số nguyên. Nhặt mảnh giấy đầu tiên ở hộp A, mở ra nhớ giá trị của mảnh giấy này
(coi là số lớn nhất tạm thời), gấp lại và bỏ vào hộp B. Nhặt mảnh giấy thứ hai, mở ra và so sánh với
giá trị lớn nhất tạm thời, và nhớ giá trị lớn nhất mới nếu thấy lớn hơn. Lặp lại công việc này đến khi
hết các mảnh giấy của hộp A.
GV có thể thêm, bớt các mảnh giấy để HS làm lại. Sau khi HS làm đề nghị các em mô tả lại
cách các em đã thực hiện để tìm ra số lớn nhất. Cách mà HS làm giống với cách máy tính tính thực
hiện theo thuật toán ở trên. Máy tính chỉ có thể tham chiếu đến từng số trong dãy số, máy tính
không có khả năng quan sát cả dãy số vì vậy máy tính phải thực hiện theo thuật toán như trên. Máy
tính thực hiện tuần tự theo đúng chỉ dẫn của con người, máy tính không có trí thông minh. Tất
nhiên, ngược lại máy tính lại có ưu điểm vượt trội đó là tốc độ xử lí.
Có thể cải biến nội dung dạy học trên đây thành nhiều trò chơi khác nhau. Ví dụ, yêu cầu các em
không sử dụng giấy, bút, GV lần lượt viết từng số lên bảng, rồi xoá đi luôn, HS quan sát để tìm ra số
lớn nhất (hoặc nhỏ nhất). Hoặc mời một nhóm HS đứng lên phía trên lớp. Mời một em đi qua từng
bạn một, khi em này đến bên bạn nào đó thì bạn này phải đưa ra một số nào đó (có thể là nói thầm
hoặc viết ra một mảnh giấy). Đi hết lượt HS phải nói được bạn nào đã đưa ra số lớn nhất (hoặc nhỏ
nhất). Kết quả này được kiểm chứng công khai bởi các bạn đã đưa ra các số.
Thuật toán tìm Max của dãy số nguyên nhập từ bàn phím như sau:
Bước 1. Nhập N và dãy A1,..., An
Bước 2. Max ← A1
Bước 3. Lần lượt gán giá trị từ 2 đến N cho i. Với mỗi giá trị của i thì thực hiện: Nếu Max <Ai
thì Max←Ai
Bước 4. Đưa ra màn hình giá trị Max rồi kết thúc.
Sau khi giới thiệu xong thuật toán tìm Max giáo viên hướng dẫn HS xác định các biến, kiểu biến và
viết khai báo biến; viết câu lệnh thực hiện các bước nhập N, nhập các phần tử của mảng, tìm Max,
in Max ra màn hình. Chương trình có thể được xây dựng dần từng phần và cuối cùng có được một
chương trình như dưới đây.
program P_Max;
Var
i, N, Max : integer;
A: array[1..100] of integer;
Begin
{Nhap N}
write('Hay nhap do dai cua day so, N = '); readln(N);
{Nhap day so}
writeln('Nhap cac phan tu cua day so:');
For i:=1 to N do
Begin
write('a[',i,']='); readln(a[i]);
End;
{Tim Max}
Max:=a[1];
for i:=2 to n do if Max<a[i] then Max:=a[i];
{Hien thi Max ra man hinh}
write('So lon nhat la Max = ',Max);
readln;
End.
Yêu cầu HS chỉnh sửa chương trình trên để tìm giá trị nhỏ nhất của dãy số nguyên, tính tổng
dãy số. Sau khi đã hiểu -rõ thuật toán và chương trình tìm Max, Min có thể yêu cầu HS kết hợp tìm
Max, Min trong cùng một chương trình như trong SGK.

3. Hướng dẫn trả lời câu hỏi và bài tập


Bài 1. Đúng.
Bài 2. Lợi ích chính của việc sử dụng biến mảng là rút gọn việc viết chương trình, có thể sử dụng
câu lệnh lặp để thay nhiều câu lệnh. Ngoài ra chúng ta còn có thể lưu trữ và xử lí nhiều dữ liệu
có nội dung liên quan đến nhau một cách hiệu quả.
Bài 3. Đáp án a) Sai. Phải thay dấu phẩy bằng hai dấu chấm; b) và c) Sai, vì giá trị nhỏ nhất và lớn
nhất của chỉ số mảng phải là số nguyên; d) Sai, vì giá trị đầu của chỉ số mảng phải nhỏ hơn
hoặc bằng chỉ số cuối; e) Đúng.
Bài 4. Không. Giá trị nhỏ nhất và lớn nhất của chỉ số mảng phải được xác định ngay khi khai báo
biến mảng.
Bài 5. Chương trình có thể như sau:
var N, i: integer;
A: array[1..100] of real;
begin
write('Nhap so phan tu cua mang, n= '); read(n);
for i:=1 to n do
begin
write('Nhap gia tri ',i,'cua mang, a[',i,']= ');
readln(a[i])
end;
end.
Bài 6. Đúng.
Bài 7. a) Nếu không sử dụng biến mảng, chương trình có thể dài như sau:
uses crt;
var So_1, So_2, So_3, So_4, So_5, Max: integer;
begin
clrscr;
write('Nhap so thu nhat: '); readln(So_1);
write('Nhap so thu hai: '); readln(So_2);
write('Nhap so thu ba: '); readln(So_3);
write('Nhap so thu tu: '); readln(So_4);
write('Nhap so thu nam: '); readln(So_5);
Max:=So_1;
If Max<So_2 then Max:=So_2;
If Max<So_3 then Max:=So_3;
If Max<So_4 then Max:=So_4;
If Max<So_5 then Max:=So_5;
writeln('So lon nhat: ',Max);
end.
b) Nếu sử dụng biến mảng, chương trình chỉ ngắn gọn như sau:

uses crt;
var i, Max: integer;
A: array[1..5] of integer;
begin
clrscr;
for i:=1 to 5 do
begin write('Nhap so thu ',i,':'); readln(A[i]) end;
Max:=a[1];
for i:=2 to 5 do If Max<a[i] then Max:=a[i];
writeln('So lon nhat: ',Max);
end.
Lưu ý. Xem cách viết chương trình ngắn gọn hơn và không sử dụng biến mảng trong bài tập
9, bài 7. Tuy nhiên, cách viết đó sẽ không cho kết quả mong muốn nếu sau khi nhập giá trị
của các biến còn cần thực hiện các thao tác dữ liệu khác với các giá trị đó.
Bài 8. Viết chương trình sử dụng biến mảng để tính giá trị trung bình của tổng N số nguyên được
nhập vào từ bàn phím.

uses crt;
var N, i: integer;
TB: real;
A: array[1..100] of real;
begin
clrscr;
write('Nhap so phan tu cua mang, n= '); read(n);
for i:=1 to n do
begin
write('Nhap gia tri ',i,'cua mang, a[',i,']= ');
readln(a[i])
end;
TB:=0;
for i:=1 to n do TB:=TB+a[i];
TB:=TB/n;
write('Trung binh bang ',TB);
end.
Bài 9. Chương trình nhập n số nguyên từ bàn phím và tính tổng các số dương:

uses crt;
var n,k,S: integer;
X: array[1..1000] of integer;
begin
clrscr;
write('Nhap so tu nhien n: '); readln(n);
for k:=1 to n do
begin write('Nhap X[',k,']='); readln(X[k]) end;
S:=0;
for k:=1 to n do
if X[k]>0 then S:=S+X[k];
writeln('Tong cac duong S=',S);
readln;
end.
Bài 10. Nội dung bài 2 của bài thực hành 6 là viết chương trình nhận biết mộtĐể có thể liệt kê,
chương trình cần phải ghi lại chúng. ý tưởng chính là sử dụng một biến mảng phục vụ cho điều
này. Chương trình tương tự như trong bài tập 9, Bài 8:

uses crt;
var n,i,k,S: integer;
X: array[1..10000] of integer;
begin
clrscr;
i:=2; S:=0;
for k:=1 to (n-1) do X[k]:=0; {Dat lai = 0}
write('Cho so tu nhien n>2: n= '); readln(n);
while i<=(n-1) do {Ghi lai uoc so vao X[i]}
begin if (n mod i)=0 then begin X[i]:=i; S:=S+X[i] end;
i:=i+1;
end;
writeln('Tong cac uoc so thuc su cua ',n,' la: ',S);
if S<>0 then begin write('Cac uoc so cua ',n,' la: ');
for i:=1 to (n-1) do if X[i]<>0 then write(X[i],' ') end
else writeln(n,' la so nguyen to.');
readln;
end.

You might also like