Tải bản đầy đủ (.pdf) (32 trang)

Bài giảng Kỹ thuật lập trình Các cấu trúc dữ liệu cơ bản (tiếp) GV. Hà Đại Dương

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (535.04 KB, 32 trang )

9/26/2016

Kỹ thuật lập trình

Tuần 6 - Các cấu trúc dữ liệu cơ
bản (tiếp)
Giáo viên: Hà Đại Dương


9/26/2016

1

Nội dung
• Mảng (array) - Bài trước
• Con trỏ (pointer)
• Xâu ký tự (string)

9/26/2016

2

1


9/26/2016

Con trỏ (Pointer)

9/26/2016


3

Con trỏ
• Cho phép quản lý vùng nhớ: Ghi, đọc dữ liệu
từ vùng nhớ này (như biến)
• Biến thông thường
int a; float b; char c
a,b,c: Biến (thường), lưu giá trị

• Biến con trỏ (con trỏ): lưu địa chỉ của vùng
nhớ.

9/26/2016

4

2


9/26/2016

Khai báo
• Cú pháp
Kiểu * Tên_Biến;
• Ví dụ:
int *pa;
float *pb;
char *pc;

9/26/2016


5

Địa chỉ và giá trị
• Ô nhớ: Được xác định bằng 1
địa chỉ và có 1 giá trị nào đó.
• Ví dụ:

Địa chỉ

Giá trị

FF01

678

FF02

34.1





– Tại địa chỉ: FF01 có giá trị là 678
– Tại địac chỉ FF02 có giá trị là 34.1

9/26/2016

6


3


9/26/2016

Địa chỉ và giá trị …
• Biến thường
int a; float b; char c
Quan tên của nó -> Biết giá trị

Địa chỉ

Giá trị

FF01

678

FF02

34.1





• Con trỏ:
int *pa; float *pb; char *pc;
Qua tên của nó -> Biết địa chỉ ô nhớ


9/26/2016

7

Địa chỉ và giá trị
• Toán tử &: Tác động đến địa chỉ của 1 biến
(thường)
– Cú pháp: &Tên_Biến_Thường
– Ví dụ: &a, &b, &c

• Toán tử *: Tác động đến giá trị ô nhớ tại địa
chỉ biến con trỏ
– Cú pháp: *Tên_Biến_Con_trỏ
– Ví dụ: *pa, *pb, *pc
9/26/2016

8

4


9/26/2016

Ví dụ 1

9/26/2016

9


Ví dụ 1…

9/26/2016

10

5


9/26/2016

Ví dụ 2

9/26/2016

11

Ví dụ 2 …

9/26/2016

12

6


9/26/2016

Cấp phát bộ nhớ
• Xét chương trình sau:


9/26/2016

13

Cấp phát bộ nhớ …
• Khi chạy báo lỗi

Sử dụng pa khi chưa khởi tạo
9/26/2016

14

7


9/26/2016

Lý do
• Khi gặp khai báo con trỏ -> chương trình chưa
dành chỗ (ô nhớ) để lưu giá trị nên

Báo lỗi
• Ở ví dụ trước
có pa = &a
nên *pa=190;
Không báo lỗi
9/26/2016

15


Hàm malloc()
• Con trỏ: Cho phép quản lý vùng nhớ (Ghi, đọc
dữ liệu từ vùng nhớ này)
• Hàm malloc(n)
– Cú pháp: void * malloc(n)
– Trả về địa chỉ (đầu) vùng nhớ n byte cấp phát
được (dạng void *)
– Ví dụ:
pa = (int *) malloc(4);
pa = (int *) malloc(sizeof(int));
9/26/2016

16

8


9/26/2016

Hàm calloc()
• Hàm calloc(k,n)
– Cú pháp: void * calloc(k,n)
– Trong đó:
• k: số phần tử
• N: kích thước (byte) mỗi phần tử

