« Home « Kết quả tìm kiếm

[Tài liệu lập trình C] - Chương 2 - Những Kỹ Thuật Nâng Cao.pdf


Tóm tắt Xem thử

- Cho đến lúc này, các bạn cũng chỉ làm việc trên một file duy nhất tên là " main.c" Điều này có thể tạm chấp nhận trong giai đoạn hiện tại vì chương trình của chúng ta vẫn còn khá ngắn, nhưng sắp tới chương trình của chúng ta sẽ chứa hàng chục, thậm chí hàng trăm functions, nếu bạn đặt tất cả chúng trong cùng một file thì sẽ rất dài ! Cũng chính vì lí do đó mà người ta đã sáng tạo ra cái gọi là modular programming .
- Về mặt nguyên tắc thì nghe có vẻ khá ngu ngốc: thay vì đặt tất cả các dòng code trong một file duy nhất (main.c), chúng ta sẽ chia ra thành nhiều file nhỏ hơn.
- Prototype để báo trước một function Chúng ta bắt đầu việc báo trước cho máy tính những function của chúng ta bằng cách viết các prototypes .
- Và tôi yêu cầu bạn gọi file source này là main.c Cách sử dụng nhiều files trong cùng một project Trong thực tế, chương trình sẽ không được viết hết toàn bộ trong mỗi file main.c Chắc chắn là chúng ta cũng có thể làm vậy nhưng việc mò mẫm trong một file chứa 10000 dòng code thật sự không thiết thực chút nào.
- Bình thường, người ta rất ít khi để những prototypes trong các file .c giống như vừa rồi chúng ta đã làm trong file main.c (chỉ trừ khi chương trình đó quá nhỏ).
- 8 - [email protected] Chúng ta hãy xem ví dụ đoạn đầu của file jeu.c tôi viết: C code: #include #include #include "game.h" void play (SDL_Surface* screen.
- Giống như bạn yêu cầu "Hãy thêm vào đây nội dung của file game.h " Vậy nội dung của file game.h là gì? Chúng ta sẽ tìm thấy trong đó những prototype của các functions nằm trong file game.c ! C code.
- Nếu như ta thêm vào những file stdio.h và stdlib.h, vậy thì những file này nằm đâu đó và chúng ta có thể tìm thấy chúng phải không? Chính xác là vậy đó ! Thông thường nó đã được cài đặt chung với IDE của bạn.
- Đừng cố gắng mở ra để đọc chúng, vì chúng không dành cho người bình thường như chúng ta.
- 21 - [email protected] Bài 2: Pointer Con tr ỏ Đã đến lúc chúng ta tìm hiểu về con trỏ.
- Nói về tầm quan trọng, chúng ta không thể nào lập trình trên ngôn ngữ C mà không dùng đến con trỏ, và bạn cũng đã từng dùng nó mà không biết.
- "Con trỏ rất cần thiết, và chúng ta sẽ thường xuyên dùng đến nó, hãy tin tôi.
- Chúng ta cũng đã học cách viết một function không trả về bất cứ giá trị nào với từ khóa void : C code: void function.
- Chúng ta không thể sử dụng hai return cùng lúc.
- đầu bài? Đã đến lúc chúng ta xem lại tâm điểm của bài học..
- Các bạn cần lưu ý là chúng ta vẫn có thể giải quyết "vấn đề" này không qua cách sử dụng con trỏ.
- luật chúng ta đã đặt ra: không sử dụng những.
- Bạn cảm thấy có chút khó khăn trong việc sử dụng các pointers? B ạn sẽ không tránh khỏi việc dùng chúng đâu! Các pointers được sử dụng thường xuyên trong C, tôi đã nói với bạn điều này! Trong bài học này, chúng ta sẽ học cách tạo những biến số type "array" hay còn gọi là mảng.
- Cách tạo một mảng (array) Bắt đầu, chúng ta sẽ xem làm thế nào để tạo một mảng chứa 4 giá trị int: C code: int array[4.
- Sau đó nó sẽ điề n t ừ ng ch ữ cái c ủ a t ừ « Hello » vào b ộ nh ớ gi ống như cách đầ u tiên chúng ta làm ở trên.
- Đôi khi, chúng ta cầ n khai báo m ộ t m ả ng char l ớn hơn, đủ l ớn để có th ể ch ứ a tên c ủa ngườ i dùng.
- Chúng ta s ẽ t ạ o m ột char[100] để ch ứ a tên ngườ i dùng.
- Vi ệ c này khi ế n b ạ n có c ảm giác chúng ta đang lãng phí bộ nh ớ.
- Chúng ta sẽ h ọ c cách t ạ o ra nh ữ ng type m ớ i ở nh ữ ng bài h ọ c sau.
- Trong th ời điể m hi ệ n t ạ i, chúng ta t ạ m th ờ i hài lòng v ớ i giá tr ị tr ả v ề c ủa strlen được lưu lạ i trong m ộ t bi ế n s ố type long (máy tính s ẽ t ự độ ng chuy ể n size_t thành long.
- Console: Cuckoo Tôi đồ ng ý v ớ i b ạ n, r ằng đây không phả i cách truy ề n th ống mà chúng ta đã đượ c h ọ c ở các bài trướ c.
- Nhưng… chúng ta chỉ có th ể đặ t duy nh ấ t m ột đoạ n code trong m ỗ i macro thôi sao? Không, th ậ t may m ắ n là chúng ta có th ể đặ t nhi ề u dòng code trong m ỗ i macro.
- 79 - [email protected] C ần lưu ý là trong main, khi gọ i m ột macro chúng ta không đặ t d ấ u ch ấ m ph ẩ y.
- Th ự c t ế, đây là mộ t dòng cho preprocessor, chúng ta không c ầ n thi ế t ph ả i k ế t thúc b ằ ng d ấ u ch ấ m ph ẩ y.
- Macro v ớ i nhi ề u tham s ố (parameters) V ừ a r ồi chúng ta đã bi ết làm cách nào để t ạ o ra m ột macro không dùng parameter, có nghĩa là không ghi gì vào trong parameter c ủ a nó.
- Trong tình hu ống như vậ y, nh ữ ng macro này càng hi ệ u qu ả hơn khi chúng ta đặ t vào chúng nh ữ ng parameter.
- Và chúng ta cũng có thể t ạ o m ộ t macro ch ứ a nhi ề u parameters: C Code: #define NGUOI_TRUONG_THANH(tuoi, ten) if (tuoi.
- Bình thườ ng chúng ta không c ầ n thi ế t ph ả i s ử d ụng thườ ng xuyên các macro.
- 81 - [email protected] #ifdef và #ifndef Bây gi ờ chúng ta s ẽ th ấ y l ợ i ích c ủ a vi ệ c #define m ộ t constan t không xác định trướ c giá tr ị, như tôi có hướ ng d ẫ n b ạn trước đó: C Code: #define CONSTANT Ta có th ể s ử d ụng #ifdef để t ạo ra điề u ki ệ n "N ế u h ằ ng s ố đã được xác đị nh." #ifndef, để t ạo ra điề u ki ệ n: "N ế u h ằ ng s ố chưa được xác đị nh." B ạn hãy xem đoạ n code sau: C code: Code C: #define WINDOWS #ifdef WINDOWS.
- V ậy thì làm cách nào để chúng ta có th ể lưu lại điể m s ố cao nh ấ t trong game? Làm sao để m ột chương trình soạ n th ả o văn bả n ho ạt độ ng n ế u t ấ t c ả nh ữ ng gì b ạ n vi ế t ra s ẽ b ị xóa khi t ắt chương trình? May m ắ n thay, b ạ n có th ể đọ c và ghi d ữ li ệ u c ủ a các t ậ p tin trong ngôn ng ữ C.
- Để có th ể đọ c và ghi d ữ li ệ u vào các t ậ p tin chúng ta s ẽ ứ ng d ụ ng t ấ t c ả nh ững gì đã học trướ c đây: con trỏ , c ấ u trúc, chu ỗ i ký t ự … M ở.
- và đóng mộ t t ậ p tin: Để đọ c và ghi d ữ li ệ u trong m ộ t t ậ p tin chúng ta s ẽ s ử d ụ ng các hàm (functions) có s ẵn trong thư vi ện “stdio” mà chúng ta đượ c h ọc trướ c gi ờ .
- T ấ t c ả nh ững thư viện (libraries) mà chúng ta đã từ ng s ử d ụ ng cho t ớ i nay (stdlib.h, stdio.h, math.h, string.h.
- Nh ững thư việ n chu ẩ n có s ố lượ ng gi ớ i h ạ n và h ỗ tr ợ cho phép b ạ n th ự c hi ệ n m ộ t s ố điều cơ bả n như chúng ta đã từ ng th ấ y trong nh ững bài trước.
- Chúng ta s ẽ h ọ c v ề chúng sau.
- Okie! Bây gi ờ chúng ta s ẽ xem nh ững thư việ n tuy ệ t v ời đó có thể làm gì, chúng ta có th ể gi ả i quy ế t câu h ỏi làm sao để m ở ho ặc đọ c ho ặ c ghi d ữ li ệ u vào m ộ t t ập tin.
- Chúng ta s ẽ g ọ i m ộ t hàm m ở t ậ p tin , th ứ s ẽ tr ả v ề cho chúng ta m ộ t con tr ỏ đế n t ậ p tin.
- Chúng ta s ẽ ki ể m tra xem thao tác m ở t ậ p tin có thành công không (t ất nhiên là trướ c tiên t ậ p tin đó phả i t ồ n t ạ i) b ằ ng cách ki ể m tra các giá tr ị con tr ỏ mà ta nh ận đượ c.
- NULL, có nghĩa là thao tác mở t ập tin đã thấ t b ại, trong trườ ng h ợ p này chúng ta không th ể ti ế p túc n ữ a (màn hình s ẽ hi ể n th ị thông báo l ỗ i).
- Trong trườ ng h ợ p thao tác m ở t ậ p tin thành công (con tr ỏ không mang giá tr ị NULL), chúng ta có th ể tho ải mái đọ c, ghi d ữ li ệ u lên t ậ p tin thông qua ch ức năng củ a các hàm mà các b ạ n s ắp đượ c h ọ c.
- M ộ t khi b ạn đã làm xong việ c v ớ i các t ậ p tin, h ẳ n là b ạ n ph ải nghĩ tớ i vi ệc đóng nó lại đúng không? Và chúng ta có fclose .
- Đầ u tiên chúng ta s ẽ tìm hi ể u v ề 2 hàm fopen và fclose .
- Sau khi đã nắ m rõ v ấn đề , chúng ta s ẽ b ắt đầ u h ọc cách đọ c n ộ i dung c ủ a m ộ t t ậ p tin và ghi d ữ li ệ u vào nó.
- fopen: hàm m ở m ộ t t ậ p tin: Trong bài h ọ c v ề chu ỗ i ký t ự (string), chúng ta đã biế t cách s ử d ụng “nguyên mẫu hàm” (prototype) như một “hướ ng d ẫ n s ử d ụng” của hàm (function).
- Tuy nhiên tôi th ấ y r ằ ng chúng ta v ẫ n c ầ n gi ả i thích thêm m ộ t s ố th ứ : C code: FILE* fopen(const char * tenTaptin, const char * chedoMotaptin).
- 102 - [email protected] FILE có cái quái gì trong đó nhưng tôi nghĩ dù có chứa gì đi nữa cũng không ảnh hưở ng nhi ề u đế n công vi ệ c c ủ a chúng ta.
- R ồ i b ạ n s ẽ th ấ y nh ững thư việ n chúng ta s ắ p h ọ c sau này cũng sử d ụ ng quy t ắc đặ t tên r ấ t gi ố ng v ớ i tôi, c ụ th ể là khi đặ t tên c ấu trúc thườ ng ch ỉ c ầ n vi ế t hoa ch ữ cái đầ u tiên.
- Quay l ạ i v ớ i hàm fopen c ủ a chúng ta.
- Bây gi ờ chúng ta s ẽ t ạ o m ộ t con tr ỏ c ủa FILE để b ắt đầ u hàm c ủ a b ạ n (VD function main): C code: int main (int argc, char *argv.
- Vì v ậ y, chúng ta s ẽ không bao gi ờ tr ự c ti ếp thay đổ i n ộ i dung c ủa FILE (vd như ta sẽ không s ử d ụ ng taptin.bienthanhphan1 để tác độ ng vào bi ế n thành ph ầ n c ủa FILE).
- Nhưng bằ ng cách s ử d ụ ng các hàm chúng ta có th ể làm vi ệc đượ c v ớ i FILE.
- 103 - [email protected] Nào bây gi ờ chúng ta s ẽ g ọ i hàm fopen và l ấ y giá tr ị nó đã trả v ề trong con tr ỏ taptin .
- Đây là một cách khá đặ c bi ệ t mà chúng ta s ẽ không đề c ậ p ở.
- Dù là ch ế độ nào thì chúng v ẫ n ho ạt độ ng theo m ột cách tương tự nhau như chúng ta thấ y trong bài h ọ c này.
- Hàm fscanf : V ẫ n là m ộ t nguyên t ắ c ho ạt động tương tự v ớ i hàm scanf mà chúng ta đã từ ng h ọ c.
- Nó s ẽ đưa vào mả ng c ủ a chúng ta 3 thành ph ần.
- B ạn có để ý r ằng trước đây tôi chỉ đặ t m ộ t %d trong d ấ u ngo ặ c kép c ủ a hàm scanf thì trong l ầ n này v ớ i hàm fscanf chúng ta có th ể đặ t m ộ t lúc nhi ề u %d nh ậ p giá tr ị .
- Di chuy ể n m ộ t t ậ p tin: Khi nãy, tôi đã nói vớ i b ạ n v ề m ột “dấ u nháy ảo” đúng không? Bây giờ chúng ta s ẽ tìm hi ể u chi ti ết hơn để th ấ y h ế t công d ụ ng c ủ a nó.
- Có 3 hàm chúng ta c ầ n ph ả i bi ế t: ftel: cho bi ế t v ị trí hi ệ n t ạ i c ủ a b ạ n trong t ậ p tin.
- rewind: đưa “dấ u nháy ảo” về v ị trí b ắt đầ u c ủ a t ập tin (tương tự, chúng ta cũng có thể s ử d ụ ng fseek để ch ỉ đị nh v ị trí “dấ u nháy ảo” về v ị trí b ắt đầ u c ủ a t ậ p tin).
- Sau đây là mộ t vài ví d ụ để chúng ta bi ế t cách làm vi ệ c v ớ i nh ữ ng bi ế n vitri_hientai và vitri_hientai.
- VD: bạ n s ắ p x ế p nh ững điể m s ố người chơi ở v ị trí 0, tên c ủa người chơi cu ố i cùng n ằ m ở v ị trí th ứ 50… Sau này chúng ta s ẽ làm vi ệ c v ớ i nh ữ ng t ậ p tin kh ổ ng l ồ , và n ếu như bạ n không có m ộ t quy t ắ c s ắ p x ế p n ộ i dung t ậ p tin riêng c ủ a mình, b ạ n s ẽ không bi ế t ph ả i làm th ế nào để l ấ y nh ữ ng thông tin mà mình c ầ n ở.
- Đổ i tên và xóa t ậ p tin: Chúng ta s ẽ k ế t thúc bài h ọ c k ỳ này v ới 2 hàm đơn giả n.
- Màn hình console s ẽ hi ể n th ị : char: 1 byte int: 4 byte dài: 4 byte Double: 8 byte Tôi đã không kiểm tra tất cả các kiểu biến mà chúng ta đã biết.
- Đơn giản là nó cũng chỉ tạo ra thêm một cái tên mới chứ không có gì nhiều, chỉ vậy thôi! Trước đây khi bộ nhớ máy tính vẫn chưa tốt như bây giờ thì những cái tên khác nhau của kiểu biến thực sự rất hữu dụng cho máy tính của chúng ta.
- Tôi nghĩ rằng đó là các chương trình cho điện thoại di động, robot … Vậy chúng ta có thể biết kích thước của những kiểu biến tùy chỉnh do mình tạo ra (chẳng hạn như đối với “cấu trúc.
- Và bây giờ chúng ta sẽ làm rõ mọi thứ, cuối cùng thì ta cũng có thể biết chính xác kích thước của từng loại biến..
- và sizeof (int) đã chỉ ra rằng chúng ta sẽ mượn 4 byte của máy tính, sau đó biến sẽ chiếm 4 byte này của bộ nhớ.
- Chúng ta cùng xem hình sau để thấy rõ hơn: Bạn thấy rõ ràng ở đây là biến kiểu int chiếm 4 byte trong bộ nhớ..
- 128 - [email protected] Nếu chúng ta làm điều tương tự với một biến kiểu char, biến sẽ chỉ chiếm một byte trong bộ nhớ như hình sau: Hãy thử tưởng tượng chúng ta có một mảng các biến kiểu int.
- Vậy nếu mảng của chúng ta có 100 ô thì sao: C code: int mang[100].
- Vậy chính xác là chúng ta sẽ chiếm 4 x 100 = 400 byte trong bộ nhớ.
- Lần này chúng ta sẽ sử dụng 8 x 100 = 800 byte trong bộ nhớ.
- Nào bây giờ chúng ta sẽ tìm hiểu sâu về nó.
- Tôi sẽ nhắc lại mục tiêu của chúng ta: học cách yêu cầu cấp phát bộ nhớ bằng cách thủ công.
- Chúng ta cần khai báo thư viện < stdlib.h.
- Thư viện này chứa 2 hàm mà chúng ta cần đến.
- hàm sẽ giải phóng vùng nhớ đã được hệ điều hàn h chỉ định cho yêu cầu cấp phát bộ nhớ của chúng ta trước đó, từ lúc này, các chương trình khác có thể tự do sử dụng vùng nhớ đó.
- Nếu chúng ta không làm thao tác này, chương trình của bạn sẽ dễ gặp phải vấn đề tràn bộ nhớ, khi được hoàn tất chương trình của bạn sẽ chiếm một dung lượng bộ nhớ khổng lồ mà trong đó có những vùng nhớ bị sử dụng không cần thiết.
- Nếu các bạn còn nhớ về những gì đã học ở bài học về hàm (function), tôi đã từng nói với bạn void có nghĩa là trả về “không gì cả”, và chúng ta sử dụng kiểu void này để chỉ định hàm này sẽ không trả về giá trị nào hết.
- Vậy ở đây chúng ta có 1 hàm sẽ trả về “con trỏ rỗng” sao? Điều này có ổn không? Xem ra các lập trình viên khá hài hước nhỉ.
- Chúng ta cũng có thể xem nó là một con trỏ linh động..
- Nào chúng ta thực hành thôi..
- 134 - [email protected] Trở lại với đoạn code của chúng ta.
- Tôi không hiểu sao chúng ta phải học cái cách phức tạp này và liệu có cần thiết không? Đúng là có phức tạp hơn một chút … nhưng nó có vô dụng không? Không! Đôi khi chúng ta buộc phải tự mình phân bổ bộ nhớ, tôi sẽ cho bạn thấy một trường hợp ngay sau đây.
- Tới bây giờ chúng ta chỉ sử dụng phương pháp “cấp phát động” để tạo những biến bình thường đơn giản.
- Có phải bạn đang tự hỏi, vậy thì khi nào chúng ta nên dùng phương pháp này? Thường thì người ta sử dụng phương pháp “cấp phát động” khi tạo ra một mảng (array) mà ta không biết trước kích thước của nó khi chạy chương trình là bao nhiêu.
- Lợi ích của “cấp phát động” là ở đó: Chúng ta sẽ hỏi số lượng bạn bè của người dùng trước, và sau đó “cấp phát động” sẽ tạo ra mảng với kích thước chính xác như được yêu cầu (không quá nhỏ mà cũng không quá lớn).
- Nếu người dùng có 15 người bạn, chúng ta sẽ tạo một mảng với 15 giá trị int , tương tự nếu họ có 28 người bạn, nó sẽ tạo ra một mảng với 28 giá trị int.
- Chúng ta sẽ dùng hàm malloc để yêu cầu cấp phát soluongBanbe * sizeof(int) byte trong bộ nhớ: C code: banbe = malloc(soluongBanbe * sizeof(int.
- Cuối cùng, vì chúng ta không còn cần đến mảng tuổi của những người bạn này nữa, ta sẽ giải phóng bộ nhớ bằng hàm free.
- Và … nó đã hoạt động … chúng ta đã lưu trữ ký t ự bí m ậ t t ại đị a ch ỉ con tr ỏ tuDuocChon .
- Chúng ta v ẫn chưa đóng tậ p tin l ạ i, m ộ t giá tr ị tr ả v ề 1 để ng ừ ng hàm l ạ i và cho th ấ y r ằ ng chương trình hoạt độ ng t ố t: C code: fclose(danhmuc).
- s ẽ giúp chương trình củ a b ạ n không ch ọ n trùng các s ố ng ẫ u nhiên, gi ố ng nh ững gì chúng ta đã từ ng làm v ới chương trình “lớn hơn hay nhỏ hơn” trong chương 1.
- 158 - [email protected]

Xem thử không khả dụng, vui lòng xem tại trang nguồn
hoặc xem Tóm tắt