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

 

Bài giảng Hệ thống máy tính và ngôn ngữ C - Chương 12: Pointer trang 1

Trang 1

Bài giảng Hệ thống máy tính và ngôn ngữ C - Chương 12: Pointer trang 2

Trang 2

Bài giảng Hệ thống máy tính và ngôn ngữ C - Chương 12: Pointer trang 3

Trang 3

Bài giảng Hệ thống máy tính và ngôn ngữ C - Chương 12: Pointer trang 4

Trang 4

Bài giảng Hệ thống máy tính và ngôn ngữ C - Chương 12: Pointer trang 5

Trang 5

Bài giảng Hệ thống máy tính và ngôn ngữ C - Chương 12: Pointer trang 6

Trang 6

Bài giảng Hệ thống máy tính và ngôn ngữ C - Chương 12: Pointer trang 7

Trang 7

Bài giảng Hệ thống máy tính và ngôn ngữ C - Chương 12: Pointer trang 8

Trang 8

Bài giảng Hệ thống máy tính và ngôn ngữ C - Chương 12: Pointer trang 9

Trang 9

Bài giảng Hệ thống máy tính và ngôn ngữ C - Chương 12: Pointer trang 10

Trang 10

Tải về để xem bản đầy đủ

pdf 109 trang xuanhieu 3880
Bạn đang xem 10 trang mẫu của tài liệu "Bài giảng Hệ thống máy tính và ngôn ngữ C - Chương 12: Pointer", để tải tài liệu gốc về máy hãy click vào nút Download ở trên

Tóm tắt nội dung tài liệu: Bài giảng Hệ thống máy tính và ngôn ngữ C - Chương 12: Pointer

