Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 164 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
164
Dung lượng
2,2 MB
Nội dung
Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 1) Modular Programming (Mô-đun Lập trình) Prototypes Headers Separate Compilation Phạm Vi Sử Dụng (scope) functions biến số 5) Preprocessor – Tiền xử lý #include #define Macro Condition 6) Tạo biến kiểu riêng bạn Cấu trúc (struct) Mảng cấu trúc Typedef 2) Pointer (Con trỏ) Vấn đề nan giải Địa nhớ Cách sử dụng pointer (con trỏ) Cách sử dụng trỏ function 7) Những thao tác làm việc với tập tin (file) Mở đóng tập tin Ghi liệu vào tập tin Đọc liệu tập tin Di chuyển tập tin Đổi tên xóa tập tin 3) Arrays (Mảng) Các Arrays nhớ Cách tạo array Liệt kê giá trị array Tạo function để liệt kê giá trị array Bài tập thực hành 8) Cấp phát động Kích thước biến Cấp phát nhớ động Giải phóng nhớ 4) Chuỗi ký tự Biến kiểu Char String hay gọi mảng ký tự Các thao tác với chuỗi ký tự Dịch giả: Mr Hung daihung.pham@yahoo.fr 9) Test Program: Người Treo Cổ Một số dẫn Giải pháp 1: Giải pháp 2: Ý tưởng cải tiến -1- Editor: M0N1M thaibaminh2512@gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 Bài 1: Modular Programming Mơ-đun Lập Trình Trong chương thứ hai hướng dẫn, bạn khám phá khái niệm lập trình ngơn ngữ C cao Cho đến lúc này, bạn làm việc file tên "main.c" Điều tạm chấp nhận giai đoạn chương trình cịn ngắn, tới chương trình chứa hàng chục, chí hàng trăm functions, bạn đặt tất chúng file dài ! Cũng lí mà người ta sáng tạo gọi modular programming Về mặt ngun tắc nghe ngu ngốc: thay đặt tất dịng code file (main.c), chia thành nhiều file nhỏ Chú ý: không đặt instruction system ("PAUSE") vào phía cuối main ( ) Hãy thêm vào bạn cần Và tơi khuyên bạn sử dụng IDE Code::Blocks Vì IDE update để đặt instruction system ("PAUSE") phía cuối main ( ) Prototypes Những hướng dẫn trước, yêu cầu bạn đặt functions trước main Tại vậy? Tại thứ tự xếp có tầm quan trọng: Khi bạn đặt function trước main, máy tính đọc nhớ Khi gọi lại main, máy tính biết phải kiếm lại function đâu Nhưng bạn đặt sau main, chương trình khơng hoạt động máy tính khơng biết function Hãy test thử, bạn thấy ! Nhưng vấn đề bất lợi, không? Tôi đồng ý với bạn điểm ! Nhưng bạn yên tâm, nhà lập trình trước gặp điều tương tự họ tìm cách khắc phục Dịch giả: Mr Hung daihung.pham@yahoo.fr -2- Editor: M0N1M thaibaminh2512@gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 Nhờ vào tơi cho bạn sau đây, bạn đặt functions theo thứ tự bạn muốn code source Prototype để báo trước function Chúng ta bắt đầu việc báo trước cho máy tính function cách viết prototypes Tôi biết bạn nghĩ từ ngữ mang đậm chất “high-tech” prototypes thứ ghê gớm thật thứ hoàn toàn ngu ngốc Hãy xem đoạn code function dientichHinhChuNhat: C code: double dientichHinhChuNhat (double chieuRong, double chieuDai) { return chieuRong * chieuDai; } Hãy copy lại dòng (double dientichHinhChuNhat ) chép vào phần đầu file source bạn (sau dòng #include) Và thêm vào dấu chấm phẩy cuối Vậy xong ! Bây bạn đặt function sau main bạn muốn Dịch giả: Mr Hung daihung.pham@yahoo.fr -3- Editor: M0N1M thaibaminh2512@gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 Và đoạn code thay đổi sau: C code: #include #include // Doan code sau chinh la prototype cua function dientichHinhChuNhat : double dientichHinhChuNhat (double chieuRong, double chieuDai); int main (int argc, char *argv[ ]) { printf ("Hinh chu nhat voi chieu rong va chieu dai 10 co dien tich la %f\n", dientichHinhChuNhat(5, 10)); printf ("Hinh chu nhat voi chieu rong 2.5 va chieu dai 3.5 co dien tich la %f\n", dientichHinhChuNhat(2.5, 3.5)); printf ("Hinh chu nhat voi chieu rong 4.2 va chieu dai 9.7 co dien tich la %f\n", dientichHinhChuNhat(4.2, 9.7)); return 0; } // function dientichHinhChuNhat bay gio co the dat o bat ki vi tri nao code source double dientichHinhChuNhat (double chieuRong, double chieuDai) { return chieuRong * chieuDai; } Và điều thay đổi là, dòng prototype thêm vào phần đầu code source Một prototype thật lời dẫn cho máy tính Nó thơng báo với máy tính có tồn function (dientichHinhChuNhat) với tham số (parameters) cần đưa vào type giá trị xuất Nhờ mà máy tính tự xếp Và nhờ vào dịng code này, bạn khơng cịn đau đầu chọn vị trí đặt function Hãy ln viết prototypes functions có chương trình Chương trình bạn khơng bị chậm sử dụng nhiều function đâu: bạn nên tập thói quen tốt kể từ bây giờ, đặt prototype cho functions bạn viết Chắc bạn thấy function main khơng có prototype Và function khơng cần prototype, máy tính biết rõ (tất chương trình dùng đến mà, bắt buộc phải biết thôi) Dịch giả: Mr Hung daihung.pham@yahoo.fr -4- Editor: M0N1M thaibaminh2512@gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 Để cho xác hơn, bạn cần biết thêm: dịng code prototype khơng cần thiết phải viết lại tên biến số cần cho parameter Máy tính cần biết type biến số thơi Vì đơn giản ta viết sau: C code: double dientichHinhChuNhat (double , double); Và với cách viết đó, chương trình chạy tốt, lợi ích cách viết bạn copy-paste nhanh chóng thêm vào dấu chấm phẩy cuối ĐỪNG QUÊN đặt dấu chấm phẩy cuối prototype Vì giúp cho máy tính nhận khác prototype function Nếu bạn không làm vậy, bạn mắc lỗi biên dịch chương trình Headers Cho đến lúc này, bạn sử dụng file source cho project bạn Và yêu cầu bạn gọi file source main.c Cách sử dụng nhiều files project Trong thực tế, chương trình khơng viết hết tồn file main.c Chắc chắn làm việc mị mẫm file chứa 10000 dịng code thật khơng thiết thực chút Chính vậy, thơng thường, project tạo nhiều files Nhưng mà project vậy? Khơng phải chứ, bạn qn ? Dịch giả: Mr Hung daihung.pham@yahoo.fr -5- Editor: M0N1M thaibaminh2512@gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 Ok, không sao, giải thích lại cho bạn, việc thống chung khái niệm thật cần thiết Project tập hợp files source chương trình Trong thời điểm tại, chương trình chứa file Hãy nhìn vào IDE, phía bên trái: Bạn thấy hình chụp phía trên, bên trái, project chứa file main.c Sau đây, tơi cho bạn xem hình ảnh chương trình thật sự, chương trình mà bạn thực sau: trò chơi Sokoban Bạn thấy đấy, có nhiều files khác Một chương trình bình thường giống trên: bạn thấy nhiều files liệt kê cột bên trái Bạn tìm thấy file main.c: bên chứa function main Và chương trình tơi viết, tơi để function main file main.c (điều không bắt buộc, người có cách xếp khác nhau, theo tốt bạn nên thực giống điểm này) Dịch giả: Mr Hung daihung.pham@yahoo.fr -6- Editor: M0N1M thaibaminh2512@gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 Nhưng phải tạo nhiều files vậy? Vậy tơi tạo tối đa file cho project ? Điều tùy thuộc vào bạn Bình thường, người ta thường hay xếp function có chủ đề vào chung với Trong hình vẽ trên, file editor.c tập hợp functions liên quan đến việc thay đổi cấp độ trò chơi, file game.c, tập hợp functions liên quan đến trò chơi, Các files h c Bạn thấy hình vẽ trên, có loại file khác nhau: file h: gọi file headers Những file chứa prototype functions file c: file source Những file chứa nội dung functions Bình thường, người ta để prototypes file c giống vừa làm file main.c (chỉ trừ chương trình q nhỏ) Mỗi file c tương ứng với file h chứa prototype functions Xem lại hình lần nữa: Có file editor.c (chứa C code functions) file editor.h (chứa prototype functions đó) Tương tự ta có file game.c file game.h Làm máy tính biết prototypes nằm file khác file c ? Ta thêm file h vào chương trình nhờ vào thị tiền xử lý (preprocessor directive) Tập trung nhé, bạn cần chuẩn bị tinh thần để hiểu biết thêm nhiều thứ ! Làm thêm vào file header ? Bạn biết cách mà, bạn làm nhiều lần nhớ không? Dịch giả: Mr Hung daihung.pham@yahoo.fr -7- Editor: M0N1M thaibaminh2512@gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 Chúng ta xem ví dụ đoạn đầu file jeu.c tơi viết: C code: #include #include #include "game.h" void play (SDL_Surface* screen) { // Và bạn biết cách thêm vào sử dụng thị tiền xử lý (preprocessor directive) #include Bây giờ, ý dòng đoạn code trên: C code: #include #include #include "game.h" // them vao file game.h Tôi thêm vào files h: stdio, stdlib game Có khác biệt đây: Những file mà bạn để chung folder project phải viết ngoặc kép " " ("game.h") file thư viện (đã cài đặt trước, bình thường nằm folder IDE bạn) phải viết ngoặc nhọn < > () Tóm lại, thơng thường ta sử dụng: Ngoặc nhọn < > để thêm vào file thư viện tìm thấy folder IDE Ngoặc kép " " để thêm vào file tìm thấy folder project bạn ( bên cạnh file c) Dịch giả: Mr Hung daihung.pham@yahoo.fr -8- Editor: M0N1M thaibaminh2512@gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 Lệnh #include yêu cầu thêm vào nội dung file h vào file c Giống bạn yêu cầu "Hãy thêm vào nội dung file game.h" Vậy nội dung file game.h gì? Chúng ta tìm thấy prototype functions nằm file game.c ! C code: /* game.h Noi dung : prototypes of functions in game */ void play (SDL_Surface* screen); void placingPlay (int card[ ][NB_BLOCK_HEIGHT], SDL_Rect *post, int direction); void placingFund (int *firstCase, int *secondCase); Và cách project thật hoạt động ! Vậy lợi ích việc đặt prototypes vào file h ? Lí đơn giản Khi code source bạn viết yêu cầu gọi function, máy tính bạn bắt buộc phải biết trước function gì, cần tham số (parameter), Vì ta cần đến prototype: giống bảng hướng dẫn sử dụng trước dùng function cho máy tính Câu hỏi tương ứng với câu hỏi thứ tự chạy chương trình: bạn đặt prototypes file h (headers) #include phần đầu file c , máy tính bạn hiểu cách sử dụng tất function kể từ giai đoạn bắt đầu chạy chương trình Và điều giúp bạn bận tâm thứ tự đặt function files c Hiện giờ, bạn viết số chương trình chứa khoảng hai ba functions, bạn chưa thấy rõ ích lợi prototypes sau, bạn viết nhiều functions rồi, bạn không đặt prototypes file h, bạn thường xuyên gặp lỗi việc dịch chương trình Dịch giả: Mr Hung daihung.pham@yahoo.fr -9- Editor: M0N1M thaibaminh2512@gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 Nếu bạn gọi function (được viết file functions.c) từ file main.c bạn cần phải thêm prototypes functions.c file main.c Bằng cách tạo #include "functions.h" đầu main.c Bạn cần nhớ: lần bạn gọi function X file, bạn cần phải thêm prototypes function vào file Điều giúp trình biên dịch kiểm tra lại xem bạn có gọi cách hay khơng Vậy làm cách tơi thêm vào project file h c ? Điều phụ thuộc vào IDE bạn sử dụng tổng quát qui trình tương tự nhau: File/New/ Empty file Việc tạo file trống File chưa có dạng h hay c, bạn cần lưu lại để thơng báo điều Cứ lưu lại (mặc dù file trống !) Máy tính hỏi bạn tên file muốn lưu lại lúc bạn lựa chọn h c : Nếu bạn đặt tên [tênfile].c có dạng c Nếu bạn đặt tên [tênfile].h có dạng h Đơn giản Lưu lại file folder chứa files khác dùng cho project (folder chứa file main.c) Thông thường, tất file h c lưu lại folder Dịch giả: Mr Hung daihung.pham@yahoo.fr - 10 - Editor: M0N1M thaibaminh2512@gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 C code: if (win(sokytuBimat)) printf ("\n\n Chuc mung, ban da chien thang ! Tu bi mat la : %s", tuBimat); else printf ("\n\n Xin chia buon, ban da thua !\n\n Tu bi mat la : %s", tuBimat); return 0; } Chúng ta dùng hàm win để kiểm tra xem người chơi có thắng hay khơng để hiển thị thơng báo cho họ biết Phân tích hàm win: Bây thấy code hàm win: C code: int win(int sokytuBimat[ ]) { int i = 0; int nguoichoiChienThang = 1; for (i = ; i < ; i++) { if (sokytuBimat[i] == 0) nguoichoiChienThang = 0; } return nguoichoiChienThang; } Hàm lấy tham số mảng sokytuBimat chứa giá trị dạng Boolean Hàm trả giá trị “true” người chơi thắng, giá trị “flase” không thắng Code hàm nhìn đơn giản khơng, bạn đọc hiểu không Chúng ta kiểm tra thử xem mảng sokytuBimat có chứa giá trị không Nếu xuất ô mảng có giá trị 0, điều có nghĩa người chơi khơng thắng được, lúc biến nguoichoiChienThang (biến kiểu Boolean) mang giá trị “false” tương đương Và tất ký tự tìm thấy, biến có giá trị “true” tương đương 1, hiển nhiên hàm trả giá trị Dịch giả: Mr Hung daihung.pham@yahoo.fr - 150 - Editor: M0N1M thaibaminh2512@gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 Phân tích hàm kiemtraKytu: Hàm kiemtraKytu có nhiệm vụ chính: Trả Boolean ký tự người dùng đốn có chứa từ bí mật hay khơng Gửi giá trị (vd: giá trị 1) vào ô giá trị mảng sokytuBimat tương ứng với vị trí ký tự mảng C code: int kiemtraKytu(char kytu, char tuBimat[ ], int sokytuBimat[ ]) { int i = 0; int kytuChinhXac = 0; // Kiem tra xem ky tu cua nguoi choi da doan co nam tu bi mat ko for (i = ; tuBimat[i] != '\0' ; i++) { if (kytu == tuBimat[i]) // Neu ky tu co chua tu bi mat { kytuChinhXac = 1; // Ky tu se duoc luu tru gia tri the hien no la ky tu chinh xac sokytuBimat[i] = 1; // Gui gia tri vao o tuong ung voi vi tri cua ky tu mang } } return kytuChinhXac; } Hàm kiểm tra ký tự mà người dùng nhập vào có nằm ký tự bí mật khơng Nếu có, có điều diễn ra: Giá trị Boolean biến kytuChinhXac 1, giá trị gửi vào vị trí tương ứng ký tự kytuBimat Chúng ta cập nhật giá trị mảng sokytuBimat tương ứng với vị trí ký tự mảng Lợi ích kỹ thuật kiểm tra lượt toàn giá trị mảng (chứ không ngừng lại sau tìm ký tự đầu tiên) Việc cho phép cập nhật xác giá trị mảng sokytuBimat, kể trường hợp có ký tự giống từ ký tự O từ FACEBOOK Dịch giả: Mr Hung daihung.pham@yahoo.fr - 151 - Editor: M0N1M thaibaminh2512@gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 Giải pháp 2: Quản lý tập tin “danh mục từ bí mật” Chúng ta có biết tạo hầu hết chức trò chơi, bạn quản lý chương trình cịn phần chưa hồn thiện, cách chọn ngẫu nhiên từ bí mật “danh mục từ bí mật” Bạn tưởng tượng danh mục giống tơi cho bạn xem trên, không cho bạn thấy cụ thể tồn nội dung tập tin dài tới vài trang giấy khơng đâu Trước tiếp tục, việc cần làm tạo “danh mục từ bí mật” cho trị chơi Ở thời điểm dù ngắn hay dài khơng quan trọng, để làm thử nghiệm cho học Tôi tạo tập tin danhmuc.txt thư mục chứa project Và tạm thời nội dung tập tin trông sau: LOVE MONEY PROGRAM FUNCTION POINTER LOOP INSTRUCTION STRING VARIABLE CONSTANT DEFINE Sau hoàn thành chương trình, dĩ nhiên tơi quay lại danh mục thêm vào tập tin từ bí mật khác để tăng thêm phong phú cho trò chơi Những chuẩn bị cho tập tin Riêng từ “danh mục” tên tập tin đủ làm bạn tưởng tượng danh sách có độ dài gần vơ hạn khơng Do đó, thêm tập tin vào project mình, tập tin danhmuc.c (tập tin có nhiệm vụ đọc danhmuc.txt) Và trình này, tạo tập tin danhmuc.h, tập tin chứa prototype danhmuc.c Trong danhmuc.c thêm vào thư viện cần thiết dĩ nhiên có danhmuc.h Như thường lệ thư viện chuẩn ưu tiên trước stdlib, stdio bên cạnh đó, cần chọn số ngẫu nhiên từ danh mục, ta phải thêm vào thư viện time.h giống làm với chương trình test chương (trị “lớn hay nhỏ hơn”, bạn nhớ ko) Và thêm nữa, ta sử dụng hàm strlen nên bạn phải thêm vào string.h nhé: Dịch giả: Mr Hung daihung.pham@yahoo.fr - 152 - Editor: M0N1M thaibaminh2512@gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 Xem thử nào: C code: #include #include #include #include #include "danhmuc.h" Hàm chonTu: Hàm cần tham số Đó trỏ đến vùng nhớ, nơi mà lưu trữ từ ngẫu nhiên danh mục vào Con trỏ cung cấp main ( ) Hàm trả giá trị kiểu int có kiểu Boolean: giá trị việc diễn tốt đẹp có lỗi xảy Sau đoạn đầu hàm: C code: int chonTu(char *tuDuocChon) { FILE* danhmuc = NULL; // Con tro tap tin de chua cac tap tin cua chung ta int soThuTuCuaTu = 0, soThuTuCuaTuDuocChon = 0, i = 0; int luuKytu = 0; Tôi tạo số biến cần thiết cho chương trình Trong main ( ), bạn thấy tơi khơng tạo tất biến lúc bắt đầu, có thứ bạn tạo sau bạn nhận thấy bạn cần đến chúng Tên biến cho bạn thấy nhiệm vụ, chức chúng Chúng ta có trỏ danhmuc để đọc tập tin danhmuc.txt, biến tạm thời để lưu trữ ký tự … Bạn có để ý khai báo kiểu int cho biến luuKytu để lưu trữ ký tự? Hơi lạ không, hàm fgetc mà tí tơi dùng trả giá trị kiểu int, nên tốt nên lưu trữ kết kiểu int Dịch giả: Mr Hung daihung.pham@yahoo.fr - 153 - Editor: M0N1M thaibaminh2512@gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 Nào xem thử nhé: C code: danhmuc = fopen("danhmuc.txt", "r"); // Tap tin duoc mo che "read-only" // Chung ta kiem tra xem thao tac mo tap tin co cong khong if (danhmuc == NULL) // Neu ban khong the mo tap tin { printf ("\n Khong the mo danh muc tu bi mat"); return 0; // Tra ve gia tri cho biet thao tac mo tap tin that bai // Sau nhan duoc gia tri tra ve cua return, ham ket thuc } Khơng có nhiều điều mẻ Tôi chọn chế độ mở tập tin danhmuc.txt “read-only” (bằng cách chọn “r”) kiểm tra xem thao tác có thành công hay không cách sử dụng if giá trị trả danhmuc NULL rõ ràng việc mở tập tin thất bại (có thể chương trình khơng tìm thấy tập tin danhmuc.txt chương trình khác sử dụng) Trong trường hợp này, hình hiển thị thơng báo lỗi giá trị trả Tại return lại nằm vị trí Thật thì, return có chức dừng hoạt động hàm lại Nếu mở tập tin, hàm dừng lại máy tính khơng tiếp tục đọc thêm Nó trả giá trị biết hàm không thực Và phần lại hàm, giả sử việc mở tập tin thành công: C code: // Dem cac tu duoc chua tap tin (chi viec dem co bao nhieu ky tu \n thoi) { luuKytu = fgetc(danhmuc); if (luuKytu == '\n') soThuTuCuaTu ++; } while(luuKytu != EOF); Bạn thấy khơng, đọc qua toàn tập tin nhờ vào hàm fgetc (và đọc ký tự nhé) Chương trình việc đếm số lần xuất ký tự \n Mỗi lần ký tự \n xuất hiện, giá trị biến soThuTuCuaTu tăng thêm Với phần code này, biết có bao nhiều từ bí mật nằm tập tin Và nhớ dòng tập tin chứa từ C code: soThuTuCuaTuDuocChon = tuNgauNhien(soThuTuCuaTu); // Chon mot tu ngau nhien Dịch giả: Mr Hung daihung.pham@yahoo.fr - 154 - Editor: M0N1M thaibaminh2512@gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 Như bạn thấy, tơi gọi hàm theo kiểu riêng mình, chọn từ có số thứ tự ngẫu nhiên từ đến giá trị soThuTuCuaTu (tham số gửi vào hàm) Đây hàm đơn giản mà đặt vào file danhmuc.c (tôi cho bạn thấy rõ chi tiết tí nữa) Nó trả giá trị số (tương ứng với số thứ tự dịng chứa từ tập tin), giá trị gửi vào biến soThuTuCuaTuDuocChon C code: // Chuong trinh doc lai tu dau tap tin va ngung lai tim thay tu ngau nhien duoc chon rewind(danhmuc); while (soThuTuCuaTuDuocChon > 0) { luuKytu = fgetc(danhmuc); if (luuKytu == '\n') soThuTuCuaTuDuocChon ; } Bây có số thự tự từ chọn ngẫu nhiên, việc gọi hàm rewind ( ) chương trình bắt đầu đọc tập tin từ đầu Nó đếm ký tự \n tập tin Lần này, giá trị biến soThuTuCuaTuDuocChon giảm xuống Vd từ chọn ngẫu nhiên từ thứ tập tin, sau vịng lặp giá trị giảm xuống 4, 3, 2, Khi giá trị soThuTuCuaTuDuocChon khỏi vịng lặp, lúc khơng cịn thỏa mãn điều kiện biến có giá trị lớn Bạn cần phải hiểu ý nghĩa đoạn code này, giúp ta tìm vị trí “dấu nháy ảo” tập tin Điều khơng thực q khó hiểu bạn phải cố gắng nhìn nhận việc cách rõ ràng Hãy cố đảm bảo bạn hiểu tơi nói làm Bây cần “dấu nháy” để vị trí từ chọn tập tin Chúng ta gửi đến trỏ tuDuocChon (đây tham số mà hàm cần) với fgets để đọc từ: C code: /* Con tro tap tin danhmuc duoc dat dung vi tri cua no Chung ta su dung ham fgets va quy dinh ham khong doc qua so luong ky tu cho phep*/ fgets(tuDuocChon, 100, danhmuc); // Chung ta se thay the ky tu \n tuDuocChon[strlen(tuDuocChon) - 1] = '\0'; Chúng ta yêu cầu hàm fgets không đọc 100 ký tự (cũng tương ứng với kích thước mảng) Hãy nhớ hàm fgets đọc toàn dịng bao gồm ln ký tự \n Dịch giả: Mr Hung daihung.pham@yahoo.fr - 155 - Editor: M0N1M thaibaminh2512@gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 Khi bạn không muốn gặp ký tự \n cuối, thay \0, ký tự có tác dụng cắt chuỗi trước gặp ký tự \n Và … hoạt động … lưu trữ ký tự bí mật địa trỏ tuDuocChon Chúng ta chưa đóng tập tin lại, giá trị trả để ngừng hàm lại cho thấy chương trình hoạt động tốt: C code: fclose(danhmuc); return 1; // Gia tri tra ve = 1, tat ca deu hoat dong tot } Và tơi khơng có để nói thêm hàm chonTu Hàm tuNgauNhien: Đây hàm mà tơi hứa giải thích cho bạn Nó chọn số thứ tự ngẫu nhiên gửi về: C code: int tuNgauNhien(int sothutuLonNhat) { srand(time(NULL)); return (rand( ) % sothutuLonNhat); } Dòng srand(time(NULL)); giúp chương trình bạn khơng chọn trùng số ngẫu nhiên, giống làm với chương trình “lớn hay nhỏ hơn” chương Dòng thứ chọn số ngẫu nhiên chuỗi giá trị từ đến giá trị biến sothutuLonNhat Tập tin danhmuc.h Sau prototype function Và điều nữa, bạn có cịn nhớ “người bảo vệ” #ifndef mà yêu cầu bạn nên thêm vào tất tập tin h bạn (tham khảo lại kiến thức học prototype tiền xử lý nhé) C code: #ifndef DEF_DANHMUC #define DEF_DANHMUC int chonTu(char *tuDuocChon); int tuNgauNhien(int sothutuLonNhat); #endif Dịch giả: Mr Hung daihung.pham@yahoo.fr - 156 - Editor: M0N1M thaibaminh2512@gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 Tập tin danhmuc.c Và sau toàn nội dung tập tin danhmuc.c, xin mời bạn thưởng thức:ư C code: /* Nguoi Treo Co danhmuc.c -Nhung function se chon mot tu ngau nhien tap tin chua danh muc tu bi an cua tro choi Nguoi Treo Co */ #include #include #include #include #include "danhmuc.h" int chonTu(char *tuDuocChon) { FILE* danhmuc = NULL; // Con tro tap tin de chua cac tap tin cua chung ta int soThuTuCuaTu = 0, soThuTuCuaTuDuocChon = 0, i = 0; int luuKytu = 0; danhmuc = fopen("danhmuc.txt", "r"); // Tap tin duoc mo che "read-only" // Chung ta kiem tra xem thao tac mo tap tin co cong khong if (danhmuc == NULL) // Neu ban khong the mo tap tin { printf ("\n Khong the mo danh muc tu bi mat"); return 0; // Tra ve gia tri cho biet thao tac mo tap tin that bai // Sau nhan duoc gia tri tra ve cua return, ham ket thuc } Dịch giả: Mr Hung daihung.pham@yahoo.fr - 157 - Editor: M0N1M thaibaminh2512@gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 // Dem cac tu duoc chua tap tin (chi viec dem co bao nhieu ky tu \n thoi) { luuKytu = fgetc(danhmuc); if (luuKytu == '\n') soThuTuCuaTu++; } while(luuKytu != EOF); soThuTuCuaTuDuocChon = tuNgauNhien(soThuTuCuaTu); // Chon mot tu ngau nhien // Chuong trinh doc lai tu dau tap tin va ngung lai tim thay tu ngau nhien duoc chon rewind(danhmuc); while (soThuTuCuaTuDuocChon > 0) { luuKytu = fgetc(danhmuc); if (luuKytu == '\n') soThuTuCuaTuDuocChon ; } /* Con tro tap tin danhmuc duoc dat dung vi tri cua no Chung ta su dung ham fgets va quy dinh ham khong doc qua so luong ky tu cho phep*/ fgets(tuDuocChon, 100, danhmuc); // Chung ta se thay the ky tu \n tuDuocChon[strlen(tuDuocChon) - 1] = '\0'; fclose(danhmuc); return 1; // Gia tri tra ve = 1, tat ca deu hoat dong tot } int tuNgauNhien(int sothutuLonNhat) { srand(time(NULL)); return (rand( ) % sothutuLonNhat); } Dịch giả: Mr Hung daihung.pham@yahoo.fr - 158 - Editor: M0N1M thaibaminh2512@gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 Chúng ta làm vài thứ main.c: Bây tập tin danhmuc.c sẵn sàng, trở lại với main.c để thêm vào số thứ cho phù hợp Với làm từ đầu đến giờ, trước hết thêm vào file danhmuc.h bạn muốn sử dụng function danhmuc.c Ngoài ra, không quên khai báo thêm thư viện string.h phải sử dụng hàm strlen: C code: #include #include "dico.h" Để bắt đầu, việc khai báo biến có chút thay đổi Bạn không cần khởi tạo chuỗi ký tự tuBimat có sẵn mảng kiểu char cho (chứa sẵn 100 ln) Với mảng sokytuBimat, kích thước phụ thuộc vào độ dài từ bí mật Bởi chưa biết kích thước đó, nên có trỏ tạo ra, với malloc gửi trỏ đến vị trí nhớ mà cấp phát Đây vd tuyệt vời cho học cấp phát động trước đây: biết trước kích thước mảng chương trình chưa chạy, bắt buộc bạn phải tạo trỏ sử dụng hàm malloc Bạn không quên giải phóng nhớ để cịn sử dụng cho mục đích khác Đó lý cho xuất free ( ) cuối main.c Chúng ta cần biến dodaiTu để lưu trữ giá trị thể số lượng ký tự từ Như bạn thấy phần đầu, giả định từ bí mật có ký tự (bởi chọn FACEBOOK làm vd mà) Nhưng làm việc linh động với từ với kích thước tùy biến Và sau đầy đủ tất biến cần cho chương trình chúng ta: C code: int main(int argc, char* argv[ ]) { char kytu = 0; // Bien se luu tru ky tu cua nguoi choi (duoc tra ve boi ham scanf) char tuBimat[100] = {0}; // Day la tu bi mat can tim int *sokytuBimat = NULL; /* Mot mang co chua cac phan dang Bolean Moi o mang se tuong ung voi mot ky tu nguoi choi se doan Neu doan dung thi gia tri = 1, va neu sai thi gia tri = */ int soluotDoan = 10; // So luot doan lai cua nguoi choi (0 = thua) int i = 0; // Bien ho tro int dodaiTu = 0; Dịch giả: Mr Hung daihung.pham@yahoo.fr - 159 - Editor: M0N1M thaibaminh2512@gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 Trên chủ yếu thay đổi ban đầu, sâu chút: C code: if (!chonTu(tuBimat)) exit(0); Đầu tiên đặt hàm chonTu vào phần điều kiện if, hàm lấy tham số biến tuBimat Và ta biết, hàm trả giá trị Boolean (1 0) biết có thực thành cơng hay khơng Vai trị if phân tích giá trị Boolean trả hàm chonTu, hàm KHÔNG hoạt động (hãy lưu ý if có chứa dấu ! để thể phủ định), ngừng lại tất exit (0) C code: dodaiTu = strlen(tuBimat); Giá trị thể kích thước tuBimat lưu trữ biến dodaiTu C code: sokytuBimat = malloc(dodaiTu * sizeof(int)); /* mang sokytuBimat se duoc cap phat dong bo nho (luc dau chung ta khong biet duoc kich thuoc cua mang nay) */ if (sokytuBimat == NULL) exit(0); Bây phải cấp phát nhớ cho mảng sokytuBimat Kích thước mảng cung cấp giá trị biến dodaiTu Sau dùng if để kiểm tra giá trị trỏ có NULL khơng Trong trường hợp NULL, chứng tỏ việc cấp phát nhớ thất bại, dừng chương trình (bằng cách gọi hàm exit (0) ) Đây tất bạn cần chuẩn bị cho chương trình Sâu cần thay đổi nốt phần lại main.c để thay tất số (số thể độ dài từ FACEBOOK mà ta giả định từ bí mật lúc đầu học) biến dodaiTu VD: C code: for (i = ; i < dodaiTu ; i++) sokytuBimat[i] = 0; Ban đầu, đoạn code đặt giá trị vào mảng sokytuBimat hiểu khơng có mảng, giá trị tăng lên với giá trị biến dodaiTu ngừng lại, kích thước xác cho mảng Tôi phải thiết kế lại prototype function win để thêm vào biến dodaiTu Nếu không hàm khơng biết phải dừng vịng lặp Dịch giả: Mr Hung daihung.pham@yahoo.fr - 160 - Editor: M0N1M thaibaminh2512@gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 Sau tập tin main.c hoàn thiện: C code: /* Nguoi Treo Co main.c -Nhung function se chon mot tu ngau nhien tap tin chua danh muc tu bi an cua tro choi Nguoi Treo Co */ #include #include #include #include #include "danhmuc.h" int win(int sokytuBimat[ ], long dodaiTu); int kiemtraKytu(char kytu, char tuBimat[ ], int sokytuBimat[ ]); char docKytu( ); int main(int argc, char* argv[ ]) { char kytu = 0; // Bien se luu tru ky tu cua nguoi choi (duoc tra ve boi ham scanf) char tuBimat[100] = {0}; // Day la tu bi mat can tim int *sokytuBimat = NULL; /* Mot mang co chua cac phan dang Bolean Moi o mang se tuong ung voi mot ky tu nguoi choi se doan Neu doan dung thi gia tri = 1, va neu sai thi gia tri = */ long soluotDoan = 10; // So luot doan lai cua nguoi choi (0 = thua) long i = 0; // Bien ho tro long dodaiTu = 0; printf ("Chao mung den voi tro choi Nguoi treo co !\n\n "); if (!chonTu(tuBimat)) exit(0); Dịch giả: Mr Hung daihung.pham@yahoo.fr - 161 - Editor: M0N1M thaibaminh2512@gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 dodaiTu = strlen(tuBimat); sokytuBimat = malloc(dodaiTu * sizeof (int)); /* mang sokytuBimat se duoc cap phat dong bo nho (luc dau chung ta khong biet duoc kich thuoc cua mang nay) */ if (sokytuBimat == NULL) exit(0); for (i = ; i < dodaiTu ; i++) sokytuBimat[i] = 0; /* Chung ta se tiep tuc tro choi neu it nhat mot luot doan Va van chua tim duoc tu bi mat*/ while (soluotDoan > && !win(sokytuBimat, dodaiTu)) { printf ("\n\n Ban co %d luot doan de choi ", soluotDoan); printf ("\n Tu bi mat la gi ?"); /* Hien thi nhung ky tu bi mat va an di nhung ky tu chua duoc tim thay Vi du: *A***OO*/ for (i = ; i < dodaiTu ; i++) { if (sokytuBimat[i]) // Neu nguoi choi tim duoc ky tu thu i printf ("%c", tuBimat[i]); // Hien thi ky tu thu i duoc tim thay else printf ("*");// Hien thi dau * doi voi nhung ky tu chua duoc tim thay } printf ("\n Xin moi ban doan mot ky tu: "); kytu = docKytu( ); // Neu ky tu nhap vao khong dung if (!kiemtraKytu(kytu, tuBimat, sokytuBimat)) { soluotDoan ; // Giam bot mot lan doan cua nguoi choi } } if (win(sokytuBimat, dodaiTu)) printf ("\n\n Chuc mung, ban da chien thang ! Tu bi mat la : %s", tuBimat); Dịch giả: Mr Hung daihung.pham@yahoo.fr - 162 - Editor: M0N1M thaibaminh2512@gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 else printf ("\n\n Xin chia buon, ban da thua !\n\n Tu bi mat la : %s", tuBimat); free (sokytuBimat); // Giai phong bo nho da duoc phan bo (boi ham malloc) return 0; } char docKytu( ) { char kytuNhapVao = 0; kytuNhapVao = getchar( ); // Doc ky tu duoc nhap dau tien kytuNhapVao = toupper(kytuNhapVao); // Viet hoa ky tu // Lan luot doc tiep cac ky tu khac cho den gap \n while (getchar( ) != '\n') ; return kytuNhapVao; // Tra ve ky tu dau tien doc duoc } int win(int sokytuBimat[ ], long dodaiTu) { long i = 0; int nguoichoiChienThang = 1; for (i = ; i < dodaiTu ; i++) { if (sokytuBimat[i] == 0) nguoichoiChienThang = 0; } return nguoichoiChienThang; } int kiemtraKytu(char kytu, char tuBimat[ ], int sokytuBimat[ ]) { long i = 0; int kytuChinhXac = 0; Dịch giả: Mr Hung daihung.pham@yahoo.fr - 163 - Editor: M0N1M thaibaminh2512@gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 // Kiem tra xem ky tu cua nguoi choi da doan co nam tu bi mat ko for (i = ; tuBimat[i] != '\0' ; i++) { if (kytu == tuBimat[i]) // Neu ky tu co chua tu bi mat { kytuChinhXac = 1; // Ky tu se duoc luu tru gia tri the hien no la ky tu chinh xac sokytuBimat[i] = 1; // Gui gia tri vao o tuong ung voi vi tri cua ky tu mang } } return kytuChinhXac; } Ý tưởng cải tiến: Chà, trò “Người treo cổ” có phức tạp với bạn khơng Bây bạn có chương trình chọn từ ngẫu nhiên từ tập tin không Sau số ý tưởng cải tiến để bạn thử sức: Hiện nay, cho phép người chơi lần Nghĩa chương trình ngừng lại có người chiến thắng sử dụng hết lượt đoán Bây giờ, bạn thử tạo yêu cầu người chơi xem họ có muốn chơi lại khơng Bạn tạo chế độ chơi người, người thứ nhập từ bí ẩn vào cho người thứ đốn Mặc dù không bắt buộc bạn không thử vẽ hình người bị treo cổ hình console (như kim từ điển hay có) gợi ý bạn làm hàm printf Hãy cố gắng bỏ thời gian để hiểu học cải tiến hết mức Cố lên nào, đừng nản lòng Dịch giả: Mr Hung daihung.pham@yahoo.fr - 164 - Editor: M0N1M thaibaminh2512@gmai.com ... daihung.pham@yahoo.fr - 22 - Editor: M0N1M thaibaminh25 12@ gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 Và kết quả: Console gio va 90 phut Ặc chương trình. .. Hung daihung.pham@yahoo.fr - 20 - Editor: M0N1M thaibaminh25 12@ gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 Bài 2: Pointer Con trỏ Đã đến... daihung.pham@yahoo.fr - 12 - Editor: M0N1M thaibaminh25 12@ gmai.com Tài liệu hướng dẫn lập trình C Apprenez programmer en C www.siteduzero.com Tác giả: M@teo21 Phân tích trình Compilation (separate