Chương 1: Những chương trình đầu tiênTa bắt đầu bằng việc phân tích một chương trình Pascal đơn giản:1.Program VD_01_01;2.Begin3. Write(Xin chao tat ca cac ban.);4. Readln;5. {Chờ gõ Enter}6.End.Chương 2 : Biến và kiểu dữ liệuTrong chương trình bạn rất hay gặp nhu cầu phải lưu trữ và xử lý những dữ liệu nào đó. Chẳng hạn trong chương trình giải phương trình thì bạn cần phải ghi nhớ các hệ số và tính toán các nghiệm của nó. Các biến(varible) trong Pascal được sử dụng trong trường hợp này.Chương 3 : Các cấu trúc điều khiểnChúng ta sẽ nghiên cứu các cấu trúc điều khiển qua các ví dụ:VD_03_01: Viết chương trình nhập vào từ bàn phím một số tự nhiên rồi kiểm tra xem nó là số chẵn hay lẻ.Phân tích:Những công việc chúng ta sẽ phải làm là:1 Nhập số nguyên n.2 Kiểm tra chẵn lẻ.3 Đưa ra thông báo.
Trang 1Chương 1: Những chương trình đầu tiên
Ta bắt đầu bằng việc phân tích một chương trình Pascal đơn giản:
Để thử nghiệm chương trình, bạn khởi động môi trường lập trình Turbo Pascal
(xin xem ngay Error! Bookmark not defined để biết chi tiết về sử dụng môi trường lập trình Turbo Pascal) rồi soạn thảo, dịch và Error! Bookmark not defined Bạn chú ý không gõ số số dòng, đó là tác giả thêm vào để tiện giải thích
hoạt động của chương trình
Đây là một chương trình Pascal rất đơn giản, chỉ thực hiện mỗi một việc là in ra
màn hình dòng chữ “Xin chào tất cả các bạn” rồi chờ Error! Bookmark not defined (user) nhấn Enter Tuy vậy chúng ta cũng nên phân tích nó:
Dòng 1 của chương khai báo tên của chương trình Khai báo bắt đầu bằng Error! Bookmark not defined (keyword) Program và theo sau đó là một Error! Bookmark not defined dùng để đặt cho chương trình Chương trình trên được
đặt tên là “VD_01_01”
Khai báo Program thường là không cần thiết nên rất ít khi xuất hiện, bạn có thể
bỏ qua trong các chương trình riêng của mình
Dòng 2 và dòng 6 là 2 từ khoá “Begin End.” khai báo nội dung chương trình
Dòng 3 là một câu lệnh của chương trình, write là Error! Bookmark not defined.
trong Pascal dùng để đưa thông tin ra thiết bị ngoài Trong chương trình này câulệnh có ý nghĩa: viết ra màn hình dòng chữ “Xin chao tat ca cac ban”
Dòng 4 là câu lệnh tiếp theo của chương trình, nó chỉ làm mỗi việc là chờ ngườidùng gõ Enter
Dòng 5 là một dòng chú thích Chú thích là những văn bản mà lập trình viên(programmer) thêm vào nhằm mục đích giúp người đọc chương trình dễ hiểu hơn.Chẳng hạn trong trường hợp này là giải thích ý nghĩa của dòng lệnh readln ở trên.Chú thích được đặt giữa cặp ngoặc {} hay giữa cặp (* *) Chú thích giúpchương trình dễ hiểu hơn nhưng không làm tăng kích thước chương trình (vì
Trang 2Turbo Pascal không dịch phần văn bản được đánh dấu là chú thích Vì thế đôi khingười ta đánh dấu chú thích phần chương trình còn sai để kiểm tra các phần khác
mà không cần thiết phải xoá những đoạn chương trình ấy)
Sau quá trình phân tích chúng ta rút ra một số điều sau:
1- Từ khoá Program dùng để khai báo tên chương trình Khai báo đó không nhấtthiết phải có Nếu có thì tên chương trình phải đặt theo các quy tắc đặt tên
2- Nội dung chương trình nằm giữa cặp từ khóa Begin End Chú ý có dấu chấm sau từ End.
3- Đơn vị cấu trúc nên nội dung chương trình là các câu lệnh Đó có thể là cấu trúcđiều khiển, lệnh gọi chương trình con hay lệnh gán trị (chúng ta sẽ nghiên cứu vềchúng trong những phần sau) Mỗi lệnh đều kết thúc bằng dấu ; Chương trìnhthực hiện các câu lệnh tuần tự từ đầu đến cuối
3.1- Lệnh write có thể dùng để viết ra màn hình các câu thông báo Chú ý câuthông báo đặt trong cặp dấu “nháy” trên (' ') Ví dụ 'This is TurboPascal'
3.2- Lệnh readln; (đọc là read-line) sẽ chờ người dùng nhấn Enter rồi mới chạytiếp
4- Chú thích có thể thêm vào chương trình giúp chương trình dễ hiểu hơn Chúthích nằm giữa cặp dấu { } hay giữa (* và *)
5- Tên (identifier) trong Pascal không phân biệt chữ hoa hay chữ thường Chẳnghạn bạn gõ WRITE hay write Pascal đều coi chúng như nhau Tuy nhiên người tathường đặt tên trong Pascal theo cách ngắn gọn, dễ đọc, gợi nhớ (chẳng hạn trongtiếng Anh write có nghĩa là “viết”)…
Cấu trúc của một chương trình Pascal có dạng như sau:
program <tên chương trình>;
<các khai báo>
begin
<nội dung chương trình>
end
Trong đó các khai báo gồm có:
1 khai báo sử dụng unit
2 khai báo hằng số
3 khai báo kiểu dữ liệu
Trang 34 khai báo biến
5 khai báo chương trình con
… (và một số khai báo không phổ biến khác)
Ngoài khai báo unit luôn phải đặt đầu tiên, ngay sau dòng khai báo program, cáckhai báo còn lại có thể đặt trình tự tuỳ ý, không nhất thiết phải giống như thứ tự ởtrên
Nội dung chương trình là dãy các câu lệnh Có các 3 câu lệnh sau:
1 lệnh tính toán biểu thức
2 lệnh gọi chương trình con
3 cấu trúc điều khiển
Các câu lệnh trong chương trình khi chạy sẽ được thực hiện theo trình tự từ đầuđến cuối
Các khai báo và các câu lệnh phân tách nhau bằng dấu ; Nghĩa là phải gõ ; ởcuối mỗi câu lệnh hay khai báo (ngoại trừ trước từ khoá end và else)
Một chương trình đầy đủ có dạng như sau:
program ; { tiêu đề chương trình }
uses ; { khai báo các unit sử dụng}
label ; { khai báo các nhãn}
const ; { khai báo các hằng}
type ; { khai báo các kiểu dữ liệu }
var ; { khai báo các biến}
procedure ; { khai báo chương trình: thủ tục}
Trang 4Chương 2 : Biến và kiểu dữ liệu
Trong chương trình bạn rất hay gặp nhu cầu phải lưu trữ và xử lý những dữ liệu nào đó Chẳng hạn trong chương trình giải phương trình thì bạn cần phải ghi nhớcác hệ số và tính toán các nghiệm của nó Các biến(varible) trong Pascal được sửdụng trong trường hợp này
Biến trong chương trình có thể hiểu là một vùng nhớ có kích thước thích hợp để lưu trữ dữ liệu theo một cấu trúc nào đó Thông tin về cấu trúc ấy tạo ra khái niệm
về kiểu dữ liệu của biến Như vậy kiểu là tập hợp nhiều đối tượng có cấu trúc giống nhau và có thể xử lý theo cùng một cách.
Pascal là ngôn ngữ có cấu trúc về mặt dữ liệu: đó là Pascal cung cấp cho bạn một
số kiểu dữ liệu cơ sở (còn gọi là vô hướng chuẩn) và bạn có thể xây dựng nhữngkiểu dữ liệu mới dựa trên những kiểu dữ liệu đã xác định bằng cách khai báo cấutrúc và các cách thức xử lý chúng
Mỗi biến trong chương trình sẽ chứa 2 thông tin: địa chỉ (là vị trí của nó trong bộnhớ) và giá trị nó đang lưu trữ Địa chỉ của mỗi biến cố định và không thay đổiđược Còn giá trị của nó thì có thể thay đổi được
Cách khai báo biến trong chương trình:
Biến được khai báo sau từ khoá var trong phần khai báo của chương trình (trước
từ khoá begin khai báo bắt đầu nội dung lệnh)
Khai báo biến có dạng:
Trang 5Có những giá trị không thay đổi trong quá trình chương trình chạy, chúng ta có thểcoi chúng là những hằng số và gọi chúng là các hằng (constant) Chẳng hạn 0, 1,
Biểu thức được tạo từ tổ hợp các biến, hằng và phép toán thích hợp
Những kiểu dữ liệu cơ sở của Turbo Pascal:
1.Kiểu nguyên:
Các số nguyên trong máy tính được lưu trữ một cách chính xác và hữu hạn Nghĩa
là tập số nguyên mà máy biểu diễn được chỉ là một tập con của tập các số nguyên
Trang 6Các phép toán thường dùng trên dữ liệu kiểu nguyên:
1- Các phép toán số học +, - , * div và mod Trong đó + (cộng ), - (trừ), * (nhân) làcác phép toán số học thông thường; div, mod là phép chia lấy phần nguyên và sốdư
Bảng sau là thông tin về các kiểu thực trong Turbo Pascal :
Tên Kích thước Khoảng biểu diễn Số chữ số đáng tinReal 6 2,9.10 -39 1,7.10 38 11-12
Single 4 1,5.10 -45 3,4.10 38 7-8
Double 8 5,0.10 -324 1,7.10 308 15-16
Extended 10 3,4.10 -4932 1,1.10 4932 19-20
Trong đó Real được dùng thường xuyên hơn cả nhất Để
sử dụng 3 kiểu còn lại bạn phải đặt đoạn mã sau đầuchương trình: {$E+,N+}
Các phép toán trên kiểu thực:
Kiểu thực cũng có một số phép toán như kiểu nguyên: các phép toán số học, logic.Tuy nhiên có một số lưu ý:
1- Ký hiệu phép chia trong kiểu thực là / (ví dụ : a/b) Không thể áp dụng phép /với kiểu nguyên và phép div, mod với kiểu thực
2- Các biến thực biểu diễn xấp xỉ, vì thế thay vì dùng dấu = để kiểm tra 2 số thựcbằng nhau hay không, bạn kiểm tra xem trị tuyệt đối hiệu của chúng có nhỏ hơngiá trị độ chính xác hay không (a b )
3- Dấu ký hiệu thập phân khi viết hằng số thực là dấu chấm “.” (vì dùng theo quyước hệ Anh-Mỹ, khác với dấu phẩy “,” ta vẫn dùng)
Trang 74- Các số thực có thể viết dạng khoa học: xE+n=x.10n; yE-m=y.10-m Chẳng hạn:2E6=2106=2’000’000; 2.125E-10=2,12510-10…
5- Các hàm sau dùng cho cả 2 kiểu thực và nguyên:
2
sqr
abs
x (x)
x (x)
6- Các hàm sau lấy đối số thực và kết quả là số thực:
x (x) sqrt
x ln (x) ln
e (x)
Quan trọng hơn là các biểu thức logic Chúng được sử dụng rất thường xuyêntrong các cấu trúc điều khiển (ta sẽ gặp trong chương 3)
Các phép toán cho giá trị logic:
Các phép so sánh =, <> ("khác"), <, >, <= ("nhỏ hơn hoặc bằng"), >=("lớn hơnhoặc bằng")…
Biểu thức so sánh thường có dạng <biểu thức 1> <op> <biểu thức 2>trong đó <biểu thức 1> và <biểu thức 2> là các kiểu thức logic cùngkiểu, <op> là một trong các dấu phép toán kể trên
Ví dụ về các biểu thức logic:
(2<3) là một biểu thức logic có giá trị true (đúng)
(4=5) là một biểu thức có giá trị false (sai)
(x<=5), (x<>y) cũng là các biểu thức, giá trị của chúng phụ thuộc giá trị hiệntại của x, y Chẳng hạn nếu lúc ấy x=6 thì (x<=5) có giá trị false
Biểu thức logic phức hợp: ghép các biểu thức logic bằng các phép toán logic tađươc biểu thức phức hợp Các phép toán logic thường dùng:
- Not: là phép toán một ngôi Nếu A là một biểu thức logic thì not A cũng làmột biểu thức logic, có giá trị true nếu A là false và ngược lại
Trang 8Ví dụ: not (a<=5) tương đương với a>5
- And: là phép toán logic 2 ngôi Nếu A, B là 2 biểu thức logic thì (A and B)cũng là một biểu thức logic, sẽ có giá trị true khi cả A, B đều là true (“chỉ đúng khi
cả hai đều đúng”) và là false trong các trường hợp còn lại
Ví dụ:
(x=5) and (x mod 2=1) là true khi x=5;
(x>5) and (x<10) chỉ là true khi 5<x<10…
- Or: cũng là phép toán logic 2 ngôi tương tự như phép and Tuy nhiên phép
or “chỉ sai khi cả 2 cùng sai”
Ví dụ:(x=0) or (x=1) là true khi x=0 hoặc x=1, chỉ sai khi x khác cả 0 và 1.Dùng các phép toán so sánh và logic chúng ta có thể biểu diễn được được các biểuthức đủ phức tạp dùng trong các chương trình của chúng ta
4.Kiểu ký tự:
Ký tự là kiểu dữ liệu phục vụ cho việc lưu trữ thông tin dưới dạng chữ Chẳng hạntên lớp như A, B, C, E…có thể lưu trữ dưới dạng ký tự Hay các chữ số 0, 1, 2,…
có thể in ra màn hình dưới dạng các ký tự
Trong Pascal tên kiểu ký tự là char (viết tắt của character), biểu diễn được 256
ký tự (đánh thứ tự từ 0 đến 255) Các bạn có thể tham khảo mã các ký tự thườnggặp ở phụ lục E
Các hằng ký tự: để viết một hằng ký tự bạn gõ chúng và đặt giữa hai dấu nháy trên(tuy nhiên khi in thì không có các dấu nháy ấy) Chẳng hạn ‘A’ là ký tự biểu diễnchữ cái A, ‘ ’ là ký tự dấu cách, ‘0’ là ký tự biểu diễn chữ số 0… Bạn cũng cóthể viết dạng #n, trong đó n là thứ tự của ký tự Ví dụ #13 là ký tự Enter, #27 là
ký tự Esc, #8 là ký tự Tab, #9 là ký tự Backspace…
Chú ý cách viết 0 và ‘0’: 0 là một hằng nguyên có giá trị 0 còn ‘0’ là ký tự chữ
Trang 93- hàm Upcase đổi chữ hoa Ví dụ Upcase(‘a’)=’A’, Upcase(‘B’) vẫn
là ‘B’…
4- các phép so sánh: =, <>, <, >, <=, >=,… So sánh các ký tự được thực hiện bằngviệc so sánh thứ tự của chúng Ví dụ (‘0’<‘A’) có giá trị true, (A’=#64) có giátrị false
5.Kiểu chuỗi (còn gọi là xâu):
Kiểu ký tự chỉ biểu diễn được một chữ Trong trường hợp dữ liệu lớn, gồm nhiềuchữ (các từ, câu…) chẳng hạn: tên người, địa điểm, dòng thông báo… bạn phải sửdụng kiểu dữ liệu dạng chuỗi Trong Pascal có kiểu String để biểu diễn chuỗi Cáccâu thông báo mà ta viết trong các chương trình ở chương 1 chính là dữ liệu kiểuchuỗi Có thể nói chuỗi là một dãy liên tục các ký tự (tối đa là 255 ký tự, đủ dùngtrong đa số trường hợp)
Các hằng chuỗi được viết giữa hai dấu nháy ‘ ’ Các ký tự đặc biệt không đượcdùng để đặt tên như dấu cách (‘ ’), dấu ‘-’…đều có thể đặt trong nội dung củachuỗi
Ví dụ: ‘Xin chao cac ban’, ‘Turbo Pascal’,…
Để viết dấu nháy ‘ chẳng hạn trong chuỗi “It’s very easy.” các bạn gõ 2dấu nháy liên tục: ‘It’’s very easy’
Các phép xử lý cơ bản trên kiểu chuỗi:
1- hàm length(s) cho lại chiều dài (số ký tự thực sự) của chuỗi s Ví dụlength(‘Pascal’)=6, length(‘Very easy’)=9 (tính cả dấu cách)…2- phép cộng chuỗi: nếu s1, s2 là 2 chuỗi thì s1+s2 sẽ là chuỗi trong đó s2 kếtiếp sau s1 Ví dụ: ‘Hoa ’+‘sen’=‘Hoa sen’
Đó là các kiểu dữ liệu cơ sở thường dùng trong Pascal Trong đó các kiểu nguyên,
ký tự, logic còn gọi là các kiểu đếm được (nghĩa là những phần tử của chúng là rờirạc và có thể đánh số thứ tự được)
6 Các kiểu dữ liệu tự tạo:
Pascal cho phép lập trình viên dựa trên những kiểu dữ liệu cơ sở tạo ra những kiểu
dữ liệu mới Quá trình đó theo hai chiều hướng:
1- thu hẹp khoảng biểu diễn hay thay tên gọi của phần tử ta được kiểu khoảng con
và kiểu liệt kê
Trang 102- xây dựng kiểu mới có thành phần là các kiểu đã biết Ta gọi chúng là kiểu dữ liệu có cấu trúc (chúng gồm kiểu dãy (kiểu mảng: array), kiểu bản ghi (record),kiểu tập hợp(set), kiểu đối tượng (object))…Chúng ta sẽ nghiên cứu chúng trongphần sau.
Khai báo các kiểu dữ liệu tự tạo (custom data type) ta dùng từ khoá type nhưsau:
Ví dụ các các ký tự chữ số gồm 10 phần tử liên tiếp từ ‘0’ đến ‘9’ của kiểu char
Ta khai báo kiểu chu_so như sau:
Type
Chu_so = ‘0’ ‘9’;
Ta thấy rằng mô tả cho một kiểu khoảng con ta viết a b, trong đó a là phần tửđầu tiên, b là phần tử cuối cùng của trong khoảng, dấu là 2 dấu chấm viết liêntiếp (Chú ý trong tài liệu này tác giả không phân biệt “khoảng” và “đoạn” như trong Toán Cả hai đều hiểu là các phần tử liên tiếp từ cận đầu đến cận cuối).Như vậy mô tả kiểu số nguyên từ 1 đến 100 ta viết là 1 100, mô tả kiểu các chữcái Latin hoa ta viết ‘A’ ‘Z’…
Trang 11Ghi nhớ: chỉ có các kiểu dữ liệu đếm được (nguyên, ký tự, logic) là có kiểukhoảng con Không thể mô tả khoảng con của kiểu thực Nếu bạn khai báo mộtkiểu có mô tả: 2.5 3.1 máy sẽ báo lỗi.
Các biến của kiểu khoảng con chỉ được nhận giá trị trong miền đã mô tả, nếukhông máy sẽ báo lỗi
Trang 12Kiểu liệt kê được mô tả bằng các liệt kê tên các phần tử đặt trong cặp ngoặc.Chẳng hạn ta muốn khai báo một kiểu planet mô tả tên các hành tinh trong hệ Mặttrời Ta viết như sau:
Type
Planet=(Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto);
Ghi nhớ: Tên các phần tử của kiểu liệt kê phải viết theo các quy tắc đặt tên
Các thao tác cơ bản trên dữ liệu:
Phần lớn chương trình đều hoạt động theo các bước:
1- Nhập dữ liệu từ phía người dùng
2- Xử lý dữ liệu theo mục đích của chương trình
3- Xuất dữ liệu đã xử lý tới người dùng
Bước 1 và bước 3 còn gọi là “I/O (Input - Output)”, là những bước tuykhông quan trọng nhất nhưng rất cần thiết
Các thao tác nhập - xuất cơ bản:
Trong chương này ta chỉ mới học các kiểu dữ liệu cơ sở nên cũng chỉ nghiên cứucác thao tác nhập - xuất cơ bản với các kiểu dữ liệu cơ sở Đó là thao tác read vàwrite
Read là thao tác nhập dữ liệu (input) cơ bản
Trong trường hợp nhập dữ liệu từ bàn phím thì lệnh read có dạng sau:
Read(<biến>);
Các kiểu dữ liệu có thể nhập bằng read: kiểu nguyên, kiểu thực, kiểu ký tự, kiểuchuỗi
Ví dụ: read(n); read(a); read(c); …
Read không chỉ nhập cho một biến mà có thể nhập cho nhiều biến Bạn chỉ cầnviết dãy biến cách nhau bởi dấu “,”
Ví dụ: 3 lệnh read trên có thể thay bởi một lệnh read(n, a, c);
Máy sẽ ngừng nhập cho một biến và chuyển sang biến tiếp theo nếu gặp các ký tựphân cách:
- với kiểu nguyên và thực: ký tự “cách” (Space), Tab, “xuống dòng” (Enter)
Trang 13- với kiểu String: ký tự “xuống dòng” (Enter).
Riêng kiểu ký tự thì máy sẽ chuyển sang nhập cho biến tiếp theo ngay khi nhậnđược một ký tự, kể cả ký tự phân cách như space, tab, enter
Nếu bạn thay lệnh Read bằng lệnh ReadLn (đọc là read line) thì máy sẽ nhập chođến khi gặp ký tự xuống dòng (do nhấn Enter) Đó là lý do vì sao ở cuối chươngtrình thường có lệnh readln; để chờ người dùng xem kết quả rồi nhấn Enter để kếtthúc chương trình Có thể hiểu readln đơn giản là read rồi xuống dòng
Đó cũng là lý do vì sao khi nhập ký tự hay nhập chuỗi người ta thường chỉ dùng lệnh readln: readln(s);
Write là thao tác xuất dữ liệu (output) cơ bản.
Trong trường hợp xuất dữ liệu ra màn hình thì lệnh write có dạng sau:
<biến> và <biểu thức > cùng kiểu Tuy nhiên có một số ngoại lệ:
1- Biến kiểu thực có thể gán bởi biểu thức kiểu nguyên Điều ngược lại không hợp
lệ, cần phải dùng các hàm làm tròn:
Hàm round(x) cho số nguyên gần x nhất (làm tròn x)
Hàm trunc(x) cho phần nguyên của số thực x
2- Biến kiểu chuỗi có thể gán bởi biểu thức kiểu ký tự Điều ngược lại không hợplệ
Trang 143- Dùng phương pháp chuyển đổi kiểu biểu thức Đây là phương pháp lập trìnhcao cấp, không đề cập ngay được trong chương này.
Chú ý phân biệt lệnh gán (:=) với phép so sánh =, bởi đó là hai dạng khác nhau.Chẳng hạn phép so sánh n = n+1 cho giá trị false còn lệnh n := n + 1; sẽtính biểu thức (n + 1) rồi gán giá trị đó cho n, kết quả là n được tăng thêm một Nếu ta khai báo:
n := ord (a);{gán cho n thứ tự của a -> n =48}
x := n; {gán giá trị của n cho x -> x =48}
s := a; {gán giá trị của a cho s -> s=’0’}
a := chr (n + 8);{gán cho a giá trị của hàm chr(n+8)-> a=’8’}
x := sqr(x) + exp(2);{gán cho x giá trị của x2 +e 2 }
Phép gán thường dùng cho các công việc tính giá trị của các biểu thức.
VD_02_01: Tính chu vi và diện tích hình chữ nhật khi biết 2 cạnh của nó
Phân tích: đây là một bài toán tính toán, dữ liệu vào là 2 cạnh, dữ liệu ra là chu vi
và diện tích Ta sẽ dùng 4 biến kiểu thực là a,b (2 cạnh ) và cv, dt (chu vi và diệntích) Để tính kết quả ta sử dụng các công thức tính chu vi và diện tích hình chữnhật trong hình học
Phần khai báo biến như sau:
var
a, b, cv, dt : real;
Sau đó là phần nhập dữ liệu vào:
write('Nhap do lon 2 canh a,b : ');
readln(a,b);
Ta dùng câu lệnh write viết ra dòng thông báo để người dùng hiểu ý nghĩa của dữ liệu mình sắp nhập.
Trang 15Ta tính giá trị cho cv và dt theo công thức trong hình học:
writeln('Chuong trinh tinh chu vi va dien tich hinh chu nhat.');
write('Nhap do lon 2 canh a,b : ');
Error! Bookmark not defined.
VD_02_02: Lập chương trình đổi inch sang cm biết 1 inch = 2,54 cm
Phân tích: đây cũng là một bài toán tính toán Dữ liệu vào là một độ dài L theo đơn
vị inch, dữ liệu ra là độ dài đó theo đơn vị cm Theo giả thiết ta chỉ việc nhân 2.54với L là được kết quả
Toàn văn chương trình:
program VD_02_02;
var
L : real;
Trang 16writeln('Chuong trinh doi don vi tu inch sang cm.');
write('Nhap do dai (theo don vi inch):');
readln(L);
writeln('Do dai do theo don vi cm la: ', 2.54*L :0:2, ' cm.');
readln;
end.
Error! Bookmark not defined.
Trong câu lệnh write ở trên ta dùng :0:2 trong định dạng output cho biểu thức kiểu thực (2.54*L) Điều đó không có nghĩa là không dành cột nào để ghi nội dung của biểu thức mà là dùng tuỳ ý, đủ để viết hết là được.
VD_02_03: Tính quãng đường đi được s của một vật chuyển động nhanh dần đềukhi biết vận tốc ban đầu v0, gia tốc a và thời gian t
Phân tích: dữ liệu vào là v0, a và t, dữ liệu ra là s Ta tính s theo công thức trongvật lý: s at2 v0t.
Trang 17Chương 3 : Các cấu trúc điều khiển
Chúng ta sẽ nghiên cứu các cấu trúc điều khiển qua các ví dụ:
VD_03_01: Viết chương trình nhập vào từ bàn phím một số tự nhiên rồi kiểm traxem nó là số chẵn hay lẻ
Phân tích:Những công việc chúng ta sẽ phải làm là:
1- Nhập số nguyên n
2- Kiểm tra chẵn lẻ
3- Đưa ra thông báo
Việc nhập số chắc các bạn đã quen Trong chương trình ta dùng biến n kiểuinteger để lưu giá trị của số tự nhiên Khi đó việc đọc số đã cho sẽ được thực hiệnbằng câu lệnh: readln(n);
Việc kiểm tra một số là số chẵn hay lẻ không khó Thật vậy số đó là số chẵn khi vàchỉ khi nó chia cho 2 dư 0 Trong Pascal phép chia dư là phép toán mod (mod chỉ
áp dụng được với số nguyên) Chẳng hạn A, B là 2 biểu thức nguyên thì A mod B
sẽ là số dư của phép chia A cho B
Vấn đề bây giờ chỉ là việc thông báo kết quả Mà kết quả chỉ có thể là một tronghai trường hợp “chẵn” và “lẻ”, phụ thuộc và kết quả của phép toán n mod 2 là 0hay 1
Để xử lý những trường hợp dạng này ta có thể dùng cấu trúc điều khiển if củaPascal
Cấu trúc có dạng đầy đủ như sau:
* if, then, else là các từ khoá (keyword);
* <biểu thức> là một biểu thức có kiểu logic;
* <câu lệnh 1> và <câu lệnh 2> là các câu lệnh Chú ý <câu lệnh1> không được kết thúc bằng dấu ;.
Hoạt động của câu lệnh if như sau:
Trang 181- tính giá trị của <biểu thức>
2- nếu kết quả là true thì <câu lệnh 1> được thực hiện, ngược lại thực hiện
<câu lệnh 2>
Nếu phần else là không cần thiết thì bạn có thể viết lệnh ở dạng khuyết:
if <biểu thức> then <câu lệnh>;
{Nghĩa là nếu <biểu thức> là true thì thực hiện <câu lệnh>.}
Như vậy đoạn chương trình của chúng ta như sau:
Error! Bookmark not defined.
VD_03_02: Viết chương trình giải phương trình bậc nhất ax+b=0
Phân tích: Thuật toán có được theo cách giải trong môn toán:
Nếu a<>0 thì có một nghiệm là x= - b/a,
ngược lại (a=0) thì
Trang 19nếu b<>0 thì vô nghiệm, ngược lại (b<>0) thì có mọi số đều là nghiệm.
Rõ ràng là chúng ta có thể dùng lệnh if, và trong trường hợp này <câu lệnh>của if lại là một lệnh if:
Trang 20VD_03_03: Giải phương trình bậc hai ax2 + bx + c = 0;
Phân tích: Ta cũng có thuật toán theo kiến thức môn toán:
ac 4 b
Δ 2
Nếu <0 thì phương trình vô nghiệm
Nếu =0 thì phương trình có nghiệm kép x 2ba
Nếu >0 thì phương trình có 2 nghiệm x b a
2
2 , 1
“đẹp” hơn là sử dụng cấu trúc câu lệnh phức
Trong chương trình trên trường hợp >0 ta có thể viết như sau:
if d>0 then
begin
x1 := (-b + sqrt(d))/ (2*a);
x2 := (-b/a) - x1; {dùng công thức Vi-et}
writeln('Phuong trinh co 2 nghiem phan biet:'); writeln('x1 = ',x1:0:5);
Trang 21Error! Bookmark not defined.
Thực ra ta không cần tách ra 3 câu lệnh if như ở chương trình trên mà có thể dùngcác lệnh if lồng nhau (câu lệnh của if là một câu lệnh if), chẳng hạn dạng:
Trang 22VD_03_04: Xét học bổng cho học sinh có thể có 4 loại: A (240.000đ), B(180.000đ), C (120.000đ), D (80.000đ) và O (không có học bổng) Cần lập chươngtrình xử lý thông tin về học bổng cho sinh viên: sẽ nhập loại học bổng và số thángđược lĩnh rồi xuất ra tổng số tiền học bổng sinh viên đó nhận được
Chương trình đầu tiên dùng cấu trúc if lồng nhau:
writeln('Chuong trinh tinh hoc bong.');
write('Ban duoc hoc bong loai nao (A,B,C,D) ');
Trang 23Error! Bookmark not defined.
Bạn thấy đấy: với 4 lệnh if lồng nhau, chương trình trông không được đẹp lắm,mặc dù vẫn chạy đúng Ngôn ngữ Pascal có một cấu trúc hay hơn dùng cho trườnghợp này, đó là cấu trúc case Cấu trúc có dạng sau:
case <biểu thức>of
* case, of, end, else là những từ khoá
* <biểu thức> là một biểu thức Error! Bookmark not defined
* <câu lệnh>, <câu lệnh 1>, , <câu lệnh n> là những câulệnh
Nhãn có thể là một biểu thức cùng kiểu, một miền con hay một dãy các nhãn hợp
lệ ngăn cách nhau bởi dấu ,
Câu lệnh thực hiện như sau:
1- Tính giá trị biểu thức
2- Lần lượt so sánh giá trị đó với các nhãn, nếu nhãn nào thoả mãn thì câu lệnhtương ứng được thực hiện rồi chuyển sang câu lệnh tiếp theo
3- Nếu không có nhãn nào thoả mãn thì câu lệnh của else sẽ được thực hiện
Cấu trúc case cũng có dạng khuyết không có else Khi đó nếu không có nhãnnào thoả mãn thì đơn giản là chuyển sang câu lệnh tiếp theo
Chương trình trên được viết lại bằng cấu trúc case như sau, có vẻ trông đẹp hơnnhiều:
program VD_03_05;
var
l : char;
m,t : real;
Trang 24writeln('Chuong trinh tinh hoc bong.');
write('Ban duoc hoc bong loai nao (A,B,C,D) '); readln(l);
write('So thang ban duoc linh: ');
Như vậy ở đây ta sẽ thực hiện công việc tính công thức truy hồi (si = si-1 + i) một
số lần xác định trước (n lần) Cấu trúc for trong Pascal cho có thể dùng trong
Trang 25trường hợp này, tức là khi phải làm một công việc lặp đi lặp lại một số lần định trước.
Cấu trúc for (còn gọi là vòng for) có dạng như sau:
for <biến đếm>:= <biểu thức 1> to <biểu thức 2> do <câu
lệnh>;
Trong đó:
* for, to, do là các từ khoá
* <biến đếm> là một biến có kiểu đếm được (nguyên, kí tự, liệt kê, logic…)
* <biểu thức 1>,<biểu thức 2> là các biểu thức có giá trị cùng kiểu với
<biến đếm>
* <câu lệnh> là một câu lệnh, có thể là câu lệnh đơn hoặc phức
Cấu trúc hoạt động như sau:
1- tính giá trị <biểu thức 1> và <biểu thức 2>
2- nếu <biểu thức 1> lớn hơn <biểu thức 2> thì chuyển sanglệnh tiếp theo
3- gán <biến đếm> bởi giá trị <biểu thức 1>
4- thực hiện <câu lệnh>
5- nếu <biến đếm> bằng <biểu thức 2> thì thoát khỏi vòng lặp,ngược lại thì gán <biến đếm> bằng giá trị tiếp theo của nó (<biếnđếm>:=succ(<biến đếm>)) và quay lại bước 4
Như vậy đoạn chương trình tính tổng có thể viết như sau:
Toàn văn chương trình:
program VD_03_06;
var
n, s, i : integer;
begin
Trang 26writeln('Chuong trinh tinh tong cac so tu 1 den n.');
Error! Bookmark not defined.
Ta xem xét một ví dụ khác dùng lệnh for rất hiệu quả:
VD_03_07: Dãy số Fibônaxi được định nghĩa như sau:
1 f 1, f
2 n 1 n
2 1
Viết chương trình in ra các số Fibônaxi với từ 1 đến 20
Phân tích: Ta dễ dàng tìm ra cách tính: cho i chạy từ 3 đến 20 rồi tính fi theo địnhnghĩa: fi=fi-1+fi-2 Đặt biến f0, f1, f2 đại diện cho fi, fi-1, fi-2 ứng với mỗi giátrị của i, thế thì ta có thể viết đoạn chương trình tính như sau:
Rõ ràng cách tính này đơn giản hơn sử dụng công thức tổng quát rất nhiều: (
5 1 2
5 1
5
1
Trang 27Toàn văn chương trình:
Error! Bookmark not defined.
Qua những ví dụ trên có thể thấy rằng cấu trúc for rất hữu hiệu khi tính các côngthức truy hồi với số lần biết trước Phần lớn các bài tập cho cấu trúc for đều có thểthiết lập công thức truy hồi Chúng ta cần tinh ý nhìn ra được công thức Ta sẽxem xét một số dạng cơ bản:
VD_03_08: Tính an với a là số thực và n là số nguyên dương
Phân tích: Trong chương 2 ta đã biết tính ab với a là số thực dương và b bất kỳtheo công thức ab eblna exp (b * ln(a)) Tuy nhiên công thức không thể tính khia0 Ta tính bằng cách khác như sau:
Với n nguyên dương đặt tn = an , ta có công thức truy hồi sau:
a t t
1 t
1 n n 0
Như vậy cho i chạy từ 1 đến n và tính công thức trên ta sẽ tính tn Cấu trúc fordùng cài đặt rất thích hợp
Trang 28Đoạn chương trình như sau:
an Ta thông báo kết quả
Toàn văn chương trình:
Error! Bookmark not defined.
VD_03_09: Lập trình tính giai thừa của một số nguyên n (do giới hạn lưu trữ sốnguyên cho n<8)
Phân tích: Giai thừa của n: n! = 1.2…n (tích các số tự nhiên từ 1 đến n) Không cócông thức tổng quát để tính n! nhưng ta có công thức truy hồi sau:
1
! 0
Đặt gn=n!, theo công thức trên ta có:
n g g
1 g
1 n n 0
Và như vậy tương tự VD_03_06 và VD_03_08 ta cũng có chương trình tính nhưsau:
Trang 29Error! Bookmark not defined.
VD_03_10: Tính gần đúng số e theo công thức chuỗi: n!1
3!
1 2!
1 1!
1 1
e với nnguyên nhập từ bàn phím
Phân tích: Ta có thể dựa trên chương trình tính giai thừa ở trên để tính một cáchtường minh theo công thức trên Tuy nhiên cách ấy không ổn vì hàm giai thừa tăngrất nhanh theo n, nếu n quá lớn thì không thể tính được
3!
1 2!
1 1!
e
n r n
1 r
r
1.
r 1, e
n 1
n n
-1 n 1
n n
-0 0
Và từ đó ta có thể viết đoạn chương trình tính dùng vòng lặp for như sau:
Trang 30Error! Bookmark not defined.
VD_03_11: Tính sin1cos1 sin2cos2 sinn cosn
sin2 sin1
cos2 cos1 sin1
r t t
0 t
Như vậy chỉ cần tính rn nữa là xong Cách đơn giản là dùng thêm một vòng lặp fornữa để tính lần lượt tử và mẫu (tính tổng lặp tương tự VD_03_06)
sin1 s
cosn cos2
cos1 c
n n
thì ta lại được công thức truy hồi sau:
s
r
sinn s
s
cosn c
c
0.
s 0, c
n n
1 - n n
1 - n n
0 0
Từ đó ta có đoạn chương trình tính như sau (cách đặt tên biến và tính công thứctruy hồi tương tự các ví dụ trên, có lẽ không cần giải thích thêm):
Trang 31Toàn văn chương trình:
VD_03_12: Tính 5 10 5n với n là một số tự nhiên nhập từ bàn phím
Phân tích: đặt si 5i 5(i 1) 5n ta có công thức truy hồi sau, chú ý là nó hơikhác những công thức ta đã biết:
Trang 33Như cấu trúc if, cấu trúc for cũng có thể lồng nhau được (nói chung ta có thể viết
<câu lệnh> của for là bất cứ cấu trúc điều khiển nào) Ta áp dụng vào mộtvấn đề nhỏ:
VD_03_13: In ra bảng cửu chương như dạng sau:
2x1= 2 2x2= 4 2x3= 6 2x4= 8 2x5=10 2x6=12 2x7=14
2x8=16 2x9=18 3x1= 3 3x2= 6 3x3= 9 3x4=12 3x5=15 3x6=18 3x7=21
3x8=24 3x9=27 4x1= 4 4x2= 8 4x3=12 4x4=16 4x5=20 4x6=24 4x7=28
4x8=32 4x9=36 5x1= 5 5x2=10 5x3=15 5x4=20 5x5=25 5x6=30 5x7=35
5x8=40 5x9=45 6x1= 6 6x2=12 6x3=18 6x4=24 6x5=30 6x6=36 6x7=42
6x8=48 6x9=54 7x1= 7 7x2=14 7x3=21 7x4=28 7x5=35 7x6=42 7x7=49
7x8=56 7x9=63 8x1= 8 8x2=16 8x3=24 8x4=32 8x5=40 8x6=48 8x7=56
8x8=64 8x9=72 9x1= 9 9x2=18 9x3=27 9x4=36 9x5=45 9x6=54 9x7=63
Trang 34readln;
end.
Error! Bookmark not defined.
Giải thích: câu lệnh for đầu tiên cho i chạy từ 2 đến 9, với mỗi i lại cho j chạy từ 1đến 9 và in ra tích i*j Câu lệnh write (dòng 8) thực hiện việc in ra tích i*j: đầutiên in dấu cách chiếm 2 cột (để phân cách giữa các cột của bảng), in i, in dấu , in
j, in dấu =, in tích i*j chiếm trên 2 cột (để căn lề phải) In hết các tích của i thìxuống dòng (lệnh writeln dòng 9) để được output dạng bảng
Đây là một cách viết output dạng ma trận, các bạn nên ghi nhớ vì có nhiều bài tập sau này yêu cầu điều này.
Một ứng dụng khác rất thú vị của cấu trúc for là tìm nghiệm nguyên của phươngtrình vô định
VD_03_14: Lập trình giải bài toán cổ: “Trăm trâu trăm cỏ, trâu đứng ăn 5, trâunằm ăn 3, lải nhải trâu già 3 con 1 bó Hỏi bao nhiêu trâu đứng, trâu nằm, trâugià”
Phân tích: đặt td là số trâu đứng, tn là số trâu nằm, tg là số trâu già thoả mãn bàitoán Thế thì td, tn, tg là các số nguyên dương thảo mãn:
tg tn
3
td
5
100 tg
tn
td
Từ phương trình thứ hai ta có 5td100 và 3tn100, suy ra 1 td 20 và 1 tn 33
Số trâu già: tg=(100-td-tn) phải chia hết cho 3 (vì số bó cỏ bọn trâu già ăn là sốnguyên, bằng tg div 3)
Như vậy ta cần tìm các số td trong khoảng 1 20 và tn trong khoảng 1 33 sao cho:
tg =(100 - td - tn) chia hết cho 3 và 5*td + 3*tn + tg div 3 = 100
Toàn văn chương trình:
Trang 35Error! Bookmark not defined
Qua những ví dụ trên ta thấy cấu trúc for rất có hiệu quả trong việc giải quyết cácvấn đế có tính lặp Tuy nhiên không phải vấn đề nào có tính lặp đều có thể xử lýmột cách hiệu quả bằng cấu trúc for Ta xét một ví dụ:
VD_03_15: Turbo Pascal đã có hàm exp để tính ex, tuy nhiên ex có thể tính theocông thức khai triển chuỗi sau:
n!
x
3!
x 2!
x x 1
e x 2 3 n
Lập trình nhập số thực x rồi tính ex với độ chính xác ep=10-6
Phân tích: dựa trên kinh nghiệm ở VD_03_10, ta xây dựng công thức truy hồi nhưsau:
Đặt:
n!
x
3!
x 2!
x x 1
sn 2 3 n và
n!
x r
n n
-1 - n n
0 0
r s
.x r
r
1 r
1, s
Và exsn khi rn<ep
Nếu giải quyết bằng cấu trúc for thì ta cần tìm số n sao cho rn<ep với mọi x (đểxác định số lần lặp) Tuy nhiên điều này không dễ dàng vì rn phụ thuộc vào x nênkhông thể tìm được giá trị n chung cho mọi x Trong trường hợp này cấu trúc lặp
có điều kiện hợp lý hơn
Cấu trúc lặp điều kiện sau của ngôn ngữ Pascal có dạng:
repeat
<câu lệnh>;
until <biểu thức>;
Trang 36Trong đó:
* repeat, until là từ khoá;
* <câu lệnh>; là một hay nhiều câu lệnh cách nhau bởi dấu ;
* <biểu thức> là một biểu thức logic
Cấu trúc hoạt động như sau:
1- thực hiện các câu lệnh giữa hai từ khoá repeat until
Trang 37Error! Bookmark not defined
Chúng ta xem xét một ví dụ nữa dùng cấu trúc repeat rất hiệu quả:
VD_03_16: Dân số hiện nay khoảng 75 triệu, tỉ lệ tăng tự nhiên là 1.7% Hỏi saubao nhiêu năm nữa thì dân số đạt xấp xỉ 100 triệu?
Phân tích: đặt snlà dân số (tính theo đơn vị triệu) sau n năm tính từ thời điểm hiệntại Ta có:
Và n là số năm cần tìm nếu n là số tự nhiên bé nhất thoả mãn sn100
Ta thấy rằng để tính trực tiếp n thì không dễ dàng nhưng chúng ta có thể sử dụngphương pháp lặp Nghĩa là chúng ta tăng dần n (bắt đầu từ 0) và tính sn theo côngthức trên cho đến khi sn100
Đoạn chương trình như sau:
Trang 38Error! Bookmark not defined
Ngoài cấu trúc lặp điều kiện sau (nghĩa là thực hiện xong câu lệnh rồi mới kiểmtra điều kiện, kiểu “tiền trảm hậu tấu”), ngôn ngữ Pascal còn cấu trúc lặp điều kiệntrước (kiểm tra rồi mới làm) có dạng như sau:
while <biểu thức> do <câu lệnh>;
Trong đó:
* while, do là các từ khoá;
* <biểu thức> là một biểu thức logic;
* <câu lệnh> là một câu lệnh Chú ý là chỉ có một câu lệnh mà thôi Nếu bạn muốn thực hiện nhiều câu lệnh thì phải gom chúng thành một câu lệnh phức.
Cấu trúc hoạt động như sau:
Trang 39Hay đoạn chương trình tính của VD_03_16:
while s<100 do begin
n := n + 1;
s := s + s*1.7%;
end
Tuy nhiên tác giả thích viết bằng repeat hơn vì không cần viết câu lệnh phức
Một ứng dụng rất cần thiết của các cấu trúc lặp (còn gọi là các vòng lặp) là việc
kiểm tra dữ liệu khi nhập Trong những chương trình trước chúng ta không hềkiểm tra rằng dữ liệu người dùng đưa vào đã chính xác chưa Chẳng hạn ở chươngtrình VD_03_09 chúng ta yêu cầu nhập giá trị n tự nhiên nhỏ hơn 8, nhưng rất cóthể người dùng không thực hiện điều ấy (nhập vào 10 hay -1) Khi đó chương trình
sẽ chạy sai và máy báo lỗi (bạn hãy Error! Bookmark not defined mà xem) Vì
thế chúng ta cần kiểm tra điều kiện 0<n<8 Ta có thể kiểm tra như sau:
1- Nhập n
2- Kiểm tra điều kiện 0<n<8
3- Nếu không thoả mãn thì nhập lại
Ta thấy rằng ở đây việc “nhập n” và “kiểm tra 0<n<8” là lặp đi lặp lại, số lần lặp ởđây không xác định được trước nên có thể dùng vòng lặp repeat (hay while) để càiđặt Tác giả viết bằng repeat:
repeat
readln(n);
if not ((n<8) and (n>0)) then
writeln(‘Yeu cau 0<n<8 nhap lai!’);
Trang 40if not ((n<8) and (n>0)) then
writeln('Yeu cau 0<n<8 Nhap lai.');
Error! Bookmark not defined
Nhận xét: trong chương trình trên ta thấy phải kiểm tra dữ liệu những 2 lần (một ởcâu lệnh if, một ở until) Người ta còn có cách viết hiệu quả hơn như sau:
Continue và break giúp việc lập trình đơn giản và gọn gàng hơn rất nhiều Taxét một ví dụ rất thường gặp:
VD_03_17: Kiểm tra một số nguyên n có phải là số nguyên tố hay không