Bài giảng Hệ thống máy tính và ngôn ngữ C - Chương 12: Pointer
ng, cú pháp khai báo hàm như sau:
kiểu * tên_hàm (danh_sách_khai_báo_đối_số);
với kiểu là kiểu của đối tượng mà pointer được hàm trả về
trỏ đến.
CHƯƠNG 12
POINTER
12.5 HÀM TRẢ VỀ POINTER VÀ MẢNG
Ví dụ: Có khai báo
int * lon_nhat (int a, int b, int c);
thì hàm lon_nhat() trả về một địa chỉ, địa chỉ đó có thể là
địa chỉ của một int hoặc địa chỉ của một mảng các int, việc
sử dụng địa chỉ theo đối tượng nào là do nơi gọi.
CHƯƠNG 12
POINTER
12.5 HÀM TRẢ VỀ POINTER VÀ MẢNG
Ví dụ: Thiết kế hàm nhập trị cho mảng các int
int *nhap_tri (int *num)
{
static int a[10];
int i, n;
printf ("Nhap kich thuoc mang:");
scanf ("%d", &n);
*num = n;
printf ("Nhap tri cho %d phan tu cua mang:", n);
for (i = 0; i < n; i++)
scanf ("%d", &a[i]);
return a; /* a là địa chỉ đầu mảng cần trả về */
}
CHƯƠNG 12
POINTER
12.5 HÀM TRẢ VỀ POINTER VÀ MẢNG
Ví dụ: Chương trình sử dụng hàm nhập trị mảng
#include 
#include 
int *nhap_tri(int *num);
main()
{ int *pint, so_phan_tu, i;
clrscr();
pint = nhap_tri (&so_phan_tu);
printf ("Cac phan tu cua mang la:");
for (i =0; i <so_phan_tu; i++)
printf ("%d", pint[i]);
getch(); }
CHƯƠNG 12
POINTER
12.6 CHUỖI KÝ TỰ
Ví dụ: Khi khai báo
“Hello, world!”
thì chuỗi này sẽ được C ghi vào một nơi nào đó trong bộ
nhớ và có địa chỉ xác định. Địa chỉ này có thể được gán
vào cho một biến con trỏ trỏ đến ký tự để quản lý chuỗi.
Ví dụ : Cho khai báo
char s[20];
s = “Hello, world!”; Không hợp lệ
CHƯƠNG 12
POINTER
12.6 CHUỖI KÝ TỰ
1- Nhập trị chuỗi
Việc nhập trị cho chuỗi bao gồm hai bước: đầu tiên cần
khai báo một nơi trống để chứa chuỗi, sau đó dùng một
hàm nhập trị để lấy chuỗi.
CHƯƠNG 12
POINTER
12.6 CHUỖI KÝ TỰ
1- Nhập trị chuỗi
- Hàm gets() đọc các ký tự đến khi nào gặp ký tự quy
định hàng mới (tức ký tự '\n', tức khi ta ấn phím ENTER)
thì kết thúc việc nhập. Sau đó hàm này lấy tất cả các ký
tự đã nhập trước ký tự '\n', gắn thêm vào cuối chuỗi một
ký tự NUL ('\0') và trả chuỗi cho chương trình gọi.
Prototype của hàm này trong file stdio.h:
char * gets (char * s);
CHƯƠNG 12
POINTER
12.6 CHUỖI KÝ TỰ
1- Nhập trị chuỗi
Ví dụ:
#include 
#include 
main()
{ char ten[41];
char *pten;
clrscr();
printf ("Ban ten gi?\n");
pten = gets (ten);
printf("%s? A! Chao ban %s\n", ten, pten);
getch(); }
CHƯƠNG 12
POINTER
12.6 CHUỖI KÝ TỰ
1- Nhập trị chuỗi
- Hàm scanf() cũng cho phép nhập chuỗi qua định dạng
nhập %s. Việc nhập chuỗi sẽ kết thúc khi hàm scanf() gặp
một trong các ký tự khoảng trắng, ký tự tab hay ký tự
xuống hàng đầu tiên mà nó gặp. Đây chính là điểm khác
nhau giữa hai hàm nhập chuỗi gets() và scanf().
CHƯƠNG 12
POINTER
12.6 CHUỖI KÝ TỰ
1- Nhập trị chuỗi
Ví dụ:
#include 
#include 
main()
{ char ten1[41], ten2[41];
clrscr();
printf(Moi ban nhap hai ten: );
scanf ("%s %s", ten1, ten2);
printf("A! Chao hai ban %s va %s \n", ten1, ten2);
getch(); }
CHƯƠNG 12
POINTER
12.6 CHUỖI KÝ TỰ
2- Xuất chuỗi
Để xuất chuỗi, hai hàm thường hay được dùng là puts() và 
printf(). 
- Hàm puts: ta chỉ cần cung cấp cho hàm đối số là địa chỉ 
của chuỗi cần in. Hàm này sẽ đọc từng ký tự của chuỗi và 
in ra màn hình cho đến khi gặp ký tự NUL thì in ra màn 
hình thêm một ký tự xuống hàng nữa. Prototype của hàm 
này như sau:
int puts (char * s);
CHƯƠNG 12
POINTER
12.6 CHUỖI KÝ TỰ
2- Xuất chuỗi
- Hàm printf () cũng cho phép xuất chuỗi ra màn hình 
nếu ta dùng định dạng xuất "%s" cho nó. Hàm này sẽ 
không tự động in thêm ký tự xuống hàng mới như hàm 
puts().
CHƯƠNG 12
POINTER
12.6 CHUỖI KÝ TỰ
2- Xuất chuỗi
Ví dụ:
#include 
#include 
main()
{ char ten[41];
clrscr();
printf ("Moi ban nhap ten: ");
gets(ten);
printf ("A! Chao ban: %s", ten);
getch();
}
CHƯƠNG 12
POINTER
12.6 CHUỖI KÝ TỰ
3- Gán trị cho chuỗi
Việc gán trị cho biến chuỗi thực tế là việc chép từng ký tự
từ hằng chuỗi hoặc biến chuỗi đã biết sang một biến chuỗi
khác. Trong C, thao tác này được thực hiện nhờ hàm
strcpy(), hàm này có prototype trong file string.h như sau:
char *strcpy(char *dest, const char *src);
CHƯƠNG 12
POINTER
12.6 CHUỖI KÝ TỰ
3- Gán trị cho chuỗi
Hàm strcpy có thể được mô tả như sau:
char *strcpy(char *dest, const char *src)
{
int i;
for (i = 0; (dest[i] = scr[i]) != '\0'; i++)
;
return dest;
}
CHƯƠNG 12
POINTER
12.6 CHUỖI KÝ TỰ
3- Gán trị cho chuỗi
Ví dụ:
#include 
#include 
#include 
main()
{ char ten1[41], ten2[41]; clrscr();
printf("Moi ban nhap ten: ");
gets(ten1);
strcpy (ten2, ten1);
printf("A! Chao ban: %s", ten2);
getch(); }
CHƯƠNG 12
POINTER
12.6 CHUỖI KÝ TỰ
4- Lấy chiều dài chuỗi
Trong C, để lấy chiều dài chuỗi ta dùng hàm strlen().
Prototype của hàm này trong file string.h:
size_t strlen(const char *s);
với size_t là một kiểu nguyên, C quy định đây là unsigned.
CHƯƠNG 12
POINTER
12.6 CHUỖI KÝ TỰ
4- Lấy chiều dài chuỗi
Ví dụ: Xét chương trình nhập một chuỗi, đổi các ký tự
thường của chuỗi đó thành ký tự hoa, in chuỗi đó ra lại
màn hình.
CHƯƠNG 12
POINTER
12.6 CHUỖI KÝ TỰ
4- Lấy 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

File đính kèm:

  • pdfbai_giang_he_thong_may_tinh_va_ngon_ngu_c_chuong_12_pointer.pdf