1. Trang chủ
  2. » Giáo án - Bài giảng

Bài Giảng Lập Trình

358 1 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 358
Dung lượng 3,83 MB

Nội dung

MỤC LỤC Phần 1 Mở đầu 9 Bài 1 Các ngôn ngữ lập trình 9 1 1 Ngôn ngữ lập trình 9 1 2 Ra lệnh cho máy tính làm việc 10 1 3 Phân loại Ngôn ngữ lập trình cấp thấp và cấp cao 12 1 4 Tổng quát và chuyên biệ[.]

MỤC LỤC Phần 1: Mở đầu Bài Các ngơn ngữ lập trình 1.1 Ngơn ngữ lập trình 1.2 Ra lệnh cho máy tính làm việc 10 1.3 Phân loại Ngôn ngữ lập trình cấp thấp cấp cao 12 1.4 Tổng quát chuyên biệt 13 1.5 Mơ hình tính tốn NNLT 14 1.6 Chọn NNLT 14 1.6.1 Yếu tố kỹ thuật 14 1.6.2 Yếu tố phi kỹ thuật 14 1.6.3 Chọn công cụ cho công việc 15 1.6.4 Sự lựa chọn nhà phát triển 15 1.7 CÁC NGƠN NGỮ LẬP TRÌNH 16 Bài Giới thiệu ngôn ngữ C / C++ 23 2.1 Ngôn ngữ C 23 2.2 C – Ngôn ngữ bậc trung 23 2.3 C - Ngôn ngữ cấu trúc 24 2.4 C++ 25 2.5 Biên dịch chương trình C/C++ 25 2.6 Tại dùng C/C++?? 26 Phần Lập trình cấu trúc C (8 tuần) 27 Bài Phân tích thiết kế chương trình 27 3.1 Cấu trúc chương trình C 27 3.1.1 Ðịnh nghĩa Hàm 28 3.1.2 Dấu phân cách (Delimiters) 28 3.1.3 Dấu kết thúc câu lệnh (Terminator) 28 3.1.4 Dịng thích (Comment) 28 3.1.5 Thư viện C (Library) 28 3.2 Biên dịch thực thi chương trình (Compiling and Running) 29 3.3 Các bước lập trình giải vấn đề 30 3.3.1 Mã giả (pseudo code) 31 3.3.2 Lưu đồ (Flowcharts) 33 Bài Cài đặt làm quen với mơi trường lập trình C/C++ với Visual Studio 49 4.1 Giới thiệu Microsoft Visual C++ 49 4.2 Các đặc trưng 49 4.3 Lịch sử 49 Bài Biến, kiểu, liệu, Toán tử, Biểu Thức 57 5.1 Biến Kiểu liệu 57 5.1.1 Biến (variable) 57 5.1.2 Hằng (constant) 59 5.1.3 Các nguyên tắc cho việc đặt tên 60 5.1.4 Các kiểu liệu (Data types) 61 5.1.5 Những kiểu liệu dẫn xuất 64 5.1.6 Các toán tử số học (Arithmetic Operators) 68 5.2 Toán tử Biểu thức 74 Mục tiêu: 74 5.2.1 Biểu thức (Expressions) 74 5.2.2 Toán tử quan hệ (Relational Operators) 76 5.2.3 Toán tử luận lý (Logical Operators) biểu thức 77 5.2.4 Toán tử luận lý nhị phân (Bitwise Logical Operators) biểu thức 78 5.2.5 Biểu thức dạng hỗn hợp & Chuyển đổi kiểu 79 5.2.6 Độ ưu tiên toán tử (Precedence) 81 Bài Nhập Xuất C 90 6.1 Tập tin tiêu đề 91 6.2 Nhập xuất C (Input and Output) 91 6.2.1 printf() 91 6.2.2 scanf() 102 6.3 Bộ nhớ đệm Nhập Xuất (Buffered I/O) 109 6.3.1.getchar() .110 6.3.2 putchar() 111 Bài Điều kiện 117 7.1 Câu lệnh điều kiện ? 117 7.2 Các câu lệnh lựa chọn: .118 7.2.1 Câu lệnh ‘if’: .118 7.2.2 Câu lệnh ‘if … else’: 120 7.2.3 Nhiều lựa chọn – Các câu lệnh ‘if … else’: 122 7.2.4 Các cấu trúc if lồng nhau: 125 7.2.5 Câu lệnh ‘switch’: 131 Bài Vòng lặp 139 8.1 Vòng lặp: .139 8.2 Vòng lặp ‘for’: 139 8.1.2 Vòng lặp ‘while’: 146 8.2 Các lệnh nhẩy: 153 8.2.1 Lệnh ‘return’: .153 8.2.2 Lệnh ‘goto’: 153 8.2.3 Lệnh ‘break’: 155 8.2.4 Lệnh ‘continue’: 156 8.2.5 Hàm ‘exit()’: .157 Bài Mảng 161 9.1 Các phần tử mảng mục: 162 9.2 Việc quản lý mảng C: .164 9.3 Mảng hai chiều: 171 Bài 10 Các thao tác với BITs kỹ thuật lập trình với bit 181 10.1 Bit 181 10.2 Các toán tử thao tác bit 181 Bài 11 Macro .185 11.1 Chỉ thị #define 185 11.1.1 Hằng tượng trưng .185 11.1.2 Macro rỗng 185 11.1.3 Macro có tham số 186 11.1.4 Truyền số lượng tham số không định trước vào macro .186 11.2 Chỉ thị undef .188 11.3 Toán tử macro 188 11.3.1 Toán tử # 188 11.4 Toán tử defined 189 11.5 Chỉ thị có điều kiện (#ifdef, #ifndef, #if, #endif, #else and #elif) 189 11.6 Chỉ thị #line .190 11.7 Chỉ thị #error 191 11.8 Chỉ thị #pragma .192 Bài 12 Kỹ thuật lập trình với hàm 192 12.1 Sử dụng hàm .193 12.2 Cấu trúc hàm .194 12.2.1 Các đối số hàm 194 12.2.2 Sự trả từ hàm .196 12.2.3 Kiểu hàm 197 12.3 Gọi hàm 197 12.4 Khai báo hàm 198 12.5 Các nguyên mẫu hàm 199 12.6 Các biến 200 12.6.1 Biến cục 200 12.6.2 Tham số hình thức .202 12.6.3 Biến toàn cục .203 12.7 Lớp lưu trữ (Storage Class) .205 12.7.1 Biến tự động .206 12.7.2 Biến ngoại 206 12.7.3 Biến tĩnh .208 12.7.4 Biến ghi 210 12.8 Các qui luật phạm vi hàm .212 12.9 Gọi hàm .213 12.9.1 Truyền giá trị 213 12.9.2 Truyền tham chiếu 215 12.10 Sự lồng lời gọi hàm 218 12.11 Hàm chương trình nhiều tập tin .219 12.12 Con trỏ đến hàm 220 Bài 13 Kỹ thuật lập trình với trỏ 222 13.1 Con trỏ gì? .222 13.1.2 Tại trỏ dùng? .223 13.2 Các biến trỏ 223 13.3 Các toán tử trỏ 224 13.4 Con trỏ mảng chiều .228 13.4.1 Con trỏ mảng nhiều chiều .231 13.5 Cấp phát nhớ 234 Bài 14 Kỹ thuật lập trình với chuỗi ký tự 246 14.1 Các biến kiểu chuỗi .247 14.1.1 Con trỏ trỏ đến chuỗi 248 14.1.2 Các thao tác nhập xuất chuỗi .248 14.2 Các hàm chuỗi 251 14.2.1 Hàm strcat() .251 14.2.2 Hàm strcmp() .252 14.2.3 Hàm strchr() .254 14.2.4 Hàm strcpy() 256 14.2.5 Hàm strlen() .257 14.3 Truyền mảng vào hàm 258 14.4 Truyền chuỗi vào hàm 261 Bài 15 CHUYỂN ĐỔI KIỂU DỮ LIỆU & CẤP PHÁT BỘ NHỚ ĐỘNG 265 15.1 Nhu cầu chuyển đổi liệu .265 15.2 Chuyển đổi liệu kiểu tự động .265 15.3 Ép kiểu tường minh 265 15.4 Cấp phát động C .266 Bài 16 Kỹ thuật lập trình cấu trúc 267 16.1 Cấu trúc .268 16.1.1 Định nghĩa cấu trúc 269 16.1.2 Khai báo biến kiểu cấu trúc .270 16.1.3 Khởi tạo biến cấu trúc 272 16.1.4 Thực cấu lệnh gán với cấu trúc 273 16.1.5 Cấu trúc lồng cấu trúc 273 16.1.6 Truyền tham số kiểu cấu trúc 275 16.1.7 Mảng cấu trúc 277 16.1.8 Khởi tạo mảng cấu trúc .278 16.1.9 Con trỏ đến cấu trúc 279 16.1.10 Truyền trỏ cấu trúc tham số 280 16.2 Từ khóa typedef 280 Bài 17 Kỹ thuật lập trình đệ quy .284 17.1 Mục tiêu 284 17.2 Nội dung 284 17.3 Sử dụng đệ quy hay vòng lặp 287 Bài 18 Dữ liệu nâng cao, thuật toán giải thuật Quick Sort 289 18.1 Sắp xếp mảng (Sorting Arrays) .289 18.1.1 Bubble Sort .289 18.1.2 Insertion Sort 292 Bài 19 Lập trình vào 296 19.1 File Streams .296 19.1.1 Streams văn 297 19.1.2 Streams nhị phân 297 19.2 Các hàm tập tin structure FILE 297 19.2.1 Các hàm tập tin 298 19.2.2 Con trỏ tập tin 298 19.3 Các tập tin văn 299 19.3.1 Mở tập tin văn 299 19.3.2 Đóng tập tin văn 300 19.3.3 Ghi ký tự 301 19.3.4 Đọc ký tự 301 19.3.5 Nhập xuất chuỗi 303 19.4 Các tập tin nhị phân 304 19.4.1 Mở tập tin nhị phân 304 19.4.2 Đóng tập tin nhị phân 304 19.4.3 Ghi tập tin nhị phân 305 19.4.4 Đọc tập tin nhị phân 305 19.5 Các hàm xử lý tập tin .308 19.5.1 Hàm feof() 308 19.5.2 Hàm rewind() 308 19.5.3 Hàm ferror() 310 19.5.4 Xóa tập tin 311 19.5.5 Làm stream 311 19.5.6 Các stream chuẩn 312 19.5.7 Con trỏ kích hoạt hành 313 19.5.8 Hàm fprintf() fscanf() 315 Phần Lập trình hướng đối tượng C++ (4 tuần) 321 Bài 20 Lập trình hướng đối tượng 321 20.1 Giới thiệu 321 20.2 Trừu tượng hóa (Abstraction) 322 20.3 Đối tượng (object) 322 20.4 Lớp (Class) .325 20.5 Thuộc tính (Attribute) 326 20.6 Phương thức (Method) .326 20.7 Thông điệp (Message) .327 20.8 Tính bao gói (Encapsulation) 328 20.9 Tính thừa kế (Inheritance) .329 20.10.Tính đa hình (Polymorphism) 329 20.1 Trình bày định nghĩa thuật ngữ: 330 20.2 Phân biệt khác lớp đối tượng, thuộc tính giá trị, thông điệp truyền thông điệp 330 20.3 Trình bày đặc điểm OOP .330 20.4 Những lợi ích có thơng qua thừa kế bao gói 330 20.5 Những thuộc tính phương thức máy giặt 330 20.6 Những thuộc tính phương thức xe 330 20.7 Những thuộc tính phương thức hình trịn 330 20.8 Chỉ đối tượng hệ thống rút tiền tự động ATM 330 20.9 Chỉ lớp kế thừa từ lớp điện thoại, xe hơi, động vật 330 Bài 21 Lập trình với C++ 331 21.1 Chương trình lập trình với C++ 331 Các thích .333 21.2 Câu lệnh vào \ C++ 334 Bài 22 Kỹ thuật lập trình với lớp 337 22.1 Lớp đơn giản 338 22.2 Các hàm thành viên nội tuyến 339 22.3 Ví dụ: Lớp Set 339 Bài 23 Hàm xây dựng (Constructor) Hàm hủy (Destructor) .345 23.1 Hàm xây dựng (Constructor) 345 23.2 Hàm hủy (Destructor) 347 Bài 24 Kỹ thuật lập trình Thừa kế 349 24.1 Ví dụ minh họa 350 24.2 Lớp dẫn xuất đơn giản .355 24.3 Ký hiệu thứ bậc lớp 357 Phần 1: Mở đầu Bài Các ngôn ngữ lập trình Mục tiêu: Kết thúc học này, bạn có thể: Các ngơn ngữ lập trình phổ biến Phân biệt khác Câu lệnh, Chương trình Phần mềm Giới thiệu Ngày nay, khoa học máy tính thâm nhập vào lĩnh vực Tự động hóa ngành chủ chốt điều hướng phát triển giới Bất ngành nghề cần phải hiểu biết nhiều Cơng nghệ Thơng tin lập trình nói chung Ðầu tiên tìm hiểu khác khái niệm: Lệnh (Command), Chương trình (Program) Phần mềm (Software) 1.1 Ngơn ngữ lập trình Ngơn ngữ lập trình (tiếng Anh: programming language) tập ngôn ngữ máy tính Đây dạng ngơn ngữ thiết kế chuẩn hóa (đối lập với ngơn ngữ tự nhiên) để truyền thị cho máy tính (hoặc máy khác có xử lí) Ngơn ngữ lập trình dùng để tạo chương trình nhằm mục đích điều khiển máy tính mơ tả thuật tốn để người khác đọc hiểu Như Ngơn ngữ lập trình (NNLT) phương tiện để giao tiếp lệnh cho máy tính thực cơng việc cụ thể Máy tính hiểu số 1, người lại không thành thạo kiểu suy nghĩ với số để lệnh cho máy tính Vì người ta phát triển dạng câu lệnh mà người đọc hiểu, tập câu lệnh gọi mã nguồn (source code) Mã nguồn phải tuân thủ tập từ vựng, cú pháp qui tắc người thiết kế NN đặt Ví dụ, đoạn mã nguồn mẫu lệnh cho máy tính hiển thị dịng chữ “Xin chào.” hình: #!/usr/bin/perl print“Xinchào.” Mã nguồn phần mềm thiết kế đặc biệt hiểu câu lệnh dịch thành dạng mã mà máy hiểu thực thi 1.2 Ra lệnh cho máy tính làm việc Khi máy tính khởi động, tự động thực thi số tiến trình xuất kết hình Ðiều diễn nào? Câu trả lời đơn giản nhờ vào Hệ điều hành cài đặt bên máy tính Hệ điều hành (operating system) xem phần mềm hệ thống Phần mềm khởi động máy tính thiết lập thơng số ban đầu trước trao quyền cho người dùng Để làm điều này, hệ điều hành phải cấu tạo từ tập hợp chương trình Mọi chương trình cố gắng đưa lời giải cho hay nhiều Bài tốn Mọi chương trình cố gắng đưa giải pháp cho hay nhiều vấn đề Mỗi chương trình tập hợp câu lệnh giải Bài tốn cụ thể Một nhóm lệnh tạo thành chương trình nhóm chương trình tạo thành phần mềm Để rõ hơn, xem xét thí dụ: Một người bạn đến nhà chơi mời sữa dâu Anh ta thấy ngon miệng muốn xin công thức làm Chúng ta hướng dẫn cho làm sau : Lấy sữa Đổ nước ép dâu vào Trộn hỗn hợp làm lạnh Bây bạn theo dẫn này, họ tạo sữa dâu tuyệt vời Chúng ta phân tích thị (lệnh) Lệnh : Lệnh hoàn chỉnh chưa ? Nó có trả lời câu hỏi lấy sữa ‘ở đâu’? Lệnh thứ hai : Một lần nữa, lệnh khơng nói rõ nước ép dâu để ‘ở đâu’ May mắn bạn đủ thơng minh để hiểu cơng thức pha chế nói trên, nhiều điểm chưa rõ ràng Do muốn phổ biến cách làm, cần bổ sung bước sau : Rót ly sữa vào máy trộn Đổ thêm vào nước dâu ép Ðóng nắp máy trộn Mở điện bắt đầu trộn Dừng máy trộn lại 10 s1 = {10,20,30,40} s2 = {30,50,10,60} s2 - {50} = {30,10,60} 20 is in s1 s1 intsec s2 = {10,30} s1 union s2 = {30,10,60,20,40} s1 s2 344 Bài 23 Hàm xây dựng (Constructor) Hàm hủy (Destructor) 23.1 Hàm xây dựng (Constructor) Hồn tồn định nghĩa khởi tạo đối tượng lớp thời điểm Điều hỗ trợ hàm đặc biệt gọi hàm xây dựng (constructor) Một hàm xây dựng ln có tên với tên lớp Nó khơng có kiểu trả rõ ràng Ví dụ, class Point { int xVal, yVal; public: Point (int x,int y) {xVal = x; yVal = y;} // constructor void OffsetPt (int,int); }; định nghĩa lớp Point, SetPt thay hàm xây dựng định nghĩa nội tuyến Bây định nghĩa đối tượng kiểu Point khởi tạo chúng lượt Điều thật ép buộc lớp chứa hàm xây dựng đòi hỏi đối số: Point pt1 = Point(10,20); Point pt2; // trái luật Hàng thứ đặc tả hình thức ngắn gọn Point pt1(10,20); Một lớp có nhiều hàm xây dựng Tuy nhiên, để tránh mơ hồ hàm xây dựng phải có dấu hiệu Ví dụ, class Point { int xVal, yVal; public: Point (int x, int y) { xVal = x; yVal = y; } Point (float, float); // tọa độ cực Point (void) { xVal = yVal = 0; } // gốc void OffsetPt (int, int); 345 }; Point::Point (float len, float angle) // tọa độ cực { xVal = (int) (len * cos(angle)); yVal = (int) (len * sin(angle)); } có ba hàm xây dựng khác Một đối tượng có kiểu Point định nghĩa sử dụng hàm hàm này: Point pt1(10,20); // tọa độ Đê-cát-tơ Point pt2(60.3,3.14); // tọa độ cực Point pt3; // gốc Lớp Set cải tiến cách sử dụng hàm xây dựng thay EmptySet: class Set { public: Set (void) { card = 0; } // }; Điều tạo thuận lợi cho lập trình viên khơng cần phải nhớ gọi EmptySet Hàm xây dựng đảm bảo tập hợp rỗng vào lúc ban đầu Lớp Set cải tiến cách cho phép người dùng điều khiển kích thước tối đa tập hợp Để làm điều định nghĩa elems trỏ số nguyên mảng số nguyên Hàm xây dựng sau cung cấp đối số đặc tả kích thước tối đa mong muốn Nghĩa maxCard khơng cịn dùng cho tất đối tượng Set mà trở thành thành viên liệu: class Set { public: Set (const int size); // private: 346 int *elems; // cac phan tu tap hop int maxCard; int card; // so phan tu toi da // so phan tu }; Hàm xây dựng dễ dàng cấp phát mảng động với kích thước mong muốn khởi tạo giá trị phù hợp cho maxCard card: Set::Set (const int size) { elems = new int[size]; maxCard = size; card = 0; } Bây định nghĩa tập hợp có kích thước tối đa khác nhau: Set ages(10), heights(20), primes(100); Chúng ta cần lưu ý hàm xây dựng đối tượng ứng dụng đối tượng tạo Điều phụ thuộc vào phạm vi đối tượng Ví dụ, đối tượng tồn cục tạo thực thi chương trình bắt đầu; đối tượng tự động tạo phạm vi đăng ký; đối tượng động tạo toán tử new áp dụng tới 23.2 Hàm hủy (Destructor) Như hàm xây dựng dùng để khởi tạo đối tượng tạo ra, hàm hủy dùng để dọn dẹp đối tượng trước thu hồi Hàm hủy ln ln có tên với tên lớp đầu với ký tự ~ Không giống hàm xây dựng, lớp có nhiều hàm hủy Hàm hủy không nhận đối số kiểu trả rõ ràng Thơng thường hàm hủy thường hữu ích cần thiết cho lớp chứa liệu thành viên trỏ Các liệu thành viên trỏ trỏ tới khối nhớ cấp phát từ lớp Trong trường hợp việc giải phóng nhớ cấp phát cho trỏ thành viên quan trọng trước đối tượng thu hồi Hàm hủy làm cơng việc 347 Ví dụ, phiên sửa lại lớp Set sử dụng mảng cấp phát động cho thành viên elems Vùng nhớ nên giải phóng hàm hủy: class Set { public: Set (const int size); ~Set (void) {delete elems;} // destructor // private: int *elems; // cac phan tu tap hop int maxCard; // so phan tu toi da int card; // so phan tu cua tap hop }; Bây xem xét xảy Set định nghĩa sử dụng hàm: void Foo (void) { Set s(10); // } Khi hàm Foo gọi, hàm xây dựng cho s triệu tập, cấp phát lưu trữ cho s.elems khởi tạo thành viên liệu Kế tiếp, phần cịn lại thân hàm Foo thực thi Cuối cùng, trước Foo trả về, hàm hủy cho cho s triệu tập, xóa vùng lưu trữ bị chiếm s.elems Kể từ cấp phát lưu trữ kể đến s ứng xử giống biến tự động kiểu có sẳn tạo phạm vi biết đến hủy phạm vi rời khỏi Nói chung, hàm xây dựng đối tượng áp dụng trước đối tượng thu hồi Điều phụ thuộc vào phạm vi đối tượng Ví dụ, đối tượng toàn cục thu hồi thực chương trình hồn tất; đối tượng tự động thu hồi toán tử delete áp dụng tới 348 Bài 24 Kỹ thuật lập trình Thừa kế Trong thực tế hầu hết lớp kế thừa từ lớp có trước mà khơng cần định nghĩa lại hồn tồn Ví dụ xem xét lớp đặt tên RecFile đại diện cho tập tin gồm nhiều mẫu tin lớp khác đặt tên SortedRecFile đại diện cho tập tin gồm nhiều mẫu tin xếp Hai lớp có nhiều điểm chung Ví dụ, chúng có thành viên hàm giống Insert, Delete, Find, thành viên liệu giống SortedRecFile phiên đặc biệt RecFile với thuộc tính mẫu tin tổ chức theo thứ tự thêm vào Vì hầu hết hàm thành viên hai lớp giống vài hàm mà phụ thuộc vào yếu tố tập tin xếp khác Ví dụ, hàm Find khác lớp SortedRecFile nhờ vào yếu tố thuận lợi tập tin để thực tìm kiếm nhị phân thay tìm tuyến tính hàm Find lớp RecFile Với thuộc tính chia sẻ hai lớp việc định nghĩa chúng cách độc lập dài dòng Rõ ràng điều dẫn tới việc phải chép lại mã đáng kể Mã không thời gian lâu để viết mà cịn khó bảo trì hơn: thay đổi tới thuộc tính chia sẻ phải sửa đổi tới hai lớp Lập trình hướng đối tượng cung cấp kỹ thuật thuận lợi gọi thừa kế để giải vấn đề Với thừa kế lớp thừa kế thuộc tính lớp có trước Chúng ta sử dụng thừa kế để định nghĩa thay đổi lớp mà không cần định nghĩa lại lớp từ đầu Các thuộc tính chia sẻ định nghĩa lần sử dụng lại cần Trong C++ thừa kế hỗ trợ lớp dẫn xuất (derived class) Lớp dẫn xuất giống lớp gốc ngoại trừ định nghĩa dựa hay nhiều lớp có sẵn gọi lớp sở (base class) Lớp dẫn xuất chia sẻ thuộc tính chọn (các thành viên hàm hay thành viên liệu) lớp sở khơng làm chuyển đổi định nghĩa lớp sở Lớp dẫn xuất lớp sở lớp dẫn xuất khác Quan hệ thừa kế lớp chương trình gọi quan hệ cấp bậc lớp (class hierarchy) 349 Lớp dẫn xuất gọi lớp (subclass) trở thành cấp thấp lớp sở quan hệ cấp bậc Tương tự lớp sở gọi lớp cha (superclass) từ có nhiều lớp khác dẫn xuất 24.1 Ví dụ minh họa Chúng ta định nghĩa hai lớp nhằm mục đích minh họa số khái niệm lập trình phần sau chương Hai lớp định nghĩa Danh sách 22.1 hỗ trợ việc tạo thư mục đối tác cá nhân #include #include class Contact { public: Contact(const char *name, const char *address, const char *tel); ~Contact (void); const char* Name (void) const {return name;} const char* Address(void) const {return address;} const char* Tel(void) const {return tel;} 10 friend ostream& operator

Ngày đăng: 12/06/2023, 01:40

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN