V- Chạy thử, thay đổi chơng trình:
2.2.1- Một số lỗi thờng gặp về cú pháp:
TURBO PASCAL ở học sinh THPT.
Chơng trình là sự diễn đạt quá trình giải bài toán bằng một ngôn ngữ để MTĐT thực hiện một cách tự động quá trình này. Chơng trình trên TP bao gồm nhiều thành phần cụ thể là các từ khoá, tên chuẩn và cú pháp và các cấu trúc lập trình đợc xếp đặt có cấu trúc có trật tự.
Vì vậy, khi mới học lập trình bằng ngôn ngữ PASCAL các em thờng hay mắc những lỗi, những thiếu sót sau:
1) Khai báo thừa, thiếu biến, sai tên biến.
2) Khai báo sai dữ liệu.
3) Lỗi chính tả.
4) Viết sai quy cách câu lệnh hoặc mô tả...
2.2.1.1: Khai báo thừa, thiếu biến,sai tên biến:
Khai báo biến là công việc phải làm đối với bất kỳ một CT, nhng công việc này không phải lúc nào cũng diễn ra nh mong muốn, có nhiều nguyên nhân gây nên việc khai báo biến có khi thiếu, có khi thừa, có khi sai tên biến, lỗi này thờng dễ phát hiện và cũng dễ sửa nhng tần số HS mắc lỗi này lại rất nhiều. Sau đây là một số ví dụ minh hoạ cụ thể.
Bài 1.1:
Một xâu ký tự có thể nén theo cách sau: một xâu con gồm n>1“ ”
kí tự giống nhau, chẳng hạn gồm n ký tự a , sẽ đ“ ” ợc ghi thành na. Ví dụ xâu aaaabbcb sẽ đ‘ ’ ợc nén thành 4a2bcb . Hãy viết ch‘ ’ ơng trình nén và giải nén các xâu ký tự. (Chú ý trong xâu đợc nén phải không đợc có chữ số, nếu không kết quả sẽ không nh ta mong muốn. Chẳng hạn xâu aaa2b’ ’
đợc nén thành 3a2b có thể sẽ bị lẫn với aaabb ).‘ ’ ‘ ’ Chơng trình minh hoạ bằng ngôn ngữ TP:
(?) 1) Program Nen_giai_xau; 2) Uses Crt; 3) Var s,s1,s2:string; 4) i,j,code:integer; 5) Begin 6) Clrscr;
7) Write(' Nhap xau s:'); Readln(s); 8) {Nen s vao s1} 9) i:=1; s1:=s[i];j:=1; 10) Repeat 11) i:=i+1; 12) If (s[i]=s[i-1]) then j:=j+1 13) Else 14) Begin 15) If j>1 then 16) Begin 17) Str(j,s2); 18) Insert(s2,s1,length(s1));
19) j:=1; 20) End; 21) s1:=s1+s[i]; 22) End;
23) Until (i>length(s));
24) Writeln(' nen s vao s1=',s1); 25) {giai nen s1 vao s2}
26) i:=0; s2:=''; s:=''; 27) Repeat
28) i:=i+1;
29) If (s1[i] in ['0'..'9']) then s:=s+s1[i] 30) Else 31) Begin 32) If s<> '' then 33) begin 34) Val(s,j,code); 35) For k:=2 to j do s2:=s2+ s1[i]; 36) s:=''; 37) end; 38) s2:=s2+s1[i]; 39) End;
40) Until (i>= length(s1));
41) Write(' giai nen s1 vao s2=',s2); 42) Readln;
43) End.
(!) : Sai lầm của học sinh trong bài trên là:
Khi dịch chơng trình con chạy sẽ dừng ở dòng 35. Với lời nhắc:
ERROR 3: Unknown Identifier, lỗi này nghĩa là: Lỗi 3: Không hiểu định danh này hay nói cách khác là tên biến này cha đợc khai báo. Lỗi này xảy ra khi các em làm bài do không đọc kỹ bài ra để dự tính cần bao nhiêu biến mà khai báo. Cho nên khi tính toán cần thì đa vào, nhng không nhớ quay lại khai báo thêm.
Để khắc phục lỗi này các em quay lại dòng 4 khai báo thêm biến k. Sau đó dịch tiếp hết lỗi TP thông báo dịch thành công.
Bài 1.2: Cho trớc số tự nhiên n. Hãy đếm số phần tử dơng của mảng A=(aij ) kích thớc n x n với:
a) aij = sin(i+j/2);
b) aij = cos(i*i+n); c) aij = sin[( i*i-j*j)/n]
Số n nhập từ bàn phím. Kết quả thể hiện trên màn hình. Chơng trình minh hoạ bằng TP:
(?) 1) Program Dem_so; 2) Uses Crt;
3) Var a,b,c:array[1..50,1..50] of real; 4) n,i,jj,d1,d2,d3,dem:integer; 5) Begin
6) Clrscr;
7) Write(' Nhap kich thuoc cua mang vuong: n='); readln(n); 8) For i:=1 to n do 9) For j:=1 to n do 10) Begin 11) Write('a[',i,',',j,']='); readln(a[i,j]); 12) end; 13) For i:=1 to n do 14) For j:=1 to n do 15) Begin 16) a[i,j]:=sin(i+j/2); 17) b[i,j]:=cos(i*i+n); 18) c[i,j]:=sin((i*i-j*j)/n); 19) end; 20) d1:=0; d2:=0; d3:=0; dem:=0; 21) For i:=1 to n do 22) For j:=1 to n do 23) begin 24) if a[i,j]>0 then d1:=d1+1; 25) if b[i,j]>0 then d2:=d2+1; 26) if c[i,j]>0 then d3:=d3+1; 27) end;
28) Writeln('a. so phan tu duong la:',d1); 29) Writeln('b. so phan tu duong la:',d2); 30) Writeln('c. so phan tu duong la:',d3); 31) Readln;
32) End.
(!) : Khi dịch chơng trình phạm phải một số sai lầm sau: Con chạy sẽ dừng ở đầu dòng 9 với lời nhắc :ERROR 3: Unknown Identifier. Nghĩa là lỗi 3: Tên cha đợc khai báo. Lỗi này xảy ra do dòng 4 khai báo với tên jj mà ở dòng 9 lại dùng tên j. Ta chuyển lên dòng 4 chữa lại jj thành j.
Chơng trình sau khi dịch hết lỗi, TP thông báo dịch thành công. Nh- ng ở đây các em đã phạm một lỗi đó là do không tìm hiểu đề kỹ càng, nên dẫn tới tình trạng khai thừa biến. Điều đó có nghĩa là máy vẫn phải cấp phát ô nhớ cho các biến này, nh thế là ta đã lãng phí bộ nhớ. Mà điều ta cần là một chơng trình chạy tốt nhng phải tiết kiệm đợc bộ nhớ. Lỗi này thờng không đợc máy phát hiện, không thông báo lỗi, để khắc phục hiện t- ợng này ta cần lu ý khi đa ra các trờng hợp khai báo thừa để các em có thể nắm vững cách tổ chức của máy tính. Và lu ý các em nên viết xong CT rồi trở lên phần khai báo các biến đó.
2.2.1.2: Lỗi chính tả:
Đây là lỗi mà các em thờng hay mắc phải, một phần do không nhớ câu lệnh cụ thể, một phần cũng có thể do khi nhập văn bản vào máy các em đã gõ sai, lỗi này xảy ra với tần số cao ở các em mới học lập trình bằng ngôn ngữ Turbo pascal. Sau đây là một số chơng trình minh hoạ cho lỗi này, nhng chỉ một số lỗi thờng gặp nhất chúng tôi đề cập đến.
Bài 2.1: Vẽ hệ trục toạ độ và đồ thị hàm số: y= x2 với đầy đủ chú thích.
Chơng trình viết bằng ngôn ngữ Turbo Pascal: (?) 1) Program Do_thi;
2) uses crt, graph;
3) const x0=320; y0=300; e=50; 4) var Gd, Gm,i,j,k:integer; 5) x,y:real;
6) s:string; 7) Begin
8) Gd:=detect; 9) initgraph(Gd,Gm,'C:\BP\BGI'); 10) line (100,y0,550,y0); 11) outextxy(450,y0*10,'x'); 12) for k:=-3 to 3 do 13) begin 14) i:= k*e+x0; 15) j:=y0; 16) str(k,s); 17) outtextxy( i-10,j+8,s); 18) bar (i-1, j-1, i+1,j+1); 19) end;
20) Line(x0,50,x0,370); 21) Outtext xy( x0-20, 50,'y'); 22) for k:=-1 to 4 do 23) begin 24) i:=x0; j:=-k*e+y0; 25) str(k,s); 26) if k<>0 then outtextxy(i-20, j,s); 27) bar(i-1,j-1,i+1,j+1); 28) end;
29) for i:=x0-2*e to x0+2*e do 30) begin
31) x:=(i-x0)/e; y:=sqr(x); 32) j:= ruond(-y *e+ y0); 33) putpixel(i,j,10); 34) end;
35) setextstyle(1,0,2);
36) outtextxy(100,400, 'do thi ham so y= sqr(x):'); 37) Readln;
38) Closegraph; 39) End.
1) Con chạy sẽ dừng ở đầu dòng 11 với lời nhắc:ERROR 3: Unknown Identifier, có nghĩa là: Lỗi 3: Không hiểu định danh này. Lỗi xảy ra do học sinh không viết đúng tên chuẩn của TP, trong thủ tục xuất chuỗi ra màn hình muốn chơng trình chạy tiếp ta sửa lại đúng với tên Outtextxy().
2) Tiếp đến ta ấn F9 và lần này con chạy dừng ở dòng 20 với thông báo: ERROR 88: ( expected“ “ . Nghĩa là: Lỗi 88: thiếu dấu ‘(‘ lỗi này xảy ra do các em đánh Outtext xy(), tức là có dấu cách giữa câu lệnh, vì vậy TP hiểu sai là bạn quên mở ngoặc trớc khi thực hiện các lệnh trong nháy. Cách khắc phục đơn giản nhất là bạn hãy bỏ dấu cách giữa hai từ.
3) Tiếp tục dịch tiếp chơng trình con chạy sẽ dừng tại dòng 31 với lời nhắc: ERROR 3: Unknown Identifier. Lỗi này đợc hiểu là xuất hiện các ký tự lạ máy không hiểu, có nghĩa là những tên này cha đợc khai báo hoặc không có trong tên chuẩn của TP. Để sửa lại ta nên viết đúng tên chuẩn của TP.
4) Dịch tiếp chơng trình con chạy sẽ dừng ở dòng 34 với thông báo lỗi nh trên, tức là cũng xuất hiện các ký tự lạ mà máy không hiểu, ở trờng hợp này do các em viết không đúng tên chuẩn do TP quy định, vậy để ch- ơng trình chạy tiếp ta gõ lại tên đúng là: Settextstyle (1,0,2). Khi dịch hết chơng trình thì TP thông báo dịch thành công.
Bài 2.2: Cho A,B,C là 3 điểm lập thành 1 tam giác trên màn hình. Hãy vẽ:
- tam giác đối xứng với tam giác ABC qua tâm màn hình.
- Hình chữ nhật nhỏ nhất chứa tam giác ABC và tam giác đối xứng của nó mà các cạnh song song với các cạnh màn hình.
Chơng trình minh hoạ cụ thể bằng TP:
(?) 1) Program tam_giac_doi_xung; 2) var a,b:array[1..3,1..2] of integer; 3) Gd,Gm,i,d1,d2,d3,d4:integer; 4) Begin
5) Clrscr;
6) write(' nhap toa do diem a:); readln(a[1,1],a[1,2]); 7) write( nhap toa do diem b:); readln(a[2,1],a[2,2]); 8) write('nhap toa do diem c:'); readln(a[3,1],a[3,2])
9) Gd:=Detect; 10) initgraph(Gd,Gm,'C:\bp\bgi'); 11) if graphresult <>0 then 12) halt 13) else 14) begin 15) Setcolor(green); 16) Line(a[1,1],a[1,2],a[2,1],a[2,2]); 17) Line(a[2,1],a[2,2],a[3,1],a[3,2]); 18) Line(a[3,1],a[3,2],a[1,1],a[1,2]); 19) for i:=1 to 3 do 20) begin 21) b[i,1]:= getmaxx-a[i,1]; 22) b[i,2]:= getmaxy-a[i,2]; 23) end; 24) Setcolor(yellow);
25) putpixel(getmaxx div 2, getmaxy div 2,yellow); 26) Cicrle(getmaxx div 2, getmaxy div 2, 2);
27) Setcolor(red); 28) Line(b[1,1],b[1,2],b[2,1],b[2,2]); 29) Line(b[2,1],b[2,2],b[3,1],b[3,2]); 30) Line(b[3,1],b[3,2],b[1,1],b[1,2]); 31) d1=a[1,1]; 32) d2:=a[1,2]; 33) Setcolor(brown); 34) for i:=1 to 3 do 35) begin
36) if d1>a[i,1] then d1:=a[i,1]; 37) if d1>b[i,1] then d1:=b[i,1]; 38) if d2< a[i,2] then d2:=a[i,2]; 39) if d2< b[i,2] then d2:=b[i,2]; 40) end;
41) Rectangle(d1,d2, getmaxx -d1, getmaxy-d2); 42) end;
43) Readln; 44) Closegraph; 45) End.
(!): Trong chơng trình này các em đã mắc phải một số lỗi nh sau: 1)Khi dịch chơng trình con chạy sẽ dừng tại dòng 5 với thông báo lỗi: ERROR 3: Unknown Identifier, nghĩa là không hiểu định danh này. Lỗi xảy ra do các em cha khai báo đơn vị chuẩn, mà lại sử dụng hàm xoá màn hình là một hàm nằm trong đơn vị chuẩn CRT. Để khắc phục lỗi này ta trở lên khai báo USES CRT;
2) Tiếp tục dịch chơng trình con chạy sẽ dừng tại dòng 6 với lời nhắc : ERROR 8: String constant exceedsline. Có nghĩa là lỗi 8: Lỗi khi viết hằng văn bản. Trờng hợp lỗi này là do các em viết sai quy định của TP, tức là nếu hằng là kiểu văn bản thì phải đặt trong dấu nháy ‘ ‘. Để sửa lại ta bổ sung thêm một nháy nữa vào sau.
3) Tiếp đến con chạy sẽ dừng tại dòng 7 với thông báo ERROR 3: Unknown Identifier. Lỗi này xảy ra cũng tơng tự lỗi ở dòng 6 để chạy tiếp chơng trình ta chỉ việc đặt hàng văn bản vào giữa hai dấu nháy đơn.
4) ấn phím F9 con chạy sẽ dừng tại dòng 9 với lời nhắc: ERROR 85: ; expected“ ” . Nghĩa là lỗi 85: Thiếu dấu “ ;”, lỗi này xảy ra ở dòng 8 thiếu dấu ; ta trở lên dòng 8 bổ sung thêm dấu ; vào cuối dòng.
5) Sau đó ấn F9 thì con chạy lại dừng tại dòng 9 nhng với thông báo lỗi 3: Không hiểu định danh này, điều này xảy ra do các em sử dụng hàm trong đồ hoạ nhng lại cha khai đơn vị đồ hoạ GRAPH, để chơng trình tiếp tục chạy ta trở lại dòng khai báo CRT, ta khai báo thêm GRAPH;
6)Tiếp tục dịch chơng trình con chạy sẽ dừng tại dòng 26 với lời nhắc là: xuất hiện ký tự lạ cha đợc khai báo, kiểm tra thì đó là do lỗi các em gõ sai tên thủ tục vẽ đờng tròn để sửa lại ta gõ CIRCLE thay cho CICRLE nh đã gõ trong chơng trình.
7) Tiếp tục dịch chơng trình con chạy sẽ dừng tại dòng 31 với thông báo: ERROR 91: : expected“ ” . Tức là thiếu dấu “:”. Để sửa lại ta bổ sung thêm dấu “:” trớc dấu “=”. Chơng trình sau khi dịch hết lỗi thì TP sẽ thông báo dịch thành công.
Bài 2.3: Thông tin về mỗi học sinh gồm:
- Họ đệm: Một xâu 25 ký tự
- Tên: Một xâu 10 ký tự
- Tuổi: Một số nguyên 2 chữ số.
- Lớp: Một xâu 2 chữ số và một chữ cái viết hoa.
Hãy lập chơng trình nhập từ bàn phím danh sách một lớp học vào một mảng bản ghi. Sau đó hiển thị danh sách lên màn hình, mỗi dòng một ngời.
Chơng trình minh hoạ bằng ngôn ngữ TP:
(?) 1) Program 40tin; 2) Uses crt; 3) Const n=15; 4) Type Danhsach=record 5) Holot: string[25]; 6) Ten:string[10]; 7) Tuoi: byte; 8) Lop: string[3]; 9) end;
10) Var ds:array[1..n] of danhsach; 11) i:byte;
12) Begin 13) clrscr;
14) Writeln(' hay nhap ds hoc sinh:'); 15) Writeln;
16) for i:=1 to n do 17) begin
18) Writeln(' thong tin hoc sinh thu ',i); 19) Write(' cho ho lot:'); readln(ds[i].holot); 20) Write(' cho ten:'); readln(ds[i].ten); 21) Write(' cho tuoi:'); readln(ds[i].tuoi); 22) Write(' cho lop:'); readln(ds[i].lop); 23) Writeln;
24) end;
25) Writeln(' Danh sach hoc sinh:'); 26) for i:=1 to n do
28) Writeln(holot:20,ten:10, tuoi:4, lop:5); 29) Writeln;
30) Write(' Bam Enter de ket thuc...'); 31) Readln; 32) End. Bài 2.4: Hãy dùng hàm đệ qui tính: 1 1 1+ 3+ 1 ... .. 103 1 101+
Chơng trình minh hoạ bằng ngôn ngữ TP: (?): 1) Program Tinh bieu thuc;
2) Uses Crt;
3) Const Max=103; 4) Var i:integer;
5) Function DQ(i:integer):real; 6) Begin
7) If i= max then DQ:=max 8) else DQ:=(i+1/DQ(i+2)); 9) End;
10) Begin 11) Clrscr;
12) Write(' Gia tri cua bieu thuc=', 1/DQ(1):10:4); 13) Readln;
14) End.
(!): Sai lầm của hai chơng trình trên là do không nắm vững cách đặt tên chơng trình.
1)Trong bài2.3, khi dịch chơng trình con chạy sẽ dừng tại dòng 1) với lời nhắc: ERROR 2: Identifier expected. Có nghĩa là Lỗi 2 : Thiếu tên gọi.
2) Còn ở trong chơng trình của bài 2.4, khi dịch máy sẽ thông báo:
ERROR 85: ; expected“ ” . Nghĩa là: Lỗi 85: Thiếu dấu ; Vậy lỗi do đâu? Do các em không nắm vững quy tắc đặt tên của TP. Tên gọi là dãy một hay nhiều chữ cái, chữ số, dấu $, dấu gạch nối _. Ký hiệu đầu tiên của tên gọi phải là chữ cái, dùng dấu gạch nối để liên kết các từ trong một tên gọi cho dễ đọc, không đợc dùng dấu cách để tách các từ. Do đó ta phải sửa lại ở chơng trình bai2.3 với tên đặt đúng là: Lop_40tin; còn trong bài 2.4 ta phải sửa lại là: Tinh_bieu_thuc; Sau đó dịch tiếp chơng trình chạy tốt, TP sẽ cho thông báo dịch thành công, kết thúc công việc dịch chơng trình.
2.2.1.3: Khai báo sai kiểu dữ liệu:
Kiểu dữ liệu là một vấn đề quan trọng khi chọn để khai báo biến, nó đợc sử dụng với quy định rất chặt chẽ, không thể lẫn lộn, phải chứa giá trị cụ thể và đi liền với nó là một kiểu dữ liệu xác định. Do một số các em không nắm vững quy định về kiểu dữ liệu trong CT, nên khai báo sai kiểu dữ liệu xảy ra với tần số cao, sau đây tôi chỉ đa ra một số ví dụ minh hoạ.
Bài 3.1:
Lập chơng trình nhập từ bàn phím n, x=(x1,x2,...,xn), y= (y1,y1,...,yn). Rồi tính và đa ra màn hình giá trị biểu thức sau:
n
∑ (xi –yi )2
i=1
Chơng trình minh hoạ bằng ngôn ngữ TP: (?) 1) Program Tinh;
2) Uses Crt;
3) Var x,y: array[1..n] of real; 4) i,n:integer;
5) s:real; 6) Begin
8) Write(' nhap n='); readln(n); 9) Writeln(' nhap cac vec to x va y:'); 10) For i:=1 to n do
11) Begin
12) Write(' x[',i,']='); readln (x[i]); 13) Write(' y[',i,']='); readln (y[i]); 14) End;
15) s:=0;
16) For i:=1 to n do s:= s+ sqr( x[i]- y[i]);
17) Writeln(' ****** Ket qua la: s=', sqrt(s):10:4); 18) Readln;
19) End.
(!): Khi dịch chơng trình TP sẽ thông báo các lỗi mà HS gặp phải là: Con chạy sẽ dừng tại dòng 3 với thông báo:ERROR 133: Cannot evaluate this expression. Nghĩa là : Lỗi 133: Không thể tính đợc giá trị biểu thức. Vì khi khai báo mảng, kích thớc của mảng phải là một số xác định để chơng trình dịch TP cấp phát bộ nhớ. Vì vậy khi khai báo nh trên TP không biết phải bố trí bao nhiêu ô nhớ cho mảng. Để khắc phục lỗi này ta chỉ cần khai báo lại chỉ số của mảng là một số xác định thay vì khai báo n nh ở trong chơng trình trên.
Bài 3.2:
Cho trớc một dãy số đợc nhập từ bàn phím và đợc lu trữ trong một mảng số phần tử của mảng đợc ghi trong một biến riêng biệt viết chơng trình thực hiện các thao tác sau:
a) Nhập thêm một phần tử và đa vào cuối của dãy dã cho
b) Nhập thêm một phần tử đa vào đầu của dãy đã cho
c) Nhập một phần tử và chèn vào một vị trí cho trớc k của dãy đã cho.
Chơng trình minh hoạ bằng ngôn ngữ TP: (?): 1) Program Day_so;
2) Uses crt;
3) Type mang=array[1..100] of integer; 4) Var a:mang;
5) n,i,k:real; 6) nh:real;
7) Begin 8) clrscr;
9) Write('so phan tu cua day so la:n='); readln(n); 10) Writeln(' nhap cac phan tu cua day so:'); 11) For i:=1 to n do
12) begin
13) Write('a[',i,']='); readln(a[i]); 14) end;
15) Write(' phan tu can them vao cuoi day so da cho la:'); 16) Readln(nh);
17) n:=n+1; 18) a[n]:=nh;
19) For i:=1 to n do write(a[i]:8:2); 20) Readln;
21) Write(' phan tu can them vao dau day so da cho la:'); readln(nh); 22) n:=n+1;
23) For i:=n downto 2 do a[i]:=a[i-1]; 24) a[1]:=nh;
25) For i:=1 to n do write(a[i]:8:2);