– Trả về địa chỉ (đầu) vùng nhớ k*n (bytes) cấp phát
được.
– Ví dụ:

pb = (float*) calloc(5,4)
(hàm malloc(), calloc() có trong thư viện malloc.h )
9/26/2016

17

Ví dụ 3

9/26/2016

18

9


9/26/2016

Ví dụ 3 …

9/26/2016

19

Quản lý mảng bằng con trỏ
• Trong ví dụ 3, lệnh
Cấp phát 5 “ô” nhớ, mỗi ô nhớ cho phép lưu
trữ 1 giá trị float.
• Khi đó pb quản lý danh sách 5 ô nhớ như là 1
mảng.


9/26/2016

20

10


9/26/2016

Quản lý mảng bằng con trỏ …
• Phép cộng/trừ con trỏ với 1 số nguyên
– Phép công: pb + N cho phép truy cập đến phần tử
(ô nhớ) thứ N+1 tính từ địa chỉ con trỏ pb.
– Phép công: pb - N cho phép truy cập đến phần tử
(ô nhớ) trước con trỏ pb N.

9/26/2016

21

Ví dụ 4

9/26/2016

22

11


9/26/2016


Ví dụ 4 …

9/26/2016

23

Ví dụ 5
• Sử dụng con trỏ, viết chương trình cho phép
nhập vào một mảng, sắp xếp tăng dần và in
kết quả ra màn hình.
• Viết chương trình (10 phút)

9/26/2016

24

12


9/26/2016

Cấp phát bộ nhớ động
• Biến thường và mảng khi khai báo chương
trình sẽ cấp phát vùng nhớ có kích thước cố
định đủ để lưu trữ dữ liệu các biến đó -> Cấp
phát tĩnh.
• Con trỏ cho phép tạo và quản lý vùng nhớ với
kích thước có thể thay đổi được -> Cấp phát
động.


9/26/2016

25

Cấp phát bộ nhớ động …
• Cấp phát vùng nhớ:
– malloc(),
– calloc()

• Khi không cần có thể thu hồi (giải phóng) vùng
nhớ:
– free();

• Nếu thiếu có thể cấp phát thêm:
– realloc()
9/26/2016

26

13


9/26/2016

Hàm free()
• Cú pháp: void free(void *p)
• Ý nghĩa: Giải phóng vùng nhớ quản lý bởi con
trỏ p.
• Ví dụ:


9/26/2016

27

Hàm realloc()
• Cú pháp: void * realloc(void *p, N)
• Ý nghĩa: cấp phát lại vùng nhớ quản lý bởi con
trỏ p với kích thước mới là N (bytes).
• Ví dụ 6:

9/26/2016

28

14


9/26/2016

9/26/2016

29

Ví dụ 6

9/26/2016

30


15


9/26/2016

Lưu ý
• Hằng con trỏ NULL: NULL - Không trỏ đến đâu
ví dụ:
pb = NULL
• Trừ 2 con trỏ cùng kiểu
Cho 1 số là khoảng cách (số phần tử) giữa 2
con trỏ đó
• Không cộng 2 con trỏ.

9/26/2016

31

Bài tập

9/26/2016

32

16


9/26/2016

Bài tập

1.
2.
3.
4.

(Sử dụng con trỏ thay vì dùng mảng)
Viết chương trình chuyển số thập phân về
bát phân, thập lục phân.
Viết chương trình chuyển số nhị phân, bát
phân, thập lục phân về dạng thập phân.
Viết chương trình tính ma trận tổng C = A + B
Viết chương trình tính ma trận tích C = A * B

9/26/2016

33

Bài tập về nhà
• Biểu diễn mảng hai chiều sử dụng con trỏ như
thế nào?

9/26/2016

34

17


9/26/2016


Xâu ký tự (string)

9/26/2016

35

