Bài giảng Hệ thống máy tính và ngôn ngữ C - Chương 12: Pointer
12.1 Khái niệm
12.2 Thao tác trên POINTER
12.3 POINTER và mảng
12.4 Đối số của hàm là pointer -
truyền đối số theo số dạng tham
số biến
12.5 Hàm trả về pointer và
mảng
12.6 Chuỗi ký tự
12.7 Pointer và việc định vị
bộ nhớ động
12.8 Mảng các pointer
12.9 Pointer của pointer
12.10 Đối số của hàm MAIN
12.11 Pointer trỏ đến hàm
12.12 Ứng dụng
Bài tập cuối chương
chiều dài chuỗi #include #include #include main() { char ten[41]; int i; clrscr(); printf("Moi ban nhap ten: "); gets(ten); for ( i = 0; i < strlen (ten); i++) if (ten[i] >= 'a' && ten[i] <= 'z') ten[i] -= 32; printf ("A! Chao ban: %s", ten); getch();} CHƯƠNG 12 POINTER 12.6 CHUỖI KÝ TỰ 5- Nối chuỗi Để nối hai chuỗi lại, C có hàm chuẩn strcat(). Hàm này nhận hai chuỗi làm đối số, và một bản sao của chuỗi thứ hai sẽ được chép nối vào cuối của chuỗi thứ nhất, để tạo ra chuỗi mới. Chuỗi thứ hai vẫn không có gì thay đổi. Prototype của hàm này trong file string.h: char *strcat(char *dest, const char *src); Ví dụ 13.37(SGT) CHƯƠNG 12 POINTER 12.6 CHUỖI KÝ TỰ 6- So sánh chuỗi Hàm này là strcmp(), có prototype trong file string.h: int strcmp(const char *s1, const char*s2); Hàm này so sánh hai chuỗi s1 và s2 và trả về một trị là: - số dương nếu s1 > s2 - số âm nếu s1 < s2 - số 0 nếu s1 == s2 CHƯƠNG 12 POINTER 12.6 CHUỖI KÝ TỰ 6- So sánh chuỗi Ví dụ:Xét chương trình ví dụ sau đây #include #include #include main() { clrscr(); printf("%d \n", strcmp("QUAN", “quan”)); printf("%d \n', strcmp("QUAN", "QUAN")); printf("%d \n", strcmp("quan", "QUAN")); printf("%d \n", strcmp("quang”, “quanG")); printf("%d \n", strcmp("quang”, “quan")); getch(); } CHƯƠNG 12 POINTER 12.6 CHUỖI KÝ TỰ 6- So sánh chuỗi Chương trình cho xuất liệu: -32 0 32 32 103 CHƯƠNG 12 POINTER 12.7 POINTER VÀ VIỆC ĐỊNH VỊ BỘ NHỚ ĐỘNG C cho phép khai báo các biến động, các biến này khi cần thì xin chỗ, không cần thì giải phóng vùng nhớ cho chương trình sử dụng vào mục đích khác. Các biến động này được cấp phát trong vùng nhớ heap, là vùng đáy bộ nhớ (vùng còn lại sau khi đã nạp các chương trình khác xong), và được quản lý bởi các biến pointer CHƯƠNG 12 POINTER 12.7 POINTER VÀ VIỆC ĐỊNH VỊ BỘ NHỚ ĐỘNG Trong C có hai hàm chuẩn để xin cấp phát bộ nhớ động malloc() và calloc(), cả hai hàm đều có prototype nằm trong file alloc.h hoặc stdlib.h như sau: void *malloc(size_t size); void *calloc(size_t nitems, size_t size); CHƯƠNG 12 POINTER 12.7 POINTER VÀ VIỆC ĐỊNH VỊ BỘ NHỚ ĐỘNG Nếu biến động được xin, sau khi dùng xong, vùng nhớ của nó không được giải phóng thì nó vẫn chiếm chổ trong bộ nhớ, mặc dù chương trình đã kết thúc. C đưa ra hàm free() để giải phóng khối bộ nhớ được xin bằng hàm malloc() hoặc calloc(). Prototype của hàm free() trong file stdlib.h hoặc alloc.h như sau: void free (void * block); CHƯƠNG 12 POINTER 12.7 POINTER VÀ VIỆC ĐỊNH VỊ BỘ NHỚ ĐỘNG Cấu trúc bộ nhớ LC-3 với ứng bộ nhớ heap CHƯƠNG 12 POINTER 12.7 POINTER VÀ VIỆC ĐỊNH VỊ BỘ NHỚ ĐỘNG Ví dụ: Cần xin một khối bộ nhớ có 10 phần tử int, ta viết như sau: int *pint; pint = (int *) malloc (10 * siezof (int)); hoặc pint = (int *) calloc (10, siezof (int)); CHƯƠNG 12 POINTER 12.7 POINTER VÀ VIỆC ĐỊNH VỊ BỘ NHỚ ĐỘNG Ví dụ: #include #include #include EXIT #include main() { int *pint, s = 0, i; pint = (int *) calloc (10, sizeof (int)); if (pint == NULL) { printf ("Khong du bo nho \n"); exit (1); } CHƯƠNG 12 POINTER 12.7 POINTER VÀ VIỆC ĐỊNH VỊ BỘ NHỚ ĐỘNG Ví dụ: clrscr(); printf ("Moi nhap 10 tri vao mang: "); for (i = 0; i <10; i++) scanf ("%d", &pint[i]); for (i = 0; i <10; i++) s += pint[i]; printf ("Tong cac phan tu cua mang la: %d \n", s); getch(); free (pint); } CHƯƠNG 12 POINTER 12.8 MẢNG CÁC POINTER Cú pháp khai báo mảng các pointer: kiểu * tên_mảng [Kích_thước]; Ví dụ: Khi khai báo int * pint[4]; CHƯƠNG 12 POINTER 12.8 MẢNG CÁC POINTER Ví dụ: Khi khai báo int * pint[4]; int a = 2, b = 3, c = 4, d = 5; pint[0] = &a; pint[1] = &b; pint[2] = &c; pint[3] = &d; CHƯƠNG 12 POINTER 12.8 MẢNG CÁC POINTER CHƯƠNG 12 POINTER 12.8 MẢNG CÁC POINTER Ví dụ: Khi khai báo int * pint[4]; int a[3], b[3], c[3], d[3]; pint[0] = a; pint[1] = b; pint[2] = c; pint[3] = d; CHƯƠNG 12 POINTER 12.8 MẢNG CÁC POINTER CHƯƠNG 12 POINTER 12.8 MẢNG CÁC POINTER Ví dụ 13.48, 13.49 (SGT) Ví dụ : Khi khai báo int a[4][5]; int *b[4]; thì khi truy xuất a[2][3] và b[2][3], C đều hiểu đây là các biến int CHƯƠNG 12 POINTER 12.8 MẢNG CÁC POINTER Một mảng các pointer cũng có thể được khởi động trị nếu mảng là mảng toàn cục hay mảng tĩnh. Ví dụ: static char *thu[7] = {"Thu 2", "Thu 3", "Thu 4", "Thu 5", "Thu 6", "Thu 7", "Chua nhat"}; CHƯƠNG 12 POINTER 12.9 POINTER CỦA POINTER Cú pháp khai báo pointer này như sau: kiểu ** tên_pointer Ví dụ: int **pint; int*p; int a[4][4]; thì pint = &p; hoặc pint = (int **) &a; CHƯƠNG 12 POINTER 12.9 POINTER CỦA POINTER CHƯƠNG 12 POINTER Thay vì truy xuất a[i][j], ta có thể truy xuất *(pint + m*i + j), với m là số phần tử trên một hàng của mảng hai chiều. 12.9 POINTER CỦA POINTER Ví dụ: #include #define MAX_ROW 3 #define MAX_COL 3 main() { int row, col; int *pint1; int a2d [MAX_ROW][MAX_COL] = { {0, 1, 2}, {10, 11, 12}, {20, 21, 22} }; CHƯƠNG 12 POINTER 12.9 POINTER CỦA POINTER int **pint2; int (*pa2d)[MAX_ROW][MAX_COL]; /* Thu dia chi cua pointer va mang 2 chieu */ pint1 = a2d[1]; pa2d = &a2d; pint2 = (int **)&a2d; printf ("pint1 = a2d[1] = %p\n", pint1); printf ("*( *( ( int (*)[MAX_COL] ) pint2 + 1)+ 2)= %d\n", *( *( ( int (*)[MAX_COL] ) pint2 + 1)+ 2)); printf ("*( *(a2d + 1) + 2) = %d\n", *( *(a2d + 1) + 2)); CHƯƠNG 12 POINTER 12.9 POINTER CỦA POINTER printf ("*pint1[2] = %d\n", pint1[2]); printf ("(*pa2d)[1][2] = %d\n", (*pa2d)[1][2]); printf ("Tri cua cac phan tu trong mang truy xuat qua pointer 2 lan:\n"); for (row = 0; row < MAX_ROW; row ++) { for (col = 0; col < MAX_COL; col ++) printf ("%d ", *( *( ( int (*)[MAX_COL] ) pint2 + row)+ col)); printf ("\n"); } getchar();} CHƯƠNG 12 POINTER 12.9 POINTER CỦA POINTER CHƯƠNG 12 POINTER 12.9 POINTER CỦA POINTER Ví dụ : int *m[4]; int a = 1, b = 2, c = 3, d = 4; int **pint; pint = m; m[0] = &a; m[1] = &b; m[2] = &c; m[3] = &d; Thay vì truy xuất trực tiếp a, b, ..., ta có thể dùng pointer *(pint[i]) CHƯƠNG 12 POINTER 12.9 POINTER CỦA POINTER Ví dụ: Xét khai báo sau: int ** pi; int * pint[4]; int a[3], b[3], c[3], d[3]; pi = pint; pint[0] = a; pint[1] = b; pint[2] = c; pint[3] = d; CHƯƠNG 12 POINTER 12.9 POINTER CỦA POINTER CHƯƠNG 12 POINTER 12.9 POINTER CỦA POINTER Ví dụ 13.56(GT) CHƯƠNG 12 POINTER 12.10 ĐỐI SỐ CỦA HÀM MAIN C hoàn toàn cho phép việc nhận đối số vào hàm main(), có hai đối số C đã quy định theo thứ tự: int agrc: đối số cho biết số tham số đã nhập, kể cả tên chương trình. char *argv[]: mảng các pointer trỏ đến các chuỗi là tham số đi theo sau tên chương trình khi chạy chương trình từ DOS. CHƯƠNG 12 POINTER 12.10 ĐỐI SỐ CỦA HÀM MAIN Ví dụ: Xét chương trình ví dụ sau: #include #include main (int argc, char *argv[]) { int i; clrscr(); printf ("Cac doi so cua chuong trinh la: \n"); printf ("Ten chuong trinh la: %s \n", argv[0]); if ( argc >1 ) for (i = 1; i < argc; i++) printf ("Doi so thu %d: %s \n", i, argv[i]); getch(); } CHƯƠNG 12 POINTER 12.10 ĐỐI SỐ CỦA HÀM MAIN Nếu nhập từ bàn phím như sau C:\>thu_main tin thu 123 thì chương trình cho xuất liệu là: Cac doi so cua chuong trinh la: Ten chuong trinh la: C:\thu_main.exe Doi so thu 1: tinDoi so thu 2: thu Doi so thu 3: 123 Ví dụ 13.59(GT) CHƯƠNG 12 POINTER 12.11 POINTER TRỎ ĐẾN HÀM Cú pháp khai báo một pointer chỉ tới hàm: kiểu (* tên_pointer) (kiểu_các_đối_số); Chú ý: kiểu * tên_hàm (kiểu_các_đối_số);Hàm trả về pointer CHƯƠNG 12 POINTER 12.11 POINTER TRỎ ĐẾN HÀM Ví dụ: Nếu khai báo int (* p_function) (int, int); và đã có hàm int cong (int a, int b) { ... } Ta có thể: p_function = cong; tong = (*p_function) (m, n); CHƯƠNG 12 POINTER 12.11 POINTER TRỎ ĐẾN HÀM Ví dụ 13.62 (GT) CHƯƠNG 12 POINTER 12.12 ỨNG DỤNG 12.12.1 Danh sách liên kết là stack 12.12.2 Danh sách liên kết là queue (GT) CHƯƠNG 12 POINTER 12.12 ỨNG DỤNG BÀI TẬP CUỐI CHƯƠNG 1. Viết chương trình với một hàm cho phép truy xuất chuỗi trong stack (danh sách liên kết và mảng) và in ra màn hình thông tin theo thứ tự alphabet. 2. Dùng cấu trúc dữ liệu queue dạng danh sách liên kết, tính biểu thức dạng đa thức bất kỳ sau: f(x) = trong phần thông tin có hai vùng biến - hệ số - số mũ CHƯƠNG 12 POINTER ...n m 3 o 1 n 1 n a x a x a x a 12.12 ỨNG DỤNG BÀI TẬP CUỐI CHƯƠNG 3. Viết chương trình với một hàm duyệt toàn bộ các phần tử trong queue, trả về số phần tử trong queue. 4. Viết chương trình tạo một danh sách liên kết lưu các thông tin là các số nguyên theo thứ tự từ lớn tới nhỏ. Thiết kế hàm insert() cho phép chèn một phần tử lưu thông tin số vào vị trí có thứ tự phù hợp trong chuỗi. 5. Viết chương trình nhập vào một số số nguyên (chưa biết có bao nhiêu số nguyên). Loại bỏ cácsố nguyên bị lặp lại. In ra dãy số mới này. Ví dụ: Nhập: 5 4 10 8 5 4 10 2 8 In ra: 5 4 10 8 2 CHƯƠNG 12 POINTER KẾT THÚC CHƯƠNG 12 CHƯƠNG 12 POINTER
File đính kèm:
- bai_giang_he_thong_may_tinh_va_ngon_ngu_c_chuong_12_pointer.pdf