Bài giảng Ngôn ngữ lập C - Vũ Văn Định
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Ngôn ngữ lập C - Vũ Văn Định", để 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:
- bai_giang_ngon_ngu_lap_c_vu_van_dinh.pdf
Nội dung text: Bài giảng Ngôn ngữ lập C - Vũ Văn Định
- NGÔN NGỮ LẬP C Giáo viên Vũ Văn Định Ngôn ngữ lập trình C - Smith.N Studio! 1
- Bài 1: Tổng quan về ngôn ngữ lập trình C Ngôn ngữ C có một số các đặc điểm nổi bật sau : Bộ lệnh phù hợp với phương pháp lập trình cấu trúc. Kiểu dữ liệu phong phú. Một chương trình C bao giờ cũng gồm một hoặc nhiều hàm và các hàm rời nhau. Là ngôn ngữ linh động về cú pháp, chấp nhận nhiều cách thể hiện chương trình . Ngôn ngữ lập trình C - Smith.N Studio! 2
- I. Hướng dẫn sử dụng môi trương kết hợp Turbo C 1. Khởi động C1: Từ DOS [ đường dẫn ]\ TC.EXE C2: Từ Win C -> TC -> BIN -> TC.EXE C3: Start -> Run -> C:\TC\BIN\TC.EXE 2. Mở File Mở file mới : File -> New Mở file đã có: File -> Open 3. Ghi File Save (F2) : Ghi tệp mới đang soạn thảo vào đĩa Save as : Ghi tệp đang soạn thảo vào đĩa theo tên mới hoặc đe lên tệp đã có Ngôn ngữ lập trình C - Smith.N Studio! 3
- Chạy một chương trình F9 : Biên dịch Ctrl F9 : Thực thi chương trình Alt F5 : Xem kết quả Thoát khỏi C Thoát tạm thời về DOS : Dos Shell Thoát hẳn khỏi C: File \ Quit ( Alt + X) Ngôn ngữ lập trình C - Smith.N Studio! 4
- II. Giới thiệu ngôn ngữ lập trình C 1. Các thành phần của NNLT C Tập các ký tự Chữ cái: A Z, a z Chữ số : 0 9 Ký hiệu toán học : + - * / = ( ) Ký tự gạch nối: _ Các ký hiệu đặc biệt khác như : . , ; : [ ] { } ? ! \ & | % # $, Từ khoá Là những từ có một ý nghĩa hoàn toàn xác định Asm, char, do, int, float, for, do, While, Tên Dùng để xác định các đại lượng khác nhau trong một chương trình Bắt đầu bằng chữ cái hoặc gạch nối Độ dài cực đại mặc định là 32 Ngôn ngữ lập trình C - Smith.N Studio! 5
- 2. Các kiểu dữ liệu cơ sở trong C Kiểu số ký tự (char) Kiểu số nguyên (int) Kiểu dấu phẩy động (chính xác đơn (float), chính xác kép (double)) Kiểu void Ngôn ngữ lập trình C - Smith.N Studio! 6
- 2.1 Kiểu ký tự (char) Một giá trị kiểu ký tự (char) chiếm 1 byte trong bộ nhớ và biểu diễn một ký tự thông qua bảng mã ASCII. Ví dụ Ký tự Mã ASCII 0 48 1 49 2 50 A 65 a 97 Ngôn ngữ lập trình C - Smith.N Studio! 7
- Trong ngôn ngữ C cung cấp hai kiểu ký tự (char) là signed char và unsigned char Phạm vi Số ký tự Kích thước signed char -128 127 1 byte unsigned char 0 255 1 byte Ví dụ : char ch, ch1; ch= „a‟ ; ch1= 97; Ngôn ngữ lập trình C - Smith.N Studio! 8
- 2.2 Kiểu số nguyên (int) Kiểu số nguyên trong C gồm các kiểu sau: Kiểu Phạm vi biểu diễn Kích thước int -32768 -> 32767 2 byte Unsigned int 0 -> 65535 2 byte -2147483648 - 4 byte 4 byte Ngôn ngữ lập trình C - Smith.N Studio! 9
- 2.3 Kiểu số thực hay còn gọi là kiểu dấu phẩy động Kiểu Phạm vi biểu diễn Số chữ số Kích có nghĩa thước float 3.4-38E -> 3.4E+38 7-8 4 byte double 1.7E-308 -> 1.7E+308 15-16 8 byte laong 3.4E-4932 -> 1.1E+4932 17-18 10 byte double Ngôn ngữ lập trình C - Smith.N Studio! 10
- 3 Hằng và biến 3.1 Hằng: Khái niệm: hằng là giá trị bất biến trong chương trình không thay đổi, không biến đổi về mặt giá trị. Các loại hằng được sử dụng trong C tương ứng với các kiểu dữ liệu nhất định Trong C có ba loại hằng : Hằng số Hằng chuỗi Hằng ký tự Ngôn ngữ lập trình C - Smith.N Studio! 11
- Hằng số: là các giá trị số đã xác định, có thể là kiểu nguyên hay kiểu thực Hằng nguyên: Giá trị chỉ bao gồm các chữ số, dấu +, - được lưu trữ theo kiểu int. Ví dụ: 12,-12 Nếu giá trị vượt quá miền giá trị của int hoặc có ký tự l (hay L ) theo sau giá trị thì lưu theo kiểu long int. Ví dụ: 43L hoặc 43l là hằng nguyên lưu theo kiểu long int. Hằng thực: Trong giá trị có dấu chấm thập phân, hoặc ghi dưới dạng số có mũ, và được lưu theo kiểu float, double, long double. Ví dụ: 1.2 , 2.1E -3 (2.1E- 3=0.0021) hoặc 3.1e-2 (3.1e-2=0.031). Ngôn ngữ lập trình C - Smith.N Studio! 12
- Hằng ký tự Một hằng kiểu ký tự được viết trong dấu ngoặc đơn (' ) như 'A' hoặc 'z'. Hằng ký tự 'A' thực sự đồng nghĩa với giá trị nguyên 65, là giá trị trong bảng mã ASCII của chữ hoa 'A' (Như vậy giá trị của hằng chính là mã ASCII của nó). Ðối với một vài hằng ký tự đặc biệt, ta cần sử dụng cách viết thêm dấu \ , như '\t' tương ứng với phím tab: Hằng ký tự có thể tham gia vào phép toán như mọi số nguyên khác: VD: '8' - '1'= 56-49=7. Ngôn ngữ lập trình C - Smith.N Studio! 13
- Cách viết Ký tự „\n‟ Xuống hàng „\t‟ Tab „\o‟ “nul” tương ứng với giá trị nguyên 0 trong bảng mã ASCII „\b‟ Backspacse „\r‟ Về đầu dòng „\f‟ Sang trái „\\‟ \ „ \” ‟ ” „ \‟ ‟ ‟ Ngôn ngữ lập trình C - Smith.N Studio! 14
- Hằng chuỗi Là chuỗi ký tự nằm trong cặp dấu nháy kép " ". Các ký tự này cũng có thể là các ký tự được biểu diễn bằng chuỗi thoát. Ví dụ: "Turbo C", "Ngôn ngữ C++ \n\r" Một hằng chuỗi được lưu trữ tận cùng bằng một ký tự Nul (\0), ví dụ chuỗi "Turbo C" được lưu trữ trong bộ nhớ như sau: T u r b o C \0 Ngôn ngữ lập trình C - Smith.N Studio! 15
- Cách định nghĩa hằng sử dụng trong chương trình Với các giá trị hằng thường được dùng trong một chương trình ta nên định nghĩa ở đầu chương trình (sau các dòng khai báo những thư viện chuẩn) theo cú pháp: #define Ví dụ: #define PI 3.1415 Ngôn ngữ lập trình C - Smith.N Studio! 16
- 3.2 Biến - Cách khai báo: Mỗi biến trong chương trình đều phải được khai báo trước khi sử dụng với cú pháp khai: Kiểu dữ liệu ; Lưu ý: nếu có nhiều tên biến thì giữa các tên biến phải có dấu , để ngăn cách Ví dụ: int a,b; float x; - Khởi đầu cho các biến Ngay trên dòng khai báo ta có thể gán cho biến một giá trị. Việc làm này gọi là khởi đầu cho biến. Ví dụ: int a,b=6,d=1; Ngôn ngữ lập trình C - Smith.N Studio! 17
- Cách truy xuất đến địa chỉ của biến Một số hàm của C dùng đến địa chỉ của biến ví dụ như hàm scanf. Ðể nhận địa chỉ của biến dùng toán tử: & Ví dụ: &tên_biến - &a : địa chỉ của biến a Ngôn ngữ lập trình C - Smith.N Studio! 18
- 3.3 Cấu trúc tổng quát của chương trình C Một chương trình C chuẩn gồm có các thành phần sau: 1. Các chỉ thị tiền biên dịch 2. Khai báo các kiểu dữ liệu mới 3. Khai báo hằng, khai báo biến 4. Khai báo hàm 5. Chương trình chính Ngôn ngữ lập trình C - Smith.N Studio! 19
- 1. Chỉ thị tiền biên dịch: giúp trình biên dịch thực hiện một số công việc trước khi thực hiện một số công việc trước khi thực hiện biên dịch chính thức VD: #include ; #include ; 2. Khai báo kiểu dữ liệu mới: dung từ khoá typedef. VD: typedef int songuyen; typedef float mang[10]; 3. Khai báo hằng và biến: khai báo các hằng số và biến dùng trong chương trình 4. Khai báo hàm: khai báo các hàm tự viết 5. Chương trình chính: hàm main là hàm bắt buộc trong chương trình. Hàm main có thể trả về giá trị kiểu nguyên (int) hoặc không trả về giá trị nào (void) Ngôn ngữ lập trình C - Smith.N Studio! 20
- /* Chương trình in ra dòng chữ Trung tâm đào tạo Trí Đức trên màn hình */ # include void main () /* Ham chinh */ { printf(" \n Trung tâm đào tạo Trí Đức "); /*xuong dong in chu Trung tâm đào tạo Trí Đức */ } Ngôn ngữ lập trình C - Smith.N Studio! 21
- * Chương trình tính chu vi và diện tích hình tròn, biết bán kính r là một hằng số có giá trị =3.1 */ # include /* khai báo thư viện hàm nhập xuất chuẩn */ # include /* khai báo thư viện hàm toán học */ #define r 3.1 void main () { float cv,dt; /* khai bao bien chu vi va dien tich kieu so thuc */ cv=2*r*M_PI; /* tinh chu vi */ dt=M_PI*r*r; /* Tinh dien tich */ printf("\nChu vi = %10.2f\nDien tich = %10.2f",cv,dt); /* In ket qua len man hinh */ getch(); /* Tam dung chuong trinh */ } Ngôn ngữ lập trình C - Smith.N Studio! 22
- *Chương trình này minh họa cách vừa khai báo, vừa khởi đầu một biến trong C */ #include void main() { char ki_tu = 'a'; /* Khai báo/khởi đầu kí tự. */ int so_nguyen = 15; /* Khai báo khởi đầu số nguyên */ float so_thuc = 27.62; /* Khai báo/khởi đầu số thực/ printf("%c la mot ki tu.\n",ki_tu); printf("%d la mot so nguyen.\n",so_nguyen); printf("%f la mot so thuc.\n",so_thuc); } Ngôn ngữ lập trình C - Smith.N Studio! 23
- Bài 2: Biểu thức và các phép toán I. Biểu thức Là sự kết hợp 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 đó. Biểu thức trong C gồm có biểu thức toán học và biểu thức logic Biểu thức toán học bao gồm các phép toán số học và các hằng, các biến, các hàm Biểu thức logic bao gồm các biến, hằng, hàm và phép toán logic (!: phép phủ định, &&: phép và, || : phép hoặc) Ngôn ngữ lập trình C - Smith.N Studio! 24
- II. Các phép toán Phép toán số học Phép toán Ý nghĩa + Cộng - Trừ * Nhân / Chia % Lấy phần dư Chú ý: -Phép toán chia 2 số nguyên sẽ chặt cụt phần thập phân. -Phép toán lấy phần dư không áp dụng cho các giá trị float và double Ngôn ngữ lập trình C - Smith.N Studio! 25
- II. Các phép toán Phép toán quan hệ Phép toán Ý nghĩa Ví dụ > Có lớn hơn không? a>b >= Có lớn hơn hay bằng không? a>=b < Có nhỏ hơn không? a<b <= Có nhỏ hơn hay bằng không? a<=b == Có bằng hay không? a==b != Có khác nhau không? a!=b Các phép toán quan hệ có độ ưu tiên thấp hơn so với các phép toán số học Ngôn ngữ lập trình C - Smith.N Studio! 26
- II. Các phép toán Phép toán logic Phép phủ định ! Phép và (AND) && Phép hoặc (OR) || Các phép toán quan hệ có độ ưu tiên nhỏ hơn so với ! nhưng lớn hơn so với phép && và || Ngôn ngữ lập trình C - Smith.N Studio! 27
- Câu lệnh gán và biểu thức Cú pháp của lệnh gán: = ; VD: x = -10; m = y + 2 – m; Trong C cho phép người sử dụng được gộp lệnh gán theo cú pháp : a = b = c = 7; Ngôn ngữ lập trình C - Smith.N Studio! 28
- Phép toán tăng giảm Toán tử + + : dùng để tăng giá trị của các biến nguyên hay biến thực Toán tử - - dùng để giảm giá trị của biến nguyên hay biến thực Toán tử + + và đều có thể đứng trước hoặc sau toán hạng VD: + + n ; n+ +; m ; m ; Khi các toán tử + +, đứng trước toán hạng thì giá trị của toán hạng được tăng hoặc giảm trước khi sử dụng và ngược lại nếu toán tử ++, đứng sau toán hạng thì toán hạng được tăng hay giảm sau khi thực hiện Ngôn ngữ lập trình C - Smith.N Studio! 29
- Chuyển đổi kiểu giá trị Việc chuyển đổi kiểu giá trị trong C thường diễn ra tự động trong trường hợp sau: Trong biểu thức có các toán hạng khác kiểu Khi gán một giá trị kiểu này cho một giá trị kiểu khác Ngoài ra ta có thể dùng phép chuyển kiểu để ép kiểu dữ liệu sang kiểu khác (type) biểu_thức Chú ý: - Khi chuyển đổi kiểu tỏng biểu thức thì đối với toán hạng có kiểu thấp hơn sẽ được nâng thành kiểu cao hơn trược khi htực hiện phép toán và kết quả thu được sẽ có kết quả theo kiểu cao hơn Ngôn ngữ lập trình C - Smith.N Studio! 30
- Kiểu int và kiểu long thì int > long int và float thì int > float Float và double thì float > double Kiểu int có thể chuyển thành float và ngược lại Ngôn ngữ lập trình C - Smith.N Studio! 31
- Bài 3 Các hàm vào ra dữ liệu I. Hàm xuất nhập chuẩn trong thư viện Hàm đưa kết quả ra màn hình Cú pháp: printf( , bt1, bt2, btk); Ý nghĩa: bt1, btk : là k biểu thức cần in kết quả ra màn hình là một hằng xâu ký tự bao gồm 3 loại: - Ký tự diều khiển việc xuống dòng tiếp theo „\n‟ - Ký tự hiển thị: là ký tự được in ra màn hình - Ký tự mô tả cách đưa ra màn hình của các biến(đặc tả của kiểu). Mỗi biểu thức có đặc tả tương ứng Ngôn ngữ lập trình C - Smith.N Studio! 32
- Đặc tả kiểu nguyên đối với biểu thức có giá trị kiểu số nguyên %[n]d . Trong đó n là số nguyên xác định độ rộng tối thiểu dành cho giá trị biểu thức in ra màn hình Đặc tả kiểu số thực %[n][.m]f. Trong đó m là số chữ số sau dấu phẩy, n là một số nguyên xác định độ rộng tối thiểu trên màn hình cho giá trị của biểu thức: VD: Ngôn ngữ lập trình C - Smith.N Studio! 33
- %c : in một ký tự có mã ASCII tương ứng %[n]d : in một số nguyên với chiều dài tối thiểu là n %[n]ld: in một số nguyên (long int) %[n.m]f : in một số thực vối chiều dài n và lấy m số thập phân %s : in ra chuỗi ký tự Ngôn ngữ lập trình C - Smith.N Studio! 34
- Hàm hiển thị một xâu ký tự ra màn hình Cú pháp: int puts(char *s); Ý nghĩa: Hiển thị một xâu ký tự s lên màn hình, sau khi in xong thì con trỏ sẽ được chuyển xuống dòng. Trong đó s là con trỏ kiểu char trỏ tới vùng chứa xâu ký tự Hàm đưa một ký tự ra màn hình Cú pháp: int putchar(int ch); Ý nghĩa: Hàm sẽ ký tự ch ra màn hình với ch là mã của lý tự cần in Ngôn ngữ lập trình C - Smith.N Studio! 35
- Hàm nhận dữ liệu từ bàn phím Cú pháp: scanf(“dt1dt2 dtk”, &biến1, &biếnk); Ý nghĩa: dt1, dtk là một hằng xâu ký tự đặc tả của k biến &biến1, &biếnk: là địa chỉcủa biến trong bộ nhớ Hàm nhận từ bàn phím một xâu ký tự Cú pháp: int *getchar(char *s); Ý nghĩa: Hàm nhận dãy ký tự từ bàn phím vào cho đến khi gặp ký tự „\n‟ thì dừng lại s là con trỏ trỏ tới vùng nhớ sẽ chứa xâu vừa nhận Ngôn ngữ lập trình C - Smith.N Studio! 36
- Hàm nhận một ký tự từ bàn phím Cú pháp: getchar(void); Ý nghĩa: nhận ký tự được nhập từ bàn phím Ngôn ngữ lập trình C - Smith.N Studio! 37
- II. Hàm xuất nhập chuẩn trong thư viện Hàm getch() và getche Cú pháp : int getch( void ) int getche( void ) - Hai hàm trên chờ nhận một ký tự trực tiếp từ bộ đệm bàn phím. Nếu bộ đệm rỗng thì chờ. Khi một phím được ấn thì nhận ngay ký tự đó mà không cần phải enter như các hàm nhập từ stdio.h - Hàm getche() cho hiện ký tự lên màn hình còn getch() thì không - Kết quả trả về của hàm là ký tự được ấn trên bàn phím. Ngôn ngữ lập trình C - Smith.N Studio! 38
- Xuất ký tự có màu Cú pháp : cprintf Ý nghĩa: in ra ký tự có màu được ấn định bởi hàm textcolor. Nhập ký tự có màu Cú pháp: cscanf Ý nghĩa: + Nội dung nhập có màu được ấn định bởi hàm textcolor + Nhận nội dung trực tiếp từ bộ đệm bàn phím. Vì vậy với hàm cscanf ta cũng phải khử ký tự \n trong bộ đệm bằng %*c hoặc bằng hàm getch() Ngôn ngữ lập trình C - Smith.N Studio! 39
- III.Một số hàm thao tác trên màn hình Hàm xóa màn hình: clrscr(); Có tác dụng xóa toàn bộ m àn hình và sau khi xóa con trỏ sẽ ở vị trí góc phía bên trái. Hàm đặt tọa độ con trỏ: gotoxy(int x, int y); Đặt con trỏ tại vị trí x, y Hàm đặt mầu nền textbackground void textbackground(int color); Đặt mầu nền Color là một biểu thức nguyên có giá trị từ 0 đến 7 tương ứng với một trong 8 hằng số màu đầu tiên của bảng mầu văn bản. Ngôn ngữ lập trình C - Smith.N Studio! 40
- Hàm đặt mầu chữ textcolor void textcolor(int newColor); Lựa chọn màu ký tự mới newColor.Trong đó newColor là một biểu thức nguyên có giá trị từ 0 đến 15 tương ứng với một trong các hằng số màu của bảng mầu văn bản. Ngôn ngữ lập trình C - Smith.N Studio! 41
- Bài 4: Cấu trúc điều khiển Câu lệnh, khối lệnh Câu lệnh: mỗi câu lệnh thực hiện một công việc và được kết thúc bởi dấu ; Khối lệnh: là tập hợp các câu lệnh bắt đầu bằng dấu “{“ và kết thúc bằng dấu “}” Ngôn ngữ lập trình C - Smith.N Studio! 42
- I. Cấu trúc điều khiển if 1. Cấu trúc if dạng 1 Cú pháp: if (bt) s ; Ý nghĩa: bt là biểu thức lôgic, s là lệnh đơn hoặc lệnh phức. nếu bt nhân giá trị true thì thực hiện s, ngược lại s được bỏ qua 2. Cấu trúc if dạng 2 Cú pháp: if(bt) s; else s1 ; Ý nghĩa: bt là biểu thức lôgic, nếu bt nhận giá trị true thì thực hiện s bỏ qua s1, ngược lại nếu bt nhận giá trị flase thì thực hiện s1 bỏ qua s(s và s1 có thể là lệnh đơn hoặc lệnh phức) Ngôn ngữ lập trình C - Smith.N Studio! 43
- Chú ý : trong C cho phép sử dụng các cấu trúc if lồng nhau để giải quyết bài toán 3. Bài tập - Nhập 2 số thực a, b từ bàn phím. Tìm và in ra màn hình số lớn nhất và số bé nhất - Giải hệ phương trình bậc nhất hai ẩn số ax + by = c dx + ey = f Ngôn ngữ lập trình C - Smith.N Studio! 44
- II. Cấu trúc rẽ nhánh switch 1. Cấu trúc tổng quát Cú pháp: switch (bt) { case n1 : s1 case n2 : s2 case nk : sk [default : s(k+1 )] } Ngôn ngữ lập trình C - Smith.N Studio! 45
- Ý nghĩa: Bt: là biểu thức toán học có giá trị kiểu nguyên Ni(i=1 k): là các số kiểu nguyên, kiểu hằng ký tự, hoặc biểu thức Si(i=1 k): là các lệnh đơn hoặc lệnh phức [default : s(k+1 )] : là phần tuỳ chọn có thể có hoặc không Ngôn ngữ lập trình C - Smith.N Studio! 46
- Hoạt động: lệnh switch phụ thuộc vào giá trị của biểu thức bt viết sau switch, nếu: Giá trị bt = ni thì thực hiện câu lệnh sau case ni; Khi giá trị biểu thức khác tất cả các ni thì thực hiện câu lệnh sau default nếu có, hoặc thoát khỏi câu lệnh switch. Khi chương trình đã thực hiện xong câu lệnh của case ni nào đó thì nó sẽ thực hiện luôn các lệnh thuộc case bên dưới nó mà không xét lại điều kiện ( do các ni còn được xem như các nhãn). Vì vậy, để chương trình thoát khỏi lệnh switch sau khi thực hiện xong một trường hợp, ta dùng lệnh break. Ngôn ngữ lập trình C - Smith.N Studio! 47
- 3. Bài tập - Viết chương trình nhập vào từ bàn phím một mã số nguyên và đưa ra đánh gía trình độ theo yêu cầu: 1: trình độ sơ cấp 2 : trình độ trung cấp 3: trình độ Đại học 4: trình độ Cao học 5: trình độ Tiến sỹ Các số khác: Không xác định - Cho một số tự nhiên, in ra màn hình tên gọi của số lên màn hình(Bài số 12) Ngôn ngữ lập trình C - Smith.N Studio! 48
- III. Câu lệnh lặp for 1. Cú pháp: for( ; ; ) S ; Ý nghĩa: S là lệnh đơn hoặc lệnh phức bt1 : thường là một lệnh gán khởi tạo cho biến điều khiển bt2: là biểu thức logic, giá trị của biểu thức lôgic này quyết định vòng lặp tiếp tục hay kết thúc bt3: thường là lệnh gán có tác dụng làm thay đổi giá trị của biến điều khiển Ngôn ngữ lập trình C - Smith.N Studio! 49
- Hoạt động: Bước 1: Thực hiện bt1 Bước 2: Tính toán, xác định giá trị của bt2 Bước 3: Nếu bt2 có giá trị false thì thoát khỏi vòng lặp. Ngược lại bt2 có giá trị true thì s được thực hiện Bước 4: sau khi thực hiện s thực hiện bt3 và quay lại bước 2 Nhận xét: chỉ được thực hiện duy nhất một lần khi bắt đầu vòng lặp , và S có thể được tính toán và thực hiện lặp nhiều lần Ngôn ngữ lập trình C - Smith.N Studio! 50
- Chú ý khi sử dụng vòng lặp for , , đều có thể vắng mặt nhưng vẫn phải giữ lại dấu ( ; ) Trường hợp đặc biệt không có thì luôn được xem là nhận giá trị true, muốn thoát khỏi vòng lặp phải dùng lệnh break, goto hoặc return Có thể dùng cấu trúc các vòng for lồng nhau Khi gặp lệnh break thì chương trình sẽ thoát khỏi vòng for sâu nhất còn chứa lệnh break Trong vòng for có thể sử dụng lệnh continue để chuyển tới chu trình mới của vòng lặp Ngôn ngữ lập trình C - Smith.N Studio! 51
- 2. Bài tập Viết chương trình tính tổng của n số đầu tiên của dãy số sau: S = 1+1/2+1/3+1/4+ +1/n. Viết chương trình tìm tất cả các số nguyên có ba chữ số sao cho tổng tam thừa của ba chữ số hàng trăm, hàng chục, hàng đơn vị sẽ bằng số nguyên đó. Ví dụ: 13+53+33=153 Ngôn ngữ lập trình C - Smith.N Studio! 52
- IV. Câu lệnh while 1. Cú pháp : While (bt) S; Ý nghĩa: bt là biểu thức lôgic, S là một lệnh hoặc một dãy lệnh Hoạt động - Xác định giá trị của bt. Nếu giá trị của bt= true(<>0) thì chuyển sang bước 2, ngược lại thì thoát khỏi vòng lặp - Thực hiện S sau đó quay về bước 1(Lệnh S có thể được thực hiện nhiều lần hoặc không được thực hiện lần nào nếu bt =false ngay từ đầu) Ngôn ngữ lập trình C - Smith.N Studio! 53
- Chú ý : trong câu lệnh lặp while ta có thể dùng câu lệnh break để thoát khỏi vòng lặp theo ý muốn 2. Bài tập : - Nhập hai số nguyên từ bàn phím, tìm và in ra màn hình ước số chung lơn nhất của hai số - Tìm hình chữ nhật có diện tích lớn nhất khi biết chu vi của nó(bài số 25) Ngôn ngữ lập trình C - Smith.N Studio! 54
- V. Câu lệnh do while 1. Cú pháp do S while (bt); Ý nghĩa: S là một câu lệnh đơn hoặc phức, bt là biểu thức lôgic Hoạt động: - (1) Thực hiện lệnh S - (2) Xác định giá trị của bt. Nếu giá trị của bt = true thì chuyển sang bước (1), ngược lại thì thoát khỏi vòng lặp - Lệnh S luôn được thực hiện ít nhất 1 lần trong câu lệnh Ngôn ngữ lập trình C - Smith.N Studio! 55
- Bài 5: Dữ liệu kiểu mảng 1. Khái niệm: Mảng được hiểu là một tập hợp các giá trị có cùng kiểu dữ liệu nằm liên tiếp nhau trong bộ nhớ máy tính Mảng được coi như một biến mảng và tên mảng được đặt theo quy tắc đặt tên biến Mảng có những thành phần sau: Kiểu dữ liệu của các phần tử trong mảng Tên mảng Số chiều và kích thước của mỗi chiều Ngôn ngữ lập trình C - Smith.N Studio! 56
- 2. Cách khai báo biến mảng VD: int A[10]; //mảng 1 chiều A gồm 10 phần tử kiểu số nguyên float B[2] [3]; // Mảng 2 chiều B gồm 2 hàng và 3 cột, các phần tử có kiểu số thực Ngôn ngữ lập trình C - Smith.N Studio! 57
- 3. Cách tổ chức và truy xuất đến phần tử mảng Phần tử của mảng được xác định thông qua chỉ số. Chỉ số của phần tử trong mảng luôn là một số nguyên không vượt qua kích thước của mảng Các phần tử của mảng được sắp xếp liền nhau trong bộ nhớ của máy tính và chỉ cho phép truy cập đến địa chỉ trực tiếp của phần tử đối với mảng một chiều. Cách truy cập theo địa chỉ &tên_biến[i] trong đó i là chỉ số của phần tử VD: a= &a[0] //Tên mảng chỉ tới địa chỉ phần tử đầu tiên của mảng Ngôn ngữ lập trình C - Smith.N Studio! 58
- 4. Cách xuất nhập dữ liệu trên mảng - Nhập xuất trực tiếp ứng dụng cho mảng một chiều và mảng hai chiều có phần tử kiểu int thông qua địa chỉ - Nhập dữ liệu cho mảng for( i=0;i<5;i++) { printf(“Phan tu thu %d= ”,i); scanf(“%d”, &a[i]); } - In các phần tử của mảng ra màn hình for(i=0;i<n;i++) printf(“%6d”,a[i]) Ngôn ngữ lập trình C - Smith.N Studio! 59
- - Nhập xuất dữ liệu gián tiếp thông qua một biến trung gian đối với mảng một chiều và mảng đa chiều for(i=0;i<2;i++) for(j=0;j<3;j++) { printf(“a[%d,%d]”, i, j); scantf(“%f”,&temp); a[i] [j] = temp; } - Bài tập - Nhập vào từ bàn phím n số nguyên, tìm và in ra màn hình số nguyên lớn nhất và số nguyên nhỏ nhất - Nhập ma trận các số thực kích thước n hàng và m cột. Tìm và in ra số thực lớn nhất trong ma trận Ngôn ngữ lập trình C - Smith.N Studio! 60
- Bài 6: Con trỏ 1. Khái niệm con trỏ và địa chỉ - Địa chỉ: Dựa vào kiểu dữ liệu khi khai báo biến máy sẽ cấp phát cho biến một địa chỉ để lưu trữ biến đó trên vùng nhớ. Mỗi biến có kiểu khác nhau thì được lưu vào các địa chỉ khác nhau - Con trỏ là một biến dùng để chứa địa chỉ. Mỗi loại địa chỉ thì có loại con trỏ tương ứng. Trước khi sử dụng biến con trỏ ta phải khai báo trước khi sử dụng - Khai báo: * ; - VD1: int x, y, *p, *c; x, y là hai biến kiểu nguyên, p, c là hai biến con trỏ kiểu nguyên Ngôn ngữ lập trình C - Smith.N Studio! 61
- VD2: float *t, *d ; //Khai báo biến con trỏ t và d có kiểu thực Biến con trỏ được dùng theo hai trường hợp sau: Tên con trỏ chỉ đến địa chỉ của biến được lưu trong con trỏ: float a,*p,*q; p=&a; /* lưu địa chỉ của biến a vào con trỏ p */ q= p; /* lưu địa chỉ trong p vào con trỏ q*/ Ngôn ngữ lập trình C - Smith.N Studio! 62
- Dạng khai báo của con trỏ chỉ đến giá trị lưu tại vùng nhớ mà con trỏ trỏ tới. VD: float x=5, y , z=20, *px, *pz;,*py; px=& x; /* khi đó *px = x =5*/ pz=&z; /* *pz=z=20*/ khi đó ba biểu thức sau là tương đương: y=3*x+z; *py=3*x+z; *py=3*(*px)+*pz; Ngôn ngữ lập trình C - Smith.N Studio! 63
- 2. Con trỏ và mảng một chiều Các phần tử của mảng có thể được xác định thông qua con trỏ. Ta có khai báo : float a[10]; //Khai báo mảng gồm 10 phần tử kiểu thực Ta có tên mảng chính là một hằng địa chỉ trỏ tới địa chỉ phần tử đầu tiên của mảng và a tương đương với &a[0] a+i tương đương với &a[i] *(a+i) tương đương với a[i] pa - i pa +i Vậy pa a[k-1] a[k] a[k+1] Ngôn ngữ lập trình C - Smith.N Studio! 64
- Các cách viết a[i], *(a+i), *(p+i), p[i] là tương đương nhau VD: Nhập từ bàn phím các phần tử của mảng và tính tổng các phần tử đó Ngôn ngữ lập trình C - Smith.N Studio! 65
- #include #include void main() { float a[5], s ; int i; for(i=0;i<5;i++) { printf(“\na[%d]= ”,i); scanf(“%f”,&a[i]); } s=0; for (i=0;i<5;i++) s+=a[i]; printf(“\n Tong =%8.2f”,s); getch(); } Ví dụ: Tro1 Ngôn ngữ lập trình C - Smith.N Studio! 66
- 3. Con trỏ với mảng nhiều chiều Phép toán lấy địa chỉ nói chung không dùng được đối với các thành phần của mảng nhiều chiều (trừ trường hợp mảng hai chiều các số nguyên). Ðể tính toán địa chỉ của thành phần a[i][j] chúng ta sử dụng công thức sau : (float *)a+i*n+j. a là một hằng con trỏ trỏ đến các dòng của một ma trân hai chiều, vì vậy a trỏ đến dòng thứ nhất a+1 trỏ đến dòng thứ hai a+2 trỏ đến dòng thứ ba Ngôn ngữ lập trình C - Smith.N Studio! 67
- Ðể tính toán được địa chỉ của phần tử ở dòng i cột j chúng ta phải dùng phép chuyển đổi kiểu bắt buộc đối với a: (float * )a a là con trỏ trỏ đến thành phần a[0][0] của ma trận. a[i][j] sẽ có địa chỉ là (float *a) +i*n+j Xét VD nhập giá trị của ma trận hai chiều: Tro2 Ngôn ngữ lập trình C - Smith.N Studio! 68
- #include #include void main() { float a[10][20]; int i,j,n; printf("Nhap vao kich thuoc ma tran n="); scanf("%n",&n); for(i=0;i<n;i++) for(j=0;j<n;j++) { printf("a[%d][%d] = ",i,j); scanf("%f",(float *)a+i*20+j); } getch(); } Ngôn ngữ lập trình C - Smith.N Studio! 69
- 4. Phép toán trên con trỏ - Phép gán: chỉ nên thực hiện trên các con trỏ có cùng kiểu, khi thực hiện trên con trỏ phải thực hiện phép ép kiểu: Vd: int x; char *p; p=(char*)(&x); - Phép tăng giảm địa chỉ VD: float x[30], *px; px=&x[10];// p là con trỏ thực trỏ tới phần tử x[10] px+i trỏ tới phần tử x[10+i] px – i trỏ tới phần tử x[10-i] Ngôn ngữ lập trình C - Smith.N Studio! 70
- - Phép so sánh: dùng so sánh các con trỏ cùng kiểu, giả sử p1 và p2 là hai con trỏ kiểu float thì tồn tại phép so sánh p1 < p2 // địa chỉ p1 trỏ tới thấp hơn địa chỉ p2 trỏ tới p1==p2 5. Con trỏ kiểu void Là con trỏ đặc biệt không có kiểu, nó có thể nhận bất kỳ địa chỉ nào. Con trỏ kiểu void thường dùng làm đối để nhận bất kỳ địa chỉ nào thông qua phép ép kiểu trong thân hàm Các phép toán tăng giảm địa chỉ, so sánh không dùng được con trỏ kiểu void Ngôn ngữ lập trình C - Smith.N Studio! 71
- 6. Mảng con trỏ Mảng con trỏ là một mảng mà mỗi phẩn tử của nó có thể chứa một địa chỉ nào đó. Mảng con trỏ có nhiều kiểu, mỗi phẩn tử của mảng kiểu nào thì sẽ chứa địa chỉ kiểu tương ứng với nó. Mảng con trỏ được khai báo theo mẫu sau: * [N] Khi gặp khai báo mảng con trỏ thì máy sẽ cấp phát N khoảng nhớ liên tiếp cho N phần tử tương ứng trong mảng Chú ý: Mảng con trỏ không dùng để lưu số liệu, trước khi sử dụng mảng con trỏ cần gán cho mỗi phần tử một giá trị là địa chỉ của một biến hoặc của một phần tử trong mảng Ngôn ngữ lập trình C - Smith.N Studio! 72
- Bài 7: Hàm và chương trình 1. Khái niệm Chương trình: Một chương trình C bao gồm một hoặc nhiều hàm. Hàm main() là thành phần bắt buộc của chương trình. Chương trình bắt đầu thực hiện từ câu lệnh đầu tiên của hàm main( ) cho đến khi gặp dấu } cuối cùng của hàm này. Hàm: Là một đoạn chương trình độc lập thực hiện trọn vẹn một công việc rồi trả về một giá trị cho chương trình đã gọi nó. Đặc điểm của hàm: Là một đơn vị độc lập của chương trình. Không cho phép xây dựng một hàm bên trong một hàm khác. Ngôn ngữ lập trình C - Smith.N Studio! 73
- Ngôn ngữ lập trình C - Smith.N Studio! 74
- 2. Quy tắc xây dựng hàm: Một hàm gồm có các thành phần sau - Nguyên mẫu của hàm: Bao gồm ; Có thể có hoặc không khai báo nguyên mẫu của hàm, khi không khai báo nguyên mẫu thì bộ biên dịch sẽ kiểm tra việc truyền tham số, giá trị trả về có phù hợp hay không rồi mới cho thực hiện hàm. Tất cả nguyên mẫu của các hàm có trong chương trình nên đặt trước hàm main(). Ngôn ngữ lập trình C - Smith.N Studio! 75
- Kiểu giá trị của hàm Giá trị trả về của hàm được xác định dựa vào mục đích của hàm. Nếu các hàm không trả về giá trị ta phải khai báo kiểu void. Tên hàm Ðặt theo qui định đối với danh định. Tên hàm trong nguyên mẫu và khi khai báo phải giống nhau. Tham số của hàm Khi viết một hàm ta phải xác định xem hàm có bao nhiêu tham số ? Nội dung của hàm Ngôn ngữ lập trình C - Smith.N Studio! 76
- Cấu trúc của một hàm ( ) { ; ; [return ]; }; Chú ý: - Đối với các hàm không có kiểu trả về ta có hàm kiểu void - Hàm không có đối thì dùng kiểu void để khai báo đối. VD void bell(void) { int i; for(i=0;i<10;i++) putch(7); } Ngôn ngữ lập trình C - Smith.N Studio! 77
- Cách sử dụng hàm: Hàm được sử dụng thông qua lời gọi hàm. ([ds tham số thực]) - Tham số thực phải bằng tham số hình thức - Kiểu của tham số thực phải phù hợp với kiểu của tham số hình thức Hoạt động của hàm khi có lời gọi hàm Cấp phát bộ nhớ cho tham số hình thức và biến cục bộ Gán giá trị của tham số thực cho tham số hình thức Thực hiện các lệnh trong thân hàm Khi gặp câu lệnh return hoặc dấu hiệu kết thúc hàm thì bộ nhớ sẽ xoá các tham số hình thức và biến cục bộ sau đó thoát khỏi hàm quay về chương trình gọi hàm Ngôn ngữ lập trình C - Smith.N Studio! 78
- 3. Các tham số trong hàm 3.1 Phân loại tham số theo cách sử dụng o Tham số hình thức: Các tham số mà ta ghi trong nguyên mẫu hay ghi lúc khai báo hàm gọi là tham số hình thức. o Tham số thực:Các giá trị, biến mà ta ghi sau tên hàm khi gọi hàm đó để thực hiện gọi là tham số thực. Trong C, các tham số thực lại chia ra làm hai loại: Tham chiếu: Là các tham số thực mà ta truyền cho Hàm dưới dạng con trỏ (dạng địa chỉ). Tham chiếu mới ghi nhận lại được những kết quả vừa tính toán trong Hàm khi Hàm kết thúc. Tham trị : Là các tham số thực mà ta truyền cho Hàm dưới dạng biến. Tham trị không bảo lưu lại những kết quả thay đổi của nó được tính toán trong Hàm khi Hàm kết thúc. Ngôn ngữ lập trình C - Smith.N Studio! 79
- 3.2 Phân loại theo công dụng Tham số của một hàm có hai công dụng: Cung cấp các giá trị cho hàm khi ta gọi nó thực hiện . Lưu các kết quả tính toán được trong quá trình hàm hoạt động Tương ứng với công dụng ta có các loại tham số: Tham số vào: Cung cấp giá trị cho hàm. Tham số ra: Lưu kết quả tính toán được trong hàm. Tham số vừa vào, vừa ra: vừa cung cấp giá trị cho hàm, vừa lưu kết quả tính toán được trong hàm. Ngôn ngữ lập trình C - Smith.N Studio! 80
- 4. Hàm có đối con trỏ Đối số của hàm là con trỏ kiểu int (float,double,. ) thì tham số thực tương ứng phải là địa chỉ của biến kiểu int (float,double,.). Khi đó địa chỉ của biến được truyền cho đối con trỏ tương ứng. Khi muốn bảo lưu lại kết quả tính toán được của các đối số trong hàm để sử dụng cho chương trình gọi hàm có đối số thì chúng ta phải khai báo đối số của hàm là tham chiếu (con trỏ hay dạng địa chỉ). VD: Ngôn ngữ lập trình C - Smith.N Studio! 81
- Bài 8: Chuỗi ký tự 1. Khái niệm Chuỗi ký tự là một dãy các ký tự đặt trong cặp dấu nháy kép. Chuỗi rỗng được ký hiệu bằng hai dấu nháy kép đi liền nhau. Một chuỗi ký tự được cấp phát một khoảng nhớ cho một mảng kiểu char chứa các ký tự của chuỗi và chứa thêm ký tự '\0' là ký tự kết thúc chuỗi. Mỗi ký tự của chuỗi được chứa trong một phần tử của mảng. Chuỗi ký tự là một trường hợp riêng của mảng một chiều khi mỗi thành phần của mảng là ký tự Chuỗi ký tự thường được khai báo theo khai báo theo hai mẫu: char ten_chuoi[] ; hoặc char *ten_chuoi; Ngôn ngữ lập trình C - Smith.N Studio! 82
- 2. Các thao tác trên chuỗi Trong C không tồn tại các phép toán so sánh, gán nội dung của chuỗi này cho chuỗi khác. Ðể thực hiện các thao tác này ta sử dụng một thư viện các hàm chuẩn là . Hàm strlen: int strlen(char s[]) Trả về độ dài của chuỗi s, chính là chỉ số của ký tự NULL trong chuỗi. Hàm strcpy: strcpy(char dest[], char source[]) Sao chép nội dung chuỗi source vào chuỗi dest. Hàm strchr: char *strchr(char s[], char c) Tìm lần xuất hiện đầu tiên của ký tự c trong chuỗi s, trả về địa chỉ của ký tự này. Ngôn ngữ lập trình C - Smith.N Studio! 83
- Hàm strncpy: strncpy(char dest[], char source[], int n) Sao chép n ký tự trong chuỗi source vào chuỗi dest. Trong trường hợp không có đủ n ký tự trong source thì hàm sẽ điền thêm các ký tự trắng vào chuỗi dest. Hàm strcat : strcat(char ch1[], char ch2[]) Nối chuỗi ch2 vào cuối chuỗi ch1. Sau lời gọi hàm này độ dài chuỗi ch1 bằng tổng độ dài của cả hai chuỗi ch1 và ch2 trước lời gọi hàm. Hàm strncat : strncat(char ch1[], char ch2[],int n) Nối n ký tự đầu tiên của ch2 vào ch1 Ngôn ngữ lập trình C - Smith.N Studio! 84
- Hàm strstr : char *strstr(char s1[], char s2[]) Tìm kiếm chuỗi s2 trong chuỗi s1, Trả về địa chỉ của lần xuất hiện đầu tiên của s2 trong s1 hoặc NULL khi không tìm thấy. Hàm strcmp : int strcmp(char ch1[], char ch2[]) So sánh hai chuỗi ch1 và ch2. Nguyên tắc so sánh theo kiểu từ điển. Giá trị trả về: = 0 nếu chuỗi ch1 bằng chuỗi ch2 > 0 nếu chuỗi ch1 lớn hơn chuỗi ch2 < 0 nếu chuỗi ch1 nhỏ hơn chuỗi ch2 VD: Đếm số lần xuất hiện của ký tự a trong một xâu ký tự cho trước Ngôn ngữ lập trình C - Smith.N Studio! 85
- #include #include #define HANG 128 void main() { char xau[HANG]; int i,na; clrscr(); printf("\nNhap mot xau ky tu:");gets(xau); na=i=0; while(xau[i]) if (xau[i++]=='a') na++; printf("\nXau co %d chu a",na); getch(); return; } Ngôn ngữ lập trình C - Smith.N Studio! 86
- 3. Mảng và chuỗi ký tự Một dạng sử dụng con trỏ đặc biệt là việc sử dụng một mảng các biến con trỏ. Khai báo theo mẫu type *pointer_array[size]; VD: khai báo char *temp[10]; sẽ khai báo một mảng 10 con trỏ char có thể được dùng để khai báo một mảng để lưu trữ địa chỉ của mười chuỗi ký tự nào đó. Bài tập:viết chương trình nhập nhiều tên người vào từ bàn phím, sắp xếp lại theo thứ tự và in kết quả đã sắp xếp ra. + Sắp xếp lại các tên này theo thứ tự alphabet + In các tên ra theo thứ tự đó. Ngôn ngữ lập trình C - Smith.N Studio! 87
- VD: xét một mảng các con trỏ ptr_array được gán các địa chỉ của các biến int có giá trị và vị trí bất kỳ. Dùng một hàm để sắp xếp lại các địa chỉ này trong mảng để sao cho các địa chỉ của các số bé được xếp trước địa chỉ của các số lớn hơn. Lúc đó dù chúng ta không làm thay đổi vị trí hoặc thay đổi các giá trị của các biến nhưng mảng vẫn giống như một mảng chỉ đến các giá trị đã sắp xếp có thứ tự. Ngôn ngữ lập trình C - Smith.N Studio! 88
- Bài tập: Viết chương trình đếm số lần xuất hiện của một ký tự trong một xâu ký tự Viết chương trình nhập một chữ, xuất ra chữ đó nhiều lần dùng con trỏ Ngôn ngữ lập trình C - Smith.N Studio! 89
- Bài 9: Cấp phát và giải phóng bộ nhớ động 1. Khái niệm Biến động: Là các biến được tạo ra lúc chạy chương trình, tùy theo nhu cầu. Số biến này hoàn toàn không được xác định từ trước. Các biến động không có tên (việc đặt tên thực chất là gán cho nó một địa chỉ xác định). Cách tạo ra biến động và truy nhập đến biến động được tiến hành như sau Việc tạo ra biến động và xóa nó đi (để thu hồi lại bộ nhớ) được thực hiện nhờ các hàm như malloc() và free() đã có sẵn trong thư viện stdlib.h Ngôn ngữ lập trình C - Smith.N Studio! 90
- Việc truy nhập đến biến động được tiến hành nhờ các biến con trỏ. Các biến con trỏ được định nghĩa như các biến tĩnh ( được khai báo ngay từ đầu trong phần khai báo biến) và được dùng để chứa địa chỉ các biến động VD1: int *p; /* Khai báo biến con trỏ p*/ p= (int *) malloc(100);/* Tạo biến động*/ Ðoạn chương trình trên sẽ cấp phát 100 bytes trong bộ nhớ và gán địa chỉ khối bộ nhớ này cho p VD2: cấp phát bộ nhớ chính xác cho 70 ký tự: /* Khai báo biến con trỏ kiểu char */ char *cp; /* Tạo biến động */ cp=(char *) malloc(70); Ngôn ngữ lập trình C - Smith.N Studio! 91
- 2. Cấp phát và giải phóng bộ nhớ động (các hàm thuộc stdlib.h và alloc.h) 2.1 Cấp phát bộ nhớ động bằng hàm malloc( ) Cú pháp void *malloc(kiểu _dl size) Chức năng: Hàm malloc cấp phát một vùng nhớ có kích thước là size. size là một giá trị kiểu_dl (là một kiểu dữ liệu định sẵn trong thư viện stdlib.h). Hàm malloc trả về con trỏ kiểu void chứa địa chỉ ô nhớ đầu của vùng nhớ được cấp phát. Nếu không đủ vùng nhớ để cấp phát hàm trả về giá trị NULL, vì vậy phải kiểm tra giá trị trả về khi sử dụng hàm malloc. Ngôn ngữ lập trình C - Smith.N Studio! 92
- 2.2 Cấp phát bộ nhớ động bằng hàm calloc Cú pháp (datatype *) calloc(n, sizeof(object)); Hàm calloc cấp phát bộ nhớ động cho các kiểu dữ liệu Trong đ ó: (datatype *) là kiểu con trỏ trỏ tới kiểu dữ liệu datatype. n là số lượng object thuộc kiểu datatype cần cấp phát bộ nhớ. datatype có thể là kiểu dữ liệu cơ sở hoặc kiểu dữ liệu mới Ngôn ngữ lập trình C - Smith.N Studio! 93
- 2.3 Cấp phát bộ nhớ động bằng hàm relloc Cú pháp (datatype *) realloc(buf _p, newsize); Hàm có chức năng cấp phát lại bộ nhớ Trong đó: buf_p là con trỏ đang trỏ đến vùng ô nhớ đã được cấp phát từ trước. newsize là kích thước mới cần cấp phát, có thể lớn hoặc nhỏ hơn. Ngôn ngữ lập trình C - Smith.N Studio! 94
- 2.4 Giải phóng bộ nhớ bằng hàm free Cú pháp void free( void *prt) Hàm free giải phóng vùng nhớ được trỏ đến bởi con trỏ ptr. Nếu con trỏ ptr = NULL thì hàm free không làm gì cả. Ngôn ngữ lập trình C - Smith.N Studio! 95
- 3. Bộ nhớ HEAP và cơ chế tạo biến động Các biến động do malloc tạo ra được C xếp vào một vùng ô nhớ tự do theo kiểu xếp chồng và được gọi là HEAP ( bộ nhớ cấp phát động). Ngôn ngữ C quản lý HEAP thông qua một con trỏ của HEAP là HEAPPTR. Nó luôn trỏ vào byte tự do đầu tiên của vùng ô nhớ còn tự do của HEAP. Mỗi lần gọi malloc(), con trỏ của HEAP được dịch chuyển về phía đỉnh của vùng ô nhớ tự do một số byte tương ứng với kích thước của biến động mới tạo ra. Ngược lại, mỗi khi giải phóng bộ nhớ biến động, bộ nhớ biến động được thu hồi Ngôn ngữ lập trình C - Smith.N Studio! 96
- Ngôn ngữ lập trình C - Smith.N Studio! 97
- Bài 10: Kiểu cấu trúc 1. Kiểu enum Câu lệnh khai báo kiểu enum có thể viết theo bốn cách enum tk {pt1,pt2, } tb1,tb2, ; enum tk {pt1,pt2, }; enum {pt1,pt2, } tb1,tb2, ; enum {pt1,pt2, }; Trong đó : Tk là tên kiểu enum (một kiểu dữ liệu mới), pt1,pt2, là tên các phần tử, tb1,tb2, là tên biến kiểu enum. Ngôn ngữ lập trình C - Smith.N Studio! 98
- Ví dụ: khai báo kiểu dữ liệu làm việc với các ngày trong tuần ta có thể dùng kiểu weekday và biến day như sau: enum weekday{SUNDAY,MONDAY,TUESDAY,W EDSDAY,THURSDAY, FRIDAY, SATURDAY} day; Chú ý biến kiểu enum thực chất là biến nguyên, nó được cấp phát 2 byte bộ nhớ và nó có thể nhận một giá trị nguyên bất kỳ. Ngôn ngữ lập trình C - Smith.N Studio! 99
- 2. Kiểu cấu trúc 2.1 Định nghĩa Cấu trúc là một kiểu dữ liệu bao gồm nhiều thành phần có thể thuộc nhiều kiểu dữ liệu khác nhau. Các thành phần được truy nhập thông qua một tên 2.2 Cú pháp tổng quát struct [tên_cấu_trúc] { khai báo các thành phần } [danh sách các biến cấu trúc]; Ngôn ngữ lập trình C - Smith.N Studio! 100
- trong đó: struct là từ khóa đứng trước một khai báo cấu trúc, tên_cấu_trúc là một tên hợp lệ được dùng làm tên cấu trúc; [danh sách các biến cấu trúc] liệt kê các biến có kiểu cấu trúc vừa khai báo VD: struct hoc_sinh { char ho_ten[20]; float diem; } hs, dshs[100]; Ngôn ngữ lập trình C - Smith.N Studio! 101
- 2.3 Cú pháp định nghĩa kiểu dữ liệu mới Ngôn ngũ C cho phép ta đặt lại tên kiểu dữ liệu mới bằng câu lệnh: typedef kiểu_đã_có tên_kiểu_mới; trong đó : kiểu_đã_có là kiểu dữ liệu mà ta muốn đổi tên. tên_kiểu_mới là tên mới mà ta muốn đặt. Ngôn ngữ lập trình C - Smith.N Studio! 102
- 2.4 Nguyên tắc truy cập đến thành phần của cấu trúc Các thành phần của cấu trúc được truy nhập thông qua tên biến cấu trúc và tên thành phần. tên_biến_cấu_trúc.tên_thành_phần Để truy nhập đến các thành phần của biến hs chúng ta viết như sau: hs.ho_ten hs.diem Chú ý:Không nên sử dụng toán tử & đối với các thành phần cấu trúc (đặc biệt đối với các thành phần không nguyên) trong khi nhập dữ liệu Ngôn ngữ lập trình C - Smith.N Studio! 103
- 2.5 Con trỏ cấu trúc Cách khai báo Một biến cấu trúc cũng là một biến trong bộ nhớ, có thể lấy địa chỉ của một biến cấu trúc bằng toán tử lấy địa chỉ &. Giá trị trả lại là địa chỉ đến trường đầu của cấu trúc. Có thể khai báo một biến con trỏ chỉ đến một cấu trúc để có thể lưu địa chỉ của một biến cấu trúc nào đó. Cú pháp khai báo một biến con trỏ cấu trúc như sau: struct tên_cấu_trúc *tên_con_trỏ; VD: struct hoc_sinh *ptrhs; Việc truy xuất đến một thành phần của cấu trúc thông qua một con trỏ được thực hiện bằng phép toán kép -> Ngôn ngữ lập trình C - Smith.N Studio! 104
- VD: printf("\nHo va ten hoc sinh %s",ptrhs->ho_ten); printf("\nDiem %6.3f",ptrhs->diem); kết quả thực hiện hai câu lệnh này tương đương với hai câu lệnh sau: printf("\nHo va ten hoc sinh %s",hs.ho_ten); printf("\nDiem %6.3f",hs.diem); Việc sử dụng con trỏ chỉ đến cấu trúc thường được sử dụng để truyền cấu trúc đến cho một hàm Một ứng dụng khác của con trỏ cấu trúc là dùng để xây dựng các cấu trúc tự trỏ như: danh sách liên kết (còn gọi là danh sách móc nối). Ngôn ngữ lập trình C - Smith.N Studio! 105
- 2.6 Mảng có cấu trúc Mảng mà gồm các thành phần có kiểu cấu trúc được gọi là mảng cấu trúc. Khai báo một mảng các cấu trúc hoàn toàn tương tự như đối với khai báo một mảng bình thường, chỉ có một điểm khác là thay cho tên các kiểu dữ liệu bình thường là một tên kiểu dữ liệu cấu trúc. Ví dụ về khai báo một mảng có cấu trúc: struct hoc_sinh dshs[100]; //hoc_sinh là kiểu cấu trúc Việc sử dụng các mảng cấu trúc sẽ làm cho việc xử lý một tập hợp các biến cấu trúc trở nên dễ nhìn hơn. Các quy định về mảng cũng được áp dụng đối với mảng các cấu trúc. Ngôn ngữ lập trình C - Smith.N Studio! 106
- 3. Cấu trúc tự trỏ Cấu trúc có ít nhất một thành phần là con trỏ chỉ đến bản thân cấu trúc được gọi là cấu trúc tự trỏ. Ví dụ struct h_sinh{ char ho_ten[20]; float diem; } struct h_sinh *next ;/*con trỏ chỉ đến học sinh tiếp theo trong danh sách*/ khai báo này định nghĩa một cấu trúc tự trỏ có thể dùng để quản lý danh sách họ tên học sinh và điểm số học sinh. Danh sách này chỉ truy cập được theo một chiều Ngôn ngữ lập trình C - Smith.N Studio! 107
- 3.1 Danh sách liên kết: danh sách liên kết gồm các phần tử, mỗi phần tử có hai vùng chính: vùng dữ liệu danh sách và vùng liên kết. Vùng liên kết là một hoặc nhiều con trỏ chỉ đến các phần tử trước hoặc sau phần tử đang được xem xét tùy thuộc vào yêu cầu của công việc cụ thể Cú pháp chung cho khai báo danh sách liên kết sử dụng kiểu dữ liệu con trỏ như sau: typedef struct kiểu_dữ_liệu{ }t_kiểu_dữ_liệu Ngôn ngữ lập trình C - Smith.N Studio! 108
- Bài 11: Kiểu tập tin(File) File là loại dữ liệu có thể ghi lên đĩa để dùng nhiều lần.Trong C chỉ có một loại File, nhưng cấu trúc của mỗi File có thể khác nhau. Cấu trúc này được hình thành khi ta ghi dữ liệu lên File, nó phụ thuộc vào hàm mà ta dùng để ghi dữ liệu lên đĩa. Trong C có hai loại hàm thao tác trên file: Dùng những hàm cấp thấp làm việc với tập tin thông qua một số hiệu tập tin (file handle). Dùng những hàm được xây dựng từ những hàm cấp thấp, dễ sử dụng hơn. Có các hàm phục vụ cho việc đọc ghi trên từng loại dữ liệu (số, chuỗi, ký tự, cấu trúc ). Các hàm này làm việc với tập tin thông qua một con trỏ tập tin. Con trỏ này được xác định khi ta mở tập tin. Ngôn ngữ lập trình C - Smith.N Studio! 109
- 1. Các kiểu xuất nhập dữ liệu trong tập tin 1.1 Xuất nhập kiểu nhị phân Dữ liệu ghi lên tập tin không bị thay đổi và khi đóng tập tin thì mã kết thúc tập tin sẽ được ghi lên đĩa là -1. 1.2 Xuất nhập kiểu văn bản Chỉ khác kiểu nhập xuất nhị phân khi xử lý ký tự xuống dòng và khi ta đóng tập tin thì mã kết thúc tập tin sẽ được ghi lên đĩa là 26. Khi ghi một ký tự chuyển dòng lên đĩa (mã 10) sẽ ghi thành 2 ký tự mã 13 và mã 10. Khi đọc nếu gặp hai ký tự liên tiếp là mã 10 và mã 13 sẽ gom lại thành một ký tự là mã 10. Ngôn ngữ lập trình C - Smith.N Studio! 110
- Chú ý: Tập tin khi ghi lên đĩa dưới dạng nào thì phải đọc dưới dạng đó. Nếu không việc xử lý sẽ không chính xác. Trong C có hàm dùng để nhập xuất cho cả hai kiểu, có hàm chỉ dùng để nhập xuất cho một kiểu nào đó. 2. Các hàm thao tác trên tập tin Các hàm sau đây dùng chung cho cả hai kiểu nhị phân và văn bản. 2.1 Mở file FILE *fopen(const char *tên_tập_tin,const char *kiểu); Ngôn ngữ lập trình C - Smith.N Studio! 111
- Mở một tập tin. Nếu thành công trả về kết quả là con trỏ FILE tương ứng với file vừa mở, ngược lại trả về giá trị NULL.Sau khi mở file phải kiểm tra xem thao tác mở tập tin thành công hay không. * tên tập tin: Là một hằng chuỗi, hoặc một con trỏ chỉ đến vùng nhớ chứa tên tập tin. * kiểu: là hằng chuỗi cho biết kiểu truy nhập: Ngôn ngữ lập trình C - Smith.N Studio! 112
- 2.2 Đóng file int fclose(FILE *f) Ðóng tập tin được chỉ đến bởi con trỏ f. Nếu thành công thì giá trị của hàm = 0 ngược lại có giá trị EOF. Sau khi đóng con trỏ f sẽ không còn trỏ đến file trước đó nữa 2.3 Làm sạch vùng đệm int fflush(FILE *f) Làm sạch vùng đệm của tập tin được chỉ đến bởi con trỏ f. Nếu thành công cho giá trị 0, ngược lại cho giá trị EOF. int flushalll(void) Làm sạch vùng đệm của tất cả các tập tin đang mở. Nếu thành công giá trị của hàm bằng số tập tin đang mở, ngược lại cho giá trị EOF Ngôn ngữ lập trình C - Smith.N Studio! 113
- 2.4 Xoá tập tin int unlink(const char *tên_tập_tin) Xóa một tập tin trên đĩa. Nếu thành công giá trị của hàm bằng 0 , ngược lại cho giá trị EOF 2.5 Đổi tên tập tin int rename(const char *tên_cũ,const char *tên_mới) Ðổi một tập tin trên đĩa. Nếu thành công giá trị của hàm bằng 0 , ngược lại cho giá trị EOF 2.6 Kiểm tra kết thúc tập tin int feof(FILE *f) Cho giá trị khác không nếu ở cuối tập tin, ngược lại =0 Ngôn ngữ lập trình C - Smith.N Studio! 114
- 3. Xuất nhập dữ liệu cho file 3.1 Nhập xuất ký tự : (file kiểu nhị phân và văn bản) Ghi ký tự lên tập tin: int putc(int ch, FILE *f) int fputc(int ch, FILE *f) Ghi lên file f ký tự có mã = ch % 256 Nếu thành công kết quả = mã của ký tự đã ghi, ngược lại =EOF (-1) Trong trường hợp ghi theo văn bản thì khi gặp mã 10 sẽ ghi thành 13 và 10 Ðọc ký tự từ tập tin: int getc( FILE *f) int fgetc( FILE *f) Ðọc một ký tự từ file f . Nếu thành công kết quả = mã của ký tự đọc được, ngược lại = -1 Ngôn ngữ lập trình C - Smith.N Studio! 115
- 3.2 Nhập xuất chuỗi: (Dùng cho kiểu văn bản) Ghi một chuỗi: int fputs(const char *s, FILE *f) Ghi một chuỗi được chỉ tới bới con trỏ s vào file f. Kết quả = ký tự cuối được ghi nếu thành công, ngược lại =EOF Ðọc một chuỗi: char *fgets(const char *s, int n, FILE *f) Ðọc một chuỗi từ File f và đưa vào vùng nhớ do s trỏ đến. Việc đọc kết thúc khi đã đọc được n-1 ký tự , hoặc gặp ký tự xuống dòng , hoặc gặp ký tự kết thúc File. Nếu việc đọc có lỗi kết quả của hàm =NULL. Ngôn ngữ lập trình C - Smith.N Studio! 116
- 3.3 Ðọc ghi dữ liệu theo khuôn dạng: (Dùng cho kiểu văn bản) Ghi dữ liệu theo khuôn dạng: int fprintf(FILE *f , const char *đặc tả, ) là danh sách các đối số tương ứng với các đặc tả. Sử dụng giống như hàm printf, dữ liệu sẽ được ghi lên file. Ðọc dữ liệu theo khuôn dạng: fscanf(FILE *f , const char *đặc tả, ) là danh sách các đối số tương ứng với các đặc tả. Sử dụng giống như hàm scanf, dữ liệu sẽ được đọc từ File f rồi đưa vào các đối số tương ứng. Ngôn ngữ lập trình C - Smith.N Studio! 117