Định nghĩa
• Xâu ký tự (hay chuỗi ký tự) là một dãy (hoặc
mảng) các ký tự liên tiếp được kết thúc bằng
ký tự ‘\0’ (còn được gọi là ký tự NULL trong
bảng mã ASCII).
• Hằng xâu ký tự là dãy ký tự nằm trong cặp “”
• Ví dụ:
“Ky thuat lap trinh”
“Hoc vien Ky thuat Quan su”
9/26/2016

36

18


9/26/2016

Xâu ký tự …
• Trong C++: có kiểu xâu ký tự string.
• Trong C: xâu là cách tổ chức dữ liệu (không
phải kiểu)
– Xâu là mảng các ký tự:
char Ten[50];

char Ten[] =“Ky thuat lap trinh”;
– Xâu là con trỏ ký tự
char * Ten;
(Trong phần này chỉ xem xét dưới khía cạnh of C)
9/26/2016

37

Nhập/Xuất xâu
• Hàm puts(s)
– Ý nghĩa: In (xuất) xâu ký tự s ra màn hình
– Cú pháp: puts(s);

• Hàm gets(s)
– Ý nghĩa: Đọc (nhập) xâu ký tự từ bàn phím
– Cú pháp: gets(s);
– Ví dụ

9/26/2016

38

19


9/26/2016

9/26/2016

39


Ví dụ 7
• Đến số ký tự trống (space bar) trong xâu vừa
nhập.
• Hàm strlen(s): trả về số ký tự của xâu s
• Viết chương trình (10 phút)

9/26/2016

40

20


9/26/2016

Ví dụ 7 …

9/26/2016

41

Xâu ký tự
• Khi xử lý từng ký tự -> Xâu là mảng các ký tự.
• Hơn thế: Xâu ký tự không chỉ là mảng các ký
tự:
– Các ký tự trong xâu có quan hệ với nhau (khác với
phần tử của mảng)
– Cộng 2 xâu: “Sinh Vien” và “Hoc vien KTQS” để
được “Sinh Vien Học vien KTQS” (khác với 2 mảng)

– ….
Xâu không chỉ là mảng các ký tự
9/26/2016

42

21


9/26/2016

Các hàm xử lý xâu
• Hàm strcat()
– Ý nghĩa: Cộng (nối) 2 xâu thành một
– Cú pháp

char *strcat(char *des, const char *source)
– Nối xâu 2 vào xâu 1.
– Ví dụ

9/26/2016

43

9/26/2016

44

22



9/26/2016

9/26/2016

45

Các hàm xử lý xâu …
• Chuyển 1 ký tự thành ký tự hoa
– char toupper(char c)

• Chuyển 1 xâu thành hoa
– char *strupr(char *s)

• Chuyển 1 xâu thành in thường
– char *strlwr(char *s)

• Sao chép (copy) 1 xâu
– char *strcpy(char *Des, const char *Source)
9/26/2016

46

23


9/26/2016

Các hàm xử lý xâu …
• Sao chép n ký tự đầu tiên

– char *strncpy(char *Des, const char *Source,
size_t n)

• Tìm kiếm nội dung
– char *strstr(const char *s1, const char *s2)
– Tìm kiếm sự xuất hiện đầu tiên của chuỗi s2 trong
chuỗi s1
– Kết quả trả về của hàm là một con trỏ chỉ đến
phần tử đầu tiên của chuỗi s1 có chứa chuỗi s2
hoặc giá trị NULL nếu chuỗi s2 không có trong
9/26/2016
47
chuỗi s1

Ví dụ

9/26/2016

48

24


9/26/2016

Các hàm xử lý xâu …
• So sánh 2 xâu
– int strcmp(const char *s1, const char *s2)
– Hàm strcmp trả về:
• Số âm: s1 < s2

• Không: s1 = s2
• Dương: s1>s2

• …

9/26/2016

49

Ví dụ 8
• Đổi năm dương lịch thành năm âm lịch
– Xem lại chương trình đã viết ở tuần 2
– Chương trình

9/26/2016

50

25


×