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

