V- Chạy thử, thay đổi 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); 26) Repeat
27) Write(' vi tri thu k can chen vao la:'); readln(k); 28) Until (k>=1) and (k<=n);
29) Write(' phan tu can chen vao vi tri thu k cua day so da cho la:'); 30) Readln(nh);
31) n:=n+1;
32) For i:=n downto k+1 do a[i]:= a[i-1]; 33) a[k]:=nh;
34) For i:=1 to n do write(a[i]:8:2); 35) Readln;
36) End.
(!): Khi dịch chơng trình các lỗi HS gặp phải là:
1) Con chạy sẽ báo lỗi tại dòng11: ERROR 97: Invalid For control variable. Có nghĩa là: Lỗi 97: Biến đếm của for sai. Lỗi này xảy ra ở dòng 5, khi ta khai báo : i,n,k:Real. Mà theo quy định của TP thì cấu trúc
FOR ...TO...DO có biến đếm phải thuộc kiểu nguyên. Không thể dùng biến số thực làm biến đếm. Để khắc phục lỗi này ta sửa lại tại dòng 5 là: i, n, k:integer;
2)Tiếp đến con chạy dừng ở dòng 18 với thông báo: ERROR 26: Type mismatch. Nghĩa là: Lỗi 26: Không đồng nhất về kiểu. Lỗi này xảy ra bắt đầu từ dòng 3, ta khai báo là: Mang=array[1..100] of integer, nhng ở dòng 6 lại khai báo một phần tử của mảng là: nh:real. Rõ ràng là không đồng nhất về kiểu rồi. Để khắc phục lỗi này ta trở lại dòng 3 sửa lại nh sau: Mang= array[1..100] of real;
Sau khi dịch hết chơng trình chạy thông suốt.
Bài1.3.3:
Tìm tất cả các hoán vị cân bằng từ một dãy đợc nhập từ bàn phím.
Chơng trình minh hoạ bằng ngôn ngữ TP:
(?): Program Hoan_vi_can_bang; 1)Uses Crt;
2)Const max=100;
3)Var a:array[1..max] of integer; 4) n,i,j,k,nl,m:integer; 5) Dn:integer; 6) dk,stop:boolean; 7) Function Check:boolean; 8) Var Kt:boolean; 9) id: integer; 10) Begin 11) kt:=true; 12) id:=n;
13) while kt and (id <=n) do
14) if a[id]= id then kt:=false else inc(id); 15) check:=kt;
16) End;
17) Procedure doicho( so1,so2:integer); 18) Begin
19) so1:=so1+so2; 20) so2:=so1- so2;
21) so1:=so1- so2; 22) End;
23) Procedure inan; 24) Var id: integer; 25) Begin
26) For id:=1 to n do Write(a[id]:4); 27) End; 28) BEGIN 30) Clrscr; 31) Write(' Nhap n='); 32) Repeat 33) Readln(n);
34) if n<2 then write( 'nhap lai (n>=2):'); 35) Until n>=2;
36) For i:=1 to n do a[i]:=i; 37) stop:= false;
38) Repeat 39) i:=n-1;
40) While a[i]> a[i+1] do 41) if i>1 then dec(i); 42) j:=n;
43) While a[i]> a[j] do 44) if j>1 then dec(j); 45) doicho(a[i],a[j]); 46) nl:=n; 47) m:=i+1; 48) while nl>m do 49) begin 50) doicho(a[n],a[m]); 51) dec(nl); 52) inc(m); 53) end; 54) dk:=true; 55) i:=1;
56) repeat
57) dk:=(a[i]=a[i+1]+1); inc(i); 58) until (i=n) or (not dk); 59) if check= true then 60) begin
61) inc(dn); inan; 62) end;
63) stop:= (dk) and (i=n); 64) until stop= true;
65) Writeln(' co',n,'hoan vi khong can bang cua ',n,'phan tu'); 66) write(' An Enter de thoat...');
67) Readln; 68) END.
(!): Chơng trình đợc bắt đầu thực hiện các lệnh gán trong thân ch- ơng trình chính, gặp lời gọi doicho(a[n],a[m]); ở đây học sinh đã phạm lỗi khá “tinh vi” mà khi dịch chơng trình TP không phát hiện đợc và chỉ khi cho kết quả cuối cùng ta mới biết sai. Bởi vì các em không nắm vững khái niệm khi nào thì dùng tham biến, khi nào thì dùng tham trị. Do đó khi chạy chơng trình máy chỉ cho ta nhập n, và treo máy. Khi ta đa con chạy đến dòng 17 ta khai báo lại là Procedur doicho( var so1,so2:integer);
Chơng trình cho ta kết quả nh mong muốn.
Bài 3.4: Giả sử hàm liên tục f(x) có một nghiệm duy nhất trong khoảng [a,b] và thoả mãn điều kiện f(a).f(b) <0. Để tìm xấp xỉ nghiệm x ta tiến hành chia đôi liên tiếp đoạn [a,b], mỗi lần chia chỉ giữ lại nửa nào có hàm f(x) trái dấu nhau tại hai đầu mút. Khi nào giá trị của f(x) tại điểm chia đủ nhỏ ta đợc nghiệm xấp xỉ. Hãy lập trình để tìm nghiệm của hàm f(x) = x3 864.23 trong khoảng [0, 20] (nghiệm là căn bậc ba của–
864.23).
Chơng trình minh hoạ bằng ngôn ngữ TP: (?): 1)Program Ham_lien_tuc;
2) Uses Crt; 3) Var a,b,c: real; 4) Function f(x:real);
5) Begin
6) f:= x*x - 196; 7) End;
8) Begin
9) Write(' nhap vao hai so a,b:'); readln(a,b); 10) If f(a)*f(b) >0 then
11) Writeln(' khong thoa dieu kien dau bai') 12) Else
13) Begin
14) While (f(a)<> 0) and (f(b) <>0) and (b-a>= 0.00001) do 15) If f((a+b)/2)*f(a) <0 then b:=(a+b)/2
16) else a:=(a+b)/2;
17) If f(b) =0 then writeln(' Nghiem la:',b:5:2) 18) else writeln(' Nghiem la:',a:5:1);
19) End; 20) Readln;
21) End.
(!): Khi dich chơng trình con chạy sẽ dừng thông báo lỗi tại:
1)Dòng 4 với lời nhắc: ERROR 86: : expected.“ ” Nghĩa là: Lỗi 86: Thiếu dấu “:”. Để sửa lại ta thay dấu “;” trên dòng 4 bằng dấu “:”.
2) Tiếp tục dịch con chạy sẽ dừng lại ở dòng 5 nhng với thông báo
ERROR 12: Type identifier expected. Nghĩa là lỗi 12: Thiếu tên kiểu ( Có thể do cha viết tên kiểu). Lỗi này xảy ra do ở dòng 4 khi dùng hàm mà học sinh cha khai báo kiểu dữ liệu mà hàm này sử dụng. Để khắc phục lỗi này các trở lên dòng 4 bổ sung thêm kiểu dữ liệu cụ thể nh sau: Function f( x:real):real;
Sau đó ấn F9 để tiếp tục dịch chơng trình, khi TP thông báo dịch thành công thì ta chạy thử chơng trình để kiểm tra thuật toán của nó.
2.2.1.4: Viết sai quy cách cấu trúc câu lệnh:
Cũng giống nh các ngôn ngữ lập trình khác, NNLT TP cũng cung cấp cho ngời LT một cấu trúc điều khiển với quy định câu lệnh khá chặt chẽ. Việc thể hiện sai cấu trúc của câu lệnh xuất phát từ việc không nắm vững cú pháp câu lệnh cụ thể. Nên việc tìm ra lỗi lầm của các em trong
vấn đề này không phải là ít. Sau đây là một số CT cụ thể minh hoạ cho lỗi này.
Bài 4.1:
Lập chơng trình mô phỏng trò chơi chẵn lẻ : Phát hú hoạ một“ ”
số nguyên ngẫu nhiên lu trong máy.
Ngời chơi đoán xem số nguyên đó là chẵn hay lẻ (từ bàn phím). Sau khi đoán xong máy thông báo số nguyên ở góc trái và thông báo cho biết bạn đoán đúng hay sai ở góc phải. Sau n lần chơi máy thông báo cho bạn biết số lần bạn đoán đúng.
Chơng trình minh hoạ bằng ngôn ngữ TP: (?): 1)Program Chan_le;
2) Uses Crt;
3)Var i,n,tra_loi,x,d: integer; 4) st:string[4];
5)Begin 6) Clrscr;
7) Gotoxy(30,2);
8) Writeln(' TRO CHOI CHAN LE'); 9) Writeln;
10) Write(' Ban thich choi may lan? n='); Readln; 11) Randomize;
12) d:=0;
13) For i:=1 to n do 14) Begin
15) { Phat so ngau nhien tu 0 den 199} 16) x:=random(200);
17) Gotoxy(2,10);
18) Write(' Lan',i,':Ban doan chan hay le? ', '(0: chan/ 1:le'); 19) Readln( Tra_loi);
20) Gotoxy(2,10); 21) delLine; 22) Gotoxy(5,2);
23) Write(' so do la:',x);
24) If odd(x) and (tra_loi=1) or (not odd(x)) and (tra_loi=0) then
25) Begin 26) d:=d+1; 27) st:='dung'; 28) End; 29) Else st:='sai'; 30) Gotoxy(60,2);
31) Write(#7' lan thu ',i,'ban',st,' !'); 32) End;
33) Gotoxy(2,15);
34) Write('Trong',n,'lan choi');
35) If d<>0 then Writeln(' ban thang',d,' lan'); 36) Else
37) Writeln(' ban khong dung lan nao. That dang tiec!'); 38) Writeln;
39) Writeln(' An Enter de ket thuc!'); 40) Readln;
41) End.
(!): Khi dịch chơng trình con chạy sẽ dừng thông báo các lỗi sau: 1) ở dòng 28 với thông báo: ERROR 113: ERROR in sta tement. Có nghĩa là: Lỗi 113: Lỗi ở trong câu lệnh. Lỗi này xảy ra do ở dòng 28 có dấu “;” ở cuối dòng nhng lại đứng trớc ELSE, Nh vậy là sai cấu trúc câu lệnh rẽ hai nhánh, bởi vì trớc ELSE không có dấu “;”. Để sửa lại ta đa con chạy về cuối dòng 28 xoá đi dấu “;”.
2) Tiếp tục dịch con chạy dừng ở dòng 36 với lỗi thông báo nh ở trên, để khắc phục trờng hợp này ta xoá đi dấu “;” cuối dòng 35.
Sau khi dịch hết thì TP sẽ thông báo dịch thông suốt, bây giờ công việc phải làm tiếp theo là chạy thử chơng trình.
Bài 4.2: Viết chơng trình nhập 3 số tự nhiên Ngày, tháng, năm. Hãy kiểm tra xem bộ 3 số trên có lập thành 1 bộ ngày, tháng, năm đúng không. Nếu đúng hãy tính xem đó là ngày thứ mấy kể từ đầu: a) Thế kỷ.
b) Công nguyên. Chơng trình minh hoạ bằng ngôn ngữ TP nh sau:
(?): 1)Program Ngay_thang_nam; 2) Uses crt;
3) Var ngay:1..31; thang:1..12; nam, sn1,sn2:longint; 4) i,nam_dtk,tnam:longint; kt:boolean;
5) Begin 6) Clrscr;
7) write(' nhap ngay:'); readln(ngay); 8) write(' nhap thang:');readln(thang); 9) write('nhap nam:'); readln(nam); 10) case thang of
11) 1,3,5,7,8,10,12: if ngay=31 then kt:= true; 12) 4,6,9,11: if ngay=30 then kt:=true;
13) 2: begin
14) if (nam mod 4=0) then 15) begin
16) if (nam mod 100=0) and (nam mod 400<>0) then 17) if ngay=29 then kt:=true
18) else kt:=false; 19) end
20) else if ngay=28 then kt:=true; 21) end
22) Else writeln('moi ban nhap lai. thang khong hop le'); 23) if kt:=true then
24) writeln(' ngay',ngay,'thang',thang,'nam',nam,'la hop le') 25) else
26) writeln(' ngay',ngay,'thang',thang,'nam',nam,'la khong hop le'); 27) tnam:=nam mod 100; sn1:=0;
28) for i:=nam- tnam to nam-1 do 29) if (i mod 4 =0) then
30) if (i mod 100 =0) and (i mod 400=0) then 31) sn1:= sn1+366
32) else sn1:=sn1+365;
33) if thang=1 then sn1:=sn1+ngay 34) else
35) begin
36) for i:=1 to thang-1 do; 37) case i of
38) 1,5,3,7,8,10,12: sn1:=sn1+31; 39) 4,6,9,11:sn1:=sn1+30;
40) 2: if (nam mod 4 =0) then
41) if (nam mod 100=0) and (nam mod 400=0) then 42) sn1:=sn1+29 43) else sn1:=sn1+28 44) else sn1:=sn1+28; 45) end; 46) sn1:=sn1+ngay; 47) sn2:=0;
48) for i:=0 to (nam- tnam-1) do 49) if (i mod 4=0) then
50) if (nam mod 4=100) and( nam mod 4=0) then sn2:=sn2+366 51) else sn2:=sn2+365
52) else sn2:= sn2+365; 53) end;
54) writeln(' do la ngay thu', sn1, 'ke tu dau the ky!');
55) writeln(' va la ngay thu', sn2 ,' ke tu dau cong nguyen'); 56) Readln;
57) End; 58) End.
(!): Khi dịch chơng trình các lỗi mà HS phạm phải là:
1) Con chạy sẽ dừng ở dòng11 với lời nhắc: ERROR 42: ERROR in expression. Nghĩa là: Lỗi 42: Lỗi trong biểu thức. Lỗi này xảy ra do không nắm vững cấu trúc câu lệnh CASE, nên cuối dòng 11 các em đánh thêm dấu: “;”, để chơng trình dịch tiếp ta đa con trỏ về cuối dòng 11 xoá dấu “;”.
2) Lần này con chạy dừng tại dòng 22 với thông báo:ERROR 85: ; expected
“ ” , có nghĩa là lỗi 85: Thiếu dấu “;”. Đây là sự khác biệt giữa câu lệnh CASE với câu lệnh IF. Tức là trong câu lệnh CASE trớc ELSE vẫn
có dấu “;”, nhng ở câu lệnh IF không nh thế. Để dịch tiếp ta chỉ việc bổ sung thêm dâú “;” vào cuối dòng 21.
3) Tiếp đến con chạy dừng lại ở dòng 23 với thông báo ERROR 57: Then expected, nghĩa là thiếu THEN, bởi trong biểu thức của câu lệnh
IF... THEN là một biểu thức LOGIC do đó ở đây không thể là phép gán đ- ợc, nên TP cho rằng ở câu lệnh trớc phép gán thiếu THEN. Để sửa lại lỗi này ta xoá đi dấu “:” trớc dấu “ =”.
4) Tiếp tục dịch con chạy sẽ dừng tại dòng 58 với lỗi 85: thiếu dấu “;”.Lỗi này xảy ra do trong câu lệnh CASE kết thúc lệnh có END;, nhng ở đây học sinh đã không sử dụng đúng cú pháp câu lệnh. Để sửa lại ta trở lên dòng22 và gõ thêm END;
Cuối cùng sau khi dịch hết và TP thông báo dịch thành công.
Bài 4.3: Số tự nhiên n đợc gọi là đối xứng nhị phân nếu biểu diễn nhị phân của n là một biểu thức đối xứng. Viết chơng trình kiểm tra tính đối xứng nhị phân của một số tự nhiên cho trớc.
Chơng trình minh hoạ bằng ngôn ngữ TP: (?): 1) Program Doi_Xung_nhi_phan; 2)Uses crt; 3)Var n:word; 4) i,j:integer; 5) dx:boolean; 6) a:array[1..16] of 0..1; 7)Begin
8) Write(' nhap so tu nhien n='); readln(n); 9) i:=0; 10) while n>0 do; 11) begin 12) i:=i+1; 13) a[i]:=n mod 2; 14) n:=n div 2; 15) end; 16) j:=1; 17) dx:=true; 18) if i>=2 then
19) while (j<=(i div 2)) do
20) if a[j]<> a[i-j+1] then dx:=false; 21) j:=j+1;
22) if dx then writeln(' so nay la doi xung nhi phan') 23) else writeln(' so nay khong doi xung nhi phan'); 24) Readln;
25)End.
(!): Khi dịch chơng trình TP thông báo dịch thành công, nhng khi chạy chơng trình thì máy cho phép ta nhập vào n, sau đó máy bị treo ấn CTRL + Pause/break, thì dòng 11 đổi màu báo lỗi tại dòng này.
Theo cấu trúc câu lệnh While..Do thì không có dấu “;”. Nhng ở trong dòng lệnh này có thêm dấu “;” nên máy hiểu đây là câu lệnh rỗng và không thực hiện các lệnh tiếp theo, dẫn đến hiện tợng treo máy. Để sửa lại ta đa con chạy về cuối dòng ta xoá đi dấu “;”.
Tiếp tục chạy chơng trình máy cũng bị treo, lỗi do đâu?. Lần này dòng 20 đổi màu có nghĩa là lỗi tại dòng này. Lỗi này xảy ra do học sinh không nắm cấu trúc câu lệnh While ..Do, nếu có từ 2 lệnh trở lên trong thân While thì bắt buộc phải đặt giữa cặp từ khoá Begin... End. Để khắc phục lỗi này các em đặt thân While vào giữa cặp từ khoá “ Begin...End”. Cuối cùng chơng trình chạy cho ta kết quả nh mong muốn.
Bài 4.4: Con lắc thử đạn: Để tính vận tốc của viên đạn ngời ta dùng con lắc thử đạn. Đó là một hộp đựng cát, khối lợng mc, treo vào một sợi dây có độ dài l. Nếu bắn một viên đạn có khối lợng md theo ph- ơng nằm ngang, thì đạn cắm vào cát làm cho hộp cát vạch một cung tròn và phơng của sợi dây sẽ lệch so với phơng thẳng đứng một góc α .
Hãy lập trình nhập các giá trị mc, md và l từ bàn phím ( mc,md tính theo kg, l tính theo mét), sau đó đa ra màn hình các giá trị vận tốc của viên đạn tính theo giá trị của α. Các giá trị của α đợc cho liên tiếp từ bàn phím, tính theo đơn vị độ cho đến khi vào giá trị a<= 0 thì chơng trình dừng. Yêu cầu vận tốc của đạn tính theo đơn vị mét/giây và lấy 2 chữ số lẻ.
Chơng trình minh hoạ bằng ngôn ngữ TP:
(?): 1) Program Con_lac; 2) Uses Crt;
3) Const g= 9.8;
4) var mc,md,anfa,v,h,k:real; 5)Begin
6) Clrscr;
7) Write(' cho biet khoi luong hop cat (kg);'); readln(mc); 8) Write(' cho biet chieu dai day (met):'); readln(l);
9) Write(' cho biet khoi luong vien dan (kg):'); readln(md); 10) k:=pi/180;
11) Write(' vao goc lech (do), <=0 de ket thuc:'); readln(anfa); 12) While anfa> 0 do
13) If anfa>0 then 14) Begin
15) h:=l*(1-cos(anfa*k));
16) v:= (mc/md+1) *sqrt(2*g*h);
17) Writeln(' van toc cua vien dan la',v:10:2,'(met/giay)'); 18) End;
19) readln; 20)End.
Bài 4.5: Một động cơ ôtô với công suất là P (kw), hiệu xuất của động cơ là h (%) và bình xăng có L(lít). Ôtô chạy hết công suất đợc một quãng đờng là s(km) thì hết xăng.
Hãy lập trình nhập các giá trị P, h, L từ bàn phím và đa ra màn hình giá trị s ứng với vận tốc v của ôtô. Các giá trị v đợc cho liên tiếp từ bàn phím ( theo đơn vị km/giờ) cho đến khi v<=0 thì dừng chơng trình. Biết năng suất toả nhiệt của xăng là 4,6.107 J/kg và khối lợng riêng x của xăng là 700 kg/m3.
Chơng trình minh hoạ bằng ngôn ngữ TP:
(?): 1) Program Cong_suat_oto; 2)Uses Crt; 3)Const q = 4.6E7; 4) x = 700; 5)Var p,l,h,a,m,t,v,s:real; 6)Begin 7) Clrscr;
8) Write('Cong suat cua dong co(kw):'); Readln(p); 9) Write('Hieu suat cua dong co(%):'); Readln(h); 10) Write('Luong xang(lit):'); Readln(l);
11) m:=x*l*1e-3; 12) a:=h*m*q*1e-2; 13) t:=a/(p*3.6e6);
14) Write('Van toc cua oto (km/gio):'); Readln(v);