Rẽ nhánh: Cấu trúc dùng để diễn đạt một việc sẽ được thực hiện khi một điều kiện cụ thể được thỏa mãn. Các từ khóa hay được dùng nhất là “if”, “else”, và “else if”. Ngoài ra, một số ngôn ngữ có thể dùng thêm dạng câu lệnh phân nhánh đặc biệt cho trường hợp có nhiều phân nhánh (thường từ khóa bắt đầu câu lệnh điều kiện kiểu này có thể là “switch” hay là “case”).
Rẽ nhánh bao gồm 2 loại:
- Dạng thiếu: Nếu … thì
Ví dụ: Nếu trời nắng thì chúng ta sẽ đi chơi. Vậy nếu trời không nắng thì chúng ta làm gì còn chưa biết.
- Dạng đủ: Nếu … thì …, nếu không thì.
Ví dụ: Nếu trời nắng thì chúng ta sẽ đi chơi, nếu không thì chúng ta sẽ đọc truyện ở nhà. Vậy nếu trời không nắng chúng ta sẽ ở nhà đọc truyện.
Câu lệnh if-then
- Dạng thiếu: if<điều kiện> then <câu lệnh>;
- Dạng đủ if<điều kiện> then <câu lệnh 1> else <câu lệnh 2>;
47
Trong đó:
- Điều kiện là biểu thức logic.
- Câu lệnh, câu lệnh 1, câu lệnh 2 là một câu lệnh của Pascal.
Ở dạng thiếu: điều kiện sẽ được tính và kiểm tra. Nếu điều kiện đúng (có giá trị true) thì câu lệnh sẽ được thực hiện, ngược lại thì câu lệnh sẽ bị bỏ qua.
Ở dạng đủ: điều kiện cũng được tính và kiểm tra. Nếu điều kiện đúng thì câu lệnh 1 sẽ được thực hiện, ngược lại thì câu lệnh 2 sẽ được thực hiện.
Câu lệnh ghép
Trong nhiều trường hợp, sau một số từ khóa (như then hoặc else) phải là một lệnh đơn. Nhưng trong nhiều trường hợp các thao tác sau những tên dành riêng đòi hỏi không chỉ một mà là nhiều câu lệnh để mô tả. Trong trường hợp như vậy, ngôn ngữ lập trình cho phép gộp một dãy các câu lệnh thành một câu lệnh ghép.
Trong Pascal câu lệnh ghép có dạng:
Begin
<các câu lệnh>; End;
Ví dụ: Viết chương trình tìm nghiệm thực của phương trình bậc hai: ax2 + bx + c = 0 với a ≠ 0.
Mã nguồn gợi ý Pascal:
Program giai_phuong_trinh_bac_2; uses crt; var a, b, c: real; D, X1, X2: real; Begin clrscr; write(‘a,b,c:’); readln(a,b,c); D:=b*b-4*a*c; If D<0 then
writeln(‘Phuong trinh vo nghiem.!’);
48 Else Begin X1:=(-b-sqrt(D))/(2*a); X2:=-b/a-X1; writeln(‘X1 = ’, X1:8:3,’ X2= ’, X2:8:3); End; readln; End. 2.3.5. Cấu trúc lặp
Vòng lặp: Dùng để lặp lại các câu lệnh giống nhau cho các đối tưọng hay các biến trong một số hữu hạn lần. Từ khóa thường gặp nhất trong các ngôn ngữ là “for” và “while”. Cấu trúc lặp mô tả thao tác lặp và có 2 dạng là:
- Lặp với số lần biết trước. - Lặp với số lần chưa biết trước.
Lặp với số lần biết trước và câu lệnh for-do.
Trong Pascal câu lệnh dùng để mô tả lặp với số lần biết trước là câu lệnh lặp for-do với hai dạng tiến và lùi.
- Dạng tiến:
For <biến đếm> :=<giá trị đầu> to <giá trị cuối> do <câu lệnh>;
- Dạng lùi:
For <biến đếm>:= <giá trị cuối> downto <giá trị đầu> do <câu lệnh>; Trong đó:
- Biến đếm: Là biến đơn, thường có kiểu nguyên.
- Giá trị đầu, Giá trị cuối: là các biểu thức cùng kiểu với biến đếm và giá trị đầu phải nhỏ hơn hoặc bằng giá trị cuối. Nếu giá trị đầu lớn hơn giá trị cuối thì vòng lặp không thực hiện.
Cơ chế hoạt động của câu lệnh for-do:
-Ở dạng lặp tiến, câu lệnh viết sau từ khóa do được thực hiện tuần tự, mỗi lần thực hiện thì biến đếm nhận giá trị tăng liên tiếp từ giá trị đầu đến giá trị cuối.
49
-Ở dạng lặp lùi, câu lệnh viết sau từ khóa do được thực hiện tuần tự, mỗi lần thực hiện thì biến đếm nhận giá trị giảm liên tiếp từ giá trị đầu đến giá trị cuối. Ví dụ: Cho số nguyên a và a>2, tính và đưa kết quả ra màn hình tổng của dãy sau:
𝑆 = 1 𝑎+ 1 𝑎 + 1+ 1 𝑎 + 2+ ⋯ + 1 𝑎 + 𝑛; 𝑣ớ𝑖 𝑛 = 100
Thuật toán để giải bài toán như sau:
Bước 1: Gán cho S := 1.0 / a ;
Bước 2: Tăng giá trị N lên 1. N := N+1;
Bước 3: Nếu N > 100 thì chuyển đến bước 5;
Bước 4: S := S + 1.0 / (a + N); quay lại bước 2 (Thao tác lặp ở đây).
Bước 5: Đưa S ra màn hình rồi kết thúc.
- Mã nguồn Pascal dạng lặp tiến:
Program Tongtien; uses crt; var S: real; a, n: integer; begin clrscr;
writeln('hay nhap gia tri cua a '); readln(a); S := 1.0 /a; for N := 1 to 100 do S := S + 1.0/(a + N); writeln('Tong S la: ',S:8:4); readln; end.
- Mã nguồn Pascal dạng lặp lùi:
program Tonglui; uses crt;
50
var S: real; a, n: integer; begin
clrscr;
writeln('hay nhap gia tri cua a '); readln(a);
S := 1.0 / a;
for N := 100 downto 1 do S := S + 1 / (a + N);
writeln('Tinh tong lui-Tong S la:', S:8:4); readln;
end.
Lặp với số lần chưa biết
Trong Pascal mô tả cấu trúc lặp với số lần chưa biết trước như sau: While <điều kiện> do <câu lệnh>;
Trong đó:
- Điều kiện là biểu thức logic.
- Câu lệnh là một câu lệnh đơn hoặc ghép.
Ví dụ: Tìm ước chung lớn nhất của hai số nguyên dương M và N.
Thuật giải cho bài toán tìm ước số chung lớn nhất của 2 số M và N như sau:
Bước 1: Nhập M, N;
Bước 2: Nếu M=N thì lấy giá trị chung này làm ước chung lớn nhất rối chuyển đến bước 5.
Bước 3: Nếu M>N thì M:=M-N ngược lại N:=N-M;
Bước 4: Quay lại bước 2.
Bước 5: Đưa ra kết quả ước chung lớn nhất rồi kết thúc.
program UCLN; uses crt;
var M, N: integer;
51
begin
clrscr;
writeln('Nhap gia tri M va N :'); readln(M, N); while M <> N do if M>N then M := M - N else N := N - M;
writeln('Uoc chung lon nhat la ', M); readln;
end.
2.4. Chương trình dịch
2.4.1. Trình biên dịch
Còn gọi là phần mềm biên dịch, compiler, là một chương trình máy tính làm công việc dịch một chuỗi các câu lệnh được viết bằng một ngôn ngữ lập trình (gọi là ngôn ngữ nguồn hay mã nguồn), thành một chương trình tương đương nhưng ở dưới dạng một ngôn ngữ máy tính mới (gọi là ngôn ngữ đích) và thường là ngôn ngữ ở cấp thấp hơn, như ngôn ngữ máy. Chương trình mới được dịch này gọi mã đối tượng.
Hầu hết các trình biên dịch sẽ chuyển dịch mã nguồn viết trong một ngôn ngữ cấp cao thành mã đối tượng hay ngôn ngữ máy mà có thể được thi hành trực tiếp bởi một máy tính hay bởi một máy ảo. Dù vậy, việc chuyển dịch từ một ngôn ngữ cấp thấp sang một ngôn ngữ cấp cao hơn cũng có thể xảy ra; quá trình này thường được hiểu như là bộ biên dịch ngược nếu nó có thể tái tạo lại một chương trình trong ngôn ngữ cấp cao. Cũng tồn tại các trình biên dịch chuyển đổi từ ngôn ngữ cao này sang ngôn ngữ cao khác, hay là chuyển đổi sang một ngôn ngữ mà nó cần để tiếp tục xử lý về sau; những trình biên dịch như vậy được biết như là bộ biên dịch phân tầng.
Các loại trình biên dịch cho kết quả là mã đối tượng thì một cách cơ bản bao gồm mã máy tăng cường thêm các thông tin về tên vị trí của các ngõ vào và các gọi ngoài (đến các hàm mà không có sẵn bên trong của nó). Một tập hợp của các tập tin đối tượng, mà không hẳn được cung cấp từ cùng một trình biên dịch,
52
thì vẫn có thể được liên kết với nhau để tạo nên các chương trình khả thi cuối cùng cho một người dùng. Dĩ nhiên, để làm được như vậy thì các tập tin đối tượng đó phải được thiết kế chung nhau về dạng thức. Ví dụ của kiểu tập đối tượng này là các tập có đuôi là.obj có thể dùng chung giữa ASM, C/C++, Fortran... hay các tập tin.DLL trong các kiến trúc Windows dùng chung được cho nhiều ngôn ngữ.
2.4.2. Trình thông dịch
Trình thông dịch biên dịch một chương trình nguồn theo từng phân đoạn. Sau đó, thực thi các đoạn mã đã được biên dịch. Hoàn toàn khác với trình biên dịch (biên dịch hoàn toàn rồi mới thực thi chương trình).
Ngôn ngữ thông dịch: Khi một ngôn ngữ lập trình được xác định là thông dịch, chương trình được viết ra khi chạy sẽ được dịch trực tiếp thành mã máy để máy tính thực thi chúng. Khi chương trình chạy đến dòng lệnh nào sẽ chuyển thành mã máy đến đó để máy tính có thể thực thi. Bộ thông dịch thực hiện quá trình thông dịch gọi là interpreter.
Ưu điểm:
-Interpreter dễ hiện thực hơn do bỏ qua việc kiểm tra lỗi và tối ưu code thường được thực hiện trong quá trình compiled.
-Hỗ trợ đa nền tảng.
-Kích thước chương trình thực thi nhỏ hơn. Khuyết điểm:
-Chương trình có độ tin cậy thấp hơn do bỏ qua bước kiểm tra loại bỏ một
số lỗi thường thực hiện trong quá trình compiled. -Source code dễ dàng bị dịch ngược.
-Tốc độ thực thi chậm hơn.
-Tiềm tàng nguy cơ có lỗi do thiếu
Ngôn ngữ biên dịch: Đối với ngôn ngữ biên dịch, chương trình sẽ dịch toàn bộ thành mã máy rồi mới tiến hành thực thi. Bộ biên dịch thực hiện quá trình biên dịch được gọi là compiler.
Ưu điểm:
- Chương trình sau đó được thực thi nhanh hơn.
- Độ tin cậy cao
- Khó bị dịch ngược mã nguồn.
53
Khuyết điểm:
-Khó xây dựng một compiler có tính chính xác cao để chuyển toàn bộ chương trình thành mã máy.
-Mã máy của mỗi nền tảng là khác nhau, khó thực hiện đa nền tảng.
Theo lý thuyết, bất kỳ ngôn ngữ lập trình nào đều có thể được biên dịch hoặc thông dịch. Vậy nên tuỳ vào mục đích và cách xây dựng của những người tạo ra, ngôn ngữ lập trình hoặc có thể thông dịch hoặc biên dịch.
54
CÂU HỎI VÀ BÀI TẬP CHƯƠNG 2
1. Hãy trình bày các phương pháp lập trình, ưu và nhược điểm của từng phương pháp.
2. Hãy trình bày cấu trúc của một chương trình bằng Pascal.
3. Tại sao phải khai báo biến? Hãy giải thích sự khác nhau giữa hằng có đặt
tên và biến.
4. Có mấy loại cấu trúc rẽ nhánh? Trình bày nguyên tắc làm việc của cấu trúc rẽ nhánh đầy đủ. Lấy ví dụ minh họa cho cấu trúc rẽ nhánh đầy đủ.
5. Trình bày cấu trúc lặp for-do. Lấy ví dụ minh họa. 6. Trình bày cấu trúc lặp while-do. Lấy ví dụ minh họa.
7. Chương trình dịch là gì? Tại sao cần phải có chương trình dịch?
8. Hãy trình bày các điểm giống và khác nhau giữa biên dịch và thông dịch? 9. Trình bày thuật toán có sử dụng cấu trúc lặp để tính tổng các số chẵn chia hết cho 3 nằm trong khoảng từ 1 đến 500.
10.Trình bày thuật toán có sử dụng cấu trúc lặp và rẽ nhánh giải bài toán cổ: Trăm trâu, trăm cỏ
Trâu đứng ăn năm Trâu nằm ăn ba Lụ khụ trâu già Ba con một bó
Hỏi mỗi loại trâu đứng, trâu nằm, trâu già có bao nhiêu con?
55
TÀI LIỆU THAM KHẢO CHƯƠNG 2
[1]. Nguyễn Ngọc Cương (Chủ biên) (20135), Giáo trình ngôn ngữ lập trình Pascal (Chương 1), Nhà xuất bản Thông tin truyền thông.
[2]. Vũ Đình Hòa – Đỗ Trung Kiên (2013), Cấu trúc dữ liệu và giải thuật (Chương 2, 3), Nhà xuất bản Đại học Sư phạm.
[3]. Nguyễn Đức Nghĩa, Nguyễn Tô Thành (2009), Toán rời rạc (Chương 2, 4,
5), Nhà xuất bản Đại học Quốc gia Hà Nội
56
CHƯƠNG 3
NGÔN NGỮ LẬP TRÌNH PASCAL
Mục tiêu: Chương này cung cấp cho người đọc tổng quan về các thành phần cơ bản của ngôn ngữ lập trình Pascal như cấu trúc chương trình, cấu trúc dữ liệu, cách khai báo và sử dụng dữ liệu phục vụ chương trình. Tìm hiểu về các cấu trúc điều khiển như cấu trúc rẽ nhánh, cấu trúc lặp... Ngoài ra, một số thành phần không thể thiếu trong ngôn ngữ lập trình là dữ liệu có cấu trúc như mảng dữ liệu, khai thác xâu kí tự và chương trình con...cũng được trình bày chi tiết từ cú pháp, giải thích và ví dụ minh họa cụ thể.
3.1. Tổng quan
3.1.1. Giới thiệu chung
PASCAL là ngôn ngữ lập trình cấp cao được giáo sư Niklaus Wirth ở trường đại học Kỹ thuật Zurich (Thụy sĩ) thiết kế và công bố vào năm 1971. Ông đặt tên cho ngôn ngữ của mình là Pascal để tưởng nhớ nhà toán học nổi tiếng người Pháp ở thế kỷ 17: Blaise Pascal, người đã sáng chế ra chiếc máy tính cơ khí đầu tiên của nhân loại. Qua thời gian sử dụng, Pascal ngày càng được đông đảo người dùng đánh giá cao, và trở thành một trong các ngôn ngữ thảo chương phổ biến nhất hiện nay.
Thành công của ngôn ngữ Pascal là ở chỗ: nó là ngôn ngữ đầu tiên đưa ra và thể hiện được khái niệm lập trình có cấu trúc. Ý tưởng về một chương trình có cấu trúc xuất phát từ suy nghĩ cho rằng có thể chia một bài toán lớn, phức tạp thành nhiều bài toán nhỏ, đơn giản hơn. Nếu mỗi bài toán nhỏ được giải quyết bằng một chương trình con, thì khi liên kết các chương trình con này lại sẽ tạo nên một chương trình lớn giải quyết được bài toán ban đầu?.
Bằng cách chia một chương trình thành các chương trình con như vậy, người lập trình có thể lập trình để giải quyết riêng lẻ từng phần một, từng khối một, hoặc có thể tổ chức để nhiều người cùng tham gia, mỗi người phụ trách một vài khối. Ðặc biệt khi phải thay đổi hay sửa chữa trong một khối thì điều đó sẽ ít ảnh hưởng đến các khối khác.
Tính cấu trúc của ngôn ngữ Pascal còn thể hiện trong việc tổ chức các câu lệnh và tổ chức dữ liệu. Từ các lệnh đã có, người lập trình có thể nhóm chúng lại với nhau và đặt giữa hai từ khóa Begin và End tạo thành một câu lệnh mới phức
57
tạp hơn gọi là câu lệnh ghép. Ðến lượt mình, hai hay nhiều lệnh ghép lại có thể được nhóm lại để tạo thành một câu lệnh ghép phức tạp hơn nữa,.. Tương tự như thế, ngôn ngữ Pascal cũng cho phép xây dựng các kiểu dữ liệu phức tạp hơn từ các kiểu dữ liệu đã có.
Pascal là một ngôn ngữ không chỉ chặt chẽ về mặt cú pháp mà còn chặt chẽ về mặt dữ liệu. Mỗi biến, mỗi hằng tham gia trong chương trình luôn có một kiểu dữ liệu xác định và chỉ nhận những giá trị có cùng kiểu dữ liệu với nó. Ðiều này buộc người lập trình phải nắm chắc cú pháp và luôn chú ý đến tính tương thích của các biểu thức về mặt kiểu dữ liệu. Chính vì thế, soạn thảo mã lệnh bằng ngôn ngữ Pascal là một cơ hội tốt không chỉ rèn luyện tư duy mà còn rèn luyện tính cẩn thận và chính xác.
Mặc dù một số trường học và người dùng không còn giảng dạy và sử dụng ngôn ngữ lập trình Pascal trong đào tạo, nghiên cứu, học tập nhưng nó vẫn là ngôn ngữ dễ học, sử dụng và hiểu về tư duy lập trình. Với văn phạm sáng sủa, dễ hiểu và khả năng đủ mạnh, Pascal được xem là ngôn ngữ thích hợp nhất để giảng dạy ở các trường phổ thông và đại học.
3.1.2. Cấu trúc của một chương trình Turbo Pascal
Chương trình là một dãy các câu lệnh chỉ thị cho máy các công việc phải thực hiện. Cấu trúc chung một chương trình Pasccal đầy đủ gồm ba phần chính :
1. Phần tiêu đề của chương trình
Phần này bao giờ cũng bắt đầu bằng từ khóa Program, sau đó là tên chương trình mang ý nghĩa đặc trưng cho chương trình đó và được kết thúc bằng dấu chấm phẩy “;”
2. Phần khai báo
Phần này có nhiệm vụ mô tả các đối tượng bài toán, mô tả dữ liệu,…để chương trình xử lý. Các phần khai báo tùy thuộc vào từng bài toán khác nhau.
o Khai báo sử dụng thư viện
Uses ... {khai báo sử dụng thư viện chuẩn}
o Khai báo biến