Upload
phuc-phan-tu
View
220
Download
0
Embed Size (px)
Citation preview
8/19/2019 Bai 5- Mang va Con tro.pdf
1/63
TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI
Ngôn ngữ lập trình C và C++
Bài 5: Bảng và Con trỏ
TS. Đỗ Đăng Khoa
Bộ môn Cơ học Ứng dụngViện Cơ khí
http://chud-dhbkhn.blogspot.com/
8/19/2019 Bai 5- Mang va Con tro.pdf
2/63
Khái niệm về Bảng (Mảng)Khi cần lưu trữ một dãy n phần tử dữ liệu chúng ta cần khaibáo n biến tương ứng với n tên gọi khác nhau -> khó khăn để có
thể nhớ và quản lý hết được tất cả các biếnMột bảng trong C/C++ là một tập hợp các phần tử dữ liệu liênquan có cùng kiểu và được truy cập bởi một tên chung
TRƯỜNG ĐẠI HỌC
BÁCH KHOA HÀ NỘI
nhớ liền kề nhau, và sử dụng chỉ số để xác định từng phần tửChỉ số bảng bắt đầu từ 0Mảng có thể có nhiều chiều
Ví dụ: danh sách sinh viên, danh sách điểm số của sinh viên,etc
2
8/19/2019 Bai 5- Mang va Con tro.pdf
3/63
Mảng một chiều
// mảng số nguyên một chiều có 10 phần tử
int A[10];
A[3]=1;
TRƯỜNG ĐẠI HỌC
BÁCH KHOA HÀ NỘI
-- -- 1--A -- -- ---- -- --4 5 630 2 8 971
A[4] A[5] A[6]A[3]A[0] A[2] A[8] A[9]A[7]A[1]
8/19/2019 Bai 5- Mang va Con tro.pdf
4/63
Khai báo bảng (mảng) một chiều
Các đặc tính riêng của bảng (mảng) cần được định nghĩa.Kiểu dữ liệu của các phần tử
Tên mảng : đại diện cho vị trí phần tử đầu tiên
Kích thước mảng : một hằng sốKhai báo mảng giống như cách khai báo biến. Chỉ khác là
TRƯỜNG ĐẠI HỌC
BÁCH KHOA HÀ NỘI
trong cặp dấu ngoặc vuông [], để xác định kích thước củamảng.
int x[20]; // x có thể chứa 20 số nguyên
float price[10]; // price có thể chứa 10 số thực
char letter[70]; // letter có thể chứa tối đa 69 kí tự
do cần cần có kí tự kết thúc không (\0) cuối xâu
8/19/2019 Bai 5- Mang va Con tro.pdf
5/63
Các qui tắc về bảng (mảng)
Các phần tử của mảng có cùng kiểu dữ liệu
Mỗi phần tử của mảng có thể được sử dụng như một biếnriêng lẻ Kiểu dữ liệu của mảng có thể là int, char , float hoặc double Mảng được “đối xử” không giống hoàn toàn với biến
TRƯỜNG ĐẠI HỌC
BÁCH KHOA HÀ NỘI
Hai mảng có cùng kiểu và cùng kích thước cũng khôngđược xem là tương đương nhau Không thể gán trực tiếp một mảng cho một mảng khác. Không thể gán trị cho toàn bộ mảng, mà phải gán trị cho
từng phần tử của mảng
8/19/2019 Bai 5- Mang va Con tro.pdf
6/63
Khởi tạo bảng (mảng) một chiều
Mỗi phần tử của một mảng cần được khởi tạo riêng rẽ.Kiểu_dữ_liệu tên_bảng[kích_thước_mảng] = {ds_các_phần_tử_bảng};
Kiểu_dữ_liệu tên_bảng[] = {ds_các_phần_tử_bảng};
Ví dụ:
int id[7] = {1, 2, 3, 4, 5, 6, 7};
TRƯỜNG ĐẠI HỌC
BÁCH KHOA HÀ NỘI
float x[] = {5.6, 5.7, 5.8, 5.9, 6.1};char vowel[6] = {'a', 'e', 'i', 'o', 'u', '\0'};
char vowel[6] = "aeiou"; // Kí tự NULL được trình biên dịchtự động thêm vào, do đó vẫn phải dự trữ thêm một chỗ cho
NULL. Các phần tử của mảng có thể được gán giá trị bằng cách sử
dụng vòng lặp for
8/19/2019 Bai 5- Mang va Con tro.pdf
7/63
Sử dụng bảng (mảng) một chiều
Để chỉ thành phần thứ i (hay chỉ số i) của một mảng ta viết
tên mảng kèm theo chỉ số trong cặp ngoặc vuông [].int id[7] = {1, 2, 3, 4, 5, 6, 7};cout a ; // sai
mà phải nhập cho từng phần tử từ a[0] đến a[9] của a
8/19/2019 Bai 5- Mang va Con tro.pdf
8/63
Ví dụ về mảng một chiều
Tìm số bé nhất của một dãy số. In ra số này và vị trí của nó
trong dãyvoid main(){
float a[100], min;// a chứa tối đa 100 số
int i,n,k;
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
cout
8/19/2019 Bai 5- Mang va Con tro.pdf
9/63
Xâu/mảng ký tự
Một xâu kí tự là một dãy bất kỳ các kí tự (kể cả dấu cách) do
vậy nó có thể được lưu bằng mảng kí tự Cần thiết phải có kí tự kết thúc xâu ‘\0’
char [độ dài] ; // không khởi tạo
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
char [độ dài] = xâu kí tự ; // có khởi tạo
char [] = xâu kí tự ; // có khởi tạo
Ví dụ:char hoten[26] ; // xâu họ tên chứa tối đa 25 kí tự
char monhoc[31] = "NNLT C++" ;
char thang[] = "Muoi hai" ; // độ dài mảng = 9
8/19/2019 Bai 5- Mang va Con tro.pdf
10/63
Sử dụng Xâu/mảng ký tự
Xâu kí tự có những đặc trưng như mảng, tuy nhiên chúng
cũng có những điểm khác biệt Truy cập một kí tự trong xâu: cú pháp giống như mảng. Ví dụ:
char s[50] = "I\'m a student" ;/* chú ý kí tự '
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
phải được viết là \‘ */cout
8/19/2019 Bai 5- Mang va Con tro.pdf
11/63
Sử dụng Xâu/mảng ký tự
Không được thực hiện các phép toán trực tiếp trên xâu như:
char s[20] = "Hello", t[20] ; /* khai báo haixâu s và t */
t = "Hello" ;// sai, chỉ gán được khi khai báo
t = s ; // sai, không gán được toàn bộ mảng
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
if (s < t) … // sai, không so sánh được hai mảng Các hàm thư viện xử lý xâu ký tự được khai báo trong file
nguyên mẫu
8/19/2019 Bai 5- Mang va Con tro.pdf
12/63
Các hàm xử lý xâu ký tự (chuỗi)
Các hàm xử lý chuỗi được tìm thấy trong thư viện chuẩn
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
8/19/2019 Bai 5- Mang va Con tro.pdf
13/63
Ví dụ về các hàm xử lý xâu ký tự (chuỗi)
Hàm strcpy(s1,s2): Hàm sao chép xâu s2 vào s1
char s[10], t[10] ;t = "Face" ; // không được dùng
s = t ; // không được dùng
strcpy(t, "Face") ; // được, gán "Face" cho t
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
strcpy(s, t) ; // được, sao chép t sang scout
8/19/2019 Bai 5- Mang va Con tro.pdf
14/63
Ví dụ về các hàm xử lý xâu ký tự (chuỗi)
Hàm strncpy (s1,s2,n): Hàm sao chép n ký tự xâu s2 vào s1
char s[10], t[10] = "Steven";
strncpy(s, t, 5) ;// copy 5 kí tự "Steve" vào s
s[5] = '\0' ; // đặt d u k t thúc xâu
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
// in câu: Steve is young brother of Steven
cout
8/19/2019 Bai 5- Mang va Con tro.pdf
15/63
Ví dụ về các hàm xử lý xâu ký tự (chuỗi)
Hàm strcat (s1,s2): Hàm nối xâu s2 vào s1
char a[100] = “Ban", b[4] = “toi";strcat(a, “ va ”);
strcat(a, b);
cout
8/19/2019 Bai 5- Mang va Con tro.pdf
16/63
Ví dụ về các hàm xử lý xâu ký tự (chuỗi)
Hàm strncat (s1,s2,n): Hàm nối n ký tự xâu s2 vào s1
char s[20] = “Nha " ;char t[] = “anh chi"
strncat(s, t, 3) ; // s = “Nha anh"
hoặc:
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
strncat(s, t+4, 3) ; // s = "Nha chi"
8/19/2019 Bai 5- Mang va Con tro.pdf
17/63
Ví dụ về các hàm xử lý xâu ký tự (chuỗi)
Hàm strcmp(s1,s2): Hàm so sánh 2 xâu s1 và s2
if (strcmp(s1,s2))cout
8/19/2019 Bai 5- Mang va Con tro.pdf
18/63
Ví dụ về các hàm xử lý xâu ký tự (chuỗi)
Hàm strcmpi(s1, s2): Như strcmp(s1, s2) nhưng không phân
biệt chữ hoa, thườngchar s[] = “Ha Noi" , t[] = “ha noi" ;cout
8/19/2019 Bai 5- Mang va Con tro.pdf
19/63
Truyền mảng một chiều cho hàm
Một hàm có thể nhận địa chỉ của một bảng một chiều theo ba
cách Một con trỏint myfunction(float *x)
Một bảng có kích thước
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
char yourfunction(float x[5]) Một bảng không có kích thước
void yourfunction(float x[ ])
Hai cách sau thường ít được sử dụng
8/19/2019 Bai 5- Mang va Con tro.pdf
20/63
Ví dụ: lấy giá trị trung bình của mảng
#include
using namespace std;
double getAverage(int arr[], int size);int main ()
{
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
nt a ance = { , , , , };
double avg;
avg = getAverage( balance, 5 ) ;
cout
8/19/2019 Bai 5- Mang va Con tro.pdf
21/63
8/19/2019 Bai 5- Mang va Con tro.pdf
22/63
Mảng hai chiều
// Mảng số nguyên hai chiều – 3 hàng và 10 cột
int A[3][10];
A[1][2] = 1;
4 5 630 2 8 971
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
-- -- ----
A
-- -- ---- -- --
-- 1 ---- -- -- ---- -- ---- -- ---- -- -- ---- -- --0
2
1
8/19/2019 Bai 5- Mang va Con tro.pdf
23/63
Mảng hai chiều
Mảng hai chiều có thể xem như là một mảng (m phầntử) với mỗi phần tử là mảng một chiều (n phần tử)Một mảng hai chiều trông giống như một ma trận gồmcác hàng và các cộtTrong bộ nhớ tất cả các phần tử của mảng được sắpliên tiếp theo từng hàng của mảng
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
Khai báo mảng hai chi u:
[m][n] ;
8/19/2019 Bai 5- Mang va Con tro.pdf
24/63
Khởi tạo bảng (mảng) hai chiều
Mỗi phần tử của một mảng cần được khởi tạo riêng rẽ.Kiểu_dữ_liệu tên_bảng[hàng][cột] = {ds_các_phần_tử_bảng};
Kiểu_dữ_liệu tên_bảng[][cột] = {ds_các_phần_tử_bảng};
Ví dụ:
int x[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
int x[][4] = { {1,2,3,4}, {5,6,7,8}, {9,10,11,12} };
Kết quả của phép gán trong cả hai trường hợp:x[0][0]=1 x[0][1]=2 x[0][2]=3 x[0][3]=4
x[1][0]=5 x[1][1]=6 x[1][2]=7 x[1][3]=8x[2][0]=9 x[2][1]=10 x[2][2]=11 x[2][3]=12
8/19/2019 Bai 5- Mang va Con tro.pdf
25/63
Khởi tạo bảng (mảng) hai chiều
Khởi tạo bảng xâu ký tựchar name[4][10] = {"Sally", "Joyce", "Lisa",
"Alice"};
Kết quả:name[0] = "Sally" name[1] = "Joyce"
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
name[2] = "Lisa" name[3] = "Alice"
8/19/2019 Bai 5- Mang va Con tro.pdf
26/63
Sử dụng bảng (mảng) hai chiều
Để chỉ thành phần hàng i (hay chỉ số i) và cột j của một mảngta viết tên mảng kèm theo các chỉ số trong 2 cặp ngoặc vuông[].
int id[2][2] = {1, 2, 3, 4};
cout
8/19/2019 Bai 5- Mang va Con tro.pdf
27/63
Truyền mảng hai chiều cho hàm
Một hàm có thể nhận địa chỉ của một bảng 2 chiều theo bacách Một bảng con trỏ
int myfunction(float **x) Một bảng có kích thước
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
char yourfunction(float x[4][5]) Một bảng không có kích thước
void yourfunction(float x[ ][5])
8/19/2019 Bai 5- Mang va Con tro.pdf
28/63
Ví dụ: truyền mảng 2 chiều cho hàm
Truyền mảng kích thước cố địnhint array[10][10];
//Định nghĩa hàm nhận mảng 2 chiều cố định
void passFunc(int a[10][10])
{ // thao tác với a[i][j] }
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
passFunc(array);Hoặcvoid passFunc(int a[][10])
{//thao tác với a[i][j] }
passFunc(array);
8/19/2019 Bai 5- Mang va Con tro.pdf
29/63
Ví dụ: truyền mảng 2 chiều cho hàm
Hoặcvoid passFunc(int (&a)[10][10])
{ // thao tác với a[i][j] }passFunc(array);
Hoặc
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
vo pass unc n a
{ // thao tác với (*a)[i][j] }
passFunc(&array);
Hoặcvoid passFunc(int (*a)[10]) // con trỏ tới mảng
{ // thao tác với a[i][j] }
passFunc(array);
8/19/2019 Bai 5- Mang va Con tro.pdf
30/63
Ví dụ: truyền mảng 2 chiều cho hàm
Sai nếu định nghĩavoid passFunc(int **a) //con trỏ tới con trỏ
{ // …}Truyền mảng kích thước thay đổi
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
n array;
array = new int *[10];
for(int i = 0; i
8/19/2019 Bai 5- Mang va Con tro.pdf
31/63
Khái niệm về Con trỏ
Con trỏ là một biến, nó chứa địa chỉ ô nhớ của một biến khácNếu p là con trỏ chứa địa chỉ của biến c ta gọi p trỏ tới c và c
được trỏ bởi p
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
Con trỏ cung cấp phương thức truy xuất gián tiếp đến giá trịcủa một phần tử dữ liệu
Các con trỏ có thể trỏ đến các biến có kiểu dữ liệu cơ bản nhưint, char, double, hay dữ liệu tập hợp như mảng hoặc cấu trúc.
Phép toán lấy địa chỉ của đối tượng: &.
31
8/19/2019 Bai 5- Mang va Con tro.pdf
32/63
Ứng dụng của con trỏ
Để trả về nhiều hơn một giá trị từ một hàm
Để truyền mảng và chuỗi từ một hàm đếnmột hàm khác thuận tiện hơn
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
vì truy xuất trực tiếp vào các phần tử nàyĐể cấp phát bộ nhớ và truy xuất bộ nhớ (Cấp
phát bộ nhớ trực tiếp)
8/19/2019 Bai 5- Mang va Con tro.pdf
33/63
Khai báo con trỏ
Khai báo con trỏ: chỉ ra một kiểu cơ sở vàmột tên biến được đặt trước bởi dấu *
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
p p a o ng qu :
Ví dụ:
;
int *p;
8/19/2019 Bai 5- Mang va Con tro.pdf
34/63
Các toán tử con trỏ * và &
Để con trỏ p trỏ đến biến x ta phải dùng phép gán p = địa chỉcủa x. Nếu x không phải là mảng ta viết: p = &x. Nếu x là mảng ta viết: p = x hoặc p = &x[0].
Khôn án cho một hằn địa chỉ cụ thể. Ví dụ viết = 200
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
là sai.Phép toán * cho phép lấy nội dung nơi p trỏ đến, ví dụ đểgán nội dung nơi p trỏ đến cho biến f ta viết f = *p.& và * là 2 phép toán ngược nhau. Cụ thể nếu p = &x thì x =
*p. Từ đó nếu p trỏ đến x thì bất kỳ nơi nào xuất hiện x đều cóthể thay được bởi *p và ngược lại.
8/19/2019 Bai 5- Mang va Con tro.pdf
35/63
Ví dụ về con trỏ
int i, j ; // khai báo 2 biến nguyên i, j
int *p, *q ; // khai báo 2 con trỏ nguyên p, q
p = &i; // cho p trỏ tới iq = &j; // cho q trỏ tới j
cout
8/19/2019 Bai 5- Mang va Con tro.pdf
36/63
Ví dụ về con trỏ
// tăng j (thông qua q) và hỏi j, j = 6
(*q)++ ;
cout
8/19/2019 Bai 5- Mang va Con tro.pdf
37/63
Phép toán con trỏ
Phép toán gánGán con trỏ với địa chỉ một biến: p = &i ;
Gán con trỏ với con trỏ khác: p = q ;Phép toán tăng giảm địa chỉ
p ± n: con trỏ trỏ đến thành phần thứ n sau (trước) p
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
của biến được trỏVí dụ giả sử p là con trỏ nguyên (2 byte) đang trỏ đếnđịa chỉ 200 thì p+1 là con trỏ trỏ đến địa chỉ 202, p - 3chứa địa chỉ 194
8/19/2019 Bai 5- Mang va Con tro.pdf
38/63
Ví dụ về phép toán +/- con trỏ
int a[100] = { 1, 2, 3, 4, 5, 6, 7 };int *p, *q;
// cho p trỏ đến mảng a, *p = a[0] = 1p = a; cout
8/19/2019 Bai 5- Mang va Con tro.pdf
39/63
Phép toán con trỏ
Phép toán tự tăng giảmp++, p--, ++p, --p: tương tự p+1 và p-1, chú ý đến tăng
(giảm) trước, sauint a[2] = {3, 7}, *p = a;
// tăng (sau) giá trị nơi p trỏ ≡ tăng a[0] thành 4
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
(*p)++ ;
// tăng (trước) giá trị nơi p trỏ ≡ tăng a[0] thành 4++(*p) ;// lấy giá trị nơi p trỏ (3) và tăng trỏ p (tăng sau),// p -> a[1]*(p++) ;
// tăng trỏ p (tăng trước), p -> a[1] và lấy giá trị//nơi p trỏ (7)
*(++p) ;
8/19/2019 Bai 5- Mang va Con tro.pdf
40/63
Phép toán con trỏ
Hiệu của 2 con trỏPhép toán này chỉ thực hiện được khi p và q là 2 con
trỏ cùng trỏ đến các phần tử của một dãy dữ liệu nàođó trong bộ nhớHiệu p - q là số thành phần giữa p và q
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
s p v q con r nguy n, p c a c v
q có địa chỉ 208. Khi đó p - q = -4Phép toán so sánhSo sánh giữa địa chỉ của hai nơi được trỏ bởi các contrỏ nàyChỉ áp dụng cho hai con trỏ trỏ đến phần tử của cùngmột mảng dữ liệu nào đó
8/19/2019 Bai 5- Mang va Con tro.pdf
41/63
Ví dụ về phép toán so sánh con trỏ
float a[100], *p, *q ;
// p trỏ đến mảng (tức p trỏ đến a[0])
p = a ;// q trỏ đến phần tử thứ 3 (a[3]) của mảng
q = &a[3] ;
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
cou
8/19/2019 Bai 5- Mang va Con tro.pdf
42/63
Cấp phát động với con trỏ
Cấp phát tĩnh: cấp sẵn trước khi chạy chương trình vàkhông thể thay đổi tăng, giảm kích thước hoặc vị trí trong
suốt quá trình chạy chương trìnhCấp phát động: kích thước cụ thể (mảng) sẽ được cấpphát trong quá trình chạy chương trình
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
ng ng n a a c u c n gọ g
phóng) số ô nhớ này để chương trình sử dụng vào việckhácViệc cấp phát và thu hồi này được thực hiện thông quacác toán tử new, delete và con trỏ p
8/19/2019 Bai 5- Mang va Con tro.pdf
43/63
Cấp phát động với con trỏ
Cú pháp của câu lệnh new.p = new ; // cấp phát 1 phần tử
p = new [n] ; // cấp phát n phần tửNếu không có vùng nhớ với số lượng như vậy thì việc cấpphát là thất bại và p = NULL
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
Ví dụ:int *p ;
// cấp phát vùng nhớ chứa được 1 số nguyên
p = new int ;
// cấp phát vùng nhớ chứa được 100 số nguyên
p = new int[100] ;
8/19/2019 Bai 5- Mang va Con tro.pdf
44/63
Ví dụ cấp phát động với con trỏ
double *p ;
int n ;cout
8/19/2019 Bai 5- Mang va Con tro.pdf
45/63
Giải phóng bộ nhớ động
Để giải phóng bộ nhớ đã cấp phát cho một biến (khi khôngcần sử dụng nữa) ta sử dụng câu lệnh delete.
delete p ; // p là con trỏ được sử dụng trong new
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
p ng o n m ng ược c p p p ng qua con r
p ta dùng câu lệnh:
delete[] p ; // p là con trỏ trỏ đến mảng
8/19/2019 Bai 5- Mang va Con tro.pdf
46/63
Con trỏ và mảng 1 chiều
Con trỏ trỏ đến mảng cũng tương tự trỏ đến các biến khác
Con trỏ p trỏ đến mảng a thì p+i là địa chỉ thành phần thứ icủa mảng a và do đó: *(p+i) = a[i] = *(a+i).
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
v p ạ c v a , cụ v p ợp
lệ còn a++ là không được phép (p thực sự là một biến, nó cóthể thay đổi được giá trị còn a là một hằng)
8/19/2019 Bai 5- Mang va Con tro.pdf
47/63
Con trỏ và xâu ký tự
Con trỏ kí tự có thể xem như một biến xâu kí tựKhác với mảng kí tự, ta được phép sử dụng phép gán cho 2
xâu dưới dạng con trỏ Ví dụ:char *s, *t = "Tin hoc" ;
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
s = ; ay c o m s rcpy s, ;
Thực chất phép gán trên chỉ là gán 2 con trỏ với nhau
8/19/2019 Bai 5- Mang va Con tro.pdf
48/63
8/19/2019 Bai 5- Mang va Con tro.pdf
49/63
Con trỏ và mảng hai chiều
float a[2][3], *p;
a không được xem là mảng 1 chiều với 6 phần tử mà được
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
quan n m n ư m ng m c u g m p n , m p n
bộ 3 số thựcĐịa chỉ của mảng a chính là địa chỉ của phần tử đầu tiên a[0][0],và a+1 không phải là địa chỉ của phần tử tiếp theo a[0][1] mà là địachỉ của phần tử a[1][0]Phép gán p = a là dễ gây nhầm lẫn vì p là con trỏ float còn a làđịa chỉ mảng (1 chiều)
8/19/2019 Bai 5- Mang va Con tro.pdf
50/63
Con trỏ và mảng hai chiều
Cách sai:p = a ; // sai vì khác kiểu
Các cách đúng:// ép kiểu của a về con trỏ float (cũng là kiểu
//của p)
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
p = oa a;
p = a[0]; // gán với địa chỉ của mảng a[0]// gán với địa chỉ số thực đầu tiên trong a
p = &a[0][0];
8/19/2019 Bai 5- Mang va Con tro.pdf
51/63
Con trỏ và mảng hai chiều
Sau khi gán a cho p (p là con trỏ thực), việc tăng giảm p chính làdịch chuyển con trỏ trên từng phần tử (thực) của a.
p trỏ tới a[0][0]
p+1 trỏ tới a[0][1]
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
p+ r a
p+3 trỏ tới a[1][0]p+4 trỏ tới a[1][1]
p+5 trỏ tới a[1][2]
8/19/2019 Bai 5- Mang va Con tro.pdf
52/63
Mảng con trỏ
Nhiều con trỏ cùng kiểu cũng được tổ chức thành mảngMỗi phần tử của mảng con trỏ là một con trỏ trỏ đến một mảng
nào đóCách khai báo:
*tên_mảng_con_trỏ[size];
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
ụ:
int *a[10];khai báo một mảng a chứa 10 con trỏ. Mỗi con trỏ a[i] chứa địa chỉ của một mảng nguyên nào đó (kích thước các mảng này có thểkhác nhau)
8/19/2019 Bai 5- Mang va Con tro.pdf
53/63
Con trỏ và Hàm
Giá trị trả lại của hàm là một mảng:Không có cách nào để giá trị trả lại của một hàm là mảng
Hàm trả lại một con trỏ trỏ đến dãy dữ liệu kết quả là tươngđương với việc trả lại mảngMảng kết quả có thể được trả lại vào trong tham đối của hàm
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
ụ:
int* tragiatri1(){
// tạo mảng kết quả với 3 giá trị 1, 2, 3
int kq[3] = { 1, 2, 3 };
return kq ;
}
8/19/2019 Bai 5- Mang va Con tro.pdf
54/63
Con trỏ và Hàm
int* tragiatri2()
{
// cấp phát 3 ô nhớ nguyênint *kq = new int[3];
*kq = 1;
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
q+ = ;
*(kq+2)=3 ;return kq ;
}
8/19/2019 Bai 5- Mang va Con tro.pdf
55/63
Con trỏ và Hàm
main()
{
int *a, i;a = tragiatri1();
for (i=0; i
8/19/2019 Bai 5- Mang va Con tro.pdf
56/63
Con trỏ và Hàm
Việc sử dụng hàm trả lại con trỏ là phải hết sức cẩn thận. Muốntrả lại con trỏ cho hàm thì con trỏ này phải trỏ đến dãy dữ liệu
nào sao cho nó không mất đi sau khi hàm kết thúc như hàmtragiatri1()
Nếu muốn trả lại giá trị con trỏ thì vùng dữ liệu mà nó trỏ đến
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
p ược c p p m c c ư ng m n ng o n new ,
chứ không để chương trình tự động cấp phát và tự động thu hồiĐối và giá trị trả lại là xâu kí tựĐối của các hàm xâu kí tự có thể khai báo dưới 2 dạng: mảngkí tự hoặc con trỏ kí tựGiá trị trả lại luôn luôn là con trỏ kí tự
8/19/2019 Bai 5- Mang va Con tro.pdf
57/63
Con trỏ và Hàm
Đối là hằng con trỏKhi các biến ngoài không có nhu cầu thay đổi nhưng đối tương
ứng với nó vẫn phải khai báo dưới dạng con trỏCó khả năng do nhầm lẫn, các biến ngoài này sẽ bị thay đổingoài ý muốn
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
c n ược a o n ư m ng con r ng c c
thêm trước khai báo kiểu của chúng từ khoá const
8/19/2019 Bai 5- Mang va Con tro.pdf
58/63
Con trỏ Hàm
Một hàm (tập hợp các lệnh) cũng có tên gọi , có địa chỉ lưu trongbộ nhớ và có thể truy nhập đến hàm thông qua tên gọi hoặc địa
chỉ của nóĐể truy nhập (gọi hàm) thông qua địa chỉ chúng ta phải khai báomột con trỏ chứa địa chỉ này và sau đó gọi hàm bằng cách gọi tên
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
con r
Khai báo (*tên biến hàm)(d/s tham đối); (*tên biến hàm)(d/s tham đối) = ;Phân biệt giữa 2 khai báo: float (*f)(int) là khai báo con trỏ hàmcó tên là f và float* f(int) là khai báo hàm f với giá trị trả lại là mộtcon trỏ float
8/19/2019 Bai 5- Mang va Con tro.pdf
59/63
Con trỏ Hàm
/* khai báo con trỏ hàm có tên là f trỏ đến hàm
có một tham đối kiểu int và cho giá trị kiểu
float*/float (*f)(int);
// con trỏ trỏ đến hàm với cặp đối (float, int).
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
vo oa , n ;
Khởi ỏ Hà
8/19/2019 Bai 5- Mang va Con tro.pdf
60/63
Khởi tạo con trỏ Hàm
Cú pháp của khởi tạo cũng như phép gán là như sau:biến con trỏ hàm = tên hàm;
Con trỏ hàm f và tên hàm được trỏ phải giống nhau về kiểu trảlại và danh sách đốiVí dụ:
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
a o m u a
float luythua(float, int);// khai báo con trỏ f tương thích với hàm luythua
float (*f)(float, int);
f = luythua; // cho f trỏ đến hàm luỹ thừa
Sử d t ỏ hà
8/19/2019 Bai 5- Mang va Con tro.pdf
61/63
Sử dụng con trỏ hàm
Để sử dụng con trỏ hàm ta phải gán nó với tên hàm cụ thểBất kỳ nơi nào được phép xuất hiện tên hàm thì ta đều có thể
thay nó bằng tên con trỏfloat bphuong(float x) {return x*x;
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
void main(){
float (*f)(float);
f = bphuong;
cout
8/19/2019 Bai 5- Mang va Con tro.pdf
62/63
Mảng con trỏ hàm
Các con trỏ hàm giống nhau có thể được gộp lại vào trong mộtmảng
Thêm [n] vào sau tên mảng với n là số lượng tối đa các con trỏVí dụ:void cong(int a, int b){
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
cou
8/19/2019 Bai 5- Mang va Con tro.pdf
63/63
Mảng con trỏ hàm
main()
{
clrscr();// khai báo, khởi tạo 4 con trỏ
void (*f[4])(int, int) = {cong, tru, nhan, chia};
TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI
n m, n;
cout "Nhập m, n " ; cin >> m >> n ;for (int i=0; i