Mỗi thuật toán cần được biểu diễn sao cho người khác hoặc máy tính có thể hiểu và thực hiện được. Người ta thường diễn tả thuật toán sử dụng một trong các ngôn ngữ
sau:
- Ngôn ngữ tự nhiên (Liệt kê các bước thực hiện) - Ngôn ngữlưu đồ(Sơ đồ khối)
36
3.3.1Ngôn ngữ tự nhiên
Với cách biểu diễn này, người ta sử dụng một loại ngôn ngữ tự nhiên (tiếng việt, tiếng anh, …) để liệt kê từng bước thực hiện của thuật toán. Cách biểu diễn này đơn
giản, không đòi hỏi người viết và người đọc thuật toán phải nắm các kí hiệu và qui tắc. Tuy vậy, phương pháp này thường dài dòng, không thể hiện rõ cấu trúc của thuật toán, câu chữ mang nhiều ý nghĩa khác nhau nên dễ gây hiểu lầm.
3.3.2Ngôn ngữlưu đồ(Sơ đồ khối)
Ngôn ngữlưu đồ là một dạng sơ đồ biểu diễn trực quan luồng dữ liệu được xử lí trong hệ thống. Khi người đọc nhìn vào sơ đồ có thể thấy rõ các thao tác được thực hiện như thế nào và trình tự của chúng trong một hệ thống. Chính vì vậy, sơ đồ khối là một công cụ rất hữu dụng để diễn đạt thuật toán.
Sơ đồ khối sử dụng một số ký hiệu hình học sau để diễn đạt:
Bảng 3.1 – Các ký hiệu hình học trong sơ đồ khối
Ví dụ: Biểu diễn thuật toán tìm giá trị lớn nhất của một dãy số nguyên a gồm N số: a0, a1, a2,…, aN-1
37 Người ta thường sử dụng sơ đồ khối trong giai đoạn đầu của việc xây dựng giải pháp để giải quyết bài toán. Nó giúp cho lập trình viên hiểu được tính logic của những bài toán phức tạp, cũng như giúp họ phân tích vấn đề hiệu quảhơn. Ngoài ra, nó còn
được sử dụng để gỡ lỗi chương trình. Tuy vậy, nó cũng có một sốnhược điểm là phải vẽ nhiều làm mất thời gian, và nó sẽ trở nên quá cồng kềnh với các bài toán phức tạp.
Đôi khi, một chút thay đổi trong các giải pháp có thể yêu cầu vẽ lại toàn bộsơ đồ.
3.3.3Mã giả
Mã giả là một ngôn ngữ gần giống với ngôn ngữ lập trình. Nó sử dụng kết hợp ngôn ngữ tự nhiên, các ký hiệu toán học, và vay mượn một số cấu trúc của một ngôn ngữ lập trình nào đó để thể hiện thuật toán. Mã giảgiúp cho người thiết kế và lập trình viên tập trung vào logic của thuật toán mà không cần quan tâm đến các chi tiết của cú pháp ngôn ngữ. Vì là mã giả nên nó không thểđược thực thi trên máy tính và không có tiêu chuẩn chung trong việc viết mã giả. Mỗi tác giả có phong cách viết cho riêng mình, miễn là trình bày rõ ràng và họ thường kèm theo chú thích về cú pháp được sử
dụng.
Các cấu trúc thường gặp trong mã giảnhư:
- Cấu trúc lựa chọn
if(điều kiện) then (hành động)
else (hành động) - Cấu trúc lặp
38 Ví dụ 1: Tìm số lớn nhất trong hai số a và b Ví dụ 2: In ra các số từ1 đến 5 Nhập giá trị a, b; if (a ≥ b) then Xuất kết quả: số lớn nhất là a; else Xuất kết quả: số lớn nhất là b; a = 1; while (a != 6) do Xuất giá trị a; a = a + 1; 3.4 Các cấu trúc cơ bản
Các nhà khoa học máy tính đã đưa ra 3 cấu trúc cơ bản để xây dựng thuật toán và
chương trình có cấu trúc gồm: cấu trúc tuần tự, cấu trúc rẽ nhánh và cấu trúc lặp. Việc sử dụng các cấu trúc này sẽlàm cho chương trình hoặc thuật toán trở nên dễ hiểu, dễ
gỡ lỗi và dễthay đổi.
3.4.1Cấu trúc tuần tự
Cấu trúc tuần tự là một cấu trúc cơ bản nhất. Trong cấu trúc tuần tự, các bước
được thực hiện theo một trình tự tuyến tính từ trên xuống, hết bước này đến bước khác. Mỗi bước thường thực hiện một trong sốcác thao tác cơ bản như: nhập dữ liệu, xuất kết quả, thực hiện các phép toán số học và phép gán. Sơ đồ khối thể hiện cấu trúc tuần tự: Ví dụ 1: Tính S = 2 2 y x C By Ax , trong đó x, y ≠ 0. - Input: A, B, C, x, y - Output: giá trị S
39
Ví dụ 2: Tính tổng trung bình của 3 số nguyên a, b, c. - Input: 3 số nguyên a, b, c
- Output: tổng trung bình của 3 số
3.4.2Cấu trúc rẽ nhánh
Trong một số thuật toán, việc thực hiện các bước cần phải được chọn lựa dựa vào một điều kiện xác định. Điều kiện ở đây là một biểu thức logic, có hai giá trị là true (T) và false (F). Tùy thuộc vào kết quả kiểm tra điều kiện mà việc thực hiện thuật toán có thể rẽ theo một trong hai nhánh khác nhau. Trong cấu trúc rẽ nhánh, ngoài các thao
tác cơ bản như trong cấu trúc tuần tự, nó còn thực hiện thao tác so sánh hai giá trị.
40
Cấu trúc rẽ nhánh có thể được biểu diễn bằng sơ đồ khối trong hai trường hợp sau:
Ví dụ 1: Vẽsơ đồ thuật toán để giải phương trình ax + b = 0 - Input: hệ số a, b
- Output: nghiệm x của phương trình
41
3.4.3Cấu trúc lặp
Cấu trúc lặp là cấu trúc cho phép một hoặc một chuỗi các tác vụ/hành động được thực hiện lặp lại nhiều lần. Trong đó, số lần lặp phải là hữu hạn và có thể xác định hoặc không xác định trước. Vòng lặp với số lần lặp không xác định sẽ dừng khi điều kiện kết thúc thỏa mãn. Nhưng người thiết kế thuật toán phải chắc chắn rằng điều kiện kết thúc sẽ được thỏa mãn sau một số hữu hạn lần lặp, nếu không sẽ gây ra vòng lặp chạy vô hạn và thuật toán không kết thúc được. Điều kiện kết thúc có thể được xét
trước hoặc sau khi thực hiện mỗi vòng lặp để quyết định có tiếp tục vòng lặp tiếp theo hay không.
Cấu trúc lặp có thểđược biểu diễn bằng sơ đồ khối như sau:
42
Ví dụ 1: Tính tổng S = 1 + 2 + … + N. - Input: giá trị N
- Output: tổng S
Mô tả thuật toán:
Bước 1: Nhập giá trị cho N Bước 2: Kiểm tra giá trị N > 0
o Nếu điều kiện sai thì quay lại bước 1
o Nếu điều kiện đúng thì chuyển sang bước 3 Bước 3:
o Khởi tạo biến S = 0
o Sử dụng biến chạy i đểđiều khiển vòng lặp. Giá trị của nó sẽ thay đổi qua mỗi vòng lặp và thường được dùng để quyết định kết thúc vòng lặp. Vì tổng S được tính từ1 đến N nên ta sẽ khởi tạo i = 1
Bước 4: Kiểm tra điều kiện i <= N
o Nếu điều kiện đúng thì thực hiện gán S = S + i, và tăng giá trị của i: i = i + 1, rồi quay vềđầu bước 4.
o Nếu điều kiện sai: chuyển sang bước 5 Bước 5: xuất giá trị tổng S
43
Ví dụ 2: Cho số tự nhiên N. Tính N!. - Input: giá trị N
- Output: giai thừa của N
Mô tả thuật toán:
Bước 1: Nhập giá trị cho N Bước 2: Kiểm tra điều kiện N < 0
o Nếu điều kiện sai thì chuyển sang bước 3
o Ngược lại, xuất “N phải là một số không âm”, rồi kết thúc thuật toán Bước 3: GT = 1, i = N
Bước 4: Kiểm tra điều kiện i > 1
o Nếu điều kiện đúng thì thực hiện gán GT = GT*i, và giảm giá trị của i: i = i - 1, rồi quay vềđầu bước 4.
o Nếu điều kiện sai: chuyển sang bước 5 Bước 5: Xuất giá trị GT
44
BÀI TẬP CHƯƠNG 3
Hãy vẽsơ đồ khối để biểu diễn thuật toán giải quyết các bài tập sau đây:
Bài 1. Tính P(n) = 1.3.5…(2n+1), với n ≥ 0
Bài 2. Cho n là sốnguyên dương, x là số thực. Tính tổng:
a. S(n) = ix i x i n i sin 1 2 1 2 1 b. S(n) = 1 2 1 ... 5 1 3 1 1 n
Bài 3. Cho một năm bất kỳnào đó. Kiểm tra xem năm này có phải là năm nhuận hay không? Biết rằng, năm nhuận là năm chia hết cho 4 nhưng không chia
hết cho 100 hoặc là chia hết cho 400.
Bài 4. Cho 3 cạnh a, b, c. Kiểm tra xem có tồn tại tam giác được tạo thành từ 3 cạnh này không? Nếu có, hãy tính diện tích của tam giác.
Bài 5. Tìm tất cả các số lẻ nằm trong đoạn từ0 đến 1000.
Bài 6. Cho một dãy số nguyên a0, a1, a2,…, an-1. Tính trung bình cộng các số chia hết cho 3.
Bài 7. Cho số nguyên n. Tính trị tuyệt đối của n.
Bài 8. Trong trang trại của một nông dân có nuôi một số gà và dê. Biết rằng, có tất cả43 đầu và 108 chân. Hỏi trang trại có bao nhiêu con gà và bao nhiêu con dê?
Bài 9. Tính lương của nhân viên dựa vào lương_theo_ngày và số_ngày_công
như sau:
lương = lương_ theo_ngày * số_ngày_công
Nếu số_ngày_công > 25, thì sốngày làm dư sẽđược tính lương gấp đôi.
Bài 10. Nhân viên của một siêu thị thực hiện sắp xếp N quả trứng (N > 0) vào trong từng hộp, mỗi hộp có 12 quả trứng. Hỏi có bao nhiêu hộp trứng và bao nhiêu trứng còn dư?
Ví dụ: với 43 quả trứng, nhân viên sẽ sắp xếp được 3 hộp trứng và còn thừa lại 7 quả trứng.
45
PHẦN 2
46
MỞ ĐẦU
Máy tính là một công cụ hỗ trợ cho con người để giải quyết các bài toán một cách nhanh chóng và chính xác. Quá trình giải quyết một bài toán bất kì nào đó trên máy tính đều phải trải qua những bước cơ bản như phân tích và xác định vấn đề, thiết kế thuật toán, lập trình, kiểm thử kết quả. Trong đó, lập trình là khâu chuyển đổi các
bước trong thuật toán thành những chỉ thị (lệnh) mà máy tính có thể hiểu và thực thi
được. Khi lập trình, lập trình viên sẽ biên soạn mã nguồn, biên dịch mã nguồn thành
chương trình, thực thi (chạy) chương trình. Mã nguồn của chương trình phải được viết bằng các ngôn ngữ lập trình. Giống như tất cả các ngôn ngữ mà con người sử dụng, ngôn ngữ lập trình cũng bao gồm một tập hợp các kí tự, các từ và các quy tắc về cú pháp. Ngôn ngữ lập trình thường được chia làm 3 loại:
Ngôn ngữ máy/mã máy (machine language): là một loại ngôn ngữ lập trình mà mọi chỉ thịđều được biểu diễn bằng chuỗi số nhị phân 0 và 1. Đây là ngôn
ngữ thế hệ đầu tiên. Tuy khó đọc, khó sử dụng, và phụ thuộc nhiều vào phần cứng của máy tính, tuy nhiên ưu điểm của ngôn ngữ máy là được máy tính thực thi một cách trực tiếp.
Ngôn ngữ bậc thấp (assembly language): là ngôn ngữ thuộc thế hệ thứ hai,
được thiết kế gần gũi hơn với con người bằng cách sử dụng các kí tự và từ có tính gợi nhớđể thay thế các chữ số nhịphân. Tuy nhiên, chương trình được viết bằng ngôn ngữ bậc thấp vẫn còn liên quan chặt chẽđến kiến trúc của máy tính nên chỉthường được sử dụng để viết những chương trình nhỏ, cần tối ưu bộ nhớ
và thời gian xử lí.
Ngôn ngữ bậc cao (high-level language): gần với ngôn ngữ tự nhiên nhất, giúp cho việc lập trình trởnên đơn giản hơn nhiều. Khác với ngôn ngữ máy và ngôn ngữ bậc thấp, chương trình viết bằng ngôn ngữ bậc cao có thể chạy được trên nhiều máy tính khác nhau. Hiện nay, có rất nhiều ngôn ngữ bậc cao đã được phát triển và sử dụng phổ biến như Pascal, C/C++/C#, Visual Basic, Java,
Python,…
Trong ba loại ngôn ngữ trên, chỉ có ngôn ngữ máy là ngôn ngữ duy nhất mà máy tính có thể hiểu được. Vì thế, một chương trình được viết bằng ngôn ngữ bậc thấp hoặc bậc cao đều phải được biên dịch sang ngôn ngữ máy. Công cụ thực hiện biên dịch
được gọi là chương trình dịch.
Trong môn học này, C được chọn làm ngôn ngữ thể hiện. Đây là ngôn ngữ cơ
bản, được sử dụng rộng rãi ở khắp nơi và là nền tảng cho người học tiếp tục tìm hiểu những ngôn ngữ khác.
47
Chương 1
TỔNG QUAN VỀ NGÔN NGỮ LẬP TRÌNH C 1.1 Giới thiệu ngôn ngữ C
1.1.1Lịch sử phát triển
C là một ngôn ngữ lập trình cấu trúc do Brian W.Kernighan và Dennis Ritchie phát triển từđầu những năm 1970 và hoàn thành vào năm 1972. Nó có nguồn gốc từ
ngôn ngữ BCPL và ngôn ngữ B. Ban đầu, ngôn ngữC được phát triển để viết HĐH,
sau đó nó đã được sử dụng rộng rãi để viết nhiều ứng dụng như xửlí văn bản, xử lí dữ
liệu, đồ họa.
Năm 1978, cuốn sách “The C Programming Language” được xuất bản lần đầu tiên để giới thiệu ngôn ngữ C. Trong những năm 1980, việc sử dụng C lan truyền rộng rãi, trình biên dịch C đã có sẵn ở hầu hết các máy tính và HĐH. Tuy nhiên, với sự lan truyền mạnh mẽ thì ngôn ngữ C bắt đầu bịthay đổi, bổ sung một số tính năng mới và bỏđi một sốtính năng cũ sao cho phù hợp với từng nền tảng riêng. Vì thế, ngôn ngữ C tồn tại dưới nhiều phiên bản khác nhau.
Mùa hè năm 1983, việc chuẩn hóa ngôn ngữC đã bắt đầu được phát triển dưới sự điều hành của Viện tiêu chuẩn quốc gia Hoa Kỳ (American National Standards
Institute -ANSI). Đến năm 1989, phiên bản chuẩn hóa ANSI C đã được hoàn thành và công bố trong lần xuất bản thứ hai của cuốn “The C Programming Language”. Trong phiên bản chuẩn hóa quy định các thư viện chuẩn cho ngôn ngữ C với đầy đủ các hàm
dùng để thực hiện chức năng xuất/nhập dữ liệu, quản lý bộ nhớ, xử lí chuỗi,… Tất cả
các phiên bản của ngôn ngữ C hiện nay đều tuân theo các mô tả trong chuẩn ANSI C, sự khác biệt chủ yếu giữa chúng là nằm ở việc đưa vào một số thư viện bổ sung vào
thư viện chuẩn của C.
C không phải là một ngôn ngữ mạnh, nhưng nó có tầm ảnh hưởng rất lớn đến các ngôn ngữ hiện đại khác như C++, C#, Objective-C, Java, Perl, Python,… Những ngôn ngữ này đều kế thừa hoặc vay mượn nhiều tính năng từ ngôn ngữ C. Chẳng hạn như,
C++ bao gồm tất cả các tính năng của ngôn ngữ C và bổ sung thêm một số tính năng khác để hỗ trợ lập trình hướng đối tượng. Vì vậy, C được xem như là một ngôn ngữcơ
bản mà tất cả các lập trình viên đều nên biết.
1.1.2Đặc điểm của ngôn ngữ C
Ngôn ngữ C có những đặc điểm cơ bản sau:
- Là một ngôn ngữ lập trình đa dụng, bậc cao nhưng hỗ trợ khảnăng lập trình bậc thấp, ví dụ như thao tác trên bit và trên địa chỉ. Vì thế, nó là một ngôn ngữ phù hợp cho lập trình hệ thống.
- C là một ngôn ngữ lập trình cấu trúc, cho phép lập trình viên có thể chia
chương trình C ra làm nhiều module và hàm, hỗ trợ tái sử dụng mã nguồn. Cấu trúc module làm cho chương trình dễ gỡ lỗi, dễ kiểm tra, và dễ bảo trì
48
- Ngôn ngữ C chỉ có 32 từ khóa chuẩn, nhưng lại có một số lượng lớn các toán tử logic và số học.
- Một trong những thế mạnh của ngôn ngữ C là tính khả chuyển cao. Với bộ thư viện chuẩn và có sẵn trình biên dịch cho hầu hết các hệ điều hành và nền tảng phần cứng giúp cho các chương trình viết bằng ngôn ngữ C ít thay
đổi trên các hệ thống máy tính khác nhau.
- Ngôn ngữ C rất linh động về ngữ pháp, nó có thể chấp nhận nhiều cách thể
hiện khác nhau cũng như những thao tác mà có thể không hợp lệở các ngôn ngữ khác. Chẳng hạn như, C cho phép cộng một ký tự với một số nguyên.