Giáo trình Lập trình C/C++ - Nguyễn Ngọc Trung

pdf 98 trang Gia Huy 17/05/2022 2211
Bạn đang xem 20 trang mẫu của tài liệu "Giáo trình Lập trình C/C++ - Nguyễn Ngọc Trung", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên

Tài liệu đính kèm:

  • pdfgiao_trinh_lap_trinh_cc_nguyen_ngoc_trung.pdf

Nội dung text: Giáo trình Lập trình C/C++ - Nguyễn Ngọc Trung

  1. ỦY BAN NHÂN THÀNH PHỐ HỒ CHÍ MINH TRƯỜNG CAO ĐẲNG GIAO THÔNG VẬN TẢI  Chủ biên :ThS. Nguyễn Ngọc Trung Thành viên :KS. Tô Diệp Khanh :ThS. Lê Kim Hòa ` :ThS. Phan Văn Bằng :ThS. Châu Văn Khánh Lưu hành nội bộ - Năm 2016
  2. Kỹ thuật điều khiển và tự động hóa là ngành nghiên cứu, ứng dụng các kỹ thuật cơ khí hiện đại, kỹ thuật điều khiển, kỹ thuật máy tính vào việc vận hành, điều khiển quá trình sản xuất nhằm thực hiện một công việc mà không cần đến sự can thiệp trực tiếp của con người. Vậy để thực hiện những công việc này thì bắt buộc chúng ta phải lập trình tạo ra những chương trình vận hành mà C/C++ là ngôn ngữ lập trình vạn năng có thể giúp chúng ta giải quyết các vần đề này. Sử dụng thành thạo ngôn ngữ C/C++ còn giúp sinh viên học tốt các môn học Lập trình PLC và lập trình vi xử lý. Giáo trình này chúng ta đi tìm hiểu thế giới của ngôn ngữ C/C++ từ những khái niệm ban đầu cơ bản nhất.
  3. .MỤC LỤC Chương 1: NGÔN NGỮ LẬP TRÌNH & PHƯƠNG PHÁP LẬP TRÌNH 1 1.1 Ngôn ngữ lập trình (Programming Language) 1 1.2 Các bước lập trình 1 1.3 Kỹ thuật lập trình 1 I-P-O Cycle (Input-Process-Output Cycle) (Quy trình nhập-xử lý-xuất) 1 Sử dụng lưu đồ (Flowchart) 3 1.4 Bài tập 6 Chương 2: LÀM QUEN LẬP TRÌNH C/C++ QUA CÁC VÍ DỤ ĐƠN GIẢN 7 2.1 Khởi động Dev C++ 7 2.2 Các ví dụ đơn giản 7 Ví dụ 1 7 Ví dụ 2 9 Ví dụ 3 9 Ví dụ 4 10 Ví dụ 5 10 Chương 3: CÁC THÀNH PHẦN TRONG NGÔN NGỮ C/C++ 11 3.1 Từ khóa 11 3.2 Tên 11 3.3 Kiểu dữ liệu 12 3.4 Ghi chú 12 3.5 Khai báo biến 12 Tên biến 12 Khai báo biến 13 Vừa khai báo vừa khởi gán 13 Vị trí đặt các khai báo biến 13 Chương 4: BIỂU THỨC 14 4.1 Biểu thức 14 4.2 Các phép toán số học 14 4.3 Các phép toán quan hệ và logic 15 4.4 Phép toán tăng giảm 15 4.5 Thứ tự ưu tiên các phép toán 16 4.6 Chuyển đổi kiểu 17 4.7 Các hàm toán học thường dùng 17 abs 17 rand 17 pow 18 sqrt 18 atoi 18 Chương 5: NHẬP - XUẤT DỮ LIỆU 19 5.1 Các hàm vào ra chuẩn - getchar() và putchar() 19 Hàm getchar () 19 Hàm putchar() 19 5.2 Đưa kết quả ra màn hình - Hàm printf 20 5.3 Vào số liệu từ bàn phím - Hàm scanf 21 5.4 Đưa kết quả ra màn hình - Hàm cout 21 5.5 Vào số liệu từ bàn phím - Hàm cin 23 Trang - i
  4. 5.6 Bài tập 23 Chương 6: CẤU TRÚC ĐIỀU KHIỂN 25 6.1 Cấu trúc có điều kiện: 25 Lệnh if-else: 25 Lệnh else-if: 28 6.2 Lệnh nhảy không điều kiện - toán tử goto: 29 6.3 Lệnh break 31 6.4 Cấu trúc rẽ nhánh - toán tử switch: 31 6.5 Bài tập 33 Sử dụng lệnh if 33 Sử dụng lệnh switch 34 Bài tập làm thêm 35 Chương 7: VÒNG LẶP 36 7.1 Lệnh continue 36 7.2 Vòng lặp for 36 7.3 Vòng lặp while 39 7.4 Vòng lặp do while 40 7.5 Vòng lặp lồng nhau 42 7.6 So sánh sự khác nhau của các vòng lặp 43 7.7 Bài tập 43 Chương 8: HÀM 46 8.1 Cơ sở 46 8.2 Hàm không cho các giá trị trả về: 48 8.3 Các ví dụ về hàm 49 Ví dụ 1 49 Ví dụ 2 49 Ví dụ 3 50 8.4 Bài tập 50 Chương 9: MẢNG VÀ CON TRỎ 52 9.1 Mảng 52 Mảng một chiều 52 Mảng nhiều chiều 54 9.2 Con trỏ 57 Khái báo biến con trỏ 57 Phép toán số học trên con trỏ 59 Con trỏ và mảng một chiều 60 9.3 Bài tập 60 Chương 10: CHUỖI 62 10.1 Cách khai báo chuỗi 62 10.2 Hàm nhập, xuất chuỗi 63 10.3 Bộ đệm và hiện tượng trôi lệnh 64 Bộ đệm (Buffer) 64 Hiện tượng trôi lệnh 64 10.4 Các phương thức, phép toán tiện ích của kiểu string 65 Các phép toán và phương thức cơ bản 65 Lấy chiều dài chuỗi 66 Truy cập một phần tử bất kỳ trong chuỗi 67 Chèn chuỗi 67 Trang - ii
  5. Xoá chuỗi 68 Lấy chuỗi con 68 Tìm kiếm chuỗi con 69 Thay thế một đoạn con trong chuỗi ban đầu. 69 Đổi chữ hoa thành thường với tolower(char ch)và đổi chữ thường thành chữ hoa với toupper(char ch) 70 10.5 Bài tập 70 Chương 11: KIỂU DỮ LIỆU CẤU TRÚC 72 11.1 Kiểu cấu trúc (Structure) 72 Khai báo kiểu structure 72 Cách khai báo biến có kiểu structure 72 Tham chiếu các phần tử trong structure 72 Structure lồng nhau 74 11.2 Danh sách liên kết 75 Khái niệm danh sách liên kết đơn 75 Khai báo danh sách liên kết đơn 76 Thêm 1 phần tử vào danh sách liên kết đơn 76 Khởi tạo danh sách liên kết đơn 77 Chèn phần tử vào danh sách liên kết đơn 78 Xóa bỏ phần tử trong danh sách 78 11.3 Bài tập 79 Mảng cấu trúc 79 Danh sách liên kết 79 Chương 12: TẬP TIN – FILE 81 12.1 Một số khái niệm về tập tin 81 12.2 Các thao tác trên tập tin 82 Khai báo biến tập tin 82 Mở và đóng tập tin 82 12.3 Truy cập tập tin văn bản 83 12.4 Truy cập tập tin nhị phân 87 12.5 Bài tập 88 Tài Liệu Tham Khảo 90 Trang - iii
  6. Ngôn ngữ lập trình & Phương pháp lập trình Chương 1: NGÔN NGỮ LẬP TRÌNH & PHƯƠNG PHÁP LẬP TRÌNH 1.1 Ngôn ngữ lập trình (Programming Language) Ngôn ngữ lập trình là hệ thống các ký hiệu để miêu tả những tính toán qua máy tính trong một dạng mà cả con người và máy đều có thể hiểu được và phải tuân theo các qui ước về ngữ pháp và ngữ nghĩa, dùng để xây dựng thành các chương trình cho máy tính. Một chương trình được viết bằng một ngôn ngữ lập trình cụ thể (ví dụ Pascal, C ) gọi là chương trình nguồn, chương trình dịch làm nhiệm vụ dịch chương trình nguồn thành chương trình thực thi được trên máy tính. 1.2 Các bước lập trình Bước 1: Phân tích vấn đề và xác định các đặc điểm. (xác định I-P-O) Bước 2: Lập ra giải pháp. (đưa ra thuật giải) Bước 3: Cài đặt. (viết chương trình) Bước 4: Chạy thử chương trình. (dịch chương trình) Bước 5: Kiểm chứng và hoàn thiện chương trình. (thử nghiệm bằng nhiều số liệu và đánh giá) 1.3 Kỹ thuật lập trình I-P-O Cycle (Input-Process-Output Cycle) (Quy trình nhập-xử lý-xuất) Quy trình xử lý cơ bản của máy tính gồm I-P-O. Input Output Process Ví dụ 1: Xác định Input, Process, Output của việc làm 1 ly cà phê Input : Ly, cà phê, nước nóng, muỗng, đá lạnh. Process : Cho cà phê vào ly, nước nóng vào ly, dùng muỗng khuấy đều, cho đá lạnh vào. Output : Ly cà phê đã sẵn sàng để dùng. Giáo trình ngôn ngữ lập trình C/C++ Trang - 1
  7. Ngôn ngữ lập trình & Phương pháp lập trình Ví dụ 2: Xác định Input, Process, Output của chương trình tính tiền lương công nhân tháng 07/2016 biết rằng lương = lương căn bản * ngày công+phụ cấp Input : Lương căn bản, ngày công, phụ cấp Process : Nhân lương căn bản với ngày công sau đó cộng với phụ cấp Output : Lương Ví dụ 3: Xác định Input, Process, Output của chương trình giải phương trình bậc nhất ax + b = 0 Input : Hệ số a, b Process : Chia – b cho a Output : Nghiệm x Ví dụ 4: Xác định Input, Process, Output của chương trình tìm số lớn nhất của 2 số x và y. Input : a, b Process : Nếu x > y thì Output = x lớn nhất, ngược lại Output = y lớn nhất  Bài tập Xác định Input, Process, Output của các chương trình sau: 1. Đổi từ tiền VND sang tiền USD. 2. Tính điểm trung bình của học sinh gồm các môn Toán, Lý, Hóa. 3. Giải phương trình bậc 2: ax2 + bx + c = 0 4. Đổi từ độ sang radian và đổi từ radian sang độ (công thức / = a/180, với : radian, a: độ) 5. Kiểm tra 2 số a, b giống nhau hay khác nhau. 6. Tính diện tích hình tròn. 7. Tính chu vi hình chữ nhật 8. Tính tiền học phí phải đóng trong 1 học kỳ. Giáo trình ngôn ngữ lập trình C/C++ Trang - 2
  8. Ngôn ngữ lập trình & Phương pháp lập trình Sử dụng lưu đồ (Flowchart) Để dễ hơn về quy trình xử lý, các nhà lập trình đưa ra dạng lưu đồ để minh họa từng bước quá trình xử lý một vấn đề (bài toán). Hình dạng (symbol) Hành động (Activity) Dữ liệu vào (Input) Xử lý (Process) Dữ liệu ra (Output) Quyết định (Decision), sử dụng điều kiện Luồng xử lý (Flow lines) Gọi CT con, hàm (Procedure, Function ) Bắt đầu, kết thúc (Begin, End) Điểm ghép nối (Connector) Giáo trình ngôn ngữ lập trình C/C++ Trang - 3
  9. Ngôn ngữ lập trình & Phương pháp lập trình Ví dụ 5: Chuẩn bị cà phê Ví dụ 6: Mô tả ví dụ 2 Ví dụ 7: Mô tả ví dụ 3 Bắt đầu Bắt đầu Bắt đầu Cà phê, nước sôi LCB, ngày công Giá trị a, b Hòa cà phê vào nước sôi Nhân LCB với ngày công Chia –b cho a Bỏ đường vào Kết quả lương Nghiệm x Khu ấy đều hỗn hợp Kết thúc Kết thúc Cà phê đã sẵn sàng Kết thúc Ví dụ 8: Cộng 2 số Ví dụ 9: so sánh 2 số Bắt đầu Bắt đầu a, b Số a, Số b c = a + b Số a có bằng Không Số b không? c Có Kết thúc Số a bằng Số b Số a không bằng Số b Kết thúc Giáo trình ngôn ngữ lập trình C/C++ Trang - 4
  10. Ngôn ngữ lập trình & Phương pháp lập trình Ví dụ 10: Kiểm tra tính hợp lệ của điểm Ví dụ 11: Xếp lon vào thùng Bắt đầu Bắt đầu Thùng = 0 Lon Điểm 1 Lon Đi ểm >=0 và Không Điểm 0? Số dương Điểm Không Có Số =0 và Không Điểm <=10? Số không Đúng Kết thúc Kết thúc Giáo trình ngôn ngữ lập trình C/C++ Trang - 5
  11. Ngôn ngữ lập trình & Phương pháp lập trình 1.4 Bài tập Vẽ lưu đồ cho các chương trình sau: 1. Đổi từ tiền VND sang tiền USD. 2. Tính điểm trung bình của học sinh gồm các môn Toán, Lý, Hóa. 3. Giải phương trình bậc 2: ax2 + bx + c = 0 4. Đổi từ độ sang radian và đổi từ radian sang độ (công thức / = a/180, với : radian, a: độ) 5. Kiểm tra 2 số a, b giống nhau hay khác nhau. Giáo trình ngôn ngữ lập trình C/C++ Trang - 6
  12. Làm quen lập trình C/C++ Qua các ví dụ đơn giản Chương 2: LÀM QUEN LẬP TRÌNH C/C++ QUA CÁC VÍ DỤ ĐƠN GIẢN 2.1 Khởi động Dev C++ Click đúp chuột vào biểu tượng Dev C++ Hình 2-1 Giao diện trình biên dịch Dev C++ ▪ Sau khi giao diện Dev C++ được mở click vào File -> New -> Source File để bắc đầu lập trình ▪ Hoặc ấn tổ hợp phím Ctrl+N. 2.2 Các ví dụ đơn giản Ví dụ 1 /* Chuong trinh in ra cau Chao Cac Ban */ #include using namespace std; main() { cout <<"Chao Cac Ban"; } • Nhấn F9 để biên dịch chương trình • Nhấn F10 để chạy trương trình • Nhấn F11 để biên dịch và chạy chương trình Dòng thứ 1: bắt đầu bằng /* và kết thúc bằng */ Là dòng diễn giải (chú thích). Khi dịch và chạy chương trình, dòng này không thực hiện. Mục đích của việc ghi chú này giúp chương trình rõ ràng hơn. Sau này đọc lại chương trình biết chương trình làm gì. Giáo trình ngôn ngữ lập trình C/C++ Trang - 7
  13. Làm quen lập trình C/C++ Qua các ví dụ đơn giản Dòng thứ 2: chứa phát biểu tiền xử lý #include . Vì trong chương trình này ta sử dụng hàm thư viện của C++ là cout, do đó cần phải có khai báo của hàm thư viện này để báo cho trình biên dịch C++ biết. Nếu không khai báo chương trình sẽ báo lỗi. Dòng thứ 3: là câu lệnh using namespace std, Chúng ta có thể khai báo hoặc không khai báo tùy thích. Nhưng nếu không khai báo thì khi sử dụng các hàm trong iostream thì phải gọi std cho nó trước, ví dụ thay vì viết cout <<"Bai hoc C dau tien."; thì phải viết std:: cout <<"Chao Cac Ban"; Dòng thứ 4: main() là thành phần chính của mọi chương trình C/C++, Mọi chương trình C/C++ đều bắt đầu thi hành từ hàm main. Cặp dấu ngoặc () cho biết đây là khối hàm (function). Dòng thứ 5 và 7: cặp dấu ngoặc móc {} giới hạn thân của hàm. Thân hàm bắt đầu bằng dấu {và kết thúc bằng dấu}. Dòng thứ 6: cout <<"Chao Cac Ban";, chỉ thị cho máy in ra chuỗi ký tự nằm trong nháy kép "". Dòng này được gọi là một câu lệnh, kết thúc một câu lệnh trong C/C++ phải là dấu chấm phẩy (;). Chú ý: ✓ Các từ include, iostream, using, namespace, std, main, cout phải viết bằng chữ thường. ✓ Chuỗi trong nháy kép cần in ra “có thể viết chữ HOA, thường tùy, ý”. ✓ Kết thúc câu lệnh phải có dấu chấm phẩy. ✓ Kết thúc tên hàm không có dấu chấm phẩy hoặc bất cứ dấu gì. ✓ Ghi chú phải đặt trong cặp /* . */. ✓ Thân hàm phải được bao bởi cặp { }. ✓ Các câu lệnh trong thân hàm phải viết thụt vào. Giáo trình ngôn ngữ lập trình C/C++ Trang - 8
  14. Làm quen lập trình C/C++ Qua các ví dụ đơn giản Ví dụ 2 /* Chuong trinh nhap va in ra man hinh gia tri bien*/ #include using namespace std; main() { int i; cout > i; cout > i. Sử dụng hàm cin để nhận từ người sử dụng một trị nào đó. Dòng thứ 9: cout using namespace std; main() { int a, b; cout >a; cout >b; cout<<"Tong cua 2 so " <<a <<" va " <<b <<" la " << a+b; } Giáo trình ngôn ngữ lập trình C/C++ Trang - 9
  15. Làm quen lập trình C/C++ Qua các ví dụ đơn giản Ví dụ 4 /* Chuong trinh nhap vao ban kinh hinh tron. Tinh dien tich */ #include using namespace std; #define PI 3.14 main() { float fR; cout >fR; cout using namespace std; main() { int a,b; cout >a; cout >b; cout<<"nghiem X = "<< (float)-b/a; } Giáo trình ngôn ngữ lập trình C/C++ Trang - 10
  16. Các thành phần trong ngôn ngữ C/C++ Chương 3: CÁC THÀNH PHẦN TRONG NGÔN NGỮ C/C++ 3.1 Từ khóa Từ khóa là từ có ý nghĩa xác định dùng để khai báo dữ liệu, viết câu lệnh Trong C/C++ có các từ khóa sau: asm default float long struct void break do for near signed volatile case double goto pascal sizeof while cdecl else huge register switch char enum if return typedef const extern int short union continue far interrupt static unsigned Lưu ý: Các từ khóa phải viết bằng chữ thường 3.2 Tên Tên thường được đặt cho hằng, biến, mảng, con trỏ, nhãn Chiều dài tối đa của tên là 32 ký tự. Tên biến hợp lệ là một chuỗi ký tự liên tục gồm: Ký tự chữ, số và dấu gạch dưới. Ký tự đầu của tên phải là chữ hoặc dấu gạch dưới. Khi đặt tên không được đặt trùng với các từ khóa. Ví dụ 1:  Các tên đúng: tamgiac, a_1, So_ODD, Case  Các tên sai: 5t_1 (ký tự đầu là số) so-odd (sử dụng dấu gạch ngang) int (đặt tên trùng với từ khóa) tam giac (có khoảng trắng) f(x) (có dấu ngoặc tròn) Lưu ý: Trong C/C++, tên phân biệt chữ hoa, chữ thường Ví dụ 2: number khác Number case khác Case (case là từ khóa, do đó đặt tên là Case vẫn đúng) Giáo trình ngôn ngữ lập trình C/C++ Trang - 11
  17. Các thành phần trong ngôn ngữ C/C++ 3.3 Kiểu dữ liệu Có 4 kiểu dữ liệu cơ bản trong C/C++ là: char, int, float, double. Kiểu dữ liệu Kích Miền giá trị TT (Type) thước (Range) (Length) 1 unsigned char 1 byte 0 đến 255 2 char 1 byte – 128 đến 127 3 enum 2 bytes – 32,768 đến 32,767 4 unsigned int 2 bytes 0 đến 65,535 5 short int 2 bytes – 32,768 đến 32,767 6 int 2 bytes – 32,768 đến 32,767 7 unsigned long 4 bytes 0 đến 4,294,967,295 8 long 4 bytes – 2,147,483,648 đến 2,147,483,647 9 float 4 bytes 3.4 * 10–38 đến 3.4 * 1038 10 double 8 bytes 1.7 * 10–308 đến 1.7 * 10308 11 long double 10 bytes 3.4 * 10–4932 đến 1.1 * 104932 3.4 Ghi chú Trong khi lập trình cần phải ghi chú để giải thích các biến, hằng, thao tác xử lý giúp cho chương trình rõ ràng dễ hiểu, dễ nhớ, dễ sửa chữa và để người khác đọc vào dễ hiểu. Trong C/C++ có các ghi chú sau: // hoặc /* nội dung ghi chú */ • // dùng để ghi chú một hàng • /* . */ có thể ghi chú một hàng hoặc nhiều hàng. 3.5 Khai báo biến Tên biến Mỗi biến khi sử dụng trong chương trình điều phải được đặt tên theo quy định như cách đặt tên biến như mục 3.2 Giáo trình ngôn ngữ lập trình C/C++ Trang - 12
  18. Các thành phần trong ngôn ngữ C/C++ Khai báo biến Mọi biến đều phải được khai báo trước khi sử dụng Cú pháp: Kiểu dữ liệu Danh sách tên biến; o Kiểu dữ liệu: 1 trong các kiểu ở mục 3.3 o 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ách nhau dấu phẩy (,), cuối cùng là dấu chấm phẩy (;). Ví du: int i; // Khai báo i là kiểu nguyên float x,y,z; // Khai báo x,y,z là kiểu thực Vừa khai báo vừa khởi gán 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. Ví dụ:  Khai báo trước, gán giá trị sau: int x, y; x = 1; y = 2;  Vừa khai báo vừa gán giá trị: int a = 1, b = 2, c = 5; Vị trí đặt các khai báo biến Khi lập trình, phải nắm rõ vị trí của biến. Nếu khai báo và sử dụng không đúng, không rõ ràng sẽ dẫn đến sai sót khó kiểm soát được, vì vậy cần phải xác định đúng vị trí, phạm vi sử dụng biến trước khi sử dụng biến. Khai báo biến ngoài (biến toàn cục): Vị trí biến đặt bên ngoài tất cả các hàm, cấu trúc Các biến này có ảnh hưởng đến toàn bộ chương trình. Chu trình sống của nó là bắt đầu chạy chương trình đến lúc kết thúc chương trình. Khai báo biến trong (biến cục bộ): Vị trí biến đặt bên trong hàm, cấu trúc . Chỉ ảnh hưởng nội bộ bên trong hàm, cấu trúc đó . Chu trình sống của nó bắt đầu từ lúc hàm, cấu trúc được gọi thực hiện đến lúc thực hiện xong. Giáo trình ngôn ngữ lập trình C/C++ Trang - 13
  19. Biểu thức Chương 4: BIỂU THỨC 4.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 toán học nào đó. Mỗi biểu thức sẽ có một giá trị. Như vậy hằng, biến, phần tử mảng và hàm cũng được xem là biểu thức. Trong C/C++, ta có hai khái niệm về biểu thức: Biểu thức gán và Biểu thức điều kiện. Biểu thức được phân loại theo kiểu giá trị: nguyên và thực. Trong các mệnh đề logic, biểu thức được phân thành đúng (giá trị khác 0) và sai (giá trị bằng 0). Biểu thức thường được dùng trong: ▪ Vế phải của câu lệnh gán. ▪ Làm tham số thực sự của hàm. ▪ Làm chỉ số. ▪ Trong các toán tử của các cấu trúc điều khiển. 4.2 Các phép toán số học Các phép toán hai ngôi số học là Phép toán Ý nghĩa Ví dụ + Phép cộng x+y - Phép trừ x-y * Phép nhân x*y x/y / Phép chia (Chia số nguyên sẽ chặt phần thập phân) x%y % Phép lấy phần dư (Cho phần dư của phép chia x cho y) Ví dụ: 14/3=4 11%7=4 Giáo trình ngôn ngữ lập trình C/C++ Trang - 14
  20. Biểu thức 4.3 Các phép toán quan hệ và logic Phép toán quan hệ và logic cho giá trị đúng (1) hoặc giá trị sai (0). Phép Ý nghĩa Ví dụ toán x>y > So sánh lớn hơn 1>5 có giá trị 0 x>=y >= So sánh lớn hơn hoặc bằng 10>=7 có giá trị 1 x 4 && 5 > 6 || Phép hoặc 5 > 4 || 5 > 6 Bốn phép toán đầu có cùng số ưu tiên, bốn phép sau có cùng số thứ tự ưu tiên nhưng thấp hơn số thứ tự của bốn phép đầu. Các phép toán quan hệ có số thứ tự ưu tiên thấp hơn so với các phép toán số học, vì vậy biểu thức: i<n-1 được hiểu là i < (n-1). 4.4 Phép toán tăng giảm C/C++ đưa ra hai phép toán một ngôi để tăng và giảm các biến (nguyên và thực). Toán tử tăng là ++ sẽ cộng 1 vào toán hạng của nó, toán tử giảm thì sẽ trừ toán hạng đi 1. Ví dụ: n=7 ++n Cho ta n=8 ; n Cho ta n=6 Ta có thể viết phép toán ++ và trước hoặc sau toán hạng như sau: ++n, n++, n, n . Giáo trình ngôn ngữ lập trình C/C++ Trang - 15
  21. Biểu thức Sự khác nhau của ++n và n++: trong phép n++ thì tăng sau khi giá trị của nó đã được sử dụng, còn trong phép ++n thì n được tăng trước khi sử dụng. Sự khác nhau giữa n và n cũng như vậy. Ví dụ: n=6 x=++n Cho ta x=7 và n=7 x=n++ Cho ta x=6 và n=7 4.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 trong cùng một biểu thức sẽ 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. Thứ tự ưu tiên của các phép toán được trình bày trong bảng sau: TT Phép toán Trình tự kết hợp 1 () [] -> Trái qua phải 2 ! ~ & * - ++ (type ) sizeof Phải qua trái 3 * ( phép nhân ) / % Trái qua phải 4 + - Trái qua phải 5 > Trái qua phải 6 >= Trái qua phải 7 == != Trái qua phải 8 & Trái qua phải 9 ^ Trái qua phải 10 | Trái qua phải 11 && Trái qua phải 12 || Trái qua phải 13 ?: Phải qua trái 14 = += -= *= /= %= >= &= ^= Phải qua trái |= 15 , Trái qua phải Giáo trình ngôn ngữ lập trình C/C++ Trang - 16
  22. Biểu thức 4.6 Chuyển đổi kiểu Trong một biểu thức các toán hạng có thể có các kiểu dữ liệu khác nhau. Vì vậy để tính toán được chính xác cần phải chuyển đổi kiểu cho phù hợp. Có hai cách chuyển đổi kiểu dữ liệu: • Chuyển kiểu tự động: Khi có hai toán hạn trong một phép toán khác kiểu dữ liệu thì toán hạn có độ ưu tiên thấp hơn sẽ tự động chuyển thành kiểu cao hơn trước khi thực hiện phép toán. Ví dụ int i ; thì sau lệnh gán i=3.23 thì kết quả là i = 3. • Chuyển kiểu bắt buộc: Thực hiện theo cú pháp sau (Kiểu) Biểu thức Ví dụ: (float) ( x+y) int a=10; b=3 float z; z = (float)a/(float)b; 4.7 Các hàm toán học thường dùng abs abs(x); Phải khai báo tiền xử lý #include Cho giá trị tuyệt đối của số x. Ví dụ: int num = - 123; num = abs(num); //kết quả num = 123 rand rand(); Phải khai báo tiền xử lý #include Cho 1 giá trị ngẫu nhiên từ 0 đến 32767 Ví dụ: int num; srand(time(NULL)); //dùng hàm này để khởi đầu bộ số ngẫu nhiên Giáo trình ngôn ngữ lập trình C/C++ Trang - 17
  23. Biểu thức Phải khai báo tiền xử lý #include num = rand(); //kết quả num = 1 con số trong khoảng 0 32767 Tạo ngẫu nhiên 1 số trong khoảng (a,b) x=rand()%(b-a+1)+a pow double pow(double x, double y); Phải khai báo tiền xử lý #include Tính x mũ y Ví dụ: double x = 2.0, y = 3.0, z; z = pow(x, y); //kết quả z = 8.0 sqrt double sqrt(double x); Phải khai báo tiền xử lý #include Tính căn bậc 2 của x. Ví dụ: double x = 4.0, y; y = sqrt(x); //kết quả y = 2.0 atoi int atoi(const char *s); Phải khai báo tiền xử lý #include Chuyển đổi 1 chuỗi sang giá trị int. Ví dụ: int i; char *str = "12345.67"; i = atoi(str); Kết quả i = 12345 Giáo trình ngôn ngữ lập trình C/C++ Trang - 18
  24. Nhập – Xuất dữ liệ Chương 5: NHẬP - XUẤT DỮ LIỆU 5.1 Các hàm vào ra chuẩn - getchar() và putchar() Hàm getchar () Cơ chế vào đơn giản nhất là đọc từng ký tự từ thiết bị vào chuẩn, nói chung là bàn phím và màn hình của người sử dụng, bằng hàm getchar().  Cách dùng: Dùng câu lệnh sau: biến = getchar();  Công dụng: Nhận một ký tự vào từ bàn phím và không đưa ra màn hình. Hàm sẽ trả về ký tự nhận được và lưu vào biến. Ví dụ: int c; c = getchar() Lưu ý: Để sủ dụng hàm getchar(), phải khai báo tiền xử lý #include Hàm putchar() Để đưa một ký tự ra thiết bị ra chuẩn, nói chung là màn hình, ta sử dụng hàm putchar()  Cách dùng: Dùng câu lệnh sau: putchar(ch);  Công dụng: Đưa ký tự ch lên màn hình tại vị trí hiện tại của con trỏ. Ký tự sẽ được hiển thị với màu trắng. Ví dụ: int c; c = getchar(); putchar(c); Lưu ý: Để sủ dụng hàm putchar(), phải khai báo tiền xử lý #include Giáo trình ngôn ngữ lập trình C/C++ Trang - 19
  25. Nhập – Xuất dữ liệ 5.2 Đưa kết quả ra màn hình - Hàm printf  Cú pháp: printf ("chuỗi định dạng"[, đối mục 1, đối mục 2, ]); - Phải khai báo tiền xử lý #include - printf: 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: ✓ Đối với chuỗi kí tự ghi như thế nào in ra giống như vậy. ✓ Đố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: %c : Ký tự đơn %s : Chuỗi %d : Số nguyên thập phân có dấu %f : Số chấm động (ký hiệu thập phân) %e : Số chấm động (ký hiệu có số mũ) %g : Số chấm động (%f hay %g) %x : Số nguyên thập phân không dấu %u : Số nguyên hex không dấu %o : Số nguyên bát phân không dấu l : Tiền tố dùng kèm với %d, %u, %x, %o để chỉ số nguyên dài (ví dụ %ld) ✓ Các ký tự điều khiển và ký tự đặc biệt \n : Nhảy xuống dòng kế tiếp 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 % Giáo trình ngôn ngữ lập trình C/C++ Trang - 20
  26. Nhập – Xuất dữ liệ 5.3 Vào số liệu từ bàn phím - Hàm scanf  Cú pháp: scanf ("chuỗi định dạng"[, đối mục 1, đối mục 2, ]); - Phải khai báo tiền xử lý #include - scanf: tên hàm, phải viết bằng chữ thường. - khung đị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, : là danh sách các đối mục cách nhau bởi dấu phẩy, mỗi đối mục sẽ tiếp nhận giá trị nhập vào. - Ta phải dùng toán tử & để lấy địa chỉ của một biến. Giã sử x là biến thì &x là địa chỉ của biến x. 5.4 Đưa kết quả ra màn hình - Hàm cout Để xuất một biểu thức ra màn hình (Standard output device), ta thực hiện như sau:  Cú pháp cout << expression; Ta cũng có thể xuất một dãy các biểu thức bằng cách sử dụng nhiều toán tử << trên cùng một hàm cout: cout << expression_1 << expression_2 << << expression_n; Hoặc cout << expression_1 << expression_2 << << expression_n; Kết quả thu được là hoàn toàn tương tự. cout cùng với toán tử << có thể xuất được nhiều kiểu dữ liệu khác nhau mà không cần sự can thiệp của lập trình viên. C++ tự động nhận biết và xuất ra dưới định dạng phù hợp. Định dạng kết quả xuất: Khi xuất dữ liệu ra màn hình, đôi khi ta cần định dạng theo một yêu cầu nào đó. Ngôn ngữ C++, cung cấp cho người lập trình một số cách để định dạng dữ liệu xuất như sau: Giáo trình ngôn ngữ lập trình C/C++ Trang - 21
  27. Nhập – Xuất dữ liệ • endl: Tương đương với kí tự xuống dòng '\n'. • setw(n): Bình thường các giá trị được in ra bởi lệnh cout Ví dụ: #include #include using namespace std; main() { float a=5678.6782; int b=3; cout << fixed <<setprecision(2) << a; // kết quả là 5678.68 cout <<endl<< setw(5)<<12; //kết qủa " 12" cout <<endl<<setw(10)<<hex <<15; // kết quả f cout <<endl<<oct <<10; // kết quả 12 cout <<endl<<dec <<0x10; // kết quả 16 cout<<"\n Xuat :” <<setw(3)<<setfill('0')<<b; // kết quả Xuat: 003 } Giáo trình ngôn ngữ lập trình C/C++ Trang - 22
  28. Nhập – Xuất dữ liệ 5.5 Vào số liệu từ bàn phím - Hàm cin Bàn phím là thiết bị nhập chuẩn (standard input device). Để vào dữ liệu từ bàn phím cho các biến ta có thể dùng cin vùng toán tử >>. Cú pháp sẽ như sau:  Cú pháp cin >> variable; Hoặc cho nhiều biến: cin >> variable_1 >> variable_2 >> >> variable_n; Khi gặp những câu lệnh như thế này chương trình sẽ dừng lại để chờ chúng ta nhập dữ liệu vào từ bàn phím. Câu lệnh cin >> variable_1 >> variable_2 >> >> variable_n; coi các ký tự trắng là ký tự phân cách các lần nhập dữ liệu. Các ký tự trắng (white space characters) bao gồm: dấu cách, dấu tab, và ký tự xuống dòng (new line). Ví dụ a, b là hai biến kiểu int, thì câu lệnh: cin >> a >> b; Sẽ đợi người dùng nhập dữ liệu hai lần, cách nhau bởi ít nhất một ký tự trắng. Ví dụ ta nhập vào bàn phím như sau : 1989 2011 ↵ thì biến a sẽ nhận giá trị 1989, còn biến b sẽ nhận giá trị 2011. Chúng ta cũng không cần quan tâm đến kiểu của các biến, C++ tự động nhận biết điều này. 5.6 Bài tập 1. Viết chương trình đọc vào 2 số nguyên và in ra kết quả của phép (+), phép trừ (-). 2. Viết chương trình đọc vào 2 số nguyên và in ra kết quả của phép nhân (*), phép chia (/). Nhận xét kết quả chia 2 số nguyên. 3. Viết chương trình nhập vào bán kính hình cầu, tính và in ra diện tích, thể tích của hình cầu đó. Hướng dẫn: S = 4 R2 và V = (4/3) R3. 4. Viết chương trình nhập vào một số a bất kỳ và in ra giá trị bình phương (a2), lập phương (a3) của a và giá trị a4. 5. Viết chương trình đọc từ bàn phím 3 số nguyên biểu diễn ngày, tháng, năm và xuất ra màn hình dưới dạng "ngay/thang/nam". Giáo trình ngôn ngữ lập trình C/C++ Trang - 23
  29. Nhập – Xuất dữ liệ 6. Nhập a, b, c. In ra màn hình dòng chữ phương trình có dạng ax^2 + bx + c = 0, trong đó các giá trị a, b, c chỉ in 2 số lẻ (ví dụ với a = 5.141, b = −2, c = 0.8 in ra 5.14 x^2 −2.00 x + 0.80). 7. Nhập a, b, c là các số thực. In ra giá trị của các biểu thức sau với 3 số lẻ: a. a2− 2b + ab/c b. 3 − 2 4 + 4√ 8. Viết chương trình nhập vào số giây từ 0 đến 86399, đổi số giây nhập vào thành dạng "gio:phut:giay" mỗi thành phần là một số nguyên có 2 chữ số. Ví dụ: 02:11:05 Giáo trình ngôn ngữ lập trình C/C++ Trang - 24
  30. Cấu trúc điều khiển Chương 6: CẤU TRÚC ĐIỀU KHIỂN Một chương trình bao gồm nhiều câu lệnh. Thông thường các câu lệnh được thực hiện một cách lần lượt theo thứ tự mà chúng được viết ra. Các cấu trúc điều khiển cho phép thay đổi trật tự nói trên, do đó máy có thể nhảy thực hiện một câu lệnh khác ở một ví trí trước hoặc sau câu lệnh hiện thời. Xét về mặt công dụng, có thể chia các cấu trúc điều khiển thành các nhóm chính: Nhảy không có điều kiện. Rẽ nhánh. Tổ chức chu trình. Ngoài ra còn một số toán tử khác có chức năng bổ trợ như break, continue. 6.1 Cấu trúc có điều kiện: Lệnh if-else: Toán tử if cho phép lựa chọn chạy theo một trong hai nhánh tuỳ thuộc vào sự bằng không và khác không của biểu thức. Nó có hai cách viết sau: if ( biểu thức ) if ( biểu thức ) khối lệnh 1; khối lệnh 1; /* Dạng một */ else khối lệnh 2 ; /* Dạng hai */ Hoạt động của biểu thức dạng 1: Máy tính giá trị của biểu thức. Nếu biểu thức đúng (biểu thức có giá trị khác 0) máy sẽ thực hiện khối lệnh 1 và sau đó sẽ thực hiện các lệnh tiếp sau lệnh if trong chương trình. Nếu biểu thức sai (biểu thức có giá trị bằng 0) thì máy bỏ qua khối lệnh 1 mà thực hiện ngay các lệnh tiếp sau lệnh if trong chương trình. Giáo trình ngôn ngữ lập trình C/C++ Trang - 25
  31. Cấu trúc điều khiển Hoạt động của biểu thức dạng 2: Máy tính giá trị của biểu thức. Nếu biểu thức đúng (biểu thức có giá trị khác 0) máy sẽ thực hiện khối lệnh 1 và sau đó sẽ thực hiện các lệnh tiếp sau khối lệnh 2 trong chương trình. Nếu biểu thức sai (biểu thức có giá trị bằng 0) thì máy bỏ qua khối lệnh 1 mà thực hiện khối lệnh 2 sau đó thực hiện tiếp các lệnh tiếp sau khối lệnh 2 trong chương trình. Ví dụ: Chương trình nhập vào hai số a và b, tìm max của hai số rồi in kết quả lên màn hình. Chương trình có thể viết bằng cả hai cách trên như sau: Cách 1: #include using namespace std; main() { int a,b,max; cout >a; cout >b; max=a; if (b>max) max=b; cout<<"\n Max cua hai so "<<a <<" va "<<b <<" la "<<max; } Giáo trình ngôn ngữ lập trình C/C++ Trang - 26
  32. Cấu trúc điều khiển Cách 2: #include using namespace std; main() { int a,b,max; cout >a; cout >b; if (a>b) max=a; else max=b; cout 0 ) /* if thứ nhất*/ if ( a>b ) /* if thứ hai*/ z=a; else z=b; thì else ở đây sẽ đi với if thứ hai. Giáo trình ngôn ngữ lập trình C/C++ Trang - 27
  33. Cấu trúc điều khiển Đoạn chương trình trên tương đương với: if ( n>0 ) /* if thứ nhất*/ { if ( a>b ) /* if thứ hai*/ z=a; else z=b; } Trường hợp ta muốn else đi với if thứ nhất ta viết như sau: if ( n>0 ) /* if thứ nhất*/ { if ( a>b ) /* if thứ hai*/ z=a; } else z=b; Lệnh else-if: Khi muốn thực hiện một trong n quyết định ta có thể sử dụng cấu trúc sau: if ( biểu thức 1 ) khối lệnh 1; else if ( biểu thức 2 ) khối lệnh 2; else if ( biểu thức n-1 ) khối lệnh n-1; else khối lệnh n; Trong cấu trúc này, máy sẽ đi kiểm tra từ biểu thức 1 trở đi đến khi gặp biểu thức nào có giá trị khác 0. Giáo trình ngôn ngữ lập trình C/C++ Trang - 28
  34. Cấu trúc điều khiển Nếu biểu thức thứ i (1,2, n-1) có giá trị khác 0, máy sẽ thực hiện khối lệnh i, rồi sau đó đi thực hiện lệnh nằm tiếp theo khối lệnh n trong chương trình. Nếu trong cả n-1 biểu thức không có biểu thức nào khác 0, thì máy sẽ thực hiện khối lệnh n rồi sau đó đi thực hiện lệnh nằm tiếp theo khối lệnh n trong chương trình. Ví dụ: Chương trình giải phương trình bậc hai. #include #include using namespace std; main() { float a,b,c,d,x1,x2; cout >a>>b>>c; d=b*b-4*a*c; if (d<0.0) cout<<"\n Phuong trinh vo nghiem "; else if (d==0.0) cout<<"\n Phuong trinh co nghiem kep x1,2="<<-b/(2*a); else { cout<<"\n Phuong trinh co hai nghiem "; cout<<"\n x1= "<<(-b+sqrt(d))/a; cout<<"\n x2= "<<(-b-sqrt(d))/a; } } 6.2 Lệnh nhảy không điều kiện - toán tử goto: Nhãn có cùng dạng như tên biến và có dấu: đứng ở phía sau. Nhãn có thể được gán cho bất kỳ câu lệnh nào trong chương trình. Ví dụ: ts: s=s++; thì ở đây ts là nhãn của câu lệnh gán s=s++. Toán tử goto có dạng: Giáo trình ngôn ngữ lập trình C/C++ Trang - 29
  35. Cấu trúc điều khiển goto nhãn; Khi gặp toán tử này máy sẽ nhảy tới câu lệnh có nhãn viết sau từ khoá goto. Khi dùng toán tử goto cần chú ý: Câu lệnh goto và nhãn cần nằm trong một hàm, có nghĩa là toán tử goto chỉ cho phép nhảy từ vị trí này đến vị trí khác trong thân một hàm và không thể dùng để nhảy từ một hàm này sang một hàm khác. Không cho phép dùng toán tử goto để nhảy từ ngoài vào trong một khối lệnh. Tuy nhiên việc nhảy từ trong một khối lệnh ra ngoài là hoàn toàn hợp lệ. Ví dụ như đoạn chương trình sau là sai. goto n1; { n1: cout using namespace std; main() { int s,i; i=s=0; tong: ++i; s=s+i; if (i<10) goto tong; cout<<"\n tong s="<<s; } Giáo trình ngôn ngữ lập trình C/C++ Trang - 30
  36. Cấu trúc điều khiển 6.3 Lệnh break Thông thường lệnh break dùng để thoát khỏi vòng lặp không xác định điều kiện dừng hoặc muốn dừng vòng lặp theo điều kiện chỉ định. Việc dùng lệnh break để thoát khỏi vòng lặp thường sử dụng phối hợp với lệnh if. Lệnh break dùng trong for, while, do while, switch. Lệnh break thoát khỏi vòng lặp chứa nó. 6.4 Cấu trúc rẽ nhánh - toán tử switch: Là cấu trúc tạo nhiều nhánh đặc biệt. Nó căn cứ vào giá trị một biểu thức nguyên để chọn một trong nhiều cách nhảy. Cấu trúc tổng quát của nó là: switch ( biểu thức nguyên ) { case n1 khối lệnh 1 case n2 khối lệnh 2 case nk khối lệnh k [ default khối lệnh k+1 ] } ➢ Với ni là các số nguyên, hằng ký tự hoặc biểu thức hằng. Các ni cần có giá trị khác nhau. Đoạn chương trình nằm giữa các dấu { } gọi là thân của toán tử switch. ➢ default là một thành phần không bắt buộc phải có trong thân của switch. ➢ Sự hoạt động của toán tử switch phụ thuộc vào giá trị của biểu thức viết trong dấu ngoặc ( ) như sau: ➢ Khi giá trị của biểu thức này bằng ni, máy sẽ nhảy tới các câu lệnh có nhãn là case ni. Giáo trình ngôn ngữ lập trình C/C++ Trang - 31
  37. Cấu trúc điều khiển ➢ Khi giá trị biểu thức khác tất cả các ni 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ủa lệnh default như sau: ➢ Khi có default máy sẽ nhảy tới câu lệnh sau nhãn default. ➢ Khi không có default máy sẽ nhảy ra khỏi cấu trúc switch. Chú ý: Máy sẽ nhảy ra khỏi toán tử switch khi nó gặp câu lệnh break hoặc dấu ngoặc nhọn đóng cuối cùng của thân switch. Ta cũng có thể dùng câu lệnh goto trong thân của toán tử switch để nhảy tới một câu lệnh bất kỳ bên ngoài switch. Khi toán tử switch nằm trong thân một hàm nào đó thì ta có thể sử dụng câu lệnh return trong thân của switch để ra khỏi hàm này (lệnh return sẽ đề cập sau). Khi máy nhảy tới một câu lệnh nào đó thì sự hoạt động tiếp theo của nó sẽ phụ thuộc vào các câu lệnh đứng sau câu lệnh này. Như vậy nếu máy nhảy tới câu lệnh có nhãn case ni thì nó có thể thực hiện tất cả các câu lệnh sau đó cho tới khi nào gặp câu lệnh break, goto hoặc return. Nói cách khác, máy có thể đi từ nhóm lệnh thuộc case ni sang nhóm lệnh thuộc case thứ ni+1. Nếu mỗi nhóm lệnh được kết thúc bằng break thì toán tử switch sẽ thực hiện chỉ một trong các nhóm lệnh này. Ví dụ: Lập chương trình phân loại học sinh theo điểm sử dụng cấu trúc switch: #include using namespace std; main() { int diem; tt: cout >diem; switch (diem) { case 0: case 1: case 2: Giáo trình ngôn ngữ lập trình C/C++ Trang - 32
  38. Cấu trúc điều khiển case 3:cout >diem; if (diem==1) goto tt; } 6.5 Bài tập Sử dụng lệnh if 1. Viết chương trình nhập vào số nguyên dương, in ra thông báo số chẵn hay lẻ. Hướng dẫn: Nhập vào số nguyên dương x. Kiểm tra nếu x chia chẵn cho hai thì x là số chẵn (hoặc chia cho 2 dư 0) ngược lại là số lẻ. 2. Viết chương trình nhập vào 4 số nguyên. Tìm và in ra số lớn nhất. Hướng dẫn: Ta có 4 số nguyên a, b, c, d. Tìm 2 số nguyên lớn nhất x, y của 2 cặp (a, b) và (c, d). Sau đó so sánh 2 số nguyên x, y để tìm ra số nguyên lớn nhất. 3. Viết chương trình giải phương trình bậc nhất ax+b =0 với a, b được nhập từ bàn phím. 4. Viết chương trình nhập vào giờ phút giây (hh:mm:ss). Cộng thêm số giây nhập vào và in ra kết quả dưới dạng hh:mm:ss. (số giây cộng thêm lớn hơn 0 và nhỏ hơn 60) Hướng dẫn: Nhập vào giờ phút giây vào 3 biến gio, phut, giay và nhập và giây công thêm vào biến them: Nếu giay + them < 60 thì Giáo trình ngôn ngữ lập trình C/C++ Trang - 33
  39. Cấu trúc điều khiển giay = giay + them Ngược lại giay = (giay + them) - 60 phut = phut + 1 Nếu phut >= 60 thì phut = phut - 60 gio = gio + 1 Hết nếu Hết nếu Sử dụng lệnh switch 1. Viết chương trình nhập vào tháng, in ra tháng đó có bao nhiêu ngày. Hướng dẫn: Nhập vào tháng Nếu là tháng 1, 3, 5, 7, 8, 10, 12 thì có 31 ngày Nếu là tháng 4, 6, 9, 11 thì có 30 ngày Nếu là tháng 2 có 28 ngày 2. Viết chương trình xác định biến ký tự color rồi in ra thông báo - RED, nếu color = 'R' hoặc color = 'r' - GREEN, nếu color = 'G' hoặc color = 'g' - BLUE, nếu color = 'B' hoặc color = 'b' - BLACK, nếu color có giá trị khác. 3. Viết chương trình nhập vào 2 số x, y và 1 trong 4 toán tử +, -, *, /. Nếu là + thì in ra kết quả x + y, nếu là – thì in ra x – y, nếu là * thì in ra x * y, nếu là / thì in ra x / y (nếu y = 0 thì thông báo không chia được) 4. Viết chương trình trò chơi One-Two-Three ra cái gì ra cái này theo điều kiện: - Búa (B) thắng Kéo, thua Giấy. - Kéo (K) thắng Giấy, thua Búa. - Giấy (G) thắng Búa, thua Kéo. Hướng dẫn: Dùng lệnh switch lồng nhau Giáo trình ngôn ngữ lập trình C/C++ Trang - 34
  40. Cấu trúc điều khiển Bài tập làm thêm 1. Viết chương trình nhập vào điểm 3 môn thi: Toán, Lý, Hóa của học sinh. Nếu tổng điểm >= 15 và không có môn nào dưới 4 thì in kết quả đậu. Nếu đậu mà các môn đều lớn hơn 5 thì in ra lời phê "Học đều các môn", ngược lại in ra "Học chưa đều các môn", các trường hợp khác là "Thi hỏng". 2. Viết chương trình nhập số giờ làm và lương giờ rồi tính số tiền lương tổng cộng. Nếu số giờ làm lớn hơn 40 thì những giờ làm dôi ra được tính 1,5 lần. 3. Viết chương trình nhập vào 3 giá trị nguyên dương a, b, c. Kiểm tra xem a, b, c có phải là 3 cạnh của tam giác không? Nếu là 3 cạnh của tam giác thì tính diện tích của tam giác theo công thức sau: S = p *( p − a)*( p − b)*( p − c) , với p là 1/2 chu vi của tam giác. Hướng dẫn: a, b, c là 3 cạnh của tam giác phải thỏa điều kiện sau: (a + b) > c và (a + c) > b và (b + c) > a 4. Viết chương trình nhập vào 3 số nguyên rồi in ra màn hình theo thứ tự tăng dần. 5. Viết chương trình tính tiền điện gồm các khoảng sau: - Tiền thuê bao điện kế: 1000đ/tháng - Định mức sử dụng điện cho mỗi hộ là: 50 KW với giá 230đ/KW - Nếu phần vượt định mức = 100KW thì tính giá 900đ/KW - Chỉ số mới và cũ được nhập vào từ bàn phím - In ra màn hình chỉ số cũ, chỉ số mới, tiền trả định mức, tiền trả vượt định mức, tổng tiền phải trả. Giáo trình ngôn ngữ lập trình C/C++ Trang - 35
  41. Vòng lặp Chương 7: VÒNG LẶP 7.1 Lệnh continue Được dùng trong vòng lặp for, while, do while. Khi lệnh continue thi hành quyền điều khiển sẽ trao qua cho biểu thức điều kiện của vòng lặp gần nhất. Nghĩa là lộn ngược lên đầu vòng lặp, tất cả những lệnh đi sau trong vòng lặp chứa continue sẽ bị bỏ qua không thi hành. 7.2 Vòng lặp for Vòng lặp xác định thực hiện lặp lại một số lần xác định của một (chuỗi hành động) • Cú pháp lệnh for (biểu thức 1; biểu thức 2; biểu thức 3) khối lệnh;  từ khóa for phải viết bằng chữ thường  Nếu khối lệnh bao gồm từ 2 lệnh trở lên thì phải đặt trong dấu { } • Lưu đồ Vào  kiểm tra điều kiện Sai Điều kiện nếu đúng đúng thì thực hiện khối lệnh; Đúng lặp lại kiểm tra điều kiện khối lệnh nếu sai thoát khỏi vòng lặp. Ra Giải thích: o Biểu thức 1: khởi tạo giá trị ban đầu cho biến điều khiển. o Biểu thức 2: là quan hệ logic thể hiện điều kiện tiếp tục vòng lặp. o Biểu thức 3: phép gán dùng thay đổi giá trị biến điều khiển. Nhận xét: o Biểu thức 1 bao giờ cũng chỉ được tính toán một lần khi gọi thực hiện for. o Biểu thức 2, 3 và thân for có thể thực hiện lặp lại nhiều lần. Giáo trình ngôn ngữ lập trình C/C++ Trang - 36
  42. Vòng lặp Lưu ý: o Biểu thức 1, 2, 3 phải phân cách bằng dấu chấm phẩy (;) o Nếu biểu thức 2 không có, vòng for được xem là luôn luôn đúng. Muốn thoát khỏi vòng lặp for phải dùng một trong 3 lệnh break, goto hoặc return. o Với mỗi biểu thức có thể viết thành một dãy biểu thức con phân cách nhau bởi dấu phẩy. Khi đó các biểu thức con được xác định từ trái sang phải. Tính đúng sai của dãy biểu thức con trong biểu thức thứ 2 được xác định bởi biểu thức con cuối cùng. o Trong thân for (khối lệnh) có thể chứa một hoặc nhiều cấu trúc điều khiển khác. o Khi gặp lệnh break, cấu trúc lặp sâu nhất sẽ thoát ra. o Trong thân for có thể dùng lệnh goto để thoát khỏi vòng lặp đến vị trí mong muốn. o Trong thân for có thể sử dụng return để trở về một hàm nào đó. o Trong thân for có thể sử dụng lệnh continue để chuyển đến đầu vòng lặp. Ví dụ 1: Viết chương trình in ra câu "Vi du su dung vong lap for" 3 lần. #include using namespace std; #define MSG "Vi du su dung vong lap for.\n" main() { int i; for(i = 1; i<=3; i++) //hoac for(i = 1; i<=3; i+=1) cout<<MSG; } Ghi chú: Có dấu chấm phẩy sau lệnh for thì các lệnh thuộc vòng lặp for sẽ không được thực hiện. Giáo trình ngôn ngữ lập trình C/C++ Trang - 37
  43. Vòng lặp Ví dụ 2: Viết chương trình nhập vào 3 số nguyên. Tính và in ra tổng của chúng. #include using namespace std; main() { int i, n, s=0; for(i = 1; i >n; s = s + n; } cout using namespace std; main() { int i, n, s=0; cout >n; for(i = 0; i<=n; i++) { if (i % 2 != 0) //neu i la so le s = s + i; //hoac is += i; } cout<<"\n Tong: "<<s; } Giáo trình ngôn ngữ lập trình C/C++ Trang - 38
  44. Vòng lặp 7.3 Vòng lặp while Vòng lặp thực hiện lặp lại trong khi biểu thức còn đúng. • Cú pháp lệnh while (biểu thức) khối lệnh;  từ khóa while phải viết bằng chữ thường  Nếu khối lệnh bao gồm từ 2 lệnh trở lên thì phải đặt trong dấu { } • Lưu đồ Vào Trước tiên biểu thức được kiểm tra nếu sai thì kết thúc vòng lặp while Sai biểu thức (khối lệnh không được thi hành 1 lần nào) Đúng nếu đúng thực hiện khối lệnh; khối lệnh lặp lại kiểm tra biểu thức Ra o Biểu thức: có thể là một biểu thức hoặc nhiều biểu thức con. Nếu là nhiều biểu thức con thì cách nhau bởi dấu phẩy (,) và tính đúng sai của biểu thức được quyết định bởi biểu thức con cuối cùng. o Trong thân while (khối lệnh) có thể chứa một hoặc nhiều cấu trúc điều khiển khác. o Trong thân while có thể sử dụng lệnh continue để chuyển đến đầu vòng lặp (bỏ qua các câu lệnh còn lại trong thân). o Muốn thoát khỏi vòng lặp while tùy ý có thể dùng các lệnh break, goto, return như lệnh for. Giáo trình ngôn ngữ lập trình C/C++ Trang - 39
  45. Vòng lặp Ví dụ 1: Viết chương trình in ra câu "Vi du su dung vong lap while" 3 lần. #include using namespace std; #define MSG "Vi du su dung vong lap while.\n" main() { int i = 0; while (i++ using namespace std; main() { int i = 0, n, s = 0; cout >n; while (i++ < n) s = s + i; //hoac s += i; cout<<"Tong: "<<s; } 7.4 Vòng lặp do while Vòng lặp thực hiện lặp lại cho đến khi biểu thức sai. • Cú pháp lệnh do khối lệnh; while (biểu thức);  từ khóa do, while phải viết bằng chữ thường  Nếu khối lệnh bao gồm từ 2 lệnh trở lên thì phải đặt trong dấu { } Giáo trình ngôn ngữ lập trình C/C++ Trang - 40
  46. Vòng lặp • Lưu đồ Vào Thực hiện khối lệnh khối lệnh Kiểm tra biểu thức Nếu đúng thì lặp lại thực hiện khối lệnh Đúng biểu thức Nếu sai thì kết thúc vòng lặp (khối lệnh được thi hành 1 lần) Sai Ra o Biểu thức: có thể là một biểu thức hoặc nhiều biểu thức con. Nếu là nhiều biểu thức con thì cách nhau bởi dấu phẩy (,) và tính đúng sai của biểu thức được quyết định bởi biểu thức con cuối cùng. o Trong thân do while (khối lệnh) có thể chứa một hoặc nhiều cấu trúc điều khiển khác. o Trong thân do while có thể sử dụng lệnh continue để chuyển đến đầu vòng lặp (bỏ qua các câu lệnh còn lại trong thân). o Muốn thoát khỏi vòng lặp do while tùy ý có thể dùng các lệnh break, goto, return. Ví dụ 1: Viết chương trình kiểm tra password. #include using namespace std; # define PASSWORD 12345 main() { int n; do { cout >n; } while (n!= PASSWORD); } Giáo trình ngôn ngữ lập trình C/C++ Trang - 41
  47. Vòng lặp Ví dụ 2: Viết chương trình nhập vào năm hiện tại, năm sinh. In ra tuoi. #include using namespace std; # define CHUC " Chuc ban vui ve (: >\n" main() { char tiep; int namhtai, namsinh; do { cout >namhtai; cout >namsinh; cout >tiep; } while (tiep== 'y' || tiep == 'Y'); } 7.5 Vòng lặp lồng nhau Ví dụ 1: Vẽ hình chữ nhật đặc bằng các dấu '*' #include using namespace std; main() { int i, j, dai, rong; cout >dai; cout >rong; for (i = 1; i <= rong; i++) { for (j = 1; j <= dai; j++) cout<<"*"; //in mot hang voi chieu dai dau * cout<<"\n"; //xuong dong khi in xong 1 hang } } Giáo trình ngôn ngữ lập trình C/C++ Trang - 42
  48. Vòng lặp Ví dụ 2: Vẽ hình chữ nhật đặc có chiều rộng = 10 hàng. Hàng thứ 1 = 10 số 0, hàng thứ 2 = 10 số 1 #include using namespace std; main() { int i = 0, j; while (i <= 9) { j = 0; //khoi tao lai j = 0 cho lan in ke tiep while (j++ <= 9) //in 1 hang 10 so i cout<<i; cout<<"\n"; //xuong dong khi in xong 1 hang i++; //tang i len 1 cho vong lap ke tiep } } Ghi chú: Các lệnh lặp for, while, do while có thể lồng vào chính nó, hoặc lồng vào lẫn nhau. Nếu không cần thiết không nên lồng vào nhiều cấp dễ gây nhầm lẫn khi lập trình cũng như kiểm soát chương trình. 7.6 So sánh sự khác nhau của các vòng lặp ➢ Vòng lặp for thường sử dụng khi biết được số lần lặp xác định. ➢ Vòng lặp while, do while thường sử dụng khi không biết rõ số lần lặp. ➢ Khi gọi vòng lặp while, do while, nếu biểu thức sai vòng lặp while sẽ không được thực hiện lần nào nhưng vòng lặp do while thực hiện được 1 lần. ➢ Số lần thực hiện ít nhất của while là 0 và của do while là 1 7.7 Bài tập 1. Viết chương trình in ra bảng mã ASCII 2. Viết chương trình nhập vào một số rồi in ra tất cả các ước số của số đó. 3. Viết chương trình vẽ một hình chữ nhật và một tam giác cân bằng các dấu * 4. Viết chương trình tính tổng nghịch đảo của N số nguyên đầu tiên theo công thức S = 1 + 1/2 + 1/3 + + 1/N Giáo trình ngôn ngữ lập trình C/C++ Trang - 43
  49. Vòng lặp 5. Viết chương trình tính tổng bình phương các số lẻ từ 1 đến N. 6. Viết chương trình nhập vào N rồi tính giai thừa của N. 7. Viết chương trình tìm USCLN, BSCNN của 2 số. 8. Viết chương trình vẽ hình chữ nhật rỗng và tam giác cân rỗng bằng các dấu *. 9. Viết chương trình nhập vào một số và kiểm tra xem số đó có phải là số nguyên tố hay không? 10. Viết chương trình tính số hạng thứ n của dãy Fibonaci. Dãy Fibonaci là dãy số gồm các số hạng p(n) với: p(n) = p(n-1) + p(n-2) với n>2 và p(1) = p(2) = 1 Dãy Fibonaci sẽ là: 1 1 2 3 5 8 13 21 34 55 89 144 11. Viết chương trình tính xn với x, n được nhập vào từ bàn phím. 12. Viết chương trình nhập vào 1 số từ 0 đến 9. In ra chữ số tương ứng. Ví dụ: nhập vào số 5, in ra "Năm". 13. Viết chương trình lặp lại nhiều lần công việc nhập một ký tự và in ra mã ASCII của ký tự đó, khi nào nhập số 0 thì dừng. 14. Viết chương trình tính dân số của một thành phố sau 10 năm nữa, biết rằng dân số hiện nay là 6.000.000, tỉ lệ tăng dân số hàng năm là 1.8% . 15. Viết chương trình tìm các số nguyên gồm 3 chữ số sao cho tích của 3 chữ số bằng tổng 3 chữ số. Ví dụ: 1*2*3 = 1+2+3. 16. Viết chương trình tìm các số nguyên a, b, c, d khác nhau trong khoảng từ 1 tới 9 thỏa mãn điều kiện a*d*d = b*c*c*c 17. Viết chương trình giải bài toán cổ điển sau: Vừa gà vừa chó 36 con, Bó lại cho tròn, đếm đủ 100 chân ,Hỏi có bao nhiêu gà, bao nhiêu chó 18. Viết chương trình giải bài toán cổ điển sau: Trăm trâu, trăm cỏ Trâu đứng ăn năm Trâu nằm ăn ba, Ba trâu già ăn một Hỏi mỗi loại trâu có bao nhiêu con. Giáo trình ngôn ngữ lập trình C/C++ Trang - 44
  50. Vòng lặp 19. Viết chương trình in ra bảng cửu chương 20. Viết chương trình xác định xem một tờ giấy có độ dày 0.1 mm. Phải gấp đôi tờ giấy bao nhiêu lần để nó có độ dày 1m. 21. Viết chương trình tìm các số nguyên tố từ 3 đến N, với N được nhập vào từ bàn phím (N>20). 22. Viết chương trình lặp đi lặp lại các công việc sau: - Nhập vào một ký tự trên bàn phím. - Nếu là chữ thường thì in ra chính nó và chữ HOA tương ứng. - Nếu là chữ HOA thì in ra chính nó và chữ thường tường ứng. - Nếu là ký số thì in ra chính nó. (số từ 0 đến 9) - Nếu nhập -1 thì kết thúc chương trình. 23. Viết chương trình nhập vào x, n tính: - x + x + + x (n dấu căn) x x n - 1 + + 2 n +1 24. Viết chương trình nhập vào N số nguyên, đếm xem có bao nhiêu số âm, bao nhiêu số dương và bao nhiêu số không. Giáo trình ngôn ngữ lập trình C/C++ Trang - 45
  51. Hàm Chương 8: HÀM Một chương trình viết trong ngôn ngữ C/C++ là một dãy các hàm, trong đó có một hàm chính (hàm main()). Hàm chia các bài toán lớn thành các công việc nhỏ hơn, giúp thực hiện những công việc lặp lại nào đó một cách nhanh chóng mà không phải viết lại đoạn chương trình. Thứ tự các hàm trong chương trình là bất kỳ, song chương trình bao giờ cũng đi thực hiện từ hàm main(). 8.1 Cơ sở Hàm có thể xem là một đơn vị độc lập của chương trình. Các hàm có vai trò ngang nhau, vì vậy không có phép xây dựng một hàm bên trong các hàm khác. Cú pháp định nghĩa hàm như sau: tên hàm ( ) { } : Là các kiểu dữ liệu được dùng làm kiểu trả về của hàm : Các tham số của hàm được gọi là các tham số hình thức. Nếu hàm có các tham số hình thức thì phải khai báo kiểu dữ liệu cho mỗi tham số (tương tự như khai báo kiểu dữ liệu cho các biến). Khi các tham số có cùng kiểu dữ liệu thì không được viết gộp lại. Ví dụ: float max3s(float a, float b, float c) khai báo các đối có dạng: Kiểu đối 1 tên đối 1, kiểu đối 2 tên đối 2, , kiểu đối n tên đối n Thân hàm:Thân hàm là nội dung chính của hàm bắt đầu và kết thúc bằng các dấu { }. Trong thân hàm có thể gồm: o Khai báo các biến cục bộ, Các biến cục bộ chỉ có giá trị trong thân hàm. o Các câu lệnh. Ví dụ: Xét bài toán: Tìm giá trị lớn nhất của ba số mà giá trị của chúng được đưa vào bàn phím. Giáo trình ngôn ngữ lập trình C/C++ Trang - 46
  52. Hàm Xây dựng chương trình và tổ chức thành hai hàm: Hàm main() và hàm max3s. Nhiệm vụ của hàm max3s là tính giá trị lớn nhất của ba số đọc vào, giả sử là a,b,c. Nhiệm vụ của hàm main() là đọc ba giá trị vào từ bàn phím, rồi dùng hàm max3s để tính như trên, rồi đưa kết quả ra màn hình. Chương trình được viết như sau: #include using namespace std; float max3s(float a,float b,float c) { float max; max=a; if (max >x>>y>>z; cout<<"\n Max cua ba so x= "<<x<<" y= "<<y<<" z= "<<z<<" la: "<<max3s(x,y,z); } /* Ket thuc ham main*/ Chú ý: ▪ Khi hàm khai báo không có kiểu ở trước nó thì nó được mặc định là kiểu int. ▪ Không nhất thiết phải khai báo nguyên mẫu hàm. Nhưng nói chung nên có vì nó cho phép chương trình biên dịch phát hiện lỗi khi gọi hàm hay tự động việc chuyển dạng. ▪ Nguyên mẫu của hàm thực chất là dòng đầu tiên của hàm thêm vào dấu;. Tuy nhiên trong nguyên mẫu có thể bỏ tên các đối. Giáo trình ngôn ngữ lập trình C/C++ Trang - 47
  53. Hàm ▪ Hàm thường có một vài đối. Ví dụ như hàm max3s có ba đối là a,b,c. cả ba đối này đều có giá trị float. Tuy nhiên, cũng có hàm không đối như hàm main. ▪ Hàm thường cho ta một giá trị nào đó. Lẽ dĩ nhiên giá trị của hàm phụ thuộc vào giá trị các đối. 8.2 Hàm không cho các giá trị trả về: Ví dụ hàm tìm giá trị max trong ba số là max3s ở trên có thể được viết thành thủ tục hiển thị số cực đại trong ba số như sau: #include using namespace std; void max3s(float a,float b,float c) { float max; max=a; if (max >x>>y>>z; max3s(x,y,z); // Goi thu tu tuc trong main } /* Ket thuc ham main*/ Giáo trình ngôn ngữ lập trình C/C++ Trang - 48
  54. Hàm 8.3 Các ví dụ về hàm Ví dụ 1 #include using namespace std; void line() /*ham khong co gia tri tra ve*/ { int i; for(i = 0; i using namespace std; int power(int ix, int in) // ham tinh so mu { int i, ip = 1; for(i = 1; i <= in; i++) ip = ip*ix; return ip; } main() { cout<<"2 mu 2 = "<<power(2, 2); cout<<"\n2 mu 3 = "<<power(2, 3); } Giáo trình ngôn ngữ lập trình C/C++ Trang - 49
  55. Hàm Ví dụ 3 #include using namespace std; int num; // bien toan cuc void oddeven() // ham kiem tra chan le { if (num % 2) cout >num; oddeven(); negative(); } 8.4 Bài tập 1. Viết hàm tính n! 2. Viết hàm tính tổng S = 1+2+ .+n. 3. Viết hàm tính tổng S = 1/2 + 2/3 + + n/(n+1) 4. Viết hàm kiểm tra số nguyên tố. 5. Viết hàm tính tổng các số chẳn từ 1,2, ,n. 6. Viết hàm tính tổng các số lẻ từ 1,2, ,n. 7. Viết hàm tìm số lớn hơn trong 2 số. Giáo trình ngôn ngữ lập trình C/C++ Trang - 50
  56. Hàm 8. Viết hàm tính ước số chung lớn nhất của hai số. 9. Viết hàm tính bội số chung nhỏ nhất của hai số. 10. Viết hàm kiểm tra xem một số có chia hết cho 3 hay không?. 11. Viết hàm đếm xem trong dãy từ 3,4, ,n có bao nhiêu số là số nguyên tố. 12. Kết hợp bài 10 đếm xem trong dãy từ 20,21, ,n có bao nhiêu số chia hết cho 3. Giáo trình ngôn ngữ lập trình C/C++ Trang - 51
  57. Kiểu dữ liệu cấu trúc Chương 9: MẢNG VÀ CON TRỎ 9.1 Mảng Là tập hợp các phần tử có cùng dữ liệ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ụ: bạn muốn tính trung bình 10 số nguyên nhập vào từ bàn phím, bạn 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: cout >a; 10 biến bạn sẽ thực hiện 2 lệnh trê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 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ì vậy khái niệm mảng được sử dụng Mảng một chiều 9.1.1.1 Cách khai báo mảng Ví dụ: int a[10]; với int là kiểu mảng, a là tên mảng, 10 số phần tử mảng Ý nghĩa: Khai báo một mảng số nguyên gồm 10 phần tử, mỗi phần tử có kiểu int. a 10 phần tử 9.1.1.2 Tham chiếu đến từng phần tử mảng Sau khi mảng được khai báo, mỗi phần tử trong mảng đều có chỉ số để tham chiếu. Chỉ số bắt đầu từ 0 đến n-1 (với n là kích thước mảng). Trong ví dụ trên, ta khai báo mảng 10 phần tử thì chỉ số bắt đầu từ 0 đến 9. 0 1 2 3 4 5 6 7 8 9 a a[2] a[7] a[2], a[7] là phần tử thứ 3, 8 trong mảng xem như là một biến kiểu int. Giáo trình ngôn ngữ lập trình C/C++ Trang - 52
  58. Kiểu dữ liệu cấu trúc 9.1.1.3 Nhập dữ liệu cho mảng for (i = 0; i >a[i]; } 9.1.1.4 Đọc dữ liệu từ mảng for(i = 0; i using namespace std; main() { int a[50], i, n, sum = 0; cout >n; //Nhap du lieu vao mang for(i = 0; i >a[i]; //Nhap gia tri cho phan tu thu i } // Hien thi mang vua nhap cout<<"\n * Mang Vua Nhap La * \n"; for(i=0;i<n;i++) cout<<a[i]<<" "; cout<<"\n Tinh tong gia tri cac phan tu \n"; for(i = 0; i < n; i++) sum = sum + a[i]; //cong don tung phan tu vao sum cout<<"\n Trung binh cong: "<<(float)sum/n; } Giáo trình ngôn ngữ lập trình C/C++ Trang - 53
  59. Kiểu dữ liệu cấu trúc Ghi chú: Sử dụng biến kiểu khác Ngoài kiểu int, bạn có thể khai báo mảng kiểu char, float, double Ví dụ 4: char cloai[20]; float ftemp[10]; cách tham chiếu, nhập dữ liệu, đọc dữ liệu như trên. 9.1.1.5 Truyền mảng sang mảng Đối với mảng trong C/C++ ta không thể dùng phép gán hai mảng cho nhau mà ta phải dùng truyền chúng theo một trong hai cách sau: • Gán từng phần tử a[i]=b[i] • Dùng hàm memmove(). Cú pháp của hàm : memmove (b, a, sizeof(a)); Trong đó ▪ a là tên mảng nguồn. ▪ b là tên mảng đích. ▪ sizeof(a) là số phần tử chép Ví dụ : Chương trình sau sẽ gán mảng a cho mảng b. #include #include using namespace std; main() { int a[] = {1,2,3,4,5,6}; int b[6], i; memmove(b, a, sizeof(a)); for (i=0; i<6;i++) cout<<"\nb["<<i<<"]"<<" = "<<b[i]; } Mảng nhiều chiều 9.1.2.1 Khai báo mảng hai chiều Khai báo mảng 2 chiều int a[5][10]; với int là kiểu mảng, a là tên mảng, số phần tử mảng là 5 x 10. Ý nghĩa: Khai báo một mảng 2 chiều số nguyên gồm 50 phần tử, mỗi phần tử có kiểu int. Giáo trình ngôn ngữ lập trình C/C++ Trang - 54
  60. Kiểu dữ liệu cấu trúc a 5 hàng 10 cột 9.1.2.2 Tham chiếu đến từng phần tử mảng 2 chiều Sau khi được khai báo, mỗi phần tử trong mảng 2 chiều đều có 2 chỉ số để tham chiếu, chỉ số hàng và chỉ số cột. Chỉ số hàng bắt đầu từ 0 đến số hàng – 1 và chỉ số cột bắt đầu từ 0 đến số cột – 1. Tham chiếu đến một phần tử trong mảng 2 chiều a: a[chỉ số hàng][chỉ số cột] a 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 a[3][2] a[1][5] a[4][8] a[3][2] là phần tử tại hàng 3 cột 2 trong mảng 2 chiều xem như là một biến kiểu int. 9.1.2.3 Nhập dữ liệu cho mảng 2 chiều for (i = 0; i >a[i][j]; } * Thứ tự nhập dữ liệu vào mảng 2 chiều Giáo trình ngôn ngữ lập trình C/C++ Trang - 55
  61. Kiểu dữ liệu cấu trúc a 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 9.1.2.4 Đọc dữ liệu từ mảng 2 chiều In giá trị các phần tử mảng 2 chiều ra màn hình. for (i = 0; i using namespace std; main() { int a[10][10]; int i,j,n; cout >n; for (i=0; i<n;i++) // Vòng for i chạy 0 đến n-1 cho hàng for(j=0;j<n;j++) // Vòng for j chạy 0 đến n-1 cho cột { Giáo trình ngôn ngữ lập trình C/C++ Trang - 56
  62. Kiểu dữ liệu cấu trúc cout >a[i][j]; } cout * Ví dụ 1: int * pa; Tên biến con trỏ Kí hiệu con trỏ Kiểu mà con trỏ chỉ đến Giáo trình ngôn ngữ lập trình C/C++ Trang - 57
  63. Kiểu dữ liệu cấu trúc Ví dụ 2: Dòng 1 #include 2 using namespace std; 3 main() 4 { 5 int x = 6, y = 7; 6 int *px, *py; 7 cout<<"\nx = "<<x<<" y = "<<y; 8 px = &x; 9 py = &y; 10 *px = *px + 10; 11 *py = *py + 10; 12 cout<<"\nx = "<<x<<" y = "<<y; 13 }  Kết quả in ra màn hình x = 6, y = 7 Chạy chương trình và quan sát kết quả. x = 16, y = 17 _  Giải thích chương trình Khai báo ở dòng 6 cấp phát 2 bytes để lưu giữ địa chỉ của biến nguyên và vùng nhớ đó có tên là px, tương tự cho py. Dấu * cho biết biến này chứa địa chỉ chứ không phải giá trị, int cho biết địa chỉ đó sẽ trỏ đến các biến nguyên. Ví dụ trên cho thấy *px và *py là 2 biến con trỏ trỏ đến địa chỉ của 2 biến x và y (dòng 8 và 9),vì vậy khi nội dung của biến con trỏ *px và *py thay đổi thì nội dung của x, y cũng thay đổi theo. Giáo trình ngôn ngữ lập trình C/C++ Trang - 58
  64. Kiểu dữ liệu cấu trúc Địa chỉ vùng nhớ 1203 6 x 1204 1205 Sau phép gán px = &x và py = &y 1206 thì giá trị của px = 1203 và py = 1207 7 y 1207 1208 1209 Địa chỉ vùng nhớ 2015 2016 *px là nội dung của px và *py là 2017 nội dung của py. Nên khi thực hiện 1203 px 2 phép cộng gán 2018 *px= *px+10 và *py =*py+10 thì 2019 giá trị của x sẽ là 16 và giá trị y sẽ 1207 py 2020 là 17. 2021 Phép toán số học trên con trỏ Các phép toán số học được áp trên một biến con trỏ củng như giá trị của nó là hai phép toán cộng và trừ. Nếu có khai báo: int *p thì ta có thể dùng: ▪ p++ : trỏ đến phần tử kế tiếp. ▪ p : trỏ đến phần tử trước đó. ▪ P=p+3 : nhảy đến phần tử cách p là 3 x sizeof(p). Giáo trình ngôn ngữ lập trình C/C++ Trang - 59
  65. Kiểu dữ liệu cấu trúc Con trỏ và mảng một chiều Xét khai báo sau : int a[10] ; int *p Với các khai báo này ta có thể gán p =a ; lúc này con trỏ p trỏ đến đầu mảng a, điều này có nghĩa p = &a[0]. Lúc này ta có các biể thức tương đương sau : ▪ *p tương đương a[0] ▪ *(p+i) tương đương a[i] ▪ p+i tương đương &a[i] ▪ p=p+4 tương đương a[4] Đây là cách khai thác mảng thông qua con trỏ. Mặt khác ta có thể khai thác con trỏ thông qua mảng bằng cách viết : p[i] thay cho *(p+i) lúc này p đóng vai trò như một mảng. 9.3 Bài tập 1. Viết hàm tìm số lớn nhất, nhỏ nhất trong một mảng n số nguyên. 2. Viết hàm sắp xếp tăng dần, giảm dần của một dãy số cho trước. 3. Cho một mảng A gồm n phần tử nguyên đã được sắp xếp (tăng dần hoặc giảm dần). Nhập vào một số nguyên x, tiến hành chèn số x này vào mảng A sao cho thứ tự trong mảng không thay đổi. 4. Hãy viết chương trình thực hiện các công việc sau. a. Khởi tạo mảng ngẫu nhiên n phần tử. b. Thông báo lên màn hình phần tử bé nhất và lớn nhất trong mảng. c. Thông báo lên màn hình trung bình cộng các số của mảng d. Nhập vào một số nguyên x. Thông báo lên màn hình số nguyên x đó có trong mảng trên hay không. e. Tính tổng các số chẳn và tổng các số lẻ. 5. Viết hàm nhập vào 2 mảng một chiều, nối hai mảng này lại thành một mảng. 6. Hãy viết một hàm gọi là merge_arrays() nhập vào hai mảng một chiều đã được sắp xếp và trộn chúng thành một mảng cũng được sắp xếp. Khi thực hiện, không được chuyển hai mảng vào một mảng rồi sắp xếp lại. Giáo trình ngôn ngữ lập trình C/C++ Trang - 60
  66. Kiểu dữ liệu cấu trúc 7. Viết chương trình thực hiện các công việc sau: a. Tạo ngẫu nhiên một ma trận A nxn kiểu int. b. In ma trận A ra màn hình. c. Tính tổng từng dòng và từng cột của ma trận A. d. Tính tổng của hai đường chéo chính A. e. Tìm giá trị lớn nhất và nhỏ nhất của ma trận A. f. Đếm xem trong ma trận A có bao nhiêu phần tử bằng với số nguyên x được nhập từ bàn phím và thông báo vị trí của chúng Giáo trình ngôn ngữ lập trình C/C++ Trang - 61
  67. Chuỗi Chương 10: CHUỖI Trong C rất bối rối khi làm việc với xâu ký tự, việc sử dụng con trỏ lưu xâu ký tự rất phức tạp, dễ gây lỗi khiến nhiều người cho rằng nó không bằng xâu ký tự trong Pascal. Các chương trình C++ có thể sử dụng chuỗi theo cách thức cũ của Ngôn ngữ C: mảng các ký tự kết thúc bởi ký tự mã ASCII là 0 (ký tự ‘\0’) cùng với các hàm thư viện khai báo trong . Có nhiều bất tiện khi dùng theo cách thức này: Người lập trình phải chủ động kiểm soát bộ nhớ cấp phát cho chuỗi ký tự. Nói chung là phải am hiểu và rất thông thạo về kỹ thuật dùng bộ nhớ và con trỏ thì chương trình mới tránh được các lỗi về kỹ thuật; Không thể gán giá trị hay sử dụng phép toán + (ghép chuỗi) và các phép toán so sánh như: > (lớn hơn), ; Nếu dùng kỹ thuật cấp phát động thì phải quản lý việc cấp thêm bộ nhớ khi chuỗi dãn ra (chẳng hạn do ghép chuỗi) và phải hủy bộ nhớ (khi không dùng nữa) để tránh việc cạn kiệt bộ nhớ của máy tính trong trường hợp có nhiều chương trình hoạt động đồng thời. Trong C++ Thư viện chuẩn STL (Standard Template Library) cung cấp kiểu string (xâu ký tự), giúp tránh khỏi hoàn toàn các phiền phức nêu trên. 10.1 Cách khai báo chuỗi Để sử dụng chuổi trong C++ phải khai báo #include Cú pháp khai báo chuỗi: string Vi dụ: string name; #include #include using namespace std; main() { string name; name ="Xin chao"; cout<<endl<<name; } Giáo trình ngôn ngữ lập trình C/C++ Trang - 62
  68. Chuỗi 10.2 Hàm nhập, xuất chuỗi Để nhập xuất chuỗi, ta dùng các lệnh cin, cout tương tự như các kiểu dữ liệu khác. Ví dụ 1: viết chương trình nhập tên người dùng. Sau đó, in ra lời chào. #include #include using namespace std ; main() { string name; cout >name ; cout #include using namespace std ; main() { string name; cout << "What is your name? "; getline(cin,name); cout << "Hello, " << name << endl ; } Giáo trình ngôn ngữ lập trình C/C++ Trang - 63
  69. Chuỗi 10.3 Bộ đệm và hiện tượng trôi lệnh Bộ đệm (Buffer) Khi ta nhập dữ liệu vào bàn phím thì dữ liệu không được đọc ngay vào biến mà được đẩy lên trên bộ đệm (buffer). Dữ liệu sẽ tồn tại trong bộ đệm cho tới khi một lệnh nào đó gửi yêu cầu đến bộ đệm “xin phép” được load dữ liệu về. Ví dụ khi chương trình gặp câu lệnh: cin >> x; // với x là một biến kiểu int Thì nó sẽ lên buffer để load dữ liệu về, nếu như trên bộ đệm có số 100 thì nó sẽ đọc 100 vào biến x mà không đợi nhập gì cả, còn nếu bộ đệm trống hoặc có những dữ liệu không phải số nguyên (ví dụ mã phím Enter của lần nhập trước) thì nó mới dừng lại đợi nhập dữ liệu vào. Như vậy thì không cần để ý nhiều việc sử dụng cin >> để nhập các dữ liệu số (nguyên hoặc dấu chấm động – floating point), nhưng để nhập dữ liệu ký tự thì lại hoàn phải hết sức chú ý. Trong đoạn chương trình ở ví dụ 1 ở trên nhập xâu ký tự bên trên ta nhận thấy biến name chỉ lưu trữ phần “Phan”, phần còn lại thì vẫn nằm trên buffer để cho lần nhập sau. Hiện tượng trôi lệnh Xét chương trình sau: #include #include using namespace std ; main() { int num; string name; cout > num; cout << num << endl; cout << "nhap ho ten = "; getline(cin,name); cout << name << endl; cout << "Ket Thuc" << endl; } Giáo trình ngôn ngữ lập trình C/C++ Trang - 64
  70. Chuỗi Chạy thử chương trình trên sẽ thấy ngay. Sau khi nhập dữ liệu cho biến num, chương trình không dừng lại cho ta nhập dữ liệu cho name. Mà in ngay ra thông báo “Ket Thuc”. Nguyên nhân là do sau khi nhập dữ liệu cho biến num ta gõ phím Enter. Mã của Enter được lưu trong bộ đệm (chính là ký tự xuống dòng ‘\n’) và do đó khi chương trình gặp câu lệnh: getline(cin,name) Nó sẽ đọc ngay ký tự này và nhận thấy đây là ký tự kết thúc nên nó sẽ loại bỏ ký tự này ra khỏi bộ đệm mà không đọc vào xâu name. Sau đó nó sẽ chạy thẳng đến câu lệnh tiếp theo là: cout Câu lệnh này có tác dụng xóa bộ đệm và do đó có thể yên tâm là sẽ không bị trôi lệnh nữa. 10.4 Các phương thức, phép toán tiện ích của kiểu string Các phép toán và phương thức cơ bản • s1+ s2 : Trả về tổng hai chuổi • s1.empty() : Trả về 1 nếu chuỗi rỗng, 0 nếu ngược lại. • s1 == s2 : Trả về 1 nếu hai chuỗi giống nhau, 0 nếu ngược lại. • s1 != s2 : Trả về 1 nếu hai chuỗi khác nhau,, 0 nếu ngược lại. • s1 s2 : Trả về 1 nếu chuỗi s1 lớn hơn s2, 0 nếu ngược lại. • s1 >= s2 : Trả về 1 nếu chuỗi s1 lớn hơn hoặc bằng s2, 0 nếu ngược lại. • s1.swap(s2) : Hoán đổi 2 chuỗi với nhau. Giáo trình ngôn ngữ lập trình C/C++ Trang - 65
  71. Chuỗi Ví dụ: #include #include using namespace std; main () { int i; string s1,s2,s3, s4=""; s1 = "Cac phuong phap "; s2 = "hoc lap trinh C/C++"; i=(s1 =s2) #include using namespace std; main() { string name; cout << "nhap ho ten = "; getline(cin,name); cout << name << endl; cout << "The length of your name is: " << name.length() << endl ; cout << "The size of your name is: " << name.size() << endl ; } Giáo trình ngôn ngữ lập trình C/C++ Trang - 66
  72. Chuỗi Truy cập một phần tử bất kỳ trong chuỗi Chuỗi thực chất là một mảng các phần tử kiểu char. Do đó, ta có thể truy xuất các phần tử trong chuỗi tương tự như truy xuất với mảng thông thường. Ví dụ: Viết chương trình nhập tên người dùng. Sau đó, in ra các kí tự của tên người dùng trên từng dòng một. #include #include using namespace std ; main() { string name; cout #include using namespace std ; main() { string myString = "Hoc that de" ; myString.insert(4, "Lap trinh ") ; // vị trí cần chèn vị trí khoảng trắng đầu tiên bên position = 4 cout<<myString ; } Giáo trình ngôn ngữ lập trình C/C++ Trang - 67
  73. Chuỗi Xoá chuỗi Để xoá chuỗi trong C++, ta dùng hàm erase theo cấu trúc sau: erase (positon , number); Trong đó: Position : là vị trí cần xoá (kiểu int). Number : là số kí tự cần xoá (kiểu int). Ví dụ: Xoá chuỗi “Khong” trong chuỗi “Toi khong thich hoc lap trinh” để tạo thành chuỗi “Toi thich hoc lap trinh” . #include #include using namespace std ; main() { string myString = "Toi khong thich Hoc lap trinh" ; myString.erase(4,6) ; // Xoa chu khong va ky tu trang sau chu khong cout #include using namespace std ; main() { string st, myString = "Toi khong thich Hoc lap trinh" ; st=myString.substr(10,9) ; // lay chuoi con la chu "thich hoc" cout<<st ; } Giáo trình ngôn ngữ lập trình C/C++ Trang - 68
  74. Chuỗi Tìm kiếm chuỗi con Dùng phương thức find() để tìm một chuỗi khác xuất hiện trong chuỗi. str.find(int ch, int pos = 0); //tìm ký tự ch kể từ pos đến cuối str.find(char *s, int pos = 0); //tìm chuỗi kiểu char* từ pos đến cuối str.find(string &s, int pos = 0); //tìm chuỗi s kể từ pos đến cuối Nếu không quy định giá trị pos thì hiểu mặc nhiên là 0; nếu tìm có thì phương thức trả về vị trí xuất hiện đầu tiên, ngược lại trả về giá trị -1. Ví dụ: Tìm chữ vị trí “chay” và “CHAY” trong câu "Con meo chay qua hang rao" #include #include using namespace std; main () { string str="Con meo chay qua hang rao"; cout #include using namespace std; main () { string str="Con meo chay qua hang rao"; cout << str.replace(4,3,"MEO") << endl; // Con MEO chay qua hang rao } Giáo trình ngôn ngữ lập trình C/C++ Trang - 69
  75. Chuỗi Đổi chữ hoa thành thường với tolower(char ch)và đổi chữ thường thành chữ hoa với toupper(char ch) Ví dụ: #include #include using namespace std; main () { int i,n; string s1,s2; s1 = "Cac phuong phap "; s2 = "TU DONG HOA"; n=s1.size(); for (i=0;i<n;i++) s1[i] = toupper(s1[i]); cout<<s1<<endl; // CAC PHONG PHAP n=s2.size(); for (i=0;i<n;i++) s2[i] = tolower(s2[i]); cout<<s2; // tu dong hoa } 10.5 Bài tập 1. Viết chương trình nhập vào 1 chuỗi và in ra chuỗi đảo ngược. Ví dụ: Nhập vào chuỗi "Lap trinh C can ban" In ra "nab nac C hnirt paL" 2. Viết chương trình nhập vào một chuỗi ký tự rồi đếm xem trong chuỗi đó có bao nhiêu chữ 'th'. 3. Viết chương trình nhập vào một chuỗi sau đó in ra màn hình mỗi dòng là một từ. Ví dụ chuỗi "Lap trinh C". Kết quả in ra Lap trinh C Giáo trình ngôn ngữ lập trình C/C++ Trang - 70
  76. Chuỗi 4. Viết chương trình nhập vào một chuỗi gồm các chữ cái (a -> z, A -> Z). Hãy đếm xem có bao nhiêu nguyên âm a, i, e, o, u. 5. Viết chương trình đảo ngược thứ tự các từ có trong chuỗi Ví dụ: Nhập: lap trinh bang ngon ngu c Xuất ra màn hình là: c ngu ngon bang trinh lap 6. Viết hàm tra xem trong chuỗi có kí tự số hay không nếu có tách ra thành một mảng số riêng. 7. Viết hàm loại bỏ các ký tự trắng thừa sau đó viết hàm chuyển đổi 1 chuỗi sang dạng Title Case (kí tự đầu của mỗi từ là chữ HOA, các kí tự còn lại chữ thường) 8. Viết hàm loại bỏ các ký tự trắng thừa sau đó viết hàm đếm xem trong chuỗi có bao nhiêu từ. 9. Viết hàm loại bỏ các ký tự trắng thừa sau đó viết hàm xem trong chuỗi từ nào có độ dài lớn nhất. Giáo trình ngôn ngữ lập trình C/C++ Trang - 71
  77. Kiểu dữ liệu cấu trúc Chương 11: KIỂU DỮ LIỆU CẤU TRÚC 11.1 Kiểu cấu trúc (Structure) Đối với mảng, chỉ có thể lưu nhiều thông tin có cùng kiểu dữ liệu. Nhưng với structure ta có thể lưu thông tin như một mảng có nhiều kiểu dữ liệu khác nhau. Khai báo kiểu structure Ví dụ: khai báo một structure về thông tin nhân viên từ khóa tên struct struct nhanvien { Các thành int manv; các phần tử của struct phần đượcbọc string hoten; trong móc }; dấu chấm phẩy kết thúc struct Ví dụ trên định nghĩa kiểu dữ liệu mới có tên là struct nhanvien. Mỗi biến kiểu này gồm 2 phần tử: biến nguyên có tên là manv và biến chuỗi có tên hoten.  struct phải viết bằng chữ thường Cách khai báo biến có kiểu structure Ví dụ: Khai báo biến nv có kiểu struct nhanvien  vừa tạo structure nhanvien vừa khai báo biến nv struct nhanvien { int manv; string hoten; } nv; Tham chiếu các phần tử trong structure nv manv hoten nv.manv nv.hoten Giáo trình ngôn ngữ lập trình C/C++ Trang - 72
  78. Kiểu dữ liệu cấu trúc • Để tham chiếu đến manv trong nv ta viết như sau: nv.manv (là biến có kiểu int) • Đối với biến khai báo kiểu con trỏ nhanvien *nv thì tham chiếu đến phần tử manv: nv -> manv. Ví dụ: Nhập và in danh sách nhân viên. /* Danh sach nhan vien */ #include #include #define MAX 50 using namespace std; main() { struct nhanvien { int manv; string hoten; }; nhanvien snv[MAX]; int i, n; cout >n; //Nhap danh sach nhan vien for(i = 0; i >snv[i].manv; fflush(stdin); cout<<"Nhap vao ho ten: ";getline(cin,snv[i].hoten); } cout<<"\n in danh sach nhan vien \n"; for(i = 0;i<n; i++) cout<<endl<<"Nguoi thu "<<i+1<<"\n Ma Nha vien : "<<snv[i].manv<<"\n ho ten : " <<snv[i].hoten; } Giáo trình ngôn ngữ lập trình C/C++ Trang - 73
  79. Kiểu dữ liệu cấu trúc Structure lồng nhau Ví dụ: Nhập và in danh sách nhân viên. #include #include using namespace std; main() { struct giacanh { string vo_chong; int con; }; struct nhanvien { int manv; string hoten; giacanh canhan; }; nhanvien snv[50]; int i, n; cout >n; for(i=0;i >snv[i].manv; cout >snv[i].canhan.con; } cout<<"\n IN DANH SACH NHAN VIEN \n"; for(i = 0; i < n; i++) { cout<<"\n Nhan Vien Thu "<<i+1<<" "; cout<<"\n Ma so: "<<snv[i].manv; cout<<"\n Ho ten: "<<snv[i].hoten; cout<<"\n Ten vo (hoac chong): "<<snv[i].canhan.vo_chong; cout<<"\n so con: "<<snv[i].canhan.con; } } Giáo trình ngôn ngữ lập trình C/C++ Trang - 74
  80. Kiểu dữ liệu cấu trúc 11.2 Danh sách liên kết Trong các ví dụ trước ta thường sử dụng mảng cấu trúc để xử lý với nhóm dữ liệu. Đây là một cách tiếp cận đúng khi ta biết trước chính xác số các cấu trúc cần có. Tuy nhiên khi con số này không rõ, mảng sẽ trở nên tốn kém vì mảng phải cấp đủ bộ nhớ để hoạt động. Do đó để giải quyết vấn đề này chúng ta dùng danh sách liên kết. Khi dùng danh sách liên kết chúng ta sử dụng bộ nhớ đến đâu chúng ta cấp phát bộ nhớ đến đó. Danh sách liên kết là cấu trúc dữ liệu dùng để lưu trữ một danh sách (tập hợp hữu hạn) dữ liệu. Điểm đặc biệt của cấu trúc này là khả năng chứa của nó động (có thể mở rộng và thu hẹp dễ dàng). Có các loại danh sách liên kết: 10. Danh sách liên kết đơn 11. Danh sách liên kết kép 12. Danh sách liên kết vòng 13. Danh sách liên kết kép vòng Mỗi danh sách liên kết là tập hợp các phần tử (node) chứa thông tin lưu trữ của dữ liệu. Giữa các phần tử có một hoặc nhiều liên kết để đảm bảo danh sách liên kết có thể giữ các phần tử này một cách chặt chẽ. Khái niệm danh sách liên kết đơn Danh sách liên kết đơn là danh sách gồm nhiều nút móc nối với nhau. Mỗi nút gồm: • Trường dữ liệu lưu trữ các gia trị của nút. • Trường lưu trữ liên kết Giáo trình ngôn ngữ lập trình C/C++ Trang - 75
  81. Kiểu dữ liệu cấu trúc Danh sách liên kết đơn cần có một con trỏ đầu danh sach (head) trỏ đến nút đầu tiên, các nút còn lại trỏ tuần tự đến nút kế tiếp và một liên kết rỗng (null) ở nút cuối cùng (không trỏ đến đâu). Khai báo danh sách liên kết đơn typedef struct node { int so; struct node *next; } dsach; typedef dsach *ds; Thêm 1 phần tử vào danh sách liên kết đơn o Thêm vào đầu danh sách void bsdau(ds &f, int x) { ds p; p = new(dsach); //Cấp phát vùng nhớ để tạo một phần tử p->so = x; p->next=f; f=p; } Giáo trình ngôn ngữ lập trình C/C++ Trang - 76
  82. Kiểu dữ liệu cấu trúc o Thêm vào cuối danh sách void bscuoi(ds &f, int x) { ds p,l; p = new(dsach); //Cấp phát vùng nhớ để tạo một phần tử p->so = x; if (f==NULL) { f=p; f->next=NULL; } else { l=f; while (l->next!=NULL) l=l->next; l->next=p; l=p; l->next=NULL; } } Khởi tạo danh sách liên kết đơn void input(ds &f) { int i,x; f=NULL; do { cout >x; bsdau(f,x); // hoặc dùng thủ tục bscuoi(f,x) i= getch(); // Nhập tiếp giá trị khác thì bấp phím bất kỳ, kết thúc nhập bấp phím Enter } while (i!=10); } Giáo trình ngôn ngữ lập trình C/C++ Trang - 77
  83. Kiểu dữ liệu cấu trúc Chèn phần tử vào danh sách liên kết đơn Để chèn một phần tử vào danh sách liên kết ta phải xác định được vị trí cần chèn. Ví dụ cần chèn p vào gữa l và q ta làm như sau: p->net = q; l->next = p; o Trước khi chèn: q l o Sau khi chèn: q l q l p Xóa bỏ phần tử trong danh sách Xóa bỏ một phần tử khỏi danh sách liên kết đơn trước tiên ta cần tìm phần tử đứng trước và đứng sau của phần tử cần xóa để nối lại với nhau. Ta cũng dùng hàm free() để giải phóng vùng nhớ bị chiếm bởi con trỏ đã xóa. Ví dụ cần xóa con trỏ p. Lệnh để xóa là: q->next = q->next->next; Giải phóng vùng nhớ: delete p; o Trước khi xóa: q p o Sau khi xóa: q Giáo trình ngôn ngữ lập trình C/C++ Trang - 78
  84. Kiểu dữ liệu cấu trúc 11.3 Bài tập Ghi chú khi sử dụng hàm getline() để nhập chuổi thì dùng hàm fflush(stdin); để làm sạch bộ đệm ví dụ cout = 15. 5. Viết chương trình tạo lập và tìm kiếm dữ liệu. Nội dung yêu cầu gồm: Nhập họ và tên, địa chỉ (gồm: Quận, phường, tổ), tuổi, lương. Tìm kiếm những người ở Quận (nhập vào) có tuổi dưới (nhập vào) thu nhập từ (nhập vào) trở lên và in ra màn hình. Danh sách liên kết 1. Tạo một danh sách liên kết số nguyên thực hiện các công việc sau: - Sắp xếp danh sách theo thứ tự tăng dần. - Chèn một phần tử vào danh sách sao cho danh sách vẫn đảm bảo tăng dần. - Nhập vào một giá trị x tìm xem x có tồn tại trong danh sách hay không. - Đếm xem số nào xuất hiện trong danh sách nhiều nhất và bao nhiêu lần. - Nhập vào giá trị x xóa tất cả các giá trị bằng x trong danh sách. - Xóa các phần tử giống nhau trong danh sách chỉ để lại một số. Giáo trình ngôn ngữ lập trình C/C++ Trang - 79
  85. Kiểu dữ liệu cấu trúc 2. Danh sách ĐIỂM SINH VIÊN Người ta quản lý điểm của các sinh viên trong lớp bằng cách sử dụng một danh sách liên kết đơn (mà ta gọi là danh sách điểm) với nút đầu được trỏ bởi con trỏ đầu. Mỗi nút của danh sách điểm là một bản ghi gồm 3 trường: trường HoTen để lưu họ tên sinh viên (là một chuỗi có tối đa 30 ký tự), trường Diem lưu điểm của sinh viên (Điểm có điểm toán, điểm lý, điểm hóa, và tổng điểm) và trường next lưu địa chỉ của nút tiếp theo. Xây dựng chương trình gồm các hàm sau: - themDau để thêm một nút vào đầu danh sách. - taoDS để tạo ds với thông tin được nhập từ bàn phím (dừng khi nhập họ tên là một chuỗi rỗng). - hienThiDS để hiển thị danh sách. - soSvThiLai để đếm xem trong danh sách có bao nhiêu sinh viên thi lại theo môn (điểm =15 và không có môn nào < 5) Giáo trình ngôn ngữ lập trình C/C++ Trang - 80
  86. Chương 12: TẬP TIN – FILE 12.1 Một số khái niệm về tập tin Đối với các kiểu dữ liệu ta đã biết như kiểu số, kiểu mảng, kiểu cấu trúc thì dữ liệu được tổ chức trong bộ nhớ trong (RAM) của máy tính nên khi kết thúc việc thực hiện chương trình thì dữ liệu cũng bị mất; khi cần chúng ta bắt buộc phải nhập lại từ bàn phím. Điều đó vừa mất thời gian vừa không giải quyết được các bài toán với số liệu lớn. Để giải quyết vấn đề, người ta đưa ra kiểu tập tin (file) cho phép lưu trữ dữ liệu ở bộ nhớ ngoài (đĩa). Khi kết thúc chương trình thì dữ liệu vẫn còn do đó chúng ta có thể sử dụng nhiều lần. Một đặc điểm khác của kiểu tập tin là kích thước lớn với số lượng các phần tử không hạn chế (chỉ bị hạn chế bởi dung lượng của bộ nhớ ngoài).  Có 3 loại dữ liệu kiểu tập tin:  Tập tin văn bản (Text File): là loại tập tin dùng để ghi các ký tự lên đĩa, các ký tự này được lưu trữ dưới dạng mã Ascii. Điểm đặc biệt là dữ liệu của tập tin được lưu trữ thành các dòng, mỗi dòng được kết thúc bằng ký tự xuống dòng (new line), ký hiệu ‘\n’; ký tự này là sự kết hợp của 2 ký tự CR (Carriage Return - Về đầu dòng, mã Ascii là 13) và LF (Line Feed - Xuống dòng, mã Ascii là 10). Mỗi tập tin được kết thúc bởi ký tự EOF (End Of File) có mã Ascii là 26 (xác định bởi tổ hợp phím Ctrl + Z). Tập tin văn bản chỉ có thể truy xuất theo kiểu tuần tự.  Tập tin định kiểu (Typed File): là loại tập tin bao gồm nhiều phần tử có cùng kiểu: char, int, long, cấu trúc và được lưu trữ trên đĩa dưới dạng một chuỗi các byte liên tục.  Tập tin không định kiểu (Untyped File): là loại tập tin mà dữ liệu của chúng gồm các cấu trúc dữ liệu mà người ta không quan tâm đến nội dung hoặc kiểu của nó, chỉ lưu ý đến các yếu tố vật lý của tập tin như độ lớn và các yếu tố tác động lên tập tin mà thôi.  Biến tập tin: là một biến thuộc kiểu dữ liệu tập tin dùng để đại diện cho một tập tin. Dữ liệu chứa trong một tập tin được truy xuất qua các thao tác với thông số là biến tập tin đại diện cho tập tin đó. Con trỏ tập tin: Khi một tập tin được mở ra để làm việc, tại mỗi thời điểm, sẽ có một vị trí của tập tin mà tại đó việc đọc/ghi thông tin sẽ xảy ra. Trang - 81
  87. Người ta hình dung có một con trỏ đang chỉ đến vị trí đó và đặt tên nó là con trỏ tập tin. Sau khi đọc/ghi xong dữ liệu, con trỏ sẽ chuyển dịch thêm một phần tử về phía cuối tập tin. Sau phần tử dữ liệu cuối cùng của tập tin là dấu kết thúc tập tin EOF (End Of File). 12.2 Các thao tác trên tập tin Để sử dụng tập tin (file) trong C++ phải khai báo #include Khai báo biến tập tin Cú pháp: fstream Các biến trong danh sách được phân cách bởi dấu phẩy(,). Ví dụ: fstream f1,f2; Ghi chú: từ khóa fstream phải viết thường. Mở và đóng tập tin 12.2.2.1 Mở tập tin Cú pháp: .open( , ); Ví dụ : fstream f; f.open("c:\\info.txt", ios::out); Các chế độ mở têp tin ios :: in Mở một tệp tin để đọc ios :: out Mở một tệp tin có sẵn để ghi ios :: app Mở một tệp tin có sẵn để thêm dữ liệu vào cuối tệp. ios :: ate Mở tệp tin và đặt con trỏ tệp tin vào cuối tệp. ios :: trunc Nếu tệp tin đã có sẵn thì dữ liệu của nó sẽ bị mất. ios :: nocreate Mở một tệp tin, tệp tin này bắt buộc phải tồn tại ios :: noreplace Chỉ mở têp tin khi tệp tin chưa tồn tại. ios :: binary Mở một tệp tin ở chế độ nhị phân ios :: text Mở một tệp tin ở chế độ văn bản. Trang - 82
  88. Một số hàm khác. Tên phương thức Chức năng Kiểm tra xem tập tin có đang mở is_open hay không. Làm sạch vùng đệm của tập tin flush đang mở Kiểm tra trạng thái của tập tin có tốt good để đọc/ghi không Kiểm tra xem đã đọc đến cuối tập eof tin chưa 12.2.2.2 Đóng tập tin Cú pháp: .close(); Ví dụ : fstream f; f. close(); 12.3 Truy cập tập tin văn bản Tên phương thức Chức năng >> Đọc dữ liệu từ tập tin << Ghi dữ liệu vào tập tin getline Đọc một dòng dữ liệu từ tập tin Đọc một kí tự hoặc một chuỗi từ tập tin, get tùy thuộc vào tham số của phương thức. put Ghi một kí tự xuống tập tin Trang - 83
  89. Ví dụ 1: Mở và đọc tập tin văn bản là các số vào mảng 1 chiều sau đó bổ sung vào file những con số khác #include #include using namespace std; main() { fstream f; int a[200],i,n; f.open("c:\\tam\\input.txt",ios::in); while(!f.eof()) f>>a[++i]; f.close(); cout<<"\n file vua doc vao mang\n"; n=i; for(i=1;i<=n;i++) cout<<" "<<a[i]; //Bo sung vao cuoi file f.open("c:\\tam\\input.txt",ios::app); f<<endl; f<<50<<" "<<60<<" "<<70<<endl; // Bo sung vao so 50 60 70 } Trang - 84
  90. Ví dụ 2: Viết chương tạo file tho.txt ghị nội dụng vào file tho.txt và sau đó đọc lại nội dung trong file ra màn hình. #include #include using namespace std; main() { fstream f; char st[800]; int num=800; //Ghi vao file f.open("c:\\tam\\tho.txt", ios::out); f<<"Chieu Chieu Ra Dung Ngo Sau"<<endl; // ghi tung dong vao file f<<"Trong Ve Que Me"<<endl; f<<"Sao Lau Gui Tien"<<endl; f.close(); //doc tu file ra f.open("c:\\tam\\tho.txt", ios::in); while (!f.eof()) { f.getline(st,num); // Doc tung dong tu file vao bien st cout<<st<<endl; } } Trang - 85
  91. Ví dụ 3: Sử dụng hàm get và put. Viết chương tạo file tho.txt ghị nội dụng vào file tho.txt và sau đó đọc lại nội dung trong file ra màn hình. #include #include #include using namespace std; main() { fstream f; char c; string s="Chieu Chieu Ra dung Ngo sau \n trong ve que me \n sao lau gui tien"; int num=800; //Ghi vao file f.open("c:\\tam\\tho.txt", ios::out); for(int i=0;i<s.size();i++) f.put(s[i]); // ghi tung ky tu vao flie f.close(); //doc tu file ra f.open("c:\\tam\\tho.txt", ios::in); while (!f.eof()) { c= f.get(); // doc tung ky tu file vao bien c cout<<c; } } Trang - 86
  92. 12.4 Truy cập tập tin nhị phân Tên phương thức Chức năng read Đọc mẫu tin (theo cấu trúc định trước) từ tập tin write Ghi mẫu tin (theo cấu trúc định trước ) vào tập tin seekg Di chuyển con trỏ file đến vị trí xác định tellp Cho biết vị trí hiện tại của con trỏ file Hàm write dùng để ghi 1 file stream ở định dạng nhị nhận. Cú pháp fileObject.write(address, size); - fileObject là tên của đối tượng file stream. - address là địa chỉ đầu tiên của 1 vùng nhớ được ghi vào file. Đối số này có thể là địa chỉ của 1 kí tự hoặc là con trỏ tới kiểu char. - size là số lượng byte của vùng nhớ mà nó được write. Đối số này bắt buộc phải là kiểu integer (số nguyên dương) Hàm read thì sẽ dùng đọc vào số dữ liệu nhị phân từ file vào bộ nhớ máy tính. Cú pháp fileObject.read(address, size); - fileObject là tên của đối tượng file stream. - address là địa chỉ đầu tiên mà vùng nhớ mà dữ liệu được đọc vào được lưu. Và đối này có thể là địa chỉ của 1 kí tự hay 1 con trỏ tới kiểu char. - size cũng là số lượng byte trong bộ nhớ được đọc vào từ file. Và đối này bắt buộc cũng phải là số kiểu integer ( nguyên dương) Trang - 87
  93. Ví dụ: dọc và ghi vào file nhị phân #include #include using namespace std; main() { fstream f; char buffer[] = { 'x' , 'y' , 'z' }; char *st; f.open("c:\\tam\\tho.dat", ios::out| ios::binary); if(f.is_open()) f.write(buffer , sizeof(buffer) ); // Ghi toàn bộ nội dung vào file f.close(); // Ðoc toan bo noi dung cua tap tin f.open("c:\\tam\\tho.dat", ios::in| ios::binary); char data[4]; f.read(data, sizeof(data)); cout<<data; f.close(); } 12.5 Bài tập 1. Viết chương trình thực hiện các yêu cầu: - Nhập 10 số thực vào một file văn bản có tên là INPUT. - Đọc nội dung file INPUT. - Tính tổng bình phương các số có trong file INPUT. 2. Mở một tập tin văn bản, tính kích thước và thống kê số lần xuất hiện các chữ cái trong tập tin văn bản đó. Trang - 88
  94. 3. Tạo file matran.txt nội dung như sau rồi lưu vào đĩa 3 4 6 1 3 8 7 8 5 8 9 3 9 0 8 7 2 1 6 6 8 8 8 7 7 2 6 1 5 9 1 5 1 4 5 7 4 2 3 2 3 5 7 1 0 2 4 1 4 6 7 8 8 8 6 9 3 0 1 0 5 5 7 8 4 5 5 5 5 5 8 7 - Viết hàm đọc file này ghi vào mảng hai chiều. - Viết hàm hiển thị mảng hai chiều này ra màn hình - Đếm số lần xuất hiện của các chữ số trong ma trận này. - Viết hàm ghi mảng hai chiều này vào file matranmoi.txt 4. Tạo file tho.txt nội dung như sau rồi lưu vào đĩa MÙA CƯỚI Thiệp hồng gửi trao tới tới Khác nào khủng bố hầu bao. Đầu tuần cưới con của sếp Cuối tuần cưới bạn cùng phòng Mỗi tuần nhận vài cái thiệp Tiền lương tháng ấy đi tong. Đời người cưới xin chỉ một Nể nang họ mới kính mời Không đi thì nghe nhồn nhột Đi thì ngân quỹ bốc hơi. Chuyện đời: Đối nhân xử thế Phải không là lẽ thường tình Để không là người sống tệ Ai mời cũng phải cố lên! Trang - 89
  95. - Viết hàm đọc file này ghi vào mảng một chiều. - Viết hàm hiển thị mảng một chiều này ra màn hình. - Viết hàm ghi mảng một chiều này vào file thomoi.txt 5. Mỗi sinh viên cần quản lý ít nhất 2 thông tin: mã sinh viên và họ tên. Viết chương trình cho phép lựa chọn các chức năng: - Nhập danh sách sinh viên từ bàn phím. - Ghi lên tập tin SinhVien.dat. - Đọc dữ liệu từ tập tin SinhVien.dat rồi hiển thị danh sách lên màn hình Tài Liệu Tham Khảo 1. Giáo trình ngôn ngữ lập trình C. Nguyễn Hữu Tuấn 2. Ngôn ngữ lập trình C++. Học viện Công nghệ Bưu chính Viễn Thông 3. Giáo trình Ngôn ngữ lập Trình C++. Đại Học Mở TP. HCM 4. Hướng Dẫn thao tác với tập tin trong C++. Đại Học Khoa Học Tự Nhiên TP.HCM 5. Bài Giảng Ngôn Ngữ Lập Trình C/C++. Trường Đại Học Công Nghệ. Đại Học Quốc Gia Hà Nội Trang - 90