Chương 2 giới thiệu về ngôn ngữ lập trình C/C++ gồm các khái niệm và các thành phân cơ bản cân có của ngôn ngữ lập trình như tập ký tự, tên, từ khóa, kiểu dữ liệu, các toán tử, cấu trúc
Trang 1L AV P T R iNA H C O sW | ở
0 - 7NHÀ XUẤT BẢN KHOA HỌC VÀ KỸ THUẬT
Trang 2DƯƠNG THẢNG LONG (CHỦ BIÊN)
Trang 3Chịu trách nhiệm xuất bản
GIÁM ĐỐC - TỔNG BIÊN TẬP PHẠM NGỌC KHÔI
Biên tập và sửa bản in: TS NGUYEN h u y t i ế n
Họa sỹ bìa : XUÂN DŨNG
NHÀ XUẤT BẢN KHOA HỌC VÀ KỸ TH U Ậ T
70 Trần Hưng Đạo - Hoàn Kiếm - Hà Nội
ĐT: 04 3942 2443 Fax: 04 3822 0658
Website: http://www.nxbkhkt.com.vn Email: nxbkhkt@hn.vnn.vn
CHI NHÁNH NHÀ XUẤT ÉvÍN KHOA HỌC VÀ KỸ THUẬT
28 Đồng KHqri?-*Quận 1 - TP Hồ Chí Minh
Ể > t:t8 3822 5062 ’ ' f
In 300 bản, khổ 16 X 24cm, tại Xí nghiệp In NXB Văn hóa Dân tộc
Địa chỉ: 128C/22 Đại La, Hà Nội SỐĐKXB: 1455 - 2014/CXB/l - 93/KHKT.
Quyết định XB số: 245/QĐXB - NXBKHKT, ngày 30/12/2014
ISBN: 978-604-67-0312-9
In xong và nộp lưu chiểu Quý I năm 2015.
Trang 4LỜI NÓI ĐẦU
Để đáp ứng nhu cầu đào tạo kỹ sư tin học của các ngành Công nghệ thông tin và Tin học trong các trường đại học, tăng cường thêm một lựa chọn cho người học tiếp cận đa dạng đến những vấn đề cơ sở
của ngành, chúng tôi biên soạn cuốn sách “K ỹ thuật lập trình cơ sở với ngôn ngữ C /C + + ” Tài liệu này mong muốn cung cấp các kiến
thức cơ sở về lập trình nói chung và các kỹ thuật xử lý trong ngôn ngữ C/C++ nói riêng, qua đó nhàm giúp sinh viên có thêm tài liệu học tập, tham khảo và đặc biệt là kỹ năng thực hành giải quyết các bài tập lập trình
Nội dung tài liệu gồm 06 chương, sắp xếp theo trật tự logic từ đon giản đến phức, đảm bảo tính hệ thống và liên thông từ đầu đến cuối
Chương 1 trình bày các khái niệm cơ bản về lập trình, ngôn ngữ lập trình và các vấn đề liên quan đến lập trình như giải thuật, độ phức tạp của giải thuật
Chương 2 giới thiệu về ngôn ngữ lập trình C/C++ gồm các khái niệm và các thành phân cơ bản cân có của ngôn ngữ lập trình như tập
ký tự, tên, từ khóa, kiểu dữ liệu, các toán tử, cấu trúc chương trình, câu lệnh, khối lệnh,
Chương 3 trình bày các cấu trúc lệnh điều khiển trong lập trình bao gồm tuần tự, rẽ nhánh và lặp Chúng được thể hiện bởi các lệnh như if, switch, for, while,
Chương 4 trình bày về lập trình cấu trúc Trong đó gồm các khái niệm liên quan, phương pháp xây dựng chương trình theo mô-đun (dưới dạng các hàm), các vấn đề liên quan đến hàm như vấn đề trao đổi dữ liệu giữa các hàm, kỹ thuật hàm đệ quy, hàm nạp chồng, hàm
m ẫu,
Trang 54 KỸ THUẬT LẬP TRÌNH c ơ SỞ VỚI NGÓN NGỮ C/C++
Chương 5 trình bày phương pháp tổ chức dữ liệu theo mảng, các bài toán và thuật toán liên quan đến mảng Trong đó bao gồm mảng một chiều, mảng hai chiều, mảng biểu diễn xâu ký tự và cách xử lý,
và đặc biệt là phương pháp khai thác sử dụng cơ chế bộ nhớ động với con trỏ
Chương 6 trình bày phương pháp tổ chức dữ liệu theo gói (hay cấu trúc - struct), phương pháp tổ chức dữ liệu dạng danh sách, dạng cây đổi với các cấu trúc dữ liệu cơ bản và các vấn đề liên quan Cũng trong chương này, phần cuối sẽ cung cấp phương pháp xử lý vào/ra tệp tin phục vụ cho việc lưu dữ liệu trên bộ nhớ ngoài (ổ đĩa).Mỗi chương được chia làm ba phần: phần thứ nhất trình bày lý thuyết các vấn đề, mỗi vấn đề đều có các ví dụ m inh họa, giải thích chi tiết hoặc/và các hình vẽ minh họa trực quan giúp cho người đọc dễ tiếp nhận Phần thứ hai gồm các bài tập có hướng dẫn thực hiện và lời giải theo hướng dẫn đó và phần thứ ba là các bài tập chưa có lời giải Các ví dụ mẫu cũng như bài giải của các bài tập đã được viết bằng ngôn ngữ C/C++ và chạy thử cho kết quả đúng trên môi trường Dev-C++
Hướng dẫn: Bạn đọc nên đọc các phần lý thuyết trước mỗi
chương và xem các ví dụ minh họa, tiếp theo tìm hiểu các bài tập đã nêu phương pháp giải để nắm rõ việc vận dụng phần lý thuyết vào mỗi bài toán cụ thể Cuối cùng bạn hãy tự làm các bài tập yêu cầu để nâng cao kỹ năng lập trình cũng như giải quyết các bài toán bàng máy tính.Nhóm tác giả mong nhận được những đóng góp để hoàn thiện hơn cho tài liệu này qua địa chỉ email: duongthanglong@ gm ail.com
Hà Nội ngày 19 thảng 05 năm 2014
Nhóm tác giả
Trang 6Các giai đoạn chính trong quá trình xây dựng một chương trình phần mềm như sau.
Chương trình phần mềm
Giai đoạn khảo sát nhàm làm rõ các yêu cầu của bài toán, giới hạn hay xác định phạm vi bài toán cần giải quyết, tiếp theo phân tích các yêu cầu của bài toán thật chi tiết về các quy trình nghiệp vụ, cách thức xử lý các vấn đề có trong phạm vi bài toán để từ đó thiết kế các
Trang 76 KỸ THUẬT LẠP TRÌNH c ơ s ở VỚI NGÔN NGỮ C/C++
thành phần cho chương trình phần mềm Giai đoạn mã hóa chương trình (hay coding) là một giai đoạn quan trọng, ở đó, các thiết kế về phần mềm sẽ được chuyển hóa thành nội dung các thành phần của một chương trình máy tính Người thực hiện ở giai đoàn này hay được gọi
là lập trình viên (programmer)
Như vậy, kết quả của lập trình là chương trình phần mềm (software), chương trình này sẽ được thực hiện trên máy tính và qua
đó giúp con người giải quyết bài toán đặt ra ban đầu
Chúng ta không đi sâu tìm hiểu chi tiết về các giai đoạn ở đây Trong khuôn khổ tài liệu này, sẽ đề cập đến giai đoạn mã hóa chương trình hay còn gọi là viết mã lệnh Giai đoạn này được thực hiện dựa trên những phân tích và thiết kế về chương trình đó Các thiết kế của chương trình gồm nhiều thành phần khác nhau như việc phân chia các rtìô-đun xử lý, các giao diện người dùng của chương trìn h nhưng quan trọng là quy trình xử lý và tính toán cho các vấn đề của bài toán bằng máy tính, hay còn gọi là thuật toán Phần thuật toán này sẽ cho thấy cấu trúc trình tự mà người lập trình sẽ viết mã lệnh cho chương trình Khái niệm và các vấn đề về thuật toán được trình bày ở phần sau.Thực tiễn đặt ra nhiều bài toán cho việc xây dựng các chương trình phần mềm ứng dụng Có một số bài toán có thể đang được giải quyết bằng sức lao động của con người, tuy nhiên có những bài toán chúng ta không thể giải quyết vì khối lượng tính toán khổng lồ hoặc diễn ra trong những môi trường đặc biệt Chẳng hạn, bài toán giải phương trình bậc hai là đơn giản và chúng ta có thể tính toán trong thời gian ngắn, trong khi bài toán phân tích một số nguyên khoảng 50 chữ số thành các thừa số nguyên tố sẽ cần một khối lượng tính toán lớn và con người không dễ gì có thể tính toán ngay được Hoặc bài toán điều khiển các thiết bị rô-bốt được phóng vào vũ trụ thì rõ ràng con người chưa thể tham gia điều khiển trực tiếp mà cần có sự tự động hóa việc điều khiển bàng máy tính Những điều này cho thấy sự cần
Trang 8KỸ THUẬT LẬP TRÌNH c ơ s ở VỚI NGÔN NGỮ C/C++
thiết đến việc ứng dụng máy tính thông qua các chương trình phầr mềm ứng dụng
M ặt khác, với đặc trưng như tính trung thực, không bị phụ thuộc vào điều kiện ngoại cảnh khi tính toán và xử lý nên việc ứng dụng máy tính giải quyết các bài toán giúp con người sẽ hiệu quả cao vè đảm bảo tính ổn định hon
1.1.2 Ngôn ngữ lập trình
Chương trình phần mềm của máy tính là tập hợp các câu lệnh CC thứ tự để điều khiển máy tính xử lý và tính toán giải quyết bài toán đ< đặt ra Các câu lệnh (hay còn gọi mã lệnh) được viết trong chươnị trình về bản chất chỉ sử dụng 2 ký hiệu 0 và 1, bởi vì máy tính điện tì hiện nay chỉ xử lý tín hiệu dạng nhị phân (tương ứng với trạng thá ON/OFF) Các lệnh biểu diễn ở dạng này gọi là mã máy Tuy nhiêi chúng ta không phải và cũng rất khó lập trình bằng các lệnh m ã máy
mà sẽ sử dụng các lệnh dưới dạng tương tự ngôn ngữ tự nhiên (chi yếu bằng tiếng Anh) để dễ dàng hơn, đó chính là nhờ sự cung cấp củi ngôn ngữ lập trình
Như vậy, ngôn ngữ lập trình có thể hiểu là tập các ký pháp, qir tắc, quy ước để viết mã lệnh cho chương trình Hiện nay có rất nhiềi loại ngôn ngữ lập trình được chia thành từng nhóm sau:
- N gôn ngữ máy: sử dụng các ký hiệu nhị phân cùng với quy tắ của máy nên rất khó áp dụng và hầu như không được dùng để viể chương trình
- Nhóm ngôn ngữ bậc thấp: sử dụng các ký hiệu là chữ cái, chi
số, d ấu hay còn gọi là các ký tự cùng với quy tắc gần với quy tắ của máy nên cũng khá khó khi áp dụng Chẳng hạn, như ngôn ng Assembler Các ngôn ngữ thuộc nhóm này thường áp dụng để vi( chương trình phần mềm dạng hệ thống, can thiệp sâu bên trong cá thiết bị vật lý để điều khiển
Trang 98 KỸ THUẬT LẬP TRÌNH c ơ SỞ VỚI NGỐN NGỮ C/C++
- Nhóm ngôn ngữ bậc cao: sử dụng các ký hiệu là các ký tự của ngôn ngữ tự nhiên (tiếng Anh) để viết lệnh với quy tắc gần với quy tắc của ngôn ngữ tự nhiên nên dễ áp dụng Chẳng hạn như Pascal, C/C++, Java,
N gôn ngữ lập trình về bản chất cung cấp cho người lập trình hai yếu tố chính thứ nhất, cung cấp các ký hiệu và quy tắc viết mã lệnh để sao cho đơn giản và dễ triển khai; thứ hai, cung cấp cơ chế để các chương trình sau khi viết bàng ngôn ngữ này sẽ được chuyển về dạng
mã máy để thực hiện trên máy tính Quá trình chuyển đổi này được gọi là biên dịch (compile) chương trình
Chương trình được viết ra sử dụng một ngôn ngữ lập trình nào
đó được gọi là chương trình nguồn (source programs), sau khi biên dịch sẽ tạo thành chương trình gồm các lệnh mã máy được gọi chương trình thực thi (executive programs)
Hình vẽ sau minh họa quá trình lập trình phần mềm và biên dịch, chạy thử chương trình trên máy tính
1.2 Thuật toán
1.2.1 Khái niệm thuật toán (algorithms)
Thuật toán là một hệ thống chặt chẽ và rõ ràng các quy tắc nhằm xác định một dãy có thứ tự các thao tác trên những đối tượng, sao cho
Trang 10KỸ THUẬT LẬP TRÌNH c ơ SỞ VỚI NGÔN NGỮ C/C++ 9
sau m ột số hữu hạn bước thực hiện các thao tác này, ta thu được kết quả mong muốn
Thuật toán là khái niệm cơ bản trong tin học để diễn tả cách thức máy tính xử lý thông tin nhằm giải quyết một bài toán nào đó Vì vậy
để lập trình cho máy tính, trước hết, chúng ta phải thiết kế một thuật toán thích hợp m à các bước tính toán trong đó là thực hiện được bởi máy tính Sự thích hợp của một thuật toán được thể hiện ở các đặc trưng cần có và chúng ta sẽ xem xét chi tiết ở phần tiếp theo
Chẳng hạn, để thực hiện bài toán giải phương trình bậc hai dạng a.x2+b.x+c = 0 chúng ta cần phải thực hiện theo thứ tự các bước như sau:
Bước 1) Xác định các hệ số của phương trình là ba số a, b và c.Bước 2) Kiểm tra, nếu a bằng 0 thì trả lời đây không phải là phương trình bậc hai và kết thúc Ngược lại thực hiện tiếp bước 3.Bước 3) Tính giá trị của delta = b2- 4a.c
Bước 4) N ếu delta < 0 thì trả lời phương trình không có nghiệm thực và kết thúc Ngược lại sang bước 5
Bước 5) Nếu delta = 0 thì trả lời phương trình có nghiệm kép là
Xi = x2 = -b/(2.a) và kết thúc Ngược lại sang bước 6
Bước 6) Nếu delta > 0 thì trả lời phương trình có hai nghiệm phân biệt là X] = (-b+delta1/2)/(2.a) và x2 = (-b-delta1/2)/(2.a) và kết thúc
Quá trình thực hiện bài toán trên có 6 bước, nội dung thực hiện các bước là rõ ràng, chính xác và đơn nghĩa Nếu chúng ta đảo lộn trật
tự của các bước thì có thể dẫn đến sai, tức là không giải quyết được bài toán đã đặt ra Đây là đặc điểm có tính thứ tự của các thao tác trong bất kỳ m ột thuật nào Để tìm hiểu kỹ các đặc trưng của thuật toán, chúng ta sẽ tiếp tục ở phần sau
Trang 1110 KỸ THUẬT LẬP TRÌNH c ơ s ở VỚI NGÔN NGỮ C/C++
1.2.2 Phương pháp trình bày thuật tuán
Vấn đề biểu diễn thuật toán cũng rất quan trọng, nhàm mục đích truyền đạt nội dung phương cách tính toán và xử lý cho một bài toán
từ người thiết kế đến người lập trình một cách chính-xác Dễ nhất là sử dụng hệ thống các ký hiệu hình thức hóa, tuy nhiên với những thuật toán lớn và để gần gũi với ngôn ngữ tự nhiên của con người, chúng ta thường sử dụng ngôn ngữ giả lập trình với mô tả từng bước
Như vậy, chúng ta có hai cách để biểu diễn thuật toán:
- Cách thứ nhất là nêu trình tự các bước từ bước 1 đến bước cuối cùng, ở mỗi bước sử dụng ngôn ngữ giả lập trình cùng với ngôn ngữ
tự nhiên để trình bày thao tác cần tính toán hoặc xử lý Các mô tả này phải chính xác, rõ ràng, đom nghĩa và dễ hiểu
Cấu trúc mô tả một thuật toán theo cách này thường gồm các 3hần như sau:
Trang 12KỸ THUẬT LẬP TRỈNH c ơ s ở VỚI NGÔN NGỮ C/C++ 11
Chúng ta xem ví dụ sau về tìm số lớn nhất trong ba số nguyên để nắm rõ hơn về phương pháp trình bày :
-thể hiện sự lựa chọn đúng hoặc sai, có một chiều
đi vào và 2 chiều đi ra tương ứng với 2 trường hợp đúng và sai
Trang 1312 KỸ THUẬT LẬP TRÌNH c ơ SỞ VỚI NGÔN NGỮ C/C++
Trong đó, một thuật toán thường chỉ có hai hình e-líp thể hiện một điểm bắt đầu và một điểm kết thúc của thuật toán Các mũi tên nổi các hình (thao tác) lại với nhau tạo nên tính thứ tự cần phải xem xét cẩn trọng N ếu m ột thao tác nào đó trong một hình vẽ m à quá lớn
và chưa cụ thể để dễ dàng lập trình thì có thể được thiết kế chi tiết thành một thuật toán con khác với một sơ đồ khác tương ứng
Chẳng hạn, với thuật toán giải phương trình bậc hai ở trên chúng
ta có thể biểu diễn bằng sơ đồ sau:
M ột thuật toán được trình bày dưới dạng sơ đồ thường là rõ ràng, tường m inh và trực quan với cách tư duy lập luận của con người hom Người lập trình sẽ dễ dàng triển khai chương trình từ thuật toán ở dạng này Tuy nhiên nếu thuật toán quá lớn thì việc trình bày bằng mô
tả các bước sẽ đơn giản hơn, khi đó các bước phải được trình bày rõ
Trang 14KỸ THUẬT LẬP TRÌNH c ơ SỞ VỚI NGÔN NGỮ C/C++ 13
chi tiết từng thao tác để người lập trình có thể nắm bắt được và mã hóa
thành các câu lệnh xử lý, tính toán trong chương trình được dễ dàng
Để hiểu rõ và chắc chắn chính xác chi tiết từng thao tác trong
một thuật toán, thông thường, trước hết chúng ta hãy làm thử từng
bước của thuật toán đã cho với các trường hợp khác nhau của dữ liệu
đầu vào (input) Ở đây chúng ta sẽ làm thử một trường hợp của thuật
toán giải phương trình bậc hai ở trên Cụ thể với sơ đồ của ví dụ trên
ta có như sau:
Sau khi bắt đầu, chúng ta nhập các hệ số tại hình vẽ thứ (2) (hình
bình hành), giả sử là a = 2, b = 5, c = 2 Tiếp theo tại hình (3) kiểm tra
a * 0 là đúng nên sang hình (4) và tính A = 5 - 4 x 2 x 2 = 9 Tiếp tục
kiểm tra A > 0 tại hình (5) là đúng nên sang hình (6) để tính giá trị
nghiệm:
sau đó kết thức thuật toán
1.2.3 Các đặc trưng của thuật toán
Thông thường, để cho biết một thuật toán là tốt hay không chúng
ta cần đưa ra các tiêu chí đánh giá Sau đây là những tiêu chí thường
được đề cập, có những tiêu chí là bắt buộc, có những tiêu chí cần đạt ở
- Tính kết thúc: thuật toán phải được kết thúc sau m ột số hữu hạn thao tác Đây là tính bắt buộc của bất kỳ một thuật toán nào
Ví dụ sau đây là một thuật toán để tìm ước số chung lớn nhất của
hai số nguyên dương mà không có tính kết thúc vì các bước trong đó
được lặp lại vô hạn lần (thuật toán bên dưới) Thực vậy, khi hai số
bàng nhau (a=b) thì tại bước 2 thuật toán sẽ trừ bớt của b và do đó giá
trị b sẽ bằng 0 (a khác 0), tiếp theo bước 3 sẽ không kết thúc vì sau bước
2 thì giá trị a khác b Bước 4 sẽ lặp lại bước 1, bây giờ sẽ lặp vô hạn lần
Trang 1514 KỸ THUẬT LẬP TRÌNH c ơ s ở VỚ! NGỒN NGỮ C/C++
VÌ b = 0 nên tại bước 1 giá trị a luôn không đổi dẫn đến không bao giờ
đạt được kết quả a = b ở bước 3 để dừng thuật toán
A lgorithm : USCLN (thuật toán không có tính dừng)
Input: a, b (là 2 số nguyên dương)
Output: u (là ước số chung lớn nhất)
Actions:
B l) N ếu a>b thì đặt a = a-b; (giảm bớt của a đi b đom vị)
B2) Nếu a<b thì đặt b = b-a; (giảm bớt của b đi a đơn vị)
B3) N ếu a=b thì kết thúc và kết quả là a;
B3) N ếu a o b thì lặp lại bước 1;
End (kết thúc thuật toán)
Để thuật toán trên có tính dừng, chúng ta có thể thay đổi điều kiện xét ở bước 3 Theo đó, thay vì xét a = b thì ta sẽ xét điều kiện
a = 0 hoặc b = 0 để kết thúc thuật toán
- Tính rõ ràng, chặt chẽ: các thao tác được trình bày trong thuật toán phải rõ ràng và đơn nghĩa, và phải thực hiện được bằng máy tính Các bước này có thứ tự nhất địrih, nếu thay đổi trật tự này thì thuật toán sẽ bị sai
Chẳng hạn, nếu có một mô tả kiểu như “nếu a là đủ lớn thì kết thúc” thì sẽ không lập trình được cho máy tính vì khái niệm “ đủ lớn”
là không rõ ràng Hoặc mô tả có dạng “nếu tốc độ gió trên 230km/h thì ngắt nguồn điện tổng” trong lập trình điều khiển tại nhà máy điện hạt nhân X nào đó, thì có hai việc mà bản thân máy tính không tự xác định được đó là “đo tốc độ gió” và “ngắt nguồn điện” mà phải thông qua các thiết bị ngoại vi hỗ trợ như là các cảm biến Tất nhiên, điều này sẽ đặt ra sự ghép nổi giữa thiết bị ngoại vi với máy tính trong điều khiển
Trang 16KỸ THUẬT LẬP TRÌNH c ơ SỞ VỚI NGỐN NGỮ C/C++ 15
- Tính phổ dụng: thuật toán có thể mở rộng, áp dụng được cho lớp các bài toán tương tự nhau, không chỉ giải quyết duy nhất một bài toán đã đặt ra
Ví dụ: bài toán đặt ra là lập trình để giải hệ 3 phương trình với 3
ẩn số (x, y, z) như sau:
'au x + an y + aìĩ.z = bì
< a 2Vx + a 12.y + a 2ĩ.z = b2
ứ3| j + ứ32 y + ữ33 ,z = ố3
Khi đó nếu chúng ta chỉ thiết kế thuật toán với hệ đúng như trên
mà không thể mở rộng để giải hệ với số phương trình là n * 3 thì có
thể nói là thuật toán chưa có tính phổ dụng
- Tính hiệu quả: thể hiện trong cả không gian và thời gian, về
không gian thuật toán phải thực hiện được trong điều kiện khả năng của máy tính hiện tại, về thời gian đòi hỏi thuật toán phải cho kết quả sớm nhất có thể được
1.2.4 Độ phức tạp của thuật toán
Với mỗi bài toán được cho chúng ta có thể thiết kế nhiều thuật toán khác nhau, và như vậy mỗi thuật toán sẽ có những đặc trưng nhất định Thông thường, các tiêu chí để lựa chọn một trong số các thuật toán cùng giải m ột bài toán sẽ dựả trên một khái niệm gọi là độ phức tạp của thuật toán
Độ phức tạp của thuật toán thường được xem xét đến ở hai yếu
tố Thứ nhất là thời gian, nó là sổ các thao tác xử lý tính toán từ khi bắt đầu cho đến khi kết thúc thuật toán Thứ hai là không gian, tức là dung lượng bộ nhớ cần đến trong quá trình chạy của thuật toán Tuy vậy, yếu tố không gian có thể mở rộng ở những mức độ chấp nhận được và do đó thường được xem nhẹ và ít quan tâm Trong đó, yếu tố thời gian đóng vai trò lớn và quyết định đến tính hiệu quả của thuật toán Vì vậy, yếu tổ này được quan tâm và đề cập chính đến việc đánh
Trang 1716 KỸ THUẬT LẬP TRÌNH c ơ s ở VỚI NGÔN NGỮ C/C++
giá độ phức tạp của thuật toán, và chúng ta chỉ quan tâm đến yếu tố này trong tài liệu
Thông thường, độ phức tạp (xét yếu tố thời gian) của thuật toán được đánh giá dựa trên kích thước dữ liệu đầu vào của bài toán, đó là
vì khi dữ liệu đầu vào có kích thước lớn sẽ dẫn đến số các thao tác xử
lý nhiều hơn Thật vậy, chẳng hạn với bài toán tính tổng của dãy các
số nguyên, khi sổ lượng số nguyên là 2 (a, b) thì chỉ cần một phép tính cộng (a+b), khi số lượng dãy là 3 (a, b, c) thì cần 2 phép tính cộng (a+b+c), tổng quát với dãy n số thì cần n-1 phép tính cộng
Tuy nhiên, số các thao tác xử lý tính toán của một thuật toán thường không xác định một cách tuyệt đối mà sẽ ước lượng ở mức trung bình Và chúng ta dùng khái niệm bậc o để thể hiện con số ước lượng này Sau đây là một số ước lượng hay được dùng trong việc đánh giá các thuật toán (được sắp xếp theo độ phức tạp tăng dần):
0(log2n) Độ phức tạp logarit của kích thước dữ liệu (n).
0(n)
Độ phức tạp tuyến tính, tức là số thao tác xử lý tính toán
sẽ tăng lên một cách tuyến tính cùng với kích thước của
dữ liệu đầu vào
0 (n.log2n) Độ phức tạp n nhân với logarit của n.
0 (n a) Độ phức tạp đa thức bậc a của n (a là một hằng số).
0(a") Độ phức tạp lũy thừa.
Chẳng hạn, với thuật toán tính tổng của m ột dãy n số nguyên theo cách mô tả như trên thì có độ phức tạp là O(n)
M ột quy ước trong việc đánh giá là nếu số ước lượng là m ột biểu thức theo n thì chúng ta sẽ lấy giá trị cao nhất, hoặc biểu thức theo n
mà nhân với một hàng số thì không tính hàng số đó Ví dụ, m ột thuật toán có ước lượng là 5+n+3.n thì ta lấy 3.n và suy ra lấy n, vậy ta có bậc O(n) M ột thuật toán có ước lượng là n+n2+2" thì ta lấy là 2n và có bậc 0(2")
Trang 18KỸ THUẬT LẬP TRỈNH c ơ s ở VỚI NGÔN NGỮ C/C++ 17
Bước 1) Chuyển thóc ở thùng A vào thùng c
Bước 2) Chuyển ngô ở thùng B vào thùng A
Bước 3) Chuyển thóc ở thùng c vào thùng B
Hình minh họa như sau:
(trung gian)
■ Ví dụ 1.2: Thuật toán “nấu cơm” :
“Nấu cơm ” là một công việc rất quen thuộc trong cuộc sống, tuy nhiên nếu có ai đó chưa một lần thực hiện trong thực tế thì không thể làm được và chúng ta phải đưa ra một thuật toán cho người đó thực hiện, thuật toán được trình bày như sau:
Bước 1) Thu thập nguyên liệu như gạo, nước và xác định các công cụ sử dụng để nấu cơm như nồi (giả sử nồi điện), nguồn điện
Bước 2) Nếu nguyên liệu không có hoặc thiếu công cụ thì thông báo không thể nấu cơm và chuyển đến bước 6
Trang 1918 KỸ THUẬT LẬP TRÌNH c ơ s ở VỚI NGÔN NGỮ C/C++
Bước 3) Lấy gạo cho vào nồi
Bước 4) Vo gạo và đổ nước, đóng nắp nồi
Bước 5) Cắm điện và bật công tắc sang chế độ nấu
Trang 20KỸ THUẬT LẬP TRÌNH c ơ SỞ VỚI NGÔN NGỮ C/C++ 19
■ Ví dụ í 4: Thuật toán tìm số nhỏ nhất trong một dãy số Cho một dãy số như sau: Xi, x 2, x 3, x 4, x 5, , x n Hãy tìm số nhỏ nhất trong dãy số trên
Ta ký hiệu X j là số thứ i trong dãy trên với i = 1,2,3,—, n và sử dụng Min để lưu số nhỏ nhất, thuật toán được trình bày (bằng cả mô tả từng bước và sơ đồ khối) như sau:
Thuật toán trên (dạng sơ đồ) được mô tả từng bước như sau:Bước 1) Xác định n và các giá trị X |, x 2, , Xn
Bước 2) Nếu n < 1 thì thông báo không có các số và kết thúc
Trang 2120 KỸ THUẬT LẬP TRÌNH c ơ SỞ VỚI NGỔN NGỮ C/C++
Bước 3) Đặt Min = Xi, giả sử số nhỏ nhất là số đầu tiên
Bước 4) Đặt i = 2, bắt đầu kiểm tra từ số thứ 2
Bước 5) Nếu i > n thì chuyển sang bước 8
Bước 6) Nếu X j < Min thì đặt lại M in = X j
Bước 7) Tăng i lên 1 (i = i + 1) và quay lại bước 5
Bước 8) Thông báo kết quả là: Min và kết thúc
Trang 22KỸ THUẬT LẶP TRÌNH c ơ SỞ VỚI NGÔN NGỮ C/C++ 21
Cho k số nguyên Xi, x 2, , X* Trình bày các thuật toán sau:
a) Tìm giá trị chẵn nhỏ nhất trong k số đã cho
b) Tìm giá trị âm lớn nhất trong k số đã cho
c) Tìm giá trị dương nhỏ nhất trong k số đã cho
Trang 2322 KỸ THUẬT LẬP TRÌNH c ơ s ở VỚI NGÔN NGỮ C/C++
Hãy trình bày thuật toán để kiểm tra một số nguyên n có phải là
số nguyên tố hay không bàng cách vẽ sơ đồ
Ví dụ: số n = 5 là sổ nguyên tố, nhưng số n = 21 không là số nguyên tố
Hãy vẽ sơ đồ thuật toán phân tích một số nguyên n thành tích các thừa số nguyên tố
Ví dụ: số n = 140 sẽ phân tích thành 2 X 2 X 5 X 7
Trang 24Chương 2
NGÔN NGỮ LẬP TRÌNH C/C++
2.1 Các thành phần cơ bản của ngôn ngữ lập trình
Chúng ta thấy trong ngôn ngữ tự nhiên, chẳng hạn như tiếng Anh hay tiếng V iệt được cấu tạo từ các phần tử nhỏ nhất, cơ bản nhất là bảng các chữ cái và các dấu Bằng các quy tắc, cú pháp và ngữ nghĩa
để ghép chúng lại với nhau tạo nên các từ, sau đó ghép các từ với nhau tạo nên câu, đoạn văn và cuối cùng là tạo nên bài văn
Ngôn ngữ lập trình cũng tương tự như vậy, được cấu tạo từ những phần tử cơ bản được gọi là bảng ký hiệu M ột chương trình phần mềm được hình thành từ các ký hiệu này bằng cách áp dụng các quy tắc của ngôn ngữ lập trình chỉ định và dựa trên các quy trình đã được thiết kế cho chương trình đó
Sau đây là các khái niệm cơ bản trong ngôn ngữ lập trĩnh nói chung và các quy tắc áp dụng trong ngôn ngữ lập trình C/C++
Cụ thể với ngôn ngữ C/C++, bảng ký hiệu được sử dụng baogồm:
Trang 2524 KỸ THUẬT LẬP TRÌNH c ơ SỞ VỚI NGÔN NGỮ C/C++
- Nhóm các chữ cái: chữ in hoa A, B, c , , z và chữ in thường a,
2.1.2 Tên và từ khóa
Tên (name) là một dãy các chữ cái, chữ số và dấu gạch nối Tên phải bắt đầu bàng chữ cái hoặc dấu gạch nối (không được bắt đầu bằng chữ số), trong tên không dùng dấu cách và các dấu đặc biệt khác.Trong các ngôn ngữ lập trình, tên được dùng để định danh các thành phần của chương trình như tên biến, tên hàm, tên hàng, tên con trỏ , sẽ đề cập chi tiết ở các phần sau
Ví dụ:
B aitapl, Hanoi2, Viet3nam là những tên đúng
lBaitap, Ha noi, Viet%nam là những tên sai, vì có chừ sổ đứng đầu, có sử dụng dấu cách, có ký hiệu đặc biệt %
Có một nhóm các tên do ngôn ngữ lập trình quy định để đưa ra các quy tắc viết lệnh trong chương trình được gọi là từ khóa (keywords) Người lập trình không được đặt các tên trong chương trình trùng với hệ thống từ khóa của ngôn ngữ lập trình
Trong C/C++, nhóm các từ khóa được giới thiệu trong bảng sau (ý nghĩa của chúng sẽ được trình bày chi tiết và cách áp dụng ở các phần tiếp theo)
Trang 26KỸ THUẬT LẬP TRÌNH c ơ s ở VỚI NGÔN NGỮ C/C++ 25
using directive
Ngoài ra, có một nhóm các tên được cung cấp bởi môi trường lập trình thông qua thư viện được gọi là tên chuẩn Nhóm này được dùng
để định danh các thành phần có sẵn trong hệ thống các thư viện, phục
vụ cho việc khai thác và sử dụng thư viện của chương trình
Trang 2726 KỸ THUẬT LẬP TRÌNH c ơ SỞ vở l NGỐN NGỮ C/C++
Ví dụ về một số tên chuẩn trong C/C++
cout, cin, scanf, printf, gets, getch, fstream
2.1.3 Các kiểu dữ liệu
Chúng ta đã biết máy tính không thể chứa hết mọi thông tin trong thực tế, hẹp hơn nữa, trong các ngôn ngữ lập trình chỉ cung cấp một số kiểu dữ liệu nguyên thủy (primitive types) N gôn ngữ lập trình C/C++ có các kiểu cơ bản sau để người lập trình có thể sử dụng trong việc biểu diễn, tính toán và xử lý thông tin gồm:
a) Kiểu ký tự: dùng để chứa ký tự trong bảng ASCII
- Tên kiểu: char, unsigned char
- M iền giá trị: một trong 256 ký tự thuộc bảng mã ASCII
- Độ lớn: 1 byte
Kiểu ký tự được lưu dưới dạng mã của nó từ 0 đến 255 quy định ưong bảng ASCII như sau (DEC là mã thập phân, HEX là m ã hexa (thập lục phân), BIN là mã nhị phân, Symbol là mẫu ký tự, Description là mô tả):
+ M ột số ký tự ASCII dùng để điều khiển (có mã từ 0 đến 31):
Trang 28KỸ THUẬT LẬP TRÌNH c ơ SỞ VỚI NGÔN NGỮ C/C++ 27
65 L 4 1 01000001 L A Các chữ cái in hoa từ A đên z
Trang 30KỸ THUẬT LẶP TRÌNH c ơ SỞ VỚI NGÔN NGỮ C/C++ 29
b) Kiểu số: chứa dữ liệu số nguyên hoặc số thực, bảng sau thể hiện tên kiểu (Type), độ lớn tính bằng byte (Length) và mô tả trên máy tính X86 chạy hệ điều hành Windows 64 bit và bộ dịch của DevC++:
(± 1.7E ± 308)
Thông thường chúng ta hay dùng kiểu int cho số nguyên và kiểu float cho số thực Tuy nhiên, một số trường hợp có thể phải dùng các kiểu phù hợp Chẳng hạn, kiểu double có độ chính xác cao hơn float ở mức gấp đôi, tức là nó chứa được số thực có phần thập phân gồm nhiều chữ số hơn
Ví dụ: cho biểu thức sau,
(sin(O.l)10)10,
nếu dùng kiểu float để chứa thì kết quả sẽ bàng 0, khi đó phải dùng kiểu double Tuy nhiên, khi lũy thừa 10 của biểu thức trên thì kiểu double không chứa được, mà phải dùng kiểu long double
c) Kiểu logic: biểu diễn giá trị đúng/sai trong chương trình,
- Tên kiểu: bool
- M iền giá trị: true, false
- Độ lớn: 1 byte
Tuy nhiên, trong ngôn ngữ C/C++ cũng xem xét số nguyên như
là kiểu logic với giá trị 0 tương ứng sai, giá trị 1 hoặc khác 0 tương ứng đúng
Trang 3130 KỸ THUẬT LẬP TRÌNH c ơ SỞ VỚI NGỔN NGỮ C/C++
2.1.4 Khái niệm về hằng và biến nhớ
a) Đại lượng hằng trong chương trình
Hằng (consts) là một đại lượng dữ liệu không thể thay đổi giá trị trong toàn bộ chương trình Nó có thể là số nguyên, số thực, ký tự hoặc chuỗi ký tự Để biểu diễn các giá trị hằng, tày theo từng ngôn ngữ, nhưng trong C/C++ ta viết như sau:
- Đối với số nguyên: chúng ta viết bình thường như trong toán học (các chữ số liền nhau), ví dụ 100 hoặc 175 hoặc 200000
- Đối với số thực: chúng dùng dấu chấm để ngăn cách phần nguyên và phần thập phân, ví dụ 1.5 hoặc 0.15 hoặc 5.0
- Đối với ký tự: chúng ta viết vào trong cặp nháy đơn ( ), ví
dụ ‘a’ hay ‘Z ’ hay ‘0 ’ hay
- Đối với chuỗi ký tự: chúng ta viết các ký tự vào trong cặp nháykép ( ), ví dụ “Ha noi Viet nam” hoặc “Ngay 10 thang 11 nam1976” hoặc “Hello, how are you?”
Trong C/C++, một hàng có thể được viết trực tiếp trong chương trình (tại các biểu thức xử lý) hoặc được định nghĩa và sử dụng thông qua một tên hằng mà ta gọi là macro (#define) như sau:
I #define tên_hằng giá_trị_cần_định nghĩa
Ví dụ: chúng ta định nghĩa hai hằng sau
#define MY_NAME "Duong Nguyen Long Khanh"
Trang 32KỸ THUẬT LẬP TRÌNH c ơ SỞ VỚI NGÔN NGỮ C/C++ 31
(imperative programming), nếu không có biến nhớ thì chúng ta không thể lập trình được bởi vì không có chỗ chứa dữ liệu cho việc tính toán
và xử lý
Mỗi biến nhớ sẽ được quy định một kiểu dữ liệu, quy định này đảm bảo biến nhớ chỉ chứa được các dữ liệu tương ứng với kiểu đó và khi đó các tính toán xử lý trên biến nhớ mới có nghĩa
M ỗi biến nhớ sẽ chiếm một ô nhớ trên bộ nhớ của máy tính, độ lớn của ô nhớ phụ thuộc vào kiểu dữ liệu của biến đó (xem bảng kiểu
dữ liệu ở trên) Hình vẽ sau minh họa các biến nhớ chứa dữ liệu trên
bộ nhớ của máy tính khi chương trình chạy
Địa chỉ bộ nhớ
1 0 0 0 1 0 0 1 1 0 0 2 1 0 0 3 1 0 0 4 1 0 0 5
Giá tri dữ liệu của biến■ I t ĩ
N hư chúng ta thấy, bộ nhớ của máy tính được chia thành các đơn
vị nhớ cơ bản M ỗi biến, tùy theo kích thước quy định bởi kiểu của nó,
sẽ chiếm một số đơn vị nhớ, và để đơn giản ta gọi mỗi biến chiếm một
Trang 3332 KỸ THUẬT LẶP TRỈNH c ơ SỞ VỚI NGÒN NGỮ C/C++
2.1.5 Các phép toán cơ bản
Các ngôn ngữ lập trình đều cung cấp các phép toán để tác động lên dữ liệu nhàm tính toán và xử lý C/C++ cung cấp danh sách các phép toán (được gọi là các toán tử - operators) được viết như sau,
- Ý nghĩa: cộng, trừ, nhân, chia, chia dư
- Dữ liệu tác động: kiểu số nguyên hoặc số thực (trong đó phép
5 + 3 hoặc 5 - 3 hoặc 5 * 3 hoặc 5 / 3 hoặc 5 % 3
C hú ý: Đối với phép chia ( / ) nếu hai vế là dữ liệu số nguyên thì máy sẽ chia lấy phần nguyên, nếu một trong vế là sổ thực thì máy cho kết quả chính xác Ngược lại, phép chia (%) chi lấy phần dư của số nguyên
Ví dụ:
7/4 sẽ cho kết quả là 1 (là phần nguyên của 7 chia 4)
7.0/4 hoặc 7/4.0 sẽ cho kết quả là 1.75
7%4 sẽ cho kết quả là 3 (là phần dư cùa 7 chia 4)
Trang 34KỸ THUẬT LẬP TRÌNH c ơ SỞ VỚI NGÔN NGỮ C/C++ 33
6 == 5 sẽ cho kết quả sai
'A' == 'a' sẽ cho kết quả sai
'A' < 'a' sẽ cho kết quả đúng
Trang 3534 KỸ THUẬT LẬP TRÌNH c ơ s ở VỚI NGÒN NGỮ C/C++
C hú ý: Phép và (&&) cho kết quả đúng khi và chỉ khi cả 2 toán hạng đều đúng, phép hoặc (II) cho kết quả sai khi và chỉ khi cả 2 toán hạng đều sai, phép phủ định (!) cho kết quả ngược lại
+ Phép & để và bít, tức là từng cặp bít lần lượt trên hai toán hạng
sẽ và với nhau cho kết quả 1 khi và chỉ khi cả 2 bít đều bàng 1 ngược lại cho kêt quả 0
Trang 36KỸ THUẬT LẬP TRÌNH c ơ SỞ VỚI NGÔN NGỮ C/C++ 35
+ Phép I để hoặc ít, nếu cặp bít đều bàng 0 thì cho kết quả 0, ngược lại cho bằng 1
+ Phép A để xor bít, nếu cặp bít giống nhau thì cho kết quả 0, ngược lại cho kết quả 1
+ Phép ~ để lấy đảo ngược giá trị của từng bít trên 1 toán hạng.+ Phép » , để dịch phải, trái các bít trên toán hạng ở phía trái với số bít cần dịch ở phía phải
Các phép toán này sẽ tác động lên từng bít của hai toán hạng để thực hiện theo bảng kết quả sau:
- Các phép tăng 1, giảm 1: ++ và —
Cách viết phép toán này như sau:
vế trái ++ và vế_tráỉ “
Trang 37Ví d ụ : _
a = 5; và
b = a++; thì b sẽ có giá trị bằng 5 và a sẽ có giá trị bằng 6,
nhưng khi viết
a = 5; và
b = ++a; thì kết quả cả b và a đều bằng 6 Máy sẽ tăng biến
a lên 1 rồi sau đó mới gán giá trị của biến a vào biến b
Phép tăng giảm chỉ thực hiện trên các biến nhớ dữ liệu kiểu số nguyên (không thực hiện được trên hàng số hoặc số thực)
Ví dụ:
5++ sẽ báo sai, hoặc
(a + 7) ++ cũng báo sai, máy tính không thực hiện được
g) Phép chuyển đổi kiểu dữ /iệu
Phép chuyển đổi kiểu dữ liệu là việc chuyển một dữ liệu từ kiểi này sang kiểu khác, khi chuyển có thể sẽ bị mất dữ liệu
Trang 38KỸ THUẬT LẬP TRÌNH c ơ s ở VỚI NGÔN NGỮ C/C++ 37
Cú pháp để chuyển như sau:
(tên_kiểu_m ới) dữ_liệu_cần_chuyến_kiếu
Ví dụ:
a = 1/2; sẽ cho kết quả là 0 vì 2 toán hạng đều là số nguyên
a = (flo a t)l/2 ; sẽ cho kết qủa 0.5 vì số 1 được chuyển thành
số thực trước khi thực hiện phép chia cho 2
Nếu kiểu dữ liệu mới có miền giá trị bao trùm miền dữ liệu của kiểu dữ liệu cũ thì việc chuyển sẽ không mất dữ liệu, ví dụ từ số nguyên (int) sang số thực (float) Nếu chuyển từ sổ thực sang số nguyên thì sẽ bị m ất phần thập phân sau dấu phẩy
Ví dụ:
a = (in t)35.687; sẽ cho kết quả a bằng 35
Đối với phép gán (=), một số trường hợp máy sẽ tự động chuyển đổi kiểu từ dữ liệu ở vế phải của phép gán về kiểu phù hợp với biến nhớ ở vế trái Do đó, chúng ta phải cẩn thận để không bị mất dữ liệu một cách nguy hiểm (vì việc này không tường minh) và rất khó kiểm soát về sau đối với chương trình lớn
Chẳng hạn, đối với phép gán sau:
int a = 1.5/2;
Rõ ràng, kết quả của vế phải sẽ là 0.75 nhưng khi gán vào biến
“a” ở vế trái kiểu nguyên (int) thì tự động ép kiểu về số nguyên với giá trị ở đây là 0 Vậy biến “a” sẽ bằng 0 thay vì bằng 0.75
2.2 Quy tắc mã hóa (coding) chương trình
Trang 39//là một câu lệnh yêu cầu máy xóa màn hình
printf("Hello, how are you?");
//là một câu lệnh yêu cầu máy hiện lên màn hình dòng chữ
trong cặp dấu nháy kép
M ột câu lệnh được viết trên một dòng, tuy nhiên, trên một dòng cũng có thể viết được nhiều câu lệnh
Thông thường một câu lệnh chưa đủ để thực hiện một chức năng hay thao tác nào đó được yêu cầu, do vậy chúng ta phải viết nhiều câu lệnh và tạo thành một khối lệnh Khối lệnh phải được viết vào trong cặp dấu ngoặc móc { và }
Trang 40KỸ THUẬT LẬP TRÌNH c ơ SỞ VỚI NGÔN NGỮ C/C++ 39
2.2.2 Cấu trúc các thành phần một chương trình C/C++
Đe viết một chương trình bàng ngôn ngữ C/C++ chúng ta sử
dụng cấu trúc chung như sau:
1- khai báo các thư viện cần dùng
2- định nghĩa các giá trị hằng
3- định nghĩa các kiểu dữ liệu mới
4- định nghĩa các chương trình con (hàm)
5- khai báo các biến nhớ toàn cục
Ở đây chúng ta chỉ nạp 2 thư viện là <stdio.h> và <conio.h>
trong những chương trình lớn, ngoài ra chúng ta có thể sử dụng thêm
các thư viện khác nếu chúng ta cần dùng đến nó Danh sách và ý nghĩa
của một số thư viện cơ bản như sau:
<stdio.h> Chứa các lệnh nhập xuất dữ liệu
<conio.h> Các lệnh hỗ trợ xử lý màn hình, bàn phím
<iostream.h> Các lớp & đối tượng xử lý nhập xuất dữ liệu
<iomanip.h> Xử lý hỗ trợ nhập xuất dữ liệu trên đối tượng