Đề cương Cơ sở kỹ thuật lập trình

Tài liệu Đề cương Cơ sở kỹ thuật lập trình: TRƢỜNG ĐẠI HỌC SƢ PHẠM KỸ THUẬT HƢNG YÊN KHOA CÔNG NGHỆ THÔNG TIN ĐỀ CƢƠNG CƠ SỞ KỸ THUẬT LẬP TRÌNH HƢNG YÊN – 2015 MỤC LỤC MỤC LỤC .............................................................................................................. 2 BÀI 1: CÁC THÀNH PHẦN CƠ BẢN CỦA NGÔN NGỮ LẬP TRÌNH ........ 8 1.1 Cấu trúc chung của một chương trình ..................................................... 8 1.1.1 Cấu trúc của một chương trình ............................................................ 8 1.1.2 Các bước để tạo và thực hiện một chương trình ................................. 9 1.1.3 Một số quy tắc cần nhớ khi viết chương trình ................................... 11 1.2 Các thành phần cơ bản của một ngôn ngữ lập trình .............................. 12 1.2.1 Bảng chữ cái ...................................................................................... 12 1.2.2 Từ khóa ....................................................................................

pdf145 trang | Chia sẻ: putihuynh11 | Lượt xem: 429 | Lượt tải: 0download
Bạn đang xem trước 20 trang mẫu tài liệu Đề cương Cơ sở kỹ thuật lập trình, để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên
TRƢỜNG ĐẠI HỌC SƢ PHẠM KỸ THUẬT HƢNG YÊN KHOA CÔNG NGHỆ THÔNG TIN ĐỀ CƢƠNG CƠ SỞ KỸ THUẬT LẬP TRÌNH HƢNG YÊN – 2015 MỤC LỤC MỤC LỤC .............................................................................................................. 2 BÀI 1: CÁC THÀNH PHẦN CƠ BẢN CỦA NGÔN NGỮ LẬP TRÌNH ........ 8 1.1 Cấu trúc chung của một chương trình ..................................................... 8 1.1.1 Cấu trúc của một chương trình ............................................................ 8 1.1.2 Các bước để tạo và thực hiện một chương trình ................................. 9 1.1.3 Một số quy tắc cần nhớ khi viết chương trình ................................... 11 1.2 Các thành phần cơ bản của một ngôn ngữ lập trình .............................. 12 1.2.1 Bảng chữ cái ...................................................................................... 12 1.2.2 Từ khóa .............................................................................................. 12 1.2.3 Tên (định danh) ................................................................................. 13 1.3 Các kiểu dữ liệu cơ bản ......................................................................... 14 1.3.1 Kiểu ký tự .......................................................................................... 15 1.3.2 Kiểu số nguyên .................................................................................. 16 1.3.3 Kiểu dấu phẩy động ........................................................................... 16 1.4 Biến, hằng và cách khai báo .................................................................. 17 1.4.1 Biến và cách khai báo ........................................................................ 17 1.4.2 Hằng và cách khai báo....................................................................... 18 BÀI 2: BIỂU THỨC, CÁC PHÉP TOÁN VÀ VẤN ĐỀ NHẬP XUẤT .......... 22 2.1 Biểu thức ................................................................................................ 22 2.2 Câu lệnh, khối lệnh ................................................................................ 22 2.2.1 Câu lệnh ............................................................................................. 22 2.2.2 Các câu lệnh và các khoảng trắng ..................................................... 23 2.2.3 Khối lệnh ........................................................................................... 24 2.3 Các phép toán......................................................................................... 24 Đề cương bài giảng Cơ sở kỹ thuật lập trình 3 2.3.1 Các phép toán số học ......................................................................... 24 2.3.2 Phép toán so sánh .............................................................................. 25 2.3.3 Phép toán logic .................................................................................. 25 2.3.4 Phép gán ............................................................................................ 26 2.3.5 Thứ tự ưu tiên các phép toán ............................................................. 26 2.3.6 Phép chuyển đối kiểu ........................................................................ 27 2.4 Nhập/xuất dữ liệu ................................................................................... 30 2.4.1 Xuất dữ liệu ....................................................................................... 30 2.4.2 Nhập dữ liệu ...................................................................................... 32 2.5 Bài tập .................................................................................................... 33 BÀI 3: CẤU TRÚC ĐIỀU KHIỂN ................................................................... 35 3.1 Giới thiệu về cấu trúc điều khiển ........................................................... 35 3.2 Cấu trúc điều khiển rẽ nhánh if .............................................................. 35 3.2.1 Cấu trúc rẽ nhánh dạng khuyết .......................................................... 35 3.2.2 Cấu trúc rẽ nhánh dạng đủ ................................................................. 36 3.3 Cấu trúc điều khiển rẽ nhánh swicth...................................................... 38 3.4 Bài tập .................................................................................................... 41 BÀI 4: CẤU TRÚC LẶP ................................................................................... 43 4.1. Giới thiệu về cấu trúc lặp ........................................................................... 43 4.2. Cấu trúc lặp xác định ............................................................................. 43 4.2.1. Cấu trúc lặp For .................................................................................. 43 4.1.2 Ví dụ áp dụng .................................................................................... 45 4.3. Cấu trúc lặp không xác định ...................................................................... 46 4.3.1. Cấu trúc lặp while ............................................................................... 46 Đề cương bài giảng Cơ sở kỹ thuật lập trình 4 4.3.2. Cấu trúc lặp do.. while ........................................................................ 49 4.4. Các câu lệnh đặc biệt ................................................................................. 52 4.4.1. Câu lệnh break .................................................................................... 52 4.4.2. Câu lệnh continue ............................................................................... 53 4.5. Bài tập ........................................................................................................ 53 BÀI 5: THẢO LUẬN/BÀI TẬP VỀ CÁC CẤU TRÚC LẶP VÀ CẤU TRÚC ĐIỀU KHIỂN 55 BÀI 6: MẢNG MỘT CHIỀU ............................................................................ 59 6.1 Giới thiệu về mảng một chiều ................................................................ 59 6.1.1 Khái niệm về mảng một chiều ........................................................... 60 6.1.2 Cách khai báo .................................................................................... 60 6.1.3 Đặc điểm của mảng một chiều .......................................................... 61 6.1.4 Cách khởi tạo phần tử cho mảng ....................................................... 62 6.2 Truy xuất các phần tử trong mảng ......................................................... 62 6.3 Các thao tác với mảng một chiều ........................................................... 63 6.3.1 Nhập mảng ........................................................................................ 63 6.3.2 Hiện mảng ......................................................................................... 64 6.2 Ví dụ áp dụng ......................................................................................... 65 BÀI 7: THỰC HÀNH VỀ CẤU TRÚC ĐIỀU KHIỂN VÀ CẤU TRÚC LẶP 72 BÀI 8: MẢNG HAI CHIỀU .............................................................................. 73 8.1. Giới thiệu về mảng hai chiều ................................................................. 73 8.1.1 Định nghĩa ......................................................................................... 73 8.1.2 Các cách khai báo .............................................................................. 74 8.2 Truy xuất các phần tử trong mảng hai chiều ......................................... 75 8.3 Các thao tác với mảng hai chiều ............................................................ 76 Đề cương bài giảng Cơ sở kỹ thuật lập trình 5 8.3.1 Nhập mảng ........................................................................................ 76 8.3.2 Hiện mảng ......................................................................................... 77 8.4 Một số ví dụ về mảng hai chiều ............................................................. 79 BÀI 9: THỰC HÀNH VỀ MẢNG (BUỔI 1) .................................................... 82 BÀI 10: THẢO LUẬN/BÀI TẬP VỀ MẢNG ................................................. 83 BÀI 11: THỰC HÀNH VỀ MẢNG (BUỔI 2) ................................................ 86 BÀI 12: THAO TÁC VỚI KÝ TỰ VÀ XÂU KÝ TỰ ..................................... 87 12.1 Giới thiệu về ký tự và xâu ký tự ............................................................ 87 12.1.1 Sử dụng các biến ký tự .................................................................... 88 12.1.2 Mảng của các ký tự ......................................................................... 89 12.1.3 Khởi tạo các mảng ký tự ................................................................. 90 12.2 Các thao tác trên xâu .............................................................................. 90 12.2.1 Nhập xâu .......................................................................................... 90 12.2.2 Hiển thị xâu và các ký tự ................................................................. 93 12.2.3 Một số thư viện hàm sử dụng trên xâu ............................................ 95 12.3 Bài tập .................................................................................................... 96 BÀI 13: THỰC HÀNH VỀ XỬ LÝ CHUỖI KÝ TỰ ...................................... 98 BÀI 14: KIỂU CẤU TRÚC VÀ TỆP ............................................................ 100 14.1 Giới thiệu về kiểu cấu trúc ................................................................... 100 14.2 Các thao tác trên biến cấu trúc ............................................................. 101 14.3 Mảng cấu trúc ...................................................................................... 102 14.4 Vấn đề vào/ra dữ liệu với tệp ............................................................... 102 14.4.1 Khai báo sử dụng tệp: .................................................................... 103 14.4.2 Mở tệp - hàm fopen ....................................................................... 103 Đề cương bài giảng Cơ sở kỹ thuật lập trình 6 14.4.3 Đóng tệp - hàm fclose ................................................................... 104 14.4.4 Làm sạch vùng đệm - hàm fflush .................................................. 105 14.4.5 Đọc/ghi tệp tin – hàm fprintf() và fscanf() .................................... 105 14.5 Bài tập .................................................................................................. 106 BÀI 15: THẢO LUẬN/ BÀI TẬP VỀ KIỂU CẤU TRÚC VÀ TỆP ............ 108 BÀI 16: THỰC HÀNH VỀ KIỂU CẤU TRÚC VÀ TỆP ............................. 111 BÀI 17: HÀM (2 BUỔI) ................................................................................ 112 17.1 Giới thiệu chung về hàm ...................................................................... 112 17.2 Cơ bản về hàm ..................................................................................... 114 17.2.1 Định nghĩa ..................................................................................... 114 17.2.2 Cấu trúc của một hàm tự xây dựng như sau: ................................. 115 17.2.3 Nguyên tắc xây dựng một hàm ...................................................... 119 17.3 Các khái niệm ...................................................................................... 120 17.3.1 Biến cục bộ .................................................................................... 120 17.3.2 Biến toàn cục ................................................................................. 120 17.3.3 Tham số hình thức ......................................................................... 120 17.3.4 Tham số thực thụ ........................................................................... 121 17.4 Cách gọi hàm ....................................................................................... 121 17.4.1 Lời gọi hàm ................................................................................... 121 17.4.2 Truyền tham số cho hàm ............................................................... 122 17.4.3 Đệ qui ............................................................................................ 122 17.5 Nguyên tắc hoạt động của hàm ............................................................ 124 17.6 Cấu trúc của một chương trình có nhiều hàm ...................................... 124 17.7 Bài tập về hàm ..................................................................................... 125 Đề cương bài giảng Cơ sở kỹ thuật lập trình 7 BÀI 18: THẢO LUẬN/BÀI TẬP VỀ HÀM ................................................. 127 BÀI 19: THỰC HÀNH VỀ HÀM .................................................................. 129 BÀI 20: CON TRỎ VÀ ỨNG DỤNG ........................................................... 130 20.1. Giới thiệu về con trỏ .............................................................................. 130 20.2. Khai báo và sử dụng con trỏ .................................................................. 130 20.2.1. Khai báo con trỏ .............................................................................. 130 20.2.2. Sử dụng con trỏ ............................................................................... 131 20.3. Một số ứng dụng của con trỏ ................................................................. 133 20.3.1. Con trỏ và mảng một chiều ............................................................. 133 20.3.2. Con trỏ và mảng hai chiều ............................................................. 135 20.3.3. Con trỏ và xâu ký tự ....................................................................... 136 BÀI 21: THỰC HÀNH VỀ CON TRỎ.......................................................... 137 BÀI 22: THẢO LUẬN/BÀI TẬP VỀ CON TRỎ ......................................... 138 BÀI 23: KIỂM TRA THỰC HÀNH .............................................................. 145 Đề cương bài giảng Cơ sở kỹ thuật lập trình 8 BÀI 1: CÁC THÀNH PHẦN CƠ BẢN CỦA NGÔN NGỮ LẬP TRÌNH MỤC TIÊU Học xong bài này sinh viên có khả năng: o Trình bày được cấu trúc chung của một chương trình và các thành phần cơ bản của ngôn ngữ lập trình; o Trình bày được đặc điểm, cách sử dụng của các kiểu dữ liệu; o Trình bày được quy tắc khai báo biến, hằng; o Sử dụng được các phép toán cơ bản vào bài toán cụ thể; o Rèn luyện tính tư duy, logic trong lập trình. 1.1 Cấu trúc chung của một chƣơng trình Ngôn ngữ lập trình là một hệ thống được ký hiệu hóa để miêu tả những tính toán (qua máy tính) dưới dạng mà cả con người và máy đều có thể đọc và hiểu được. Như vậy, theo định nghĩa ở trên thì một ngôn ngữ lập trình phải thỏa mãn được hai điều kiện cơ bản sau: - Dễ hiểu và dễ sử dụng đối với người lập trình, để có thể dùng để giải quyết nhiều bài toán khác nhau. - Miêu tả một cách đầy đủ và rõ ràng các tiến trình, để chạy được trên các hệ máy tính khác nhau. Một tập hợp các chỉ thị được biểu thị qua ngôn ngữ lập trình nhằm mục đích thực hiện các thao tác nào đó được gọi là một chương trình. Khái niệm này còn có những tên khác như chương trình máy tính hay chương trình điện toán. 1.1.1 Cấu trúc của một chƣơng trình Cấu trúc chung của một chương trình gồm những thành phần chính như sau: Đề cương bài giảng Cơ sở kỹ thuật lập trình 9 Để có cái nhìn tổng quan về cấu trúc của một chương trình, hãy xét ví dụ về chương trình hiện lên dòng chữ “Hello World” trên màn hình. Trong giới lập trình, chương trình “Hello World” không quá xa lạ gì, vì đó được xem là một chương trình đầu tiên và chuẩn nhất cho cái nhìn bao quát về một ngôn ngữ nào đó được đề cập đến. Nhưng nếu bạn chưa biết gì về lập trình thì cũng nên biết về chương trình này, và sau này nếu có muốn học một ngôn ngữ khác thì bạn vẫn có thể tìm kiếm một “Hello World” khác để biết ngôn ngữ đó khai báo như thế nào? bắt đầu ra sao? có khác gì so với ngôn ngữ mà mình đã biết hay không. Và để có câu trả lời, hãy cùng theo dõi ví dụ sau. Ví dụ được minh họa trên ngôn ngữ lập trình C: 1.1.2 Các bƣớc để tạo và thực hiện một chƣơng trình a) Qui trình viết và thực hiện chương trình Trước khi viết và chạy một chương trình thông thường chúng ta cần: 1. Xác định yêu cầu của chương trình: Nghĩa là xác định dữ liệu đầu vào (input) cung cấp cho chương trình và tập các dữ liệu cần đạt được - tức đầu ra (output). Các tập hợp dữ liệu này ngoài các tên gọi còn cần xác định kiểu của nó. Ví dụ để giải một #include /* Lời gọi thư viện Nhập xuất */ #include /* Lời gọi thư viện xử lý màn hình */ int main() /* Hàm chính(bắt buộc có) của chương trình*/ { printf("Hello World!"); /* Xuất ra màn hình dòng chữ Hello World!*/ getch(); /* Đợi người dùng nhập vào 1 phím bất kỳ rồi mới tiếp tục */ return 0; /* Kết thúc hàm*/ } 1. Lời gọi các thư viện sẽ sử dụng trong chương trình 2. Khai báo hằng, biến toàn cục 3. Khai báo chương trình con 4. Chương trình chính Đề cương bài giảng Cơ sở kỹ thuật lập trình 10 phương trình bậc 2 dạng: ax2 + bx + c = 0, cần báo cho chương trình biết dữ liệu đầu vào là a, b, c và đầu ra là nghiệm x1 và x2 của phương trình. Kiểu của a, b, c, x1, x2 là các số thực. 2. Xác định thuật toán giải. 3. Cụ thể hoá các khai báo kiểu và thuật toán thành dãy các lệnh, tức viết thành chương trình thông thường là trên giấy, sau đó bắt đầu soạn thảo vào trong máy. Quá trình này được gọi là soạn thảo chương trình nguồn. 4. Dịch chương trình nguồn để tìm và sửa các lỗi gọi là lỗi cú pháp. 5. Chạy chương trình, kiểm tra kết quả in ra trên màn hình. Nếu sai, sửa lại chương trình, dịch và chạy lại để kiểm tra. Quá trình này được thực hiện lặp đi lặp lại cho đến khi chương trình chạy tốt theo yêu cầu đề ra của lập trình. b) Soạn thảo tệp chương trình nguồn Soạn thảo chương trình nguồn là một công việc đơn giản: gõ nội dung của chương trình (đã viết ra giấy) vào trong máy và lưu lại nó lên đĩa. Thông thường khi đã lưu lại chương trình lên đĩa lần sau sẽ không cần phải gõ lại. Mục đích của soạn thảo là tạo ra một văn bản chương trình và đưa vào bộ nhớ của máy. Văn bản chương trình cần được trình bày sáng sủa, rõ ràng. Các câu lệnh cần gióng thẳng cột theo cấu trúc của lệnh (các lệnh chứa trong một lệnh cấu trúc được trình bày thụt vào trong so với điểm bắt đầu của lệnh). Các chú thích nên ghi ngắn gọn, rõ nghĩa và phù hợp. c) Dịch chương trình Sau khi đã soạn thảo xong chương trình nguồn, bước tiếp theo thường là dịch (trong C ấn phím F11 hoặc chọn Build/ compile) để tìm và sửa các lỗi gọi là lỗi cú pháp. Trong khi dịch chương trình sẽ đưa ra thông báo lỗi và chỉ ra nơi gây lỗi. Để chương trình có thể chạy được thì người lập trình phải sửa hết những lỗi đó. Quá trình dịch và sửa lỗi cứ diễn ra cho đến khi nào chương trình không còn lỗi và đưa ra thông báo dịch thành công. Sản phẩm sau khi dịch là một tệp mới gọi là chương trình đích có đuôi EXE tức là tệp mã máy để thực hiện. Tệp này có thể lưu tạm thời trong bộ nhớ phục vụ cho quá trình chạy chương trình hoặc lưu lại trên đĩa tuỳ theo tuỳ chọn khi dịch của lập trình. Đề cương bài giảng Cơ sở kỹ thuật lập trình 11 d) Chạy chương trình Để chạy chương trình, trong C ấn phím F5 hoặc chọn Build/ Run, nếu chương trình chưa dịch sang mã máy, máy sẽ tự động dịch lại trước khi chạy. Kết quả của chương trình sẽ hiện ra trong một cửa sổ kết quả để người lập trình kiểm tra. Nếu kết quả chưa được như mong muốn thì quay lại văn bản để sửa và lại chạy lại chương trình. Quá trình này được lặp lại cho đến khi chương trình chạy đúng như yêu cầu đã đề ra. Khi chương trình chạy, cửa sổ kết quả sẽ hiện ra tạm thời che khuất cửa sổ soạn thảo. Sau khi kết thúc chạy chương trình cửa sổ soạn thảo sẽ tự động hiện ra trở lại và che khuất cửa sổ kết quả. 1.1.3 Một số quy tắc cần nhớ khi viết chƣơng trình a) Quy tắc 1: Mỗi câu lệnh có thể viết trên một hay nhiều dòng nhưng phải kết thúc bằng dấu chấm phẩy (;) b) Quy tắc 2: Có 2 cách ghi chú thích trong chương trình: - Cách 1: Các lời giải thích cần đặt giữa các dấu /* và */ và có thể được viết:  Trên một dòng  Trên nhiều dòng  Trên phần còn lại của dòng - Cách 2: Các lời chú thích đặt sau dấu // thường được dùng khi lời chú thích được viết trên 1 dòng. c) Quy tắc 3: Trong chương trình, khi ta sử dụng các hàm chuẩn, ví dụ như getch() mà hàm này lại được chứa trong file conio.h trong thư mục của C, vì vậy ở đầu chương trình ta phải khai báo sử dụng: #include d) Quy tắc 4: Đề cương bài giảng Cơ sở kỹ thuật lập trình 12 Một chương trình có thể chỉ có một hàm chính (hàm main()) hoặc có thể có thêm vài hàm khác nữa. 1.2 Các thành phần cơ bản của một ngôn ngữ lập trình 1.2.1 Bảng chữ cái Mọi ngôn ngữ lập trình đều được xây dựng từ một bộ ký tự nào đó. Các ký tự được nhóm lại theo nhiều cách khác nhau để tạo nên các từ. Các từ lại đươc liên kết với nhau theo một quy tắc nào đó để tạo nên các câu lệnh. Một chương trình bao gồm nhiều câu lệnh thể hiện một thuật toán để giải một bài toán cụ thể. Hầu hết các ngôn ngữ lập trình đều được xây dựng trên bộ ký tự sau: 26 chứ cái hoa: A, B, C,.Z 26 chữ cái thường: a,b,c,.z 10 chữ số: 0,1,20 Các ký hiệu toán học như: + - * / = ( ) Ký tự gạch nối: _ (chú ý phân biệt với dấu - ) Các ký hiệu đặc biệt khác như: . , ; [] {} ? ! \ & | % # $ . Dấu cách (space) thực sự là một khoảng trống để tách các từ. Ví dụ HUNG YEN gồm 8 ký tự, còn HUNGYEN gồm 7 ký tự.  Chú ý: Khi viết chương trình ta không được sử dụng bất kỳ ký hiệu nào khác ngoài tập các ký tự nói trên. Chẳng hạn, khi giải phương trình bậc hai: ax 2 + bx + c = 0 ta cần tính biệt thức: ∆ = b2 - 4ac Ký tự ∆ không cho phép dùng trong ngôn ngữ C, vì vậy ta phải dùng một ký hiệu khác để thay thế như là d hoặc delta 1.2.2 Từ khóa Từ khóa trong ngôn ngữ lập trình là các từ hay ký hiệu mà đã được ngôn ngữ đó gán cho một ý nghĩa xác định. Người lập trình sẽ không được phép dùng lại các từ khóa này dưới một ý nghĩa khác. Thường các từ khóa này được ngôn ngữ xác định Đề cương bài giảng Cơ sở kỹ thuật lập trình 13 dùng trong các kiểu dữ liệu cơ bản hay trong các dòng điều khiển. Ví dụ một số từ khóa thường sử dụng trong ngôn ngữ C: break case Char continue default double else Float for goto if int Long return short static struct switch typedef unsigned void while Ý nghĩa và cách sử dụng của chúng sẽ được lần lượt giới thiệu ở các mục sau. Ở đây ta chỉ cần nhớ hai trường hợp: - Không được dùng từ khóa để đặt tên cho các hằng, biến, mảng, hàm, - Từ khóa phải được viết bằng chữ thường. Chẳng hạn, không được viết BREAK mà phải viết là break. 1.2.3 Tên (định danh) Tên (định danh) được dùng để xác định các đối tượng khác nhau trong một chương trình. Chúng ta có tên hằng, tên biến, tên mảng, tên con trỏ, tên tệp, tên nhãn, Trong ngôn ngữ C, khi đặt tên phải tuân thủ theo quy tắc sau: - Không chứa dấu cách - Không bắt đầu bằng số - Không chứa các ký tự đặc biệt (như: % ? / + =,) - Không trùng với từ khóa, kiểu dữ liệu Ví dụ 1.1: Cách đặt tên đúng: Ví dụ 1.2: Cách đặt tên sai: 4abc_3; // ký tự đầu tiên là số abc#3; //sử dụng ký tự sinh_vien; gptb_2; Đề cương bài giảng Cơ sở kỹ thuật lập trình 14 f(x); //sử dụng các dấu ngoặc tròn int; //trùng với từ khóa del ta; //sử dụng khoảng trống A-1; //sử dụng dấu gạch ngang  Chú ý: Trong C, với các tên thì chữ hoa và chữ thường được xem là khác nhau, như vậy tên HocSinh và hocsinh là khác nhau. Thường dùng chữ hoa để đặt tên cho các hằng và dùng chữ thường để đặt tên cho hầu hết các đối tượng khác như biến, hằng, mảng, hàm, cấu trúc. Tuy nhiên, đây không phải là điều bắt buộc. 1.3 Các kiểu dữ liệu cơ bản Thông thường, dữ liệu hay dùng là số và chữ. Tuy nhiên việc phân chia chỉ 2 loại dữ liệu là không đủ. Để dễ dàng hơn cho việc lập trình, hầu hết các ngôn ngữ lập trình đều phân chia dữ liệu thành nhiều kiểu khác nhau được gọi là các kiểu cơ bản hay chuẩn. Trên cơ sở kết hợp các kiểu dữ liệu chuẩn, người sử dụng có thể tự đặt ra các kiểu dữ liệu mới để phục vụ cho chương trình giải quyết bài toán của mình. Có nghĩa lúc đó mỗi đối tượng được quản lý trong chương trình sẽ là một tập hợp nhiều thông tin hơn và được tạo thành từ nhiều loại (kiểu) dữ liệu khác nhau. Tất cả các biến cần phải được khai báo trước khi sử dụng và kiểu của chúng phải được mô tả ngay khi khai báo. Việc khai báo này sẽ làm chương trình quản lý các biến dễ dàng hơn như trong việc phân bố bộ nhớ cũng như quản lý các tính toán trên biến theo nguyên tắc: chỉ có các dữ liệu cùng kiểu với nhau mới được phép làm toán với nhau. Do đó, khi đề cập đến một kiểu chuẩn của một ngôn ngữ lập trình, thông thường chúng ta sẽ xét đến các yếu tố sau: - Tên kiểu: là một từ dành riêng để chỉ định kiểu của dữ liệu. - Số byte trong bộ nhớ để lưu trữ một đơn vị dữ liệu thuộc kiểu này: Thông thường số byte này phụ thuộc vào các trình biên dịch và hệ thống máy khác nhau, ở đây ta chỉ xét đến hệ thống máy PC thông dụng hiện nay. - Miền giá trị của kiểu: Cho biết một đơn vị dữ liệu thuộc kiểu này sẽ có thể lấy giá trị trong miền nào, ví dụ nhỏ nhất và lớn nhất là bao nhiêu. Hiển nhiên các giá trị này phụ thuộc vào số byte mà hệ thống máy qui định cho từng kiểu. Đề cương bài giảng Cơ sở kỹ thuật lập trình 15 Người sử dụng cần nhớ đến miền giá trị này để khai báo kiểu cho các biến cần sử dụng một cách thích hợp. Dưới đây sẽ lần lượt trình bày về 3 kiểu dữ liệu đơn giản chuẩn và thông dụng: Kiểu ký tự, kiểu nguyên, kiểu dấu phẩy động. 1.3.1 Kiểu ký tự Một giá trị kiểu ký tự chiếm 1 byte (8 bit) và biểu diễn được một ký tự thông qua bảng mã ASCII. Ví dụ: Ký tự Mã ASCII 0 048 1 049 2 050 A 065 B 066 A 097 B 098 Trong C, có hai kiểu ký tự là signed char và unsigned char. Kiểu thứ nhất biểu diễn một số nguyên từ -128 đến 127, kiểu thứ hai có giá trị từ 0 đến 255. Bảng dưới đây cho kích cỡ và phạm vi biểu diễn của giá trị kiểu char. Kiểu Phạm vi biểu diễn Số ký tự Kích thƣớc (byte) unsigned char 0 ->255 256 1 Char -128 ->127 256 1 Phân loại ký tự: Có thể chia 256 ký tự thành 3 nhóm: - Nhóm thứ nhất là các ký tự điều khiển có mã từ 0 đến 31. Chẳng hạn ký tự mã 13 dùng để chuyển con trỏ về đầu dòng, ký tự 10 chuyển con trỏ xuống dòng dưới (trên cùng cột). Các ký tự nhóm này nói chung không hiển thị ra màn hình. - Nhóm thứ hai là các ký tự văn bản có mã từ 32 đến 126. Các ký tự này có thể đưa ra màn hình và máy in. Đề cương bài giảng Cơ sở kỹ thuật lập trình 16 - Nhóm thứ ba là các ký tự đồ họa có mã từ 127 đến 255. Các ký tự này có thể đưa ra màn hình nhưng không in được. 1.3.2 Kiểu số nguyên Kiểu số nguyên là kiểu dữ liệu dùng để lưu các giá trị nguyên hay còn gọi là kiểu đếm được. Kiểu số nguyên trong C được chia thành các kiểu dữ liệu con, mỗi kiểu có một miền giá trị khác nhau. Trong C cho phép sử dụng: số nguyên (int), số nguyên dài (long) và số nguyên không dấu (unsigned). Kích cỡ và phạm vi biểu diễn của chúng được chỉ ra trong bảng dưới đây: Kiểu Phạm vi biểu diễn Kích thƣớc (byte) unsigned int 0 -> 65535 2 int -32768 -> 32767 2 unsigned long [int] 0 -> 4.294967295 4 long [int] -2147483648 -> 2147483648 4  Lƣu ý: Kiểu long int có thể viết gọn thành long, kiểu unsigned int viết gọn thành unsigned. Có thế kết hợp nhiều tiền tố với một kiểu dữ liệu cơ sở, chẳng hạn unsigned long int viết gọn thành unsigned long. 1.3.3 Kiểu dấu phẩy động Kiểu dấu phẩy động biểu diễn cho các số thập phân có dấu. Trong C cho phép sử dụng 3 loại giá trị dấu phẩy động là float, double và long double. Kích cỡ và phạm vi biểu diễn của chúng được chỉ ra trong bảng dưới đây: Kiểu Phạm vi biểu diễn Kích thƣớc (byte) float 3.4E-38 -> 3.4E+38 4 double 1.7E-308 -> 1.7E+308 8 long double 3.4E4932 -> 3.4E+4932 10 Đề cương bài giảng Cơ sở kỹ thuật lập trình 17 Máy tính có thể lưu trữ được số kiểu float có giá trị tuyệt đối từ 3.4E-38 đến 3.4E+38. Số có giá trị tuyệt đối nhỏ hơn 3.4E-38 được xem bằng 0. Phạm vi biểu diễn của số double cũng được hiểu theo nghĩa tương tự. 1.4 Biến, hằng và cách khai báo 1.4.1 Biến và cách khai báo Một biến là một tên gọi cho một đại lượng hoặc một đối tượng nào đó. Mỗi biến đều được phân bổ một địa chỉ trong bộ nhớ dùng để lưu giữ giá trị của biến. Giá trị này có thể thay đổi trong khi chương trình thực hiện. Trong C, một biến chỉ có thể được sử dụng sau khi đã được khai báo. Một khai báo biến cho chương trình dịch biết tên của biến và kiểu của dữ liệu mà nó lưu giữ. a) Khai báo Quy tắc khai báo: Kiểu_dữ_liệu  Danh_sách_tên_biến; Danh sách tên biến: Gồm các tên biến có cùng kiểu dữ liệu, mỗi tên biến được phân cách nhau bằng dấu phẩy(,), cuối cùng là dấu chấm phẩy (;). Ví dụ 1.3: Biến kiểu int chỉ nhận được các giá trị kiểu int. Các biến khác nhau cũng có ý nghĩa tương tự, chẳng hạn biến kiểu char chỉ chứa được một ký tự. Để lưu trữ một xâu ký tự cần sử dụng một mảng kiểu char. b) Khởi tạo cho các biến Khi khai báo biến, giá trị của nó mặc nhiên là không xác định. Nhưng có thể bạn sẽ muốn nó mang một giá trị xác định khi được khai báo. Để làm điều đó, bạn chỉ cần int a; /* Khai báo biến a kiểu int */ long ax, bx, cx; /* Khai báo ba biến kiểu long */ char beta, alpha; /* Khai báo hai biến kiểu char */ float x,y; /* Khai báo hai biến kiểu float */ double x,y; /* Khai báo hai biến kiểu double */ Đề cương bài giảng Cơ sở kỹ thuật lập trình 18 viết dấu bằng và giá trị bạn muốn biến đó sẽ mang. Chúng ta có thể kết hợp việc khai báo với toán tử gán để biến nhận ngay giá trị cùng lúc với khai báo:  Khai báo trước, gán giá trị sau: Kiểu_dữ_liệu  Tên_biến; Tên_biến = Giá_trị_khởi_tạo; Ví dụ 1.4:  Vừa khai báo, vừa gán giá trị Kiểu_dữ_liệu  Tên_biến = Giá_trị_khởi_tạo; Ví dụ 1.6: 1.4.2 Hằng và cách khai báo Hằng cũng là một biến nhưng giá trị của hằng không thay đổi. Tuy nhiên khi làm việc với một giá trị được định nghĩa là không thay đổi, ta phải đảm bảo giá trị của nó không được thay đổi trong suốt chương trình nên khi đó sử dụng biến sẽ không thích hợp. Chẳng hạn, khi lập một chương trình thí nghiệm hóa học liên quan đến nhiệt độ sôi hay nhiệt độ đông của nước, chương trình cần khai báo hai biến là DoSoi và DoDong, nhưng không cho phép giá trị của hai biến này bị thay đổi hay bị gán. Để ngăn việc gán giá trị khác, ta phải sử dụng biến kiểu hằng. a) Cách khai báo hằng Hằng có thể định nghĩa bằng hai cách: Cách 1: Dùng toán tử #define nhằm định nghĩa một hằng, ký hiệu #define   int a,b,c; /* Khai báo các biến a,b,c kiểu int */ char ch; /* Khai báo biến ch kiểu char */ a=0; b=15; c=21; ch=’A’; /* Khởi tạo giá trị cho các biến */ int a=0,b=15,c=21; /* Khai báo, đồng thời khởi tạo giá trị cho các biến */ char ch=’A’; Đề cương bài giảng Cơ sở kỹ thuật lập trình 19 Cấu trúc này định nghĩa một hằng ký hiệu có tên bằng . Khi biên dịch chương trình, chương trình dịch thay thế các lần xuất hiện của bằng xâu ký tự tương ứng, ví dụ: #define MAX 100 Cách 2: const  kieu_du_kieu  ten_hang = gia_tri_hang; const int n=20; b) Một số loại hằng cơ bản  Hằng số nguyên(int) - Hệ thập phân bình thường, ví dụ: 545 - Hệ cơ số 8 (Octal): Bắt đầu bằng số 0 và chỉ biểu diễn số dương, ví dụ: 024=2010 - Hệ cơ số 16 (Hecxa) Bắt đầu bằng 0x, ví dụ: 0xAB = 16310  Chú ý: Nếu là hằng kiểu long thì thêm l (hay L) vào đuôi, ví dụ: 123L, 858L Một hằng số nguyên có giá trị vượt ra ngoài phạm vi cho phép được ngầm hiểu là hằng long.  Hằng số thực Được viết theo hai cách sau: - Dạng thập phân gồm: Phần nguyên, dấu chấm thập phân, phần thập phân, ví dụ: 34.2 -344.122  Chú ý: Phần nguyên hay phần thập phân có thể vắng mặt nhưng dấu chấm thập phân không được thiếu, ví dụ: 343. .454 - Dạng khoa học(dạng mũ) gồm: Phần định trị và phần mũ. Phần định trị là số nguyên hay số thực dạng thập phân, phần mũ bắt đầu bằng E hoặc e theo sau là số nguyên, ví dụ: 1234.54E-122  Hằng ký tự Là một ký hiệu trong bảng mã ASCII được đặt trong hai dấu nháy đơn. Giá trị của hằng kí tự chính là mã ASCII của kí hiệu, ví dụ: Hằng „A‟ có giá trị là 65. Đề cương bài giảng Cơ sở kỹ thuật lập trình 20  Chú ý: Hằng ký tự biểu thị mã của ký tự đó trong bảng mã ASCII. Do vậy một hằng ký tự cũng có thể tham gia vào các phép toán, ví dụ: „A‟+10 có giá trị (65+10=75). Hằng ký tự còn có thể được viết theo cách: „\c1c2c3‟ Trong đó, c1c2c3 là một số hệ 8 mà giá trị của nó chính là mã ASCII của ký tự cần biểu diễn, ví dụ: „a‟ hay „\141‟ Một số ký tự đặc biệt: Viết Ký tự Diễn giải \‟ „ Dấu nháy đơn \” “ Dấu nháy kép \\ \ Dấu gạch chéo ngược \n \n Xuống dòng mới \0 \0 Ký tự null \t Nhảy cách ngang, ký tự tab \b Xoá trái \r Về đầu dòng \f Sang trang  Hằng xâu ký tự - Là một dãy các ký tự đặt trong hay dấu nháy “......” - Xâu ký được lưu trữ trong một mảng ô nhớ liền nhau song còn thêm ô nhớ cuối cùng chứa mã là 0 (ký hiệu là „\0‟ ) Ví dụ 1.6: Xâu ký tự: “Nguyen Van Anh” Được tổ chức trong bộ nhớ như sau: N g u y e n V a n A n h \0  Chú ý: Chúng ta cần phân biệt “A” và „A‟. Trong đó “A” được chứa trong 2 byte, còn „A‟ chỉ mất 1 byte và nó có thể tham gia tính toán trong các biểu thức. Đề cương bài giảng Cơ sở kỹ thuật lập trình 21 TÓM TẮT  Cấu trúc chung của một chương trình  Các thành phần cơ bản của một ngôn ngữ lập trình: Bảng chữ cái, từ khóa, tên.  Các kiểu dữ liệu cơ bản  Biến, hằng và cách khai báo Đề cương bài giảng Cơ sở kỹ thuật lập trình 22 BÀI 2: BIỂU THỨC, CÁC PHÉP TOÁN VÀ VẤN ĐỀ NHẬP XUẤT MỤC TIÊU Học xong bài này sinh viên có khả năng: o Phân biệt được câu lệnh và khối lệnh o Sử dụng được các phép toán cơ bản trong C vào bài toán cụ thể o Viết được câu lệnh nhập/xuất dữ liệu o Rèn luyện tính cẩn thận và tư duy sáng tạo trong lập trình. 2.1 Biểu thức Biểu thức là một sự kết hợp giữa các phép toán và các toán hạng để diễn đạt một công thức nào đó. Các toán hạng có thể là một đại lượng nào đó có giá trị như: hằng, biến hay một biểu thức con. Mỗi biểu thức có một giá trị, tùy theo giá trị của biểu thức mà có các biểu thức nguyên hay biểu thức thực. Các mệnh đề logic có giá trị nguyên trong đó có giá trị khác 0 tương ứng mệnh đề đúng, còn giá trị 0 tương ứng mệnh đề sai. Biểu thức được sử dụng trong: Vế phải của lệnh gán; làm tham số thực của các hàm; làm chỉ số; các câu lệnh if, for, while, do while; các biểu thức lớn hơn của các hàm; làm chỉ số; các câu lệnh if, for, while, do while; các biểu thức lớn hơn.. Trong C, một biểu thức là một mệnh đề dùng để tính ra một giá trị nào đó. Các biểu thức C có thể có độ phức tạp tùy ý. 2.2 Câu lệnh, khối lệnh 2.2.1 Câu lệnh Một câu lệnh là một phương hướng hành động hướng dẫn cho máy tính thực hiện một nhiệm vụ nào đó. Mỗi câu lệnh được viết trên một dòng, nhưng cũng có những câu lệnh phải viết trên nhiều dòng. Mỗi câu lệnh được kết thúc bằng dấu chấm phẩy (;) (trừ các chỉ thị, chẳng hạn như #include và #define). Ngăn cách này chỉ đơn giản Đề cương bài giảng Cơ sở kỹ thuật lập trình 23 là chỉ cho ngôn ngữ lập trình biết rằng, đã kết thúc một câu lệnh và có thể chuyển qua câu lệnh mới. Ví dụ 2.1: char ten[30];// đây là một câu lệnh printf(“Nhap vao ten cua ban:”); scanf(“%s”, ten); printf(“Chao ban%s”, ten); 2.2.2 Các câu lệnh và các khoảng trắng Thuật ngữ khoảng trắng (whitespace) là để chỉ các dấu cách, tabs và các dòng rỗng trong chương trình gốc. Chương trình dịch C không xét đến các khoảng trắng. Khi chương trình dịch đọc một câu lệnh trong một chương trình gốc, nó sẽ đọc tất cả các ký tự trong câu lệnh này cho đến khi gặp dấu chấm phẩy nhưng bỏ qua tất cả các khoảng trắng. Vì vậy, câu lệnh x=2+3; trên đây là hoàn toàn tương đương với x = 2 + 3; và với x = 2 + 3 ; Mỗi câu lệnh nên viết trên một dòng và nên có một dấu cách đứng trước và một dấu cách đứng sau mỗi tên biến. Trước và sau mỗi khối nên có một dòng trống để dễ nhận biết từng khối một. Ngoài ra, có thể dùng tabs để đẩy một khối thụt vào so với lề trái nhằm tạo ra một cấu trúc có tính phân cấp trong chương trình. Tuy nhiên, trong một xâu các ký tự thì các dấu cách và các dấu tabs lại không bị bỏ qua, chúng được coi là một bộ phận của xâu ký tự này. Một xâu là một dãy các ký tự. Các hằng ký tự thực sự là các xâu được đặt trong các dấu nháy và được chương trình dịch xử lý từng ký tự một. Đề cương bài giảng Cơ sở kỹ thuật lập trình 24 Nếu chỉ có đúng một dấu chấm phẩy trên một dòng nào đó, thì dòng này được gọi là câu lệnh rỗng. Câu lệnh rỗng không thực hiện bất kỳ hành động nào. 2.2.3 Khối lệnh Khối lệnh là một tập hợp gồm hai hay nhiều câu lệnh với nhau và được đặt trong cặp dấu { }. Ví dụ 2.2: { // đây là đầu khối lệnh char ten[30]; printf(“Nhap vao ten cua ban:”); scanf(“%s”, ten); printf(“Chao ban %s”, ten); } // đây là cuối khối lệnh 2.3 Các phép toán 2.3.1 Các phép toán số học STT Phép toán Ý nghĩa Ví dụ Kết quả 1 - Phép đổi dấu -(10+2) -12 2 + Phép cộng 3+12 15 3 - Phép trừ 7-2 5 4 * Phép nhân 2*3 6 5 / Phép chia 6/3 2 6 % Phép lấy phần dư a = 6%4 2  Chú ý: - Nếu phép chia hai toán hạng đều nguyên thì phép chia cho kết quả là phần nguyên của thương hai toán hạng đó, ví dụ: 5/2=2 - Nếu một trong hai toán hạng là kiểu thực thì lúc này kết quả của phép chia cho ta giá trị đúng, ví dụ 5/2.0=2.5 Đề cương bài giảng Cơ sở kỹ thuật lập trình 25 2.3.2 Phép toán so sánh Phép toán so sánh được dùng để so sánh giữa hai giá trị, và sau đó trả về kết quả là một giá trị kiểu bool (true hay false). Ví dụ toán tử so sánh lớn hơn (>) trả về giá trị là true nếu giá trị bên trái của toán tử lớn hơn giá trị bên phải của toán tử. Do vậy 5 > 2 trả về một giá trị là true, trong khi 2 > 5 trả về giá trị false. STT Phép toán ý nghĩa Ví dụ Kết quả 1 > So sánh lớn hơn 1>2 false 2 >= So sánh lớn hơn hoặc bằng 2>=2 true 3 < So sánh nhỏ hơn 3<3 false 4 <= So sánh nhỏ hơn hoặc bằng 4<2 false 5 == So sánh bằng nhau 4==5 false 6 != So sánh không bằng nhau 2!=7 true 2.3.3 Phép toán logic Các phép toán logic cũng trả ra giá trị kiểu bool (true hay false). STT Phép toán Ý nghĩa Ví dụ Kết quả 1 ! Phép phủ định một ngôi (not) !(3>1) false 2 && Liên kết hai biểu thức logic Phép và (and). Giá trị bằng 1 khi cả 2 toán hạng có giá trị 1 (2>1)&&(5=2) false 3 || Liên kết hai biểu thức logic. Phép hoặc (or). Giá trị biểu thức bằng 1 khi một trong hai toán hạng bằng 1 (4>3)||(1>8) true Bảng giá trị của các phép toán logic: X Y X && Y X || Y ! X true true true true false true false false true false false true false true true Đề cương bài giảng Cơ sở kỹ thuật lập trình 26 false false false false true 2.3.4 Phép gán Phép gán được ký hiệu là dấu bằng (=). Cách dùng của nó trong C có khác một chút so với cách dùng của nó trong toán học thông thường. Nếu viết x = y; thì không có nghĩa là "x bằng y", mà là "gán giá trị của y cho x." Trong một câu lệnh gán, vế phải có thể là một biểu thức bất kỳ còn vế trái phải là một tên biến. Vì vậy, dạng của câu lệnh gán là: tenbien = bieuthuc; Khi được thực hiện, bieuthuc được ước lượng và giá trị của kết qủa được gán cho tenbien. 2.3.5 Thứ tự ƣu tiên các phép toán Các phép toán có độ ưu tiên khác nhau, điều này có nghĩa là trong cùng một biểu thức, một số phép toán này được thực hiện trước một số phép toán khác. Việc xác định thứ tự ưu tiên của các phép toán ảnh hưởng rất lớn đến kết quả của một phép toán. Sau đây là bảng liệt kê thứ tự ưu tiên của các phép toán: Đề cương bài giảng Cơ sở kỹ thuật lập trình 27 Các phép toán được liệt kê cùng loại sẽ có thứ tự theo mục thứ thự của bảng: thứ tự trái tức là độ ưu tiên của các phép toán từ bên trái sang, thứ tự phải thì các phép toán có độ ưu tiên từ bên phải qua trái. Các toán tử khác loại thì có độ ưu tiên từ trên xuống dưới, do vậy các toán tử loại cơ bản sẽ có độ ưu tiên cao nhất và phép toán gán sẽ có độ ưu tiên thấp nhất trong các toán tử. 2.3.6 Phép chuyển đối kiểu Khi tính toán một biểu thức phần lớn các phép toán đều yêu cầu các toán hạng phải cùng kiểu. Ví dụ để phép gán thực hiện được thì giá trị của biểu thức phải có cùng kiểu với biến. Trong trường hợp kiểu của giá trị biểu thức khác với kiểu của phép gán thì hoặc là chương trình sẽ tự động chuyển kiểu giá trị biểu thức về thành kiểu của biến được gán (nếu được) hoặc sẽ báo lỗi. Do vậy khi cần thiết người lập trình phải sử dụng các câu lệnh để chuyển kiểu của biểu thức cho phù hợp với kiểu của biến. a) Chuyển kiểu tự động Về mặt nguyên tắc, khi cần thiết các kiểu có giá trị thấp sẽ được chương trình tự động chuyển lên kiểu cao hơn cho phù hợp với phép toán. Cụ thể phép chuyển kiểu có thể được thực hiện theo sơ đồ như sau: char ↔ int → long int → float → double. Ví dụ 2.3: int i = 3; float f ; f = i + 2; Trong ví dụ trên i có kiểu nguyên và vì vậy i+2 cũng có kiểu nguyên, trong khi f có kiểu thực. Tuy vậy phép toán gán này là hợp lệ vì chương trình sẽ tự động chuyển kiểu của i+2 (bằng 5) sang kiểu thực (bằng 5.0) rồi mới gán cho f. Đề cương bài giảng Cơ sở kỹ thuật lập trình 28 b) Ép kiểu Trong chuyển kiểu tự động, chương trình chuyển các kiểu từ thấp đến cao, tuy nhiên chiều ngược lại không thể thực hiện được vì nó có thể gây mất dữ liệu. Do đó, nếu cần thiết người lập trình phải ra lệnh cho chương trình. Ví dụ 2.4: int i; float f = 3 ; // tự động chuyển 3 thành 3.0 và gán cho i = f + 2 ; // sai vì mặc dù f + 2 = 5 nhưng không gán được cho i Trong ví dụ trên để câu lệnh i = f+2 thực hiện được ta phải ép kiểu của biểu thức f+2 về thành kiểu nguyên. Cú pháp tổng quát như sau: (tên_kiểu)biểu_thức; trong đó, tên_kiểu là kiểu cần được chuyển sang. Như vậy câu lệnh trên phải được viết lại: i = int(f + 2) ; Khi đó f+2 (bằng 5.0) được chuyển thành 5 và gán cho i. Dưới đây ta sẽ xét một số ví dụ về lợi ích của việc ép kiểu.  Phép ép kiểu từ một số thực về số nguyên sẽ cắt bỏ tất cả phần thập phân của số thực, chỉ để lại phần nguyên. Như vậy để tính phần nguyên của một số thực x ta chỉ cần ép kiểu của x về thành kiểu nguyên, có nghĩa int(x) là phần nguyên của số thực x bất kỳ. Ví dụ để kiểm tra một số nguyên n có phải là số chính phương, ta cần tính căn bậc hai của n. Nếu căn bậc hai x của n là số nguyên thì n là số chính phương, tức nếu int(x) = x thì x nguyên và n là chính phương. Ví dụ 2.5: int n = 10 ; Đề cương bài giảng Cơ sở kỹ thuật lập trình 29 float x = sqrt(n) ; // hàm sqrt(n) trả lại căn bậc hai của số n if (int(x) == x) printf("n chinh phuong"); else printf("n khong chinh phuong");  Để biết mã ASCII của một kí tự ta chỉ cần chuyển kí tự đó sang kiểu nguyên. char c ; printf("Hay nhap vao 1 ky tu bat ky: "); scanf(“%c”, &c) ; printf( "Ma cua ki tu vua nhap la %d “, int(c));  Ghi chú: Xét ví dụ sau: int i = 3 , j = 5; float x ; x = i / j * 10; // x = 6 ? printf(“%f”,x) ; Trong ví dụ này mặc dù x được khai báo là thực nhưng kết quả in ra sẽ là 0 thay vì 6 như mong muốn. Lý do là vì phép chia giữa 2 số nguyên i và j sẽ cho lại số nguyên, tức i/j = 3/5 = 0. Từ đó x = 0*10 = 0. Để phép chia ra kết quả thực ta cần phải ép kiểu hoặc i hoặc j hoặc cả 2 thành số thực, khi đó phép chia sẽ cho kết quả thực và x được tính đúng giá trị. Cụ thể câu lệnh x = i/j*10 được đổi thành: x = float(i) / j * 10 ; // đúng x = i / float(j) * 10 ; // đúng x = float(i) / float(j) * 10 ; // đúng Đề cương bài giảng Cơ sở kỹ thuật lập trình 30 x = float(i/j) * 10 ; // sai Phép ép kiểu: x = float(i/j) * 10 ; vẫn cho kết quả sai vì trong dấu ngoặc phép chia i/j vẫn là phép chia nguyên, kết quả x vẫn là 0. 2.4 Nhập/xuất dữ liệu 2.4.1 Xuất dữ liệu Để đưa dữ liệu ra màn hình, trong lập trình C sử dụng hàm printf, cú pháp để xuất dữ liệu như sau: printf(“Chuỗi định dạng”[đối mục 1, đối mục 2,]);  Chú ý: Để sử dụng được hàm printf cần phải khai báo thư viện #include Trong đó: - printf là tên hàm, phải viết bằng chữ thường - Đối mục 1,: Là các mục dữ kiện cần in ra màn hình. Các đối mục này có thể là biến, hằng hoặc biểu thức phải được định trị trước khi in ra. - Chuỗi định dạng: Được đặt trong cặp nháy kép (“ ”), gồm 3 loại: o Đối với chuỗi ký tự ghi như thế nào thì in ra màn hình giống như vậy. o Đối với những kí tự chuyển đổi dạng thức cho phép kết xuất giá trị của các đối mục ra màn hình tạm gọi là mã định dạng. Sau đây là các dấu mô tả định dạng: Ký hiệu Ý nghĩa %c Ký tự đơn %s Chuỗi %d In ra kiểu int %f In ra kiểu float %e Số chấm động (ký hiệu có mũ) Đề cương bài giảng Cơ sở kỹ thuật lập trình 31 %g Số chấm động (%f hay %g) %u Số nguyên thập phân không dấu (unsigned) %x In ra số ở dạng cơ số 16 %0 In ra số ở dạng cơ số 8 L Tiền tố dùng kèm với %d, %u, %x, %0 để chỉ số nguyên dài (ví dụ ld) o Các ký tự điều khiển và ký tự đặc biệt Ký hiệu Ý nghĩa \n \n Nhảy xuống dòng kế tiếp và canh về cột đầu tiên \t Canh cột tab ngang \r Nhảy về đầu hàng, không xuống hàng \a Tiếng kêu bip \\ In ra dấu \ \” In ra dấu ” \‟ In ra dấu ‟ %% In ra dấu % Ví dụ 2.6 printf (“Bài học về nhập xuất dữ liệu\n”); // “Bài học về nhập xuất dữ liệu” là chuỗi ký tự cần in ra màn hình // \n là ký tự điều khiển xuống dòng Ví dụ 2.7 In ra màn hình tổng của hai số nguyên //Chương trình in ra tổng hai số nguyên Đề cương bài giảng Cơ sở kỹ thuật lập trình 32 #include //Khai báo thư viện nhập xuất #include //Khai báo thư viện xử lý màn hình int main() { int a = 7, b = 5; // Khai báo và khởi tạo giá trị cho biến printf(“tong cua hai so %d và %d la %d”, a, b, a+b); //In ra màn hình getch();// dừng màn hình chờ nhập vào 1 phím bất kỳ return 0; } Kết quả sau khi chạy chương trình: 2.4.2 Nhập dữ liệu Để nhập dữ liệu vào từ bàn phím, trong lập trình C sử dụng hàm scanf, cú pháp nhập như sau: scanf(“chuỗi định dạng”[đối mục 1, đối mục 2,]);  Chú ý: Để sử dụng được hàm nhập, xuất dữ liệu thì đều cần phải khai báo thư viện #include Trong đó: - scanf: Tên hàm, phải viết bằng chữ thường - Chuỗi định dạng: được đặt trong cặp nháy kép (“ ”) là hình ảnh dạng dữ liệu nhập vào. - Đối mục 1,.: mỗi đối mục sẽ tiếp nhận giá trị nhập vào. Ví dụ 2.8 scanf(“%d”, &i); //%d : định dạng dữ liệu kiểu int Đề cương bài giảng Cơ sở kỹ thuật lập trình 33 //&i: đối mục i Kết quả: Nếu nhập vào 31xyz thì biến i chỉ nhận giá trị 31, còn nếu nhập 3.1 thì biến i chỉ nhận giá trị 3. Ví dụ 2.9 Nhập vào hai số nguyên a, b rồi tính tổng của hai số nguyên đó. //Chương trình tính tổng hai số nguyên #include // Khai báo thư viện để sử dụng hàm nhập xuất #include // Thư viện xử lý màn hình int main() { int a,b; // Khai báo 2 biến nguyên printf(“Nhap gia tri cho bien a = ”); scanf(“%d”,&a); printf(“Nhap gia tri cho bien b = ”); scanf(“%d”,&b); printf(“Tong cua %d va %d la %d”,a,b,a+b); /*in ra tổng của hai số*/ getch(); return 0; } Kết quả: 2.5 Bài tập Bài tập 2.1: Hãy nhập và dịch chương trình sau đây. Chương trình này làm việc gì? Giải thích từng dòng lệnh? (không viết các số hiệu dòng khi soạn chương trình) 1: #include 2: float bankinh, dientich; 3: main() 4:  5: printf( "Nhập bán kính: " ); 6: scanf( "%f", &bankinh ); 7: dientich = 3.14159 * bankinh * bankinh; 8: printf( "\n\nDiện tích = %f", dientich ); Đề cương bài giảng Cơ sở kỹ thuật lập trình 34 9: return 0; 10:  Bài tập 2.2: . Chương trình sau đây đang có lỗi. Hãy nhập và dịch nó. Các dòng nào sinh ra thông báo lỗi? 1: include 2: main(); 3:  4: printf( "Hãy nhìn xem!" ) 5: printf( "Bạn sẽ tìm thấy nó!" ); 6: return ; 7:  Bài tập 2.3: Viết chương trình định dạng và in ra một bài thơ nào đó. Bài tập 2.4: Viết chương trình nhập vào điểm của ba môn toán, lý, hóa của một học sinh rồi in ra điểm trung bình của học sinh đó với hai số lẻ thập phân. Bài tập 2.5: Viết chương trình nhập vào ngày, tháng, năm. In ra ngày tháng năm theo định dạng dd/mm/yy. (dd: ngày, mm: thang, yy: năm; ví dụ 02/01/15). TÓM TẮT  Cấu trúc chung của một chương trình  Các thành phần cơ bản của một ngôn ngữ lập trình: Bảng chữ cái, từ khóa, tên.  Các kiểu dữ liệu cơ bản  Biến, hằng và cách khai báo Đề cương bài giảng Cơ sở kỹ thuật lập trình 35 BÀI 3: CẤU TRÚC ĐIỀU KHIỂN MỤC TIÊU Học xong bài này sinh viên có thể: o Hiểu và giải thích được cú pháp của các cấu trúc điều khiển o Vận dụng được các điều khiển if, ifthen, switchcase vào từng bài toán cụ thể o So sánh được đặc điểm của các cấu trúc điều khiển o Rèn luyện tính cẩn thận, tư duy trong lập trình. 3.1 Giới thiệu về cấu trúc điều khiển Cấu trúc lệnh điều khiển hay còn gọi là câu lệnh rẽ nhánh, là một phần không thể thiếu trong bất cứ ngôn ngữ lập trình cấp cao, có tác dụng chia chương trình ra nhiều hướng xử lý khác nhau trong một số trường hợp xác định. 3.2 Cấu trúc điều khiển rẽ nhánh if 3.2.1 Cấu trúc rẽ nhánh dạng khuyết a) Cú pháp if () Cong_viec; Trong đó: - if là từ khóa - bieu_thuc là biểu thức điều kiện - Cong_viec là một lệnh hoặc một khối lệnh b) Nguyên tắc hoạt động Bước 1: Xác định giá trị của bieu_thuc Đề cương bài giảng Cơ sở kỹ thuật lập trình 36 Bước 2: Tùy thuộc vào giá trị của bieu_thuc mà máy sẽ tiến hành lựa chọn một trong hai nhánh: - Nếu bieu_thuc trả ra giá trị True thì máy sẽ tiến hành thực hiện Công_việc. - Nếu bieu_thuc trả ra giá trị False thì máy sẽ bỏ qua Công_việc trong câu lệnh if mà tiến hành thực hiện các câu lệnh sau câu lệnh if. Ví dụ 3.1 Viết chương trình nhập vào 3.2.2 Cấu trúc rẽ nhánh dạng đủ a) Cú pháp if() Cong_viec_1; else Cong_viec_2; Trong đó: - if, else là từ khóa - bieu_thuc là biểu thức điều kiện - Cong_viec_1, Cong_viec_2 là một lệnh hoặc một khối lệnh. b) Nguyên tắc hoạt động Bước 1: Xác định giá trị của biểu thức điều kiện Bước 2: Tùy vào giá trị của bieu_thuc mà máy sẽ tiến hành lựa chọn một trong hai nhánh: - Nếu bieu_thuc trả ra giá trị True thì máy sẽ tiến hành thực hiện Cong_viec_1; - Ngược lại, nếu bieu_thuc trả ra giá trị False thì máy sẽ tiến hành thực hiện Cong_viec_2; Ví dụ 3.2 Đề cương bài giảng Cơ sở kỹ thuật lập trình 37 Viết chương trình nhập vào tổng điểm của 3 môn toán, lý, hóa. Nếu tổng điểm 3 môn >=15 thì in ra màn hình: “Đạt” Ngược lại thì in ra màn hình: “Không đạt”. Hƣớng dẫn: Input: Tổng điểm của 3 môn. Output: Đạt/ Không đạt - Bước 1: Nhập điểm của 3 môn, giả sử đặt tên biến là tong có kiểu dữ liệu float (vì điểm có thể lẻ). - Bước 2: Sử dụng cấu trúc ifelse để kiểm tra: o Nếu tong >=15 thì in ra màn hình: “Đạt” o Ngược lai thì in ra màn hình: “Không đạt” - Bước 3: Kết thúc chương trình; Chƣơng trình minh họa: // Chương trình nhập và kiểm tra giá trị #include // Khai báo thư viện nhập xuất #include // Khai báo thư viện xử lý màn hình int main() // Chương trình chính { float tong; // Khai báo biến // Nhap gia tri cho bien printf(“Nhap vao tong diem cua 3 mon: ”); scanf(“%f”,&tong); if (tong>=15) printf(“\n Dat”); else printf(“\n Khong dat”); Đề cương bài giảng Cơ sở kỹ thuật lập trình 38 getch(); return 0; } 3.3 Cấu trúc điều khiển rẽ nhánh swicth a) Cú pháp switch () { case gt1: Khối_lệnh_1; [break;] case gt2: Khối_lệnh_2; [break;] .. case gtn: Khối_lệnh_n; [break;] [default: Khối_lệnh_n+1;] } Trong đó: - switch, case, default là các từ khóa - bieu_thuc là một biểu thức nguyen bất kỳ - gti là giá trị mà bieu_thuc có thể nhận được. Có thể là kiểu chả vì nó có thể chuyển đổi thành kiểu int. - Những phần đặt trong hai dấu [ và ] có thể có hoặc không. b) Nguyên tắc hoạt động Sự hoạt động của cấu trúc điều khiển switch phụ thuộc vào giá trị của bieu_thuc. - Bước 1: Tính giá trị của bieu_thuc - Bước 2: Tùy thuộc vào giá trị của bieu_thuc mà máy sẽ thực hiện những công viêc khác nhau, cụ thể: Đề cương bài giảng Cơ sở kỹ thuật lập trình 39 o Khi giá trị này bằng gti máy sẽ nhảy tới khối lệnh có nhãn case gti và thực hiện Khối_lệnh_i. Nếu Khối_lệnh_i là rỗng thì ta có thể đặt break sau Khối_lệnh_i hoặc không, với trường hợp không có break thì máy sẽ tiến hành nhảy xuống thực hiện Khối_lệnh_i+1. Nếu Khối_lệnh_i khác rỗng (tức là có công việc thực hiện) thì sau Khối_lệnh_i ta phải đặt break. Khi máy gặp câu lệnh break thì sẽ thoát khỏi cấu trúc switch và thực hiện các câu lệnh tiếp theo sau cấu trúc lệnh này. o Khi giá trị của bieu_thuc khác tất cả các giá trị gti thì cách làm việc của máy lại phụ thuộc vào sự có mặt hay không có mặt của default. Khi có default máy nhảy tới câu lệnh có nhãn default. Khi không có default máy tiến hành thực hiện các câu lệnh sau cấu trúc này. Ví dụ 3.3 Viết chương trình nhập vào một số nguyên từ 2 đến 8 và in ra thứ tương ứng. Hƣớng dẫn: Input: Một số nguyên a trong khoảng 2 đến 8. Output: Thứ tương ứng với giá trị vừa nhập - Bước 1: Nhập vào một số bất kỳ trong đoạn từ 28 (giả sử đặt là a có kiểu dữ liệu là int) - Bước 2: Kiểm tra xem số vừa nhập vào tương ứng với ngày nào trong tuần sử dụng cấu trúc rẽ nhánh switch Nếu giá trị nhập vào không nằm trong khoảng từ 2 đến 8 thì in ra thông báo: “Giá trị bạn vừa nhập không hợp lệ!” - Bước 3: Kết thúc chương trình Chƣơng trình minh họa /* chương trình hiển thị thứ trong tuần tương ứng với giá trị nhập vào từ bàn phím*/ Đề cương bài giảng Cơ sở kỹ thuật lập trình 40 #include #include int main() //Chương trình chính { int a; //Khai báo biến nguyên nhận giá trị nhập vào printf("\nHay nhap mot so nguyen tu 2 den 8: "); scanf(“%d”, &a); //Kiểm tra giá trị nhập vào rồi in ra thứ tương ứng switch(a) { case 2: printf("\nThu hai"); break; case 3: printf("\nThu ba"); break; case 4: printf("\nThu tu"); break; case 5: printf("\nThu nam"); break; case 6: printf("\nThu sau"); break; case 7: printf("\nThu bay"); break; case 8: printf("\nChu nhat"); break; default: printf("\nGia tri ban nhap khong hop le"); } getch(); return 0; } Kết quả Đề cương bài giảng Cơ sở kỹ thuật lập trình 41 3.4 Bài tập Bài tập 3.1: Viết chương trình giải phương trình bậc nhất ax+b=0 rồi in ra màn hình các nghiệm của phương trình. Hƣớng dẫn: Input: Hai tham số a,b Output: Nghiệm của phương trình - Bước 1: Nhập các tham số a,b từ bàn phím sử dụng hàm printf, scanf (a,b có kiểu int) - Bước 2: Dùng cấu trúc điều khiển ifelse để kiểm tra: + Nếu a = 0 thì kiểm tra:  Nếu b=0 thì in ra thông báo: “Phương trình có vô số nghiệm”  Ngược lại thì in ra thông báo: “Phương trình vô nghiệm” + Ngược lại thì tính nghiệm x = -b/a và in kết quả ra màn hình. - Bước 3: Kết thúc chương trình. Bài tập 3.2: Viết chương trình nhập vào một số 1=< n <=12 từ bàn phím rồi in ra tháng tương ứng với số vừa nhập vào đó. Hƣớng dẫn: Input: Số nguyên n Output: Tháng tương ứng - Bước 1: Nhập số nguyên n từ bàn phím sử dụng hàm printf, scanf (n có kiểu int) - Bước 2: : Kiểm tra xem số vừa nhập vào tương ứng với tháng nào trong năm sử dụng cấu trúc rẽ nhánh switch Nếu giá trị nhập vào không nằm trong khoảng từ 1 đến 12 thì in ra thông báo: “Giá trị bạn vừa nhập không hợp lệ!” Đề cương bài giảng Cơ sở kỹ thuật lập trình 42 - Bước 3: Kết thúc chương trình. Đề cương bài giảng Cơ sở kỹ thuật lập trình 43 BÀI 4: CẤU TRÚC LẶP MỤC TIÊU Học xong bài này sinh viên có thể: o Hiểu và giải thích được cú pháp của các cấu trúc lặp o Vận dụng được các cấu trúc lặp for, while, do.. while vào từng bài toán cụ thể o So sánh được đặc điểm của các cấu trúc lặp o Rèn luyện tính cẩn thận, tư duy trong lập trình. 4.1. Giới thiệu về cấu trúc lặp Trong thực tế cuộc sống chúng ta gặp rất nhiều tình huống lặp. Ví dụ chương trình tính điểm cho 40 sinh viên trong lớp học. Quá trình giáo viên nhập họ tên, điểm cho từng sinh viên là quá trình lặp liên tục cho đến khi nhập đầy đủ cho 40 sinh viên thì mới kết thúc. Như vậy quá trình lặp ở trên là quá trình lặp với điều kiện cụ thể là nhập thông tin đến sinh viên thứ 40. Hoặc tình huống thứ 2 là: Em thực hiện công việc để gánh nước đổ vào thùng nước? Em có biết cần bao nhiêu thùng nước là đủ không? Như vậy em cần phải đổ đầy thùng nước mà không biết cần bao nhiêu gánh nước. Đó là một tình huống lặp mà không biết trước số lần lặp. Vậy cấu trúc vòng lặp cho phép lặp lại nhiều lần 1 công việc (được thể hiện bằng một câu lệnh hay một khối lệnh) nào đó cho đến khi thỏa mãn một điều kiện cụ thể. 4.2. Cấu trúc lặp xác định 4.2.1. Cấu trúc lặp For a) Cú pháp câu lệnh for(bt1;btđk;bt2) Công_việc; Trong đó: * for là từ khoá Đề cương bài giảng Cơ sở kỹ thuật lập trình 44 * bt1,bt2 là các biểu thức gán, btđk là một biểu thức cho giá trị logic * Công_việc có thể là một lệnh đơn, một cấu trúc điều khiển nào đó hay một khối lệnh Ví dụ 4.1: Viết đoạn chương trình in ra màn hình giá trị từ 1-5 int i; // Khai báo biến printf("Day so tu 1 den 5");// câu lệnh thông báo ra màn hình for(i=1;i<=5;i++) //câu lệnh kiểm tra điều kiện nhập printf(" Số nguyên thứ ",i); // câu lệnh in ra màn hình b) Sự hoạt động của câu lệnh for - Bước 1: Xác định giá trị của bt1 - Bước 2: Xác định giá trị của btđk - Bước 3: Tuỳ thuộc vào tính đúng, sai của biểu thúc btđk máy sẽ tiến hành lựa chọn một trong hai nhánh sau: + Nếu btđk có giá trị bằng không, máy sẽ ra khỏi vòng lặp for và chuyển tới câu lệnh sau cấu trúc for + Nếu btđk có giá trị khác không, máy sẽ tiến hành thực hiện các câu lệnh trong thân for . Khi thực hiện xong Công_việc hay gặp câu lệnh continue trong thân vòng lặp for máy sẽ chuyển sang bước 4(khởi đầu lại). - Bước 4: Tính bt2 sau đó quay lại bước 2 để bắt đầu lại vòng lặp mới của chu trình. Chú ý:  Các bt1,bt2,btđk có thể vắng mặt nhưng phải để lại dấu chấm phẩy  Nếu btđk vắng mặt thì máy coi luôn đúng. Khi đó muốn thoát khỏi vòng lặp thì phải dùng câu lệnh return, break hay goto.  Các bt1,bt2 có thể gồm nhiều biểu thức cách nhau bởi dấu phẩy  Thông thường bt1 dùng để khởi gán giá trị cho các biến trong vòng lặp, bt2 dùng để thay đổi giá trị của các biến điều khiển trong vòng lặp sao cho Đề cương bài giảng Cơ sở kỹ thuật lập trình 45 lúc đầu btđk cho giá trị True nhưng sau một số hữu hạn bước thực hiện thì btđk cho giá trị False. 4.1.2 Ví dụ áp dụng Ví dụ 4.2: Viết chương trình in ra màn hình các số nguyên từ 1 đến 5 #include #include main() { int i; // Khai báo biến printf("Day so tu 1 den 5");// câu lệnh thông báo nhập for(i=1;i<=5;i++) //câu lệnh kiểm tra điều kiện nhập printf(" Số nguyên thứ ",i); // câu lệnh in ra màn hình getch(); } Ví dụ 4.3: Viết chương trình nhập vào một số nguyên dương N sau đó tính tổng N số nguyên dương đầu tiên Hƣớng dẫn: - Dữ liệu nhập vào: n nguyên dương - Dữ liệu xuất ra: S=1+2+3+..+n o Bước 1: Nhập số nguyên dương N o Bước 2: Áp dụng cấu trúc lặp for để duyệt từ 1n, tại mỗi lần duyệt cộng giá trị vào viết S o Bước 3: In kết quả ra màn hình Chƣơng trình minh họa: #include #include Đề cương bài giảng Cơ sở kỹ thuật lập trình 46 int main() { int i,n,s; // Khai báo biến printf(“Ban hay nhap gia tri n :”); scanf(“%d”,&n); s=0; // Khởi tạo giá trị cho biến tổng for(i=1;i<=n;++i) // Kiểm tra điều kiện lặp s= s+i; // Tăng giá trị tổng sau mỗi lần tăng biến đếm printf(“Gia tri cua tong la %d”,s); getch(); return 0; } 4.3. Cấu trúc lặp không xác định 4.3.1. Cấu trúc lặp while a) Cú pháp câu lệnh while(bt) Công_việc; Trong đó: - while là từ khoá - bt là một biểu thức - Công_việc có thể là một lệnh đơn, một khối lệnh hay một cấu trúc điều khiển khác b) Nguyên tắc hoạt động của cấu trúc lặp while - Bước 1: Tiến hành tính toán giá trị của bt. - Bước 2: Nếu biểu thức có giá trị false máy thoát khỏi chu trình và tiến hành thực hiện các câu lệnh sau câu lệnh while. Nếu biểu thức có giá trị true máy tiến hành thực hiện Công_việc và quay về bước 1. c) Ví dụ Đề cương bài giảng Cơ sở kỹ thuật lập trình 47 Ví dụ 4.4: Viết chương trình nhập vào một số nguyên dương n. Tính tổng các số nguyên dương từ 1 đến n #include #include int main () { unsigned int n,i,tong; printf("\n Nhap vao so nguyen duong n:"); scanf("%d",&n); tong=0;i=1; //Khởi tạo giá trị cho biến đếm và biến tổng while (i<=n) //cấu trúc lặp kiểm tra điều kiện của i { tong=tong+i; //tổng tăng sau mỗi lần tăng i i=i+1; // Tăng biến đếm i lên 1 đơn vị } printf("\n Tong tu 1 den %d = %d ",n,tong); getch(); return 0; } Ví dụ 4.5: Viết chương trình nhập vào một số nguyên bất kỳ và in tất cả các ước số của số đó /* In tat ca cac uoc so cua n*/ #include #include int main() { int n, i; //Khai báo biến printf("Cho gia tri n = "); scanf("%d", &n); printf("Cac uoc so cua %d la :\n", n); i=1; //Khởi tạo giá trị cho biến i while(i<n) //Cấu trúc lặp kiểm tra điều kiện của i Đề cương bài giảng Cơ sở kỹ thuật lập trình 48 { i=i+1; // tăng biến đếm lên 1 if((n%i)==0) //kiểm tra nếu n chia hết cho i printf("%5d", i); /* quy định độ rộng cho giá trị của i là 5*/ } getch(); return 0; } Ví dụ 4.6: Viết chương trình tính tổng sau s= a-a 2 +a 3 -....+(-1) n+1 a n #include #include int main() { int n,i,dau; float s,tg,a; printf(“Ban hay cho gia tri n=”);scanf(“%d”,&n); printf(“Ban hay cho gia tri cua a=”);scanf(“%f”,&a); s=0; i=1; dau=-1; tg=1; //Khởi tạo giá trị cho các biến while (i++<=n) /*Kiểm tra điều kiện của i, thực hiện các câu lệnh trong thân vòng lặp while sau đó tăng biến i*/ { dau=dau*(-1); tg=tg*a; s=s+dau*tg; } printf(“Gia tri cua tong la=%8.2f”,s); /* định dạng Đề cương bài giảng Cơ sở kỹ thuật lập trình 49 8 chữ số phần nguyên và 2 chữ số phần thập phân cho tổng s*/ getch(); return 0; } Chú ý: bt có thể là một dãy các biểu thức đặt cách nhau bởi dấu phẩy. Tính đúng sai của bt được hiểu là tính đúng sai của biểu thức cuối cùng trong dãy. 4.3.2. Cấu trúc lặp do.. while a) Cú pháp câu lệnh do Công_việc; while(bt); Trong đó: - while ,do là từ khoá - bt là một biểu thức b) Nguyên tắc hoạt động của câu lệnh do.. while - Bước 1: Thực hiện Công_việc; - Bước 2: Sau khi thực hiện xong Công_việc máy tiến hành tính toán giá trị của bt. Nếu bt có giá trị bằng true thì máy sẽ trở lại bước 1 để tiếp tục thực hiện vòng lặp mới của chu trình. Nếu bt có giá trị bằng false thì máy sẽ ra khỏi chu trình và chuyển tới câu lệnh đứng sau cấu trúc do...while. c) Ví dụ Ví dụ 4.7: Viết đoạn chương trình in dãy số nguyên từ 1 đến 10 #include #include int main () Đề cương bài giảng Cơ sở kỹ thuật lập trình 50 { int i; printf("\n Day so tu 1 den 10 :"); i=1; do printf("%d ",i++); while (i<=10); getch(); return 0; } Ví dụ 4.8: Viết chương trình nhập vào một số nguyên n. Tính tổng các số nguyên từ 1 đến n #include #include int main () { unsigned int n,i,tong; clrscr(); printf("\n Nhap vao so nguyen duong n:"); scanf("%d",&n); tong=0; i=1; do { tong+=i; i++; } while (i<=n); printf("\n Tong tu 1 den %d =%d ",n,tong); getch(); return 0; } Ví dụ 4.9: Nhập một dãy số từ bàn phím và đếm xem ta nhập được bao nhiêu phần tử có giá trị dương. Khi không nhập nữa thì nhập giá trị 0 Đề cương bài giảng Cơ sở kỹ thuật lập trình 51 #include #include int main() { int i=0,n,tong=0; printf(“Ban hay tien hanh nhap cac so nguyen \n”); do { printf(“So thu: %d”,++i);scanf(“%d”,&n); if(n>0) tong++; } while(n!=0); printf(“Tong so phan tu ban da nhap la %d trong do co %d so duong “,i,tong); getch(); return 0; }  Ghi chú: So sánh các cấu trúc lặp - Giống nhau: của cấu trúc lặp for, while, do.. while đó là vòng lặp kết thúc khi nào điều kiện sai - Khác nhau: Cấu trúc lặp for, while Cấu trúc lặp do..while Kiểm tra điều kiện trước thực hiện công việc sau nên đoạn lệnh thực hiện công việc có thể không được thực hiện . Thực hiện công việc trước kiểm tra điều kiện sau nên đoạn lệnh thực hiện công việc được thực hiện ít nhất 1 lần. - Cách dùng các cấu trúc lặp: Nếu nhìn vào cấu trúc của ba cấu trúc lặp này, thì có thể nói rằng cả ba đều có thể dùng để giải quyết một bài toán lặp. Tuy nhiên mỗi cấu trúc lặp đều có nét riêng Đề cương bài giảng Cơ sở kỹ thuật lập trình 52 của nó. Cấu trúc for là tốt nhất nếu cần phải khởi tạo và tăng trong vòng lặp. Nếu chỉ có một điều kiện cần phải thỏa mãn và không quan tâm đến số lần thực hiện của vòng lặp thì while là một sự lựa chọn tốt. Còn nếu biết rằng một khối các câu lệnh cần phải thực hiện ít nhất một lần thì do ... while là cấu trúc tốt nhất. 4.4. Các câu lệnh đặc biệt 4.4.1. Câu lệnh break Dùng để thoát khỏi vòng lặp. Khi gặp câu lệnh này trong vòng lặp, chương trình sẽ thoát ra khỏi vòng lặp và chỉ đến câu lệnh liền sau nó. Nếu nhiều vòng lặp --> break sẽ thoát ra khỏi vòng lặp gần nhất. Ngoài ra, break còn được dùng trong cấu trúc lựa chọn switch. Ví dụ 4.10: Viết chương trình cho phép người dùng nhập liên tục giá trị của n cho đến khi nhập vào một giá trị âm. Chƣơng trình minh họa #include #include int main() { int n; while (1) { printf("\nNhap n: "); scanf("%d",&n); if(n<0) break; } getch(); return 0; Đề cương bài giảng Cơ sở kỹ thuật lập trình 53 } 4.4.2. Câu lệnh continue - Khi gặp lệnh này trong các vòng lặp, chương trình sẽ bỏ qua phần còn lại trong vòng lặp và tiếp tục thực hiện lần lặp tiếp theo. - Ðối với lệnh for, biểu thức 3 sẽ được tính trị và quay lại bước 2. - Ðối với lệnh while, do while; biểu thức điều kiện sẽ được tính và xét xem có thể tiếp tục thực hiện nữa hay không? (dựa vào kết quả của biểu thức điều kiện). Ví dụ 4.11: In ra màn hình các số từ 10 đến 20 trừ số 13 và số 17. #include #include int main() { int i; for(i=10;i<=20;i++) { if (i==13||i==17) continue; printf("%d\t",i); } getch(); return 0; } } 4.5. Bài tập 1. Viết chương trình nhập vào từ bàn phím hai số nguyên dương x, n (10<x, n<20). Tính và in ra màn hình tổng: S= S = x+x/2+x/3+...+x/n 2. Viết chương trình: nhập một số n từ bàn phím, kiểm tra n và in ra kết quả sau: Nếu n âm thì in ra thì bắt người dùng nhập lại Nếu n nguyên dương và là số chẵn thì tính và in ra tổng các số lẻ từ 1  n Nếu n nguyên dương và là số lẻ thì tính và in ra tổng các số chẵn từ 1  n Đề cương bài giảng Cơ sở kỹ thuật lập trình 54 3. Viết chương trình thực hiện nhập vào ba số nguyên dương từ bàn phím. Kiểm tra xem ba số vừa nhập vào có phải là ba cạnh của một tam giác hay không? Nếu phải thực hiện in ra diện tích tam giác có cạnh là ba số đã nhập. 4. Viết chương trình in ra màn hình giá trị các biểu thức sau: Trong đó N là số nguyên dương được nhập vào từ bàn phím 5. Viết chương trình in ra màn hình giá trị các biểu thức sau: Trong đó n là số nguyên dương được nhập vào từ bàn phím Đề cương bài giảng Cơ sở kỹ thuật lập trình 55 BÀI 5: THẢO LUẬN/BÀI TẬP VỀ CÁC CẤU TRÚC LẶP VÀ CẤU TRÚC ĐIỀU KHIỂN MỤC TIÊU Học xong bài học này sinh viên có thể: o Vận dụng được cách thức hoạt động của các cấu trúc rẽ nhánh vào từng bài toán cụ thể o Phân biệt được điểm giống và khác nhau giữa các cấu trúc lặp o Sử dụng thành thạo các câu lệnh lặp để giải các bài toán cụ thể A. TỔ CHỨC THỰC HIỆN - Giáo viên chia lớp thành nhiều nhóm cùng thảo luận các bài tập ở dưới (nhóm thảo luận từ 20 đến 35 phút với mỗi bài thảo luận ở dưới). - Giáo viên định hướng và giúp đỡ các nhóm thực hiện thảo luận một cách hiệu quả. - Các nhóm trình bày kết quả thảo luận; giáo viên góp ý, nhận xét và giải đáp các vướng mắc của sinh viên. B. NỘI DUNG THẢO LUẬN Bài thảo luận số 1: Viết chương trình tính lương của nhân viên dựa theo thâm niên công tác (TNCT) như sau: Lương = hệ số * lương căn bản, trong đó lương căn bản là 650000 đồng.  Nếu TNCT < 12 tháng: hệ số= 1.92  Nếu 12 <= TNCT < 36 tháng: hệ số= 2.34  Nếu 36 <= TNCT < 60 tháng: hệ số= 3 Đề cương bài giảng Cơ sở kỹ thuật lập trình 56  Nếu TNCT >= 60 tháng: hệ số= 4.5 Hƣớng dẫn: - Lựa chọn cấu trúc: Bài toán có nhiều lựa chọn để tính thâm niên công tác nên dùng cấu trúc điều khiển if else - Cách thực hiện: const int luongcb = 650; int tnct; double heso, luong; if (tnct < 12) heso = 1.92; else if (tnct < 36) heso = 2.34; else if (tnct < 60) heso = 3; else heso = 4.5; luong = luongcb * heso; Bài thảo luận số 2: Một điểm KARAOKE tính tiền khách hàng theo công thức sau:  Mỗi giờ trong 3 giờ đầu tiên tính 30.000 đồng/giờ,  Mỗi giờ tiếp theo có đơn giá giảm 30% so với đơn giá trong 3 giờ đầu tiên. Ngoài ra nếu thời gian thuê phòng từ 8 – 17 giờ thì được giảm giá 10%. Viết chương trình nhập vào giờ bắt đầu, giờ kết thúc và in ra số tiền khách hàng phải trả biết rằng 8 ≤giờ bắt đầu < giờ kết thúc ≤24. Hƣớng dẫn: - Lựa chọn cấu trúc: Bài toán có nhiều lựa chọn để tính thời gian nên dùng cấu trúc điều khiển if else - Cách thực hiện: int giobd, giokt, thoigian, tien; Đề cương bài giảng Cơ sở kỹ thuật lập trình 57 //Nhập giobd, giokt và kiểm tra điều kiện giobd >= 8 và giokt <= 24 sử dụng do...while thoigian = giokt – giobd; if (thoigian > 3) tien = 3 * 30000 + (thoigian – 3) * 30000 * 0.7; else tien = thoigian * 30000; if (giokt <= 17) //tìm cách tính tổng quát hơn tien *= 0.9; //Giảm 10% Bài thảo luận số 3: Viết chương trình tính n!! với n!! = 1.3.5n nếu n lẻ, n!! = 2.4.6n nếu n chẵn. Hƣớng dẫn: - Lựa chọn cấu trúc: Bài toán có công việc lặp là tính giai thừa dựa vào giá trị n nhập từ bàn phím nên dùng cấu trúc lặp for - Cách thực hiện: Ta cần xác định i chạy từ 1 hay 2 phụ thuộc vào n chẵn hay lẻ? for(i = (n % 2)? 1 : 2; i <= n; i += 2) gt *= i; Bài thảo luận số 4: Viết chương trình đếm và in ra số lượng các số nguyên chia hết cho 3 hoặc 7 nằm trong đoạn 1 đến 100. Hƣớng dẫn: - Lựa chọn cấu trúc: Bài toán có công việc lặp là in ra số lương các số nguyên trong đoạn 1 đến 100 nên dùng cấu trúc lặp for để kiểm tra điều kiện của biến chạy, kết hợp với cấu trúc điều khiển if để kiểm tra điều kiện của i có chia hết cho 3 hoặc 7 hay không. - Cách thực hiện: Đề cương bài giảng Cơ sở kỹ thuật lập trình 58 int Dem = 0,i; for (i = 1; i <= 100; i++) if( (i % 3 ==0) || (i % 7 == 0)) { Dem++; } Bài thảo luận số 5: Viết chương trình nhập vào một số nguyên dương, xuất ra dạng phân tích thừa số nguyên tố của số đó. Hƣớng dẫn: - Lựa chọn cấu trúc: Bài toán có công việc lặp là nhập vào số nguyên dương bất kỳ nên dùng cấu trúc lặp while để kiểm tra điều kiện của i, sau đó dùng cú pháp điều khiển if để kiểm tra điều kiện về số nguyên tố là chia hết cho 1 và chính nó. Đề cương bài giảng Cơ sở kỹ thuật lập trình 59 BÀI 6: MẢNG MỘT CHIỀU MỤC TIÊU Học xong bài này sinh viên có thể: o Trình bày được cấu trúc của mảng một chiều o Cài đặt bài toán trên mảng một chiều o Rèn luyện tư duy, sáng tạo trong các ứng dụng mảng một chiều 6.1 Giới thiệu về mảng một chiều Giả sử bạn muốn lưu n số nguyên để tính trung bình, bạn không thể khai báo n biến để lưu n giá trị rồi sau đó tính trung bình. Ví dụ 6.1: Giả sử tính trung bình 10 số nguyên nhập vào từ bàn phím, ta sẽ khai báo 10 biến: a, b, c, d, e, f, g, h, i, j có kiểu int và lập thao tác nhập cho 10 biến này như sau: printf("Nhap vao bien a: "); scanf("%d", &a); Với 10 biến thì 2 lệnh trên sẽ phải thực hiện 10 lần, sau đó tính trung bình: (a + b + c + d + e + f + g + h + i + j)/10 Điều này thật mất thời gian và chỉ phù hợp với n nhỏ, còn đối với n lớn thì khó có thể thực hiện được. Và để giải quyết những bài toán này thì giải pháp đơn giản và tối ưu nhất là sử dụng mảng. Mảng có thể có một hay nhiều chiều và chúng ta có thể khai báo mảng là một, hay nhiều chiều. Trong ngôn ngữ C không giới hạn số chiều của mảng. Đề cương bài giảng Cơ sở kỹ thuật lập trình 60 6.1.1 Khái niệm về mảng một chiều Một mảng (array) là một tập hợp liên tiếp các vị trí lưu trữ dữ liệu được đặt chung một tên và được khai báo chung một kiểu. Mỗi vị trí lưu trữ được gọi là một phần tử mảng. Có bao nhiêu kiểu biến thì cũng có bấy nhiêu kiểu mảng. Một mảng một chiều hay còn gọi là mảng đơn là một mảng chỉ có một chỉ số. Một chỉ số là một số nằm trong các dấu ngoặc vuông đứng ngay sau tên mảng. Số này chỉ thị số phần tử khác nhau của mảng. Ví dụ: float chi_tieu 12; Hình ảnh về mảng một chiều int a[10]; Phía trên là hình minh hoạ thể hiện một mảng có tên là a có thể chứa tối đa 10 phần tử kiểu int. Mỗi phần tử được biểu diễn bằng một vùng nhớ. Được lưu trữ theo chỉ số bắt đầu từ phần tử 0. - Kích thước của mảng chính là số phần tử mà mảng đó có thể chứa, như ví dụ trên thì kích thước của mảng a trong ví dụ trên là 10. 6.1.2 Cách khai báo a) Kiểu tường minh: []; int a[10]; //Khai báo một mảng số nguyên có tên là a gồm 10 phần tử. float b[20]; //Khai báo một mảng số thực có tên là b gồm 20 phần tử. int c[]; //Khai báo một mảng số nguyên có tên là c với số phần tử không xác định.  Chú ý: - Phải xác định số lượng phần tử cụ thể bằng hằng số khi khai báo. Đề cương bài giảng Cơ sở kỹ thuật lập trình 61 - Mảng luôn xác định phần tử đầu tiên xuất phát từ 0. b) Khai báo không tường minh: typedef []; typedef int mang[10]; typedef dùng để đặt tên cho một kiểu dữ liệu. Tên kiểu sẽ được dùng để khai báo dữ liệu sau này. Nói một cách nôm na thì từ khóa typedef sẽ giúp bạn tự do đặt tên khai báo các kiểu dữ liệu cho riêng mình phù hợp với mục đích lập trình dựa vào các kiểu dữ liệu đã có sẵn. Sau này có thể dùng kiểu mang như là một kiểu dữ liệu mảng kiểu int mà không cần phải khai báo dài dòng nữa. Khi viết một chương trình và trong chương trình đó có một kiểu dữ liệu được sử dụng nhiều lần, hoặc muốn viết code một cách tường mình, đọc là hiểu ngay, hoặc kiểu khai báo cũ mất quá nhiều thời gian thì những lúc này đây typedef sẽ phát huy tác dụng của nó. Ví dụ 6.2: typedef int mang[10]; mang a,b; Lúc này a,b là các mảng 1 chiều có kiểu dữ liệu là int và có độ rộng bằng 10. 6.1.3 Đặc điểm của mảng một chiều - Mảng là một kiểu dữ liệu có cấu trúc do người lập trình tự định nghĩa. - Biểu diễn một dãy các biến có cùng kiểu dữ liệu. Ví dụ: Dãy số nguyên, dãy các ký tự - Kích thước được xác định ngay khi khai báo và không bao giờ thay đổi. - Trong ngôn ngữ lập trình C luôn chỉ định một khối nhớ liên tục cho một biến kiểu mảng. Đề cương bài giảng Cơ sở kỹ thuật lập trình 62 6.1.4 Cách khởi tạo phần tử cho mảng a) Khởi tạo phần tử ngay trong câu lệnh khai báo mảng: int a[4]={2912, 1706, 1506, 1904}; b) Khởi tạo giá trị cho mọi phần tử int a[4]={0}; Trong trường hợp khởi tạo giá trị như thế này thì tất các các phần tử của mảng đều có giá trị là 0. c) Tự động xác định số lượng phần tử int a[]={1, 4, 3, 4}; Lúc này mảng có 4 phần tử và các phần tử của mảng sẽ lần lượt nhận các giá trị như sau: a[0]=1; a[1]=4; a[2]=3; a[3]=4; 6.2 Truy xuất các phần tử trong mảng Việc truy xuất đến các phần tử của mảng một chiều được xác định bởi tên mảng cùng với chỉ số của phần tử được đặt trong cặp dấu ngoặc vuông “[” và “]”, cụ thể: Đề cương bài giảng Cơ sở kỹ thuật lập trình 63 tên_mảng[chỉ số] int a[] = {1, 2, 3, 4}; // lúc này a[0] = 1, a [1] = 2, a[2]=3, a[3]=4 printf (“%d”, a [0]); //kết quả in ra là 1; printf (“%d”,a[2]); //Kết quả in ra là 3 ; 6.3 Các thao tác với mảng một chiều 6.3.1 Nhập mảng Để nhập các giá trị cho mảng một chiều ta làm như sau: - Bước 1: Nhập số phần tử của ma trận - Bước 2: Khai báo mảng với kích thước vừa nhập int A[so_phan_tu]; ------------Với mảng được xác định trước số phần tử thì bỏ qua bước 1,2 và thực hiện luôn bước 3---------- - Bước 3: Cho một biến i chạy từ 0 đến so_phan_tu Với mỗi giá trị của i thì ta nhập giá trị cho từng phần tử của mảng for (int i=0;i<so_phan_tu;i++) { // Tiến hành nhập giá trị cho các phần tử của mảng: printf (“Nhap phan tu A[%d]:”,i); scanf(“%d”,&A[i]); } Ví dụ 6.3: Nhập giá trị cho các phần tử của mảng các số nguyên, biết rằng số phần tử của mảng được nhập từ bàn phím. Đề cương bài giảng Cơ sở kỹ thuật lập trình 64 #include #include int main() { int m; printf(“Nhap so phan tu cua mang: ”); scanf(“%d”,&m); int A[m]; for(int i=0; i < m; i++) //duyet cac phan tu tu 0 den m { printf (“Nhap phan tu A[%d]:”,i); scanf(“%d”,&A[i]); } getch(); return 0; } Kết quả sau khi chạy chƣơng trình: 6.3.2 Hiện mảng Để hiển thị giá trị của mảng lên màn hình theo hình ma trận thì ta làm như sau: - Cho một biến i chạy từ 0 đến so_phan_tu for (int i=0;i<so_hang;i++) //Hiển thị mỗi ptu trên cùng 1 hàng và cách nhau 1 tab printf (“%d\t”,A[i]); Ví dụ 6.4: Nhập giá trị cho các phần tử của mảng các số nguyên rồi hiện mảng đó lên màn hình, biết rằng số phần tử của mảng được nhập từ bàn phím. Đề cương bài giảng Cơ sở kỹ thuật lập trình 65 #include #include int main() { int m; printf("Nhap so phan tu cua mang: "); scanf("%d",&m); int A[m]; for(int i=0; i < m; i++) //duyet cac phan tu tu 0 den m { printf ("Nhap phan tu A[%d]:",i); scanf("%d",&A[i]); } printf("Mang vua nhap la:\n "); for(int i=0; i < m; i++) //duyet cac phan tu tu 0 den m printf ("%d\t",A[i]); getch(); return 0; } Kết quả sau khi chạy chương trình: 6.2 Ví dụ áp dụng Ví dụ 6.5: Viết chương trình in ra những số chẵn trong mảng nhập từ bàn phím Đề cương bài giảng Cơ sở kỹ thuật lập trình 66 Hƣớng dẫn: Xác định yêu cầu bài toán: - Yêu cầu 1: Nhập mảng từ bàn phím - Yêu cầu 2: In ra những số chẵn ở trong mảng. Các bƣớc thực hiện nhƣ sau: Bước 1. Nhập mảng từ bàn phím - Khai báo một phần tử kiểu nguyên lưu trữ số lượng phần tử của mảng spt (giá trị phần tử được nhập từ bàn phím). - Khai báo một mảng gồm spt phần tử (spt đã được nhập vào trước đó). - Duyệt từ 0 ->spt-1 để nhập giá trị cho từng phần tử trong mảng=>Kết thúc việc nhập các phần tử từ bàn phím. Bước 2. Tìm các phần tử chẵn trong mảng. - Duyệt qua từng phần tử của mảng (tương tự như quá trình nhập phần tử trong mảng) - Sử dụng cấu trúc rẽ nhánh để kiểm tra phần tử có chẵn hay không. Nếu phần tử chẵn thì in giá trị phần tử ra màn hình. (Để kiểm tra phần tử chẵn hay lẻ ta đem giá trị của phần tử %2 nếu được giá trị số dư là 0 thì phần tử là chẵn ngược lại là lẻ). Bước 3: Kết thúc chương trình. #include #include int main() { int spt; printf (“Nhap phan so phan tu cua mang: ”); //Nhập spt scanf(“%d”, &spt); //số phần tử của mảng int a[spt]; //khai báo mảng mới với số phần tử nhập vào //nhập các giá trị cho các biến mảng từ bàn phím Đề cương bài giảng Cơ sở kỹ thuật lập trình 67 for (int i = 0; i <spt; i++) { printf (“Nhap phan tu thu %d= ”,i); //thông báo việc nhập scanf(“%d”,&a[i]); //nhập giá trị cho phần tử a[i] } for(int i=0; i < spt ; i++) //duyệt các phần tử 0, 1, 2, 3 ... { if (a[i] %2==0) //Kiểm tra xem phần tử có chia hết cho 2? { printf (“%d\t”,a[i]); //In phần tử nếu chẵn } } getch(); return 0; } Kết quả sau khi chạy chƣơng trình: Ví dụ 6.6: Tìm phần tử lớn nhất trong mảng gồm 4 phần tử với yêu cầu với các phần tử được khởi tạo sẵn. Yêu cầu: Đề cương bài giảng Cơ sở kỹ thuật lập trình 68 Yêu cầu 1: Khai báo một mảng một chiều gồm 4 phần tử, khởi tạo dữ liệu cho mảng được khai báo. Yêu cầu 2: Tìm phần tử lớn nhất trong mảng một chiều vừa khai báo Hƣớng dẫn: Bước 1. Khai báo một mảng gồm 4 phần tử có khởi tạo dữ liệu (xem mục 6.2 a). Bước 2. Tìm phần tử lớn nhất: - Khởi tạo biến max= giá trị phần tử đầu tiên. - Duyệt qua tất cả các phần tử của mảng, nếu phần tử nào có giá trị lớn hơn max thì gán giá trị của phần tử đó cho max. Kết thúc vòng lặp giá trị của biến max sẽ là giá trị của phần tử lớn nhất trong mảng. #include #include int main() { int a[4] = {1, 6, 4, 5}; //khai báo mảng và khởi tạo giá trị cho mảng bước 1 //các bước thực hiện tìm phần tử max int max =a[0]; //khởi tạo giá trị biến max bước 2 for(int i=0; i < 4; i++) //duyệt các phần tử 0, 1, 2, 3 bước 3 { if (max < a[i]) //so sánh giá trị max với phần tử { max = a[i]; //gán giá trị của phần tử lớn cho biến max } } printf (“%d”,max); //tìm được giá trị max trong mảng. getch(); Đề cương bài giảng Cơ sở kỹ thuật lập trình 69 return 0; } Ví dụ 6.7: Viết chương trình tính tổng các số lẻ ở trong mảng nhập từ bàn phím Hƣớng dẫn Xác định yêu cầu bài toán Yêu cầu 1: Nhập mảng vào từ bàn phím Yêu cầu 2: Tính tổng các số lẻ Các bƣớc thực hiện Bước 1. Nhập mảng từ bàn phím - Tương tự bước 1 của ví dụ 6.2 Bước 2. Tính tổng các số lẻ - Khởi tạo một biến để lưu trữ tổng các số lẻ: int tong=0; - Duyệt qua từng phần tử của mảng - Sử dụng cấu trúc rẽ nhánh để kiểm tra phần tử có lẻ hay không. Nếu phần tử lẻ thì cộng thêm giá trị của phần tử vào biến tổng (các bước kiểm tra như với số chẵn). - In biến tổng ra màn hình và kết thúc bài toán. #include #include int main() { int spt; printf ("Nhap so phan tu cua mang:"); scanf("%d", &spt); //Nhập số phần tử của mảng Đề cương bài giảng Cơ sở kỹ thuật lập trình 70 int a[spt]; //khai báo mảng với spt vừa nhập //Nhập các giá trị cho các biến mảng for (int i = 0; i <spt; i++) { printf ("Nhap phan tu thu %d= ",i); //thông báo việc nhập scanf("%d",&a[i]); //Nhập giá trị cho phần tử a[i] } int tong=0; //Kh?i t?o giá tr? t?ng for(int i=0; i < spt ; i++) //duyệt các phần tử của mảng { if (a[i] %2!=0) //Kiểm tra xem phần tử a[i] có lẻ không { tong+=a[i]; //Cộng vào biến tong nếu a[i] lẻ } } printf ("tong cac so le là: %d",tong); getch(); return 0; } Kết quả sau khi chạy chương trình: Đề cương bài giảng Cơ sở kỹ thuật lập trình 71 Ví dụ 6.8: Viết chương trình tính tích của các phần tử trong mảng nhập vào từ bàn phím. Hƣớng dẫn: Input: Nhập mảng vào từ bàn phím Output: Tính tích của các phần tử của mảng - Bước 1: Nhập mảng từ bàn phím Tương tự ví dụ 6.2 - Bước 2: Tính tích của các phần tử trong mảng. - Khởi tạo một biến để lưu trữ tích của các phần tử: int tich=1; (khởi tạo khi tính tích phần tử) - Duyệt qua từng phần tử của mảng nhân vào với biến lưu trữ là biến “tich” (tich=tich*a[i]; hoặc tich*=a[i];) - In biến “tich” ra màn hình và kết thúc bài toán. Đề cương bài giảng Cơ sở kỹ thuật lập trình 72 BÀI 7: THỰC HÀNH VỀ CẤU TRÚC ĐIỀU KHIỂN VÀ CẤU TRÚC LẶP Đề cương bài giảng Cơ sở kỹ thuật lập trình 73 BÀI 8: MẢNG HAI CHIỀU MỤC TIÊU Học xong bài này sinh viên có thể: o Hiểu và giải thích được cấu trúc của mảng hai chiều o Xây dựng được chương trình xử lý dữ liệu trên mảng hai chiều o Rèn luyện tư duy, sáng tạo trong các ứng dụng mảng hai chiều 8.1. Giới thiệu về mảng hai chiều 8.1.1 Định nghĩa Có nhiều cách để hiểu về mảng hai chiều. Sau đây là một số cách định nghĩa mảng hai chiều. Cách 1: Mảng hai chiều là một mảng các phần tử trong đó mỗi phần tử của nó là mảng một chiều có kích thước bằng nhau. Đây là cách định nghĩa đệ quy thông qua định nghĩa mảng một chiều. Sử dụng phương pháp này ta có thể định nghĩa mảng n chiều (với n>=2) bằng cách thông qua định nghĩa của mảng n-1 chiều. Ví dụ 8.1: int a[2][3]; Đây là một mảng trong đó có 2 phần tử, mỗi phần tử của mảng là một mảng một chiều có kích thước là 3 phần tử. Cách 2. Mảng hai chiều là tập hợp các phần tử có cùng kiểu dữ liệu được tổ chức dưới dạng bảng (có thể coi nó như một ma trận). Với định nghĩa này các phần tử của mảng được sắp xếp dựa trên chỉ số hàng và cột. Thông qua định nghĩa này ta gọi một mảng hai chiều là một ma trận cấp m × ntrong đó m được gọi là chỉ số hàng và được gọi là chỉ cố cột. Đề cương bài giảng Cơ sở kỹ thuật lập trình 74 Ở hình trên là một mảng với: - Tên mảng là: m - Số lượng phần tử của mỗi chiều là: 4 dòng, 5 cột - Kiểu dữ liệu của các phần tử là: kiểu nguyên - Phần tử của mảng được tham chiếu đến là m[2][3] có giá trị = 0 8.1.2 Các cách khai báo Để khai báo một mảng 2 chiều ta khai báo một biến mảng có 2 chỉ số kích thước đại diện cho hàng và cột. [số hàng][số cột] Ví dụ 8.2: int a[m][n]; Đề cương bài giảng Cơ sở kỹ thuật lập trình 75 Theo như khai báo trên: m là số hàng của ma trận, n là số cột của ma trận. Trong đó m, n là những số nguyên xác định. Với cách khai báo này các phần tử trong mảng sẽ mặc định có giá trị là NULL. - Việc khai báo mảng có thể kết hợp với gán giá trị cho mảng: Cách 1: int a[2][3]={1,2,3,4,5,6}; Trong cách khai báo này ta giá trị các phần tử được khởi tạo như sau: a[0][0]=1; //Phần tử đầu tiên a[0][1]=2; //Phần tử thứ hai a[0][2]=3; //Phần tử thứ ba a[1][0]=4; //Phần tử thứ tư a[1][1]=5; //Phần tử thứ năm a[1][2]=6; //Phần tử thứ sáu Cách 2: int a[3][3]={{1,2,3},{4,5,6},{7,8,9}}; Trong cách khai báo này ta giá trị các phần tử được khởi tạo như sau: a[0][0]=1; a[0][1]=2; a[0][2]=3; a[1][0]=4; a[1][1]=5; a[1][2]=6; a[2][0]=7; a[2][1]=8; a[2][2]=9; 8.2 Truy xuất các phần tử trong mảng hai chiều Việc truy xuất đến các phần tử của mảng 2 chiều được xác định bởi tên mảng cùng với hai chỉ số là hàng và được đặt trong cặp dấu ngoặc vuông “[” và “]”, cụ thể: tên_mảng[chỉ số hàng][ chỉ số cột] Chẳng hạn, muốn truy xuất đến phần tử tại hàng thứ 3 và cột thứ 5 của mảng a thì ta viết: a[3][5]. Đề cương bài giảng Cơ sở kỹ thuật lập trình 76 Ví dụ 8.3: int b = a[i][j]; Trong ví dụ trên giá trị của mảng a tại dòng i, cột j được gán vào cho biến b. Thông thường trong các bài toán liên quan đến mảng 2 chiều ta thường sử dụng 2 cấu trúc lặp lồng nhau để thực hiện duyệt qua tất cả các hàng và cột của mảng. 8.3 Các thao tác với mảng hai chiều 8.3.1 Nhập mảng Để nhập giá trị cho các phần tử của mảng hai chiều A[m][n] ta làm như sau: - Bước 1: Nhập số hàng, số cột của ma trận - Bước 2: Khai báo mảng với kích thước là số hàng và số cột vừa nhập int A[so_hang][so_cot]; - Bước 3: Cho một biến i chạy từ 0 đến so_hang Với mỗi giá trị của i thì j chạy từ 0 đến so_cot for (int i=0;i<so_hang;i++) for (int j=0;i<so_cot;j++) { // Tiến hành nhập giá trị cho các phần tử của mảng: printf (“Nhap phan tu A[%d][%d]:”,i,j); scanf(“%d”,&A[i][j]); } Ví dụ 8.4: Nhập giá trị cho các phần tử của mảng hai chiều a[m][n] với m,n được nhập từ bàn phím. #include int main() Đề cương bài giảng Cơ sở kỹ thuật lập trình 77 { int m,n; printf ("Nhap so hang, so cot cua ma tran:"); scanf("%d%d",&m,&n); int a[m][n]; for (int i=0;i<m;i++) //duyet theo hang for (int j=0;j<n;j++) //duyet theo cot { //Nhap gia tri cho cac phan tu cua mang printf ("Nhap phan tu a[%d][%d]:",i,j); scanf("%d",&a[i][j]); } return 0; } Kết quả sau khi chạy chƣơng trình: 8.3.2 Hiện mảng Để hiển thị giá trị của mảng lên màn hình theo hình ma trận thì ta thực hiện các bước như sau: - Bước 1: Cho một biến i chạy từ 0 đến so_hang Với mỗi giá trị của i thì j chạy từ 0 đến so_cot for (int i=0;i<so_hang;i++) Đề cương bài giảng Cơ sở kỹ thuật lập trình 78 { for (int j=0;i<so_cot;j++) //Hiển thị mỗi ptu trên cùng 1 hàng và cách nhau 1 tab printf (“%d\t”,A[i][i]); //Hết 1 hàng thì xuống dòng printf (“\n”); } Ví dụ 8.5: Nhập giá trị cho các phần tử của mảng hai chiều a[m][n] rồi hiển thị mảng vừa nhập lên màn hình,với n,m được nhập từ bàn phím. #include int main() { int n,m; printf ("Nhap so hang, so cot cua ma tran:"); scanf("%d%d",&m,&n); int a[m][n]; for (int i=0;i<m;i++) //duyet theo hang for (int j=0;j<n;j++) //duyet theo cot { //Nhap gia tri cho cac phan tu cua mang printf ("Nhap phan tu a[%d][%d]:",i,j); scanf("%d",&a[i][j]); } //-------Hiển thị mảng vừa nhập------------ printf ("\nMang vua nhap la:\n"); Đề cương bài giảng Cơ sở kỹ thuật lập trình 79 for (int i=0;i<m;i++) { for (int j=0;j<n;j++) printf ("%d\t",a[i][j]); printf ("\n"); } return 0; } Kết quả sau khi chạy chƣơng trình: 8.4 Một số ví dụ về mảng hai chiều Ví dụ 8.6: Nhập và tính tổng các phần tử của một ma trận số nguyên gồm m dòng, n cột với m, n nhập từ bàn phím. Hƣớng dẫn: Xác định yêu cầu bài toán: - Yêu cầu 1. Nhập số phần tử của hàng và cột m, n - Yêu cầu 2. Khai báo mảng 2 chiều m × n và nhập các phần tử của ma trận - Yêu cầu 3. Tính tổng các phần tử trong ma trận Thực hiện Đề cương bài giảng Cơ sở kỹ thuật lập trình 80 - Bước 1: Nhập m, n từ bàn phím, khai báo 2 số nguyên m, n và sử dụng lệnh cin để nhập số nguyên vào. - Bước 2: Khai báo mảng m x n số nguyên và nhập vào từ bàn phím (xem ví dụ 8.1) - Bước 3: Tính tổng các phần tử của mảng (thực hiện khởi tạo biến tổng và duyệt qua từng phần tử của mảng và cộng vào biến tổng) #include int main() { //khai bao so hang va so cot int n,m; printf(”Nhap so hang và so cot cua mang:”); scanf(“%d%d”,&m,&n); //nhap cac phan tu cho mang int a[m][n]; for(int i=0;i<m;i++) for(int j=0;j<n;j++) { printf(”Nhap phan tu [%d][%d]:”,i,j); scanf(“%d”,&a[i][j]); } //tinh tong cac phan tu cua mang int tong=0; for(int i=0;i<m;i++) for(int j=0;j<n;j++) { Đề cương bài giảng Cơ sở kỹ thuật lập trình 81 tong+=a[i][j]; // hoac tong = tong+a[i][j]; } printf(”Tong cac phan tu cua mang=%d”, tong); return; } Ví dụ 8.7: Nhập và tính tổng các phần tử của hàng chẵn trong một ma trận số nguyên gồm m dòng, n cột với m, n nhập từ bàn phím. Hƣớng dẫn: Xác định yêu cầu bài toán: - Yêu cầu 1. Nhập số phần tử của hàng và cột m, n - Yêu cầu 2. Khai báo mảng 2 chiều m × n và nhập các phần tử của ma trận - Yêu cầu 3. Xác định các phần tử thuộc hàng chẵn trong ma trận, tính tổng các phần tử trong ma trận Ví dụ 8.8: Nhập và tính tích các phần tử của một ma trận số nguyên gồm m dòng, n cột với m, n nhập từ bàn phím. Hƣớng dẫn: Xác định yêu cầu bài toán: - Yêu cầu 1. Nhập số phần tử của hàng và cột m, n - Yêu cầu 2. Khai báo mảng 2 chiều m × n và nhập các phần tử của ma trận - Yêu cầu 3. Tính tích các phần tử trong ma trận Đề cương bài giảng Cơ sở kỹ thuật lập trình 82 BÀI 9: THỰC HÀNH VỀ MẢNG (BUỔI 1) Đề cương bài giảng Cơ sở kỹ thuật lập trình 83 BÀI 10: THẢO LUẬN/BÀI TẬP VỀ MẢNG MỤC TIÊU Học xong bài này sinh viên có thể: o Nắm vững kỹ thuật sử dụng dữ liệu kiểu mảng. o Vận dụng một cách hiệu quả dữ liệu kiểu mảng để xử lý một bài toán cụ thể o Tăng cường kỹ năng làm việc nhóm và rèn luyện tính cẩn thận trong công việc. C. TỔ CHỨC THỰC HIỆN - Giáo viên chia lớp thành nhiều nhóm cùng thảo luận các bài tập ở dưới (nhóm thảo luận từ 20 đến 35 phút với mỗi bài thảo luận ở dưới). - Giáo viên định hướng và giúp đỡ các nhóm thực hiện thảo luận một cách hiệu quả. - Các nhóm trình bày kết quả thảo luận; giáo viên góp ý, nhận xét và giải đáp các vướng mắc của sinh viên. D. NỘI DUNG THẢO LUẬN Bài thảo luận số 1: Viết chương trình thực hiện việc sau: - Nhập mảng gồm n số nguyên từ bàn phím - Hiển thị mảng ra màn hình - Tìm kiếm một phần tử trong mảng: nhập số a, kiểm tra xem số a có trong mảng không. Nếu có thì hiển thị ra màn hình vị trí mà số a xuất hiện lần đầu tiên. - Sắp xếp các số nguyên trong mảng theo thứ tự giảm dần và in ra màn hình - Sắp xếp các số nguyên trong mảng theo thứ tự tăng dần và in ra màn hình Bài thảo luận số 2: Đề cương bài giảng Cơ sở kỹ thuật lập trình 84 Viết chương trình thực hiện việc sau: - Nhập mảng có tên là a gồm n số nguyên từ bàn phím - Hiển thị mảng a ra màn hình - Kiểm tra xem mảng a có là nguyên tố hay không (mảng là nguyên tố khi tất cả các phần tử của mảng đều là số nguyên tố) - Tách các phần tử chẵn của mảng a đưa sang mảng có tên là chan; các phần tử lẻ đưa sang mảng có tên là le. - Sắp xếp mảng chan, mảng le theo thứ tự tăng dần - Loại bỏ các phần tử giống nhau của mảng chan, mảng le - Gộp hai mảng chan và le thành mảng tonghop sao cho các phần tử của mảng tonghop vẫn được sắp theo thứ tự tăng dần. Bài thảo luận số 3: Viết chương trình thực hiện việc sau: - Nhập mảng có tên là a gồm n số nguyên từ bàn phím - Hiển thị mảng a ra màn hình - Sắp xếp mảng a theo thứ tự giảm dần - Nhập từ bàn phím số b và bổ sung vào mảng a sao cho mảng a vẫn được sắp theo thứ tự giảm dần - Loại bỏ các phần tử giống nhau của mảng chan, mảng le - Gộp hai mảng chan và le thành mảng tonghop sao cho các phần tử của mảng tonghop vẫn được sắp theo thứ tự tăng dần. Bài thảo luận số 4: Viết chương trình thực hiện việc sau: - Nhập mảng có tên là a gồm n số nguyên từ bàn phím - Hiển thị mảng a ra màn hình Đề cương bài giảng Cơ sở kỹ thuật lập trình 85 - Kiểm tra xem mảng a có phải là mảng toàn số chẵn - Kiểm tra xem mảng a có phải là mảng tăng dần - Có bao nhiêu số trong mảng a chia hết cho 4 nhưng không chia hết cho 5 - Tính tổng các số nguyên tố có trong mảng a - Hiển thị ra màn hình số nhỏ nhất, số lớn nhất của mảng a. - Xóa tất cả các số nguyên tố của mảng a và hiển thị mảng a ra màn hình TÓM TẮT  Thảo luận về cách khai báo và sử dụng mảng một chiều. Đề cương bài giảng Cơ sở kỹ thuật lập trình 86 BÀI 11: THỰC HÀNH VỀ MẢNG (BUỔI 2) Đề cương bài giảng Cơ sở kỹ thuật lập trình 87 BÀI 12: THAO TÁC VỚI KÝ TỰ VÀ XÂU KÝ TỰ MỤC TIÊU Học xong bài này người học sẽ: o Sử dụng được kiểu char để lưu giữ các ký tự đơn. o Tạo lập các mảng kiểu char để lưu giữ các xâu nhiều ký tự. o Thực hiện được các thao tác cơ bản trên xâu ký o Cài đặt được các bài toán trên xâu ký tự 12.1 Giới thiệu về ký tự và xâu ký tự Một ký tự là một chữ, một chữ số, hoặc một ký hiệu đặc biệt nào đó. Một xâu ký tự (viết gắn gọn là xâu) là một dãy các ký tự. Các xâu được sử dụng để lưu giữ các dữ liệu văn bản bao gồm các chữ, các chữ số và các ký hiệu khác. Ký tự và xâu là một kiểu dữ liệu có ở trên tất cả các ngôn ngữ lập trình. Vì thế việc thành thạo trong việc thao tác với ký tự và xâu là rất quan trọng đối với các lập trình viên. Trong C dùng kiểu char để lưu giữ các ký tự. Trong Bài 1, ta đã thấy char là một trong các kiểu dữ liệu số nguyên. Như vậy, nếu char là một kiểu số, thì làm sao nó có thể được sử dụng để giữ các ký tự ? Câu trả lời nằm ở chỗ C lưu trữ các ký tự như thế nào. Bộ nhớ của máy tính ghi tất cả các dữ liệu đều ở dạng số. Không có cách ghi trực tiếp các ký tự. Tuy nhiên mỗi một ký tự có một mã số tương ứng dùng để mã hóa cho nó. Các mã này được gọi là các mã ASCII (Amerian Standard Code for Information Interchange). Bảng mã này gán các giá trị từ 0 đến 255 cho các chữ cái thường và hoa, các chữ số, và các ký hiệu khác. Ví dụ, 97 là mã của chữ a. Khi ghi chữ a trong một biến kiểu char, thực ra là ghi số 97 này. Bởi vì miền giá trị cho phép của kiểu char trùng với tập hợp mã ASCII, nên char cũng là kiểu thích hợp để lưu giữ các ký tự. Đề cương bài giảng Cơ sở kỹ thuật lập trình 88 12.1.1 Sử dụng các biến ký tự Giống như các biến khác, các biến kiểu này cần phải được khai báo rồi mới được sử dụng. Ngoài ra, có thể khởi tạo chúng cùng lúc với việc khai báo. Ví dụ, char a, b, c; /* Khai báo ba biến kiểu char */ char code = 'x'; /* Khai báo biến char có tên code và gán ký tự x cho biến này */ code = „!‟; /* Ghi ! vào biến char có tên code */ Để tạo ra các hằng ký tự thực sự, phải để ký tự trong các dấu nháy đơn. Chương trình dịch sẽ tự động chuyển các hằng ký tự thực sự thành mã ASCII tương ứng và giá trị của mã này được gán cho biến. Có thể tạo ra các hằng ký tự ký hiệu bằng chỉ thị #define hoặc từ khóa const: #define EX „x‟ char code = EX; /* Gán „x‟ cho code */ const char A = „z‟; Chương trình 12.1 là một ví dụ minh họa về bản chất số của việc lưu giữ ký tự. Hàm printf() có thể được sử dụng để in cả các ký tự và các số. Xâu format %c dùng để in một ký tự, còn %d để in một số nguyên hệ thập phân. Ví dụ 12.1: Chương trình minh họa bản chất của các biến kiểu /*Chương trình 12.1. Minh họa bản chất số của các biến kiểu*/ #include /* Khai báo và khởi tạo hai biến kiểu char */ char c1 = 'a'; char c2 = 97; int main() { /* In biến c1 như một ký tự, sau đó như một số */ printf("\nLà một ký tự, biến c1 là %c", c1); printf("\nLà một số, biến c1 là %d", c1); /* Tương tự như vậy đối với biến c2 */ printf("\nLà một ký tự, biến c2 là %c", c1); printf("\nLà một số, biến c2 là %d\n ", c1); return 0; } Đề cương bài giảng Cơ sở kỹ thuật lập trình 89 Kết quả của chƣơng trình 12.1 là: Là một ký tự, biến c1 là a Là một số, biến c1 là 97 Là một ký tự, biến c2 là a Là một số, biến c2 là 97 Trong Bài 1 có nói rằng miền giới hạn của một biến kiểu char chỉ đến 127, trong khi đó mã ASCII lại có thể đến 255. Thực ra, các mã ASCII được chia thành hai phần. Các mã ASCII thông thường chỉ đến 127; miền này chứa tất cả các chữ, các chữ số và các ký hiệu khác. Các mã trong khoảng 128-255 là các mã ASCII mở rộng và dùng để biểu diễn các chữ cái đặt biệt của các nước khác và các ký hiệu đồ họa. Vì vậy đối với các dữ liệu văn bản thông thường, có thể dùng các biến kiểu char; nếu muốn in các ký tự ASCII mở rộng, thì phải dùng kiểu unsigned char. Các biến kiểu char chỉ có thể giữ một ký tự đơn, do đó chúng có tác dụng rất hạn chế. Vì vậy, cần có một cách khác để lưu giữ các xâu, tức là một dãy các ký tự đơn. Mặc dù không có một kiểu riêng biệt cho các xâu, nhưng C thao tác kiểu thông tin này thông qua mảng của các ký tự. 12.1.2 Mảng của các ký tự Để giữ một xâu gồm 9 ký tự chẳng hạn, cần phải khai báo một mảng kiểu char có 10 phần tử. Các mảng kiểu char cũng được khai báo giống như các mảng kiểu khác. Câu lệnh char string[10]; khai báo một mảng 10 phần tử kiểu char. Mảng này có thể chứa một xâu dài nhất là 9 ký tự. Nhưng tại sao khai báo 10 phần tử lại chỉ giữ được nhiều nhất là 9 phần tử ? Trong C, một xâu được định nghĩa là một dãy các ký tự kết thúc bằng một ký tự không (null). Nó là một ký tự đặc biệt được biểu diễn bằng \0. Mặc dù được biểu diễn bằng hai ký hiệu, ký hiệu không vẫn chỉ được hiểu là một ký tự đơn và có mã ASCII là 0. Một biến kiểu char có cỡ là một byte, vì vậy số byte của một mảng ký tự bằng đúng số phần tử của mảng. Đề cương bài giảng Cơ sở kỹ thuật lập trình 90 12.1.3 Khởi tạo các mảng ký tự Giống như các kiểu dữ liệu khác, các mảng ký tự cũng phải được khởi tạo khi chúng được khai báo. Các mảng có thể được gán các giá trị theo phương thức tuần tự: char string[

Các file đính kèm theo tài liệu này:

  • pdf01200047_6448_1983577.pdf
Tài liệu liên quan