Nội dung
1. Con trỏ và mảng 1 chiều.
Như trong bài Mảng chúng ta đã biết ta có thể coi biến mảng như một con trỏ, vì vậy ta có thể sử dụng chính biến mảng đó để truy cập mảng theo cách của con trỏ.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| #include void nhapMang( int a[], int n) { int i; for (i = 0; i < n; i++) { printf ( "Nhap a[%d] = " , i); scanf ( "%d" , &a[i]); } } void nhapContro( int a[], int n){ int i; for (i = 0; i < n; i++) { printf ( "Nhap a[%d] = " , i); scanf ( "%d" , a + i); } } void xuatMang( int a[], int n) { int i; for (i = 0; i < n; i++) { printf ( "%d \t" , a[i]); } } int main() { // khai bao mang a co n phan tu int n = 5; int a[n]; nhapContro(a, n); xuatMang(a, n); return 0; } |
Ở hàm thứ hai, chúng ta chỉ thay &a bằng a+i vì khi khai báo a[20] thì a coi như là một con trỏ và máy sẽ cấp phát cho ta các ô nhớ liên tiếp từ a đến a + 19. Và a + i là địa chỉ của a[i] (tức nó <=> &a[i]). a trỏ đến vị trí a[0].
Ngoài ra bạn có thể khai báo 1 mảng sau đó dùng 1 con trỏ trỏ tới đầu mảng thì con trỏ đó cũng trở thành mảng đó.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
| #include int main() { int n = 5, i; int a[n], *pa; pa = a; // con tro pa tro toi dau mang a for (i = 0; i < n; i++) { printf ( "Nhap a[%d] = " , i); scanf ( "%d" , pa + i); } for (i = 0; i < n; i++) { printf ( "%d \t" , *(pa + i)); } return 0; } |
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
| #include #include int main() { int n = 5, i; // cap phat bo nho cho pa int *pa = ( int *) malloc (n * sizeof ( int )); for (i = 0; i < n; i++) { printf ( "Nhap a[%d] = " , i); scanf ( "%d" , pa + i); } for (i = 0; i < n; i++) { printf ( "%d \t" , *(pa + i)); } return 0; } |
2. Nhập mảng trong hàm
Việc nhập mảng không phải lúc nào cũng thuận lợi vì như các ví dụ trước chúng ta cần phải có số lượng phần tử của mảng trước khi cấp phát hoặc nhập, vậy nếu chúng ta chưa biết trước số phần tử mà lại phải dùng hàm để nhập mảng thì sao. Các bạn xem ví dụ sau.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| #include #include void nhapContro( int *(*a), int *n) { int i; printf ( "Nhap so phan tu cua mang: " ); scanf ( "%d" , n); // khong phai &n *a = ( int *) malloc ((*n) * sizeof ( int )); // *a : lay dia chi cua mang a chu khong phai gia tri cua a for (i = 0; i < *n; i++) { printf ( "Nhap a[%d] = " , i); scanf ( "%d" , (*a + i)); } } void xuatMang( int *a, int n) { int i; for (i = 0; i < n; i++) { printf ( "%d \t" , a[i]); } } int main() { int *a, n; nhapContro(&a, &n); // lay dia chi cua a va n xuatMang(a, n); return 0; } |
Có 1 điểm chú ý là trong hàm nhập mảng a bằng con trỏ thì có 2 dấu *. 1 dấu là của mảng a (dấu thứ 2), còn dấu đầu tiên là dùng để truyền địa chỉ làm giá trị của mảng có thể giữ nguyên khi ra khỏi hàm, nó giống như là dấu * trong hàm HoanVi(int *a,int *b) vậy.
3.Con trỏ và xâu ký tự
Do xâu ký tự bản chất cũng là mảng các ký tự nên phần này nó cũng tương tự như mảng 1 chiều, mình sẽ nói qua 1 chút bằng 1 ví dụ đơn giản.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
| #include #include int main() { char *name; name = ( char *) malloc (100* sizeof ( char )); printf ( "What your name? " ); gets (name); printf ( "Oh, Hello %s" , name); return 0; } |
4. Con trỏ và mảng 2 chiều, mảng các con trỏ – Con trỏ đa cấp
a. Con trỏ và mảng 2 chiều
Phần trên chúng ta đã tìm hiểu về con trỏ và mảng 1 chiều, và phần này con trỏ và mảng 2 chiều cũng tương tự như vậy.Như ta đã biết thực chất trong máy tính thì bộ nhớ lưu mảng 2 chiều giống như mảng 1 chiều. Vì vậy ta hoàn toàn có thể biểu diễn mảng 2 chiều bằng con trỏ giống như mảng 1 chiều.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
| #include #include int main() { double a[10][10], *pa; int n, m, i; pa = ( double *) a; printf ( "Nhap so hang va so cot: " ); scanf ( "%d %d" , &n, &m); for (i = 0 ; i < n * m; i++) { printf ( "Nhap a[%d][%d] = " , i / m, i % m); scanf ( "%lf" , pa + i); } for (i = 0 ; i < n * m; i++) { if (i % m == 0) printf ( "\n" ); // xuong dong printf ( "%-5.2lf" , *(pa + i)); } return 0; } |
Nhap so hang va so cot: 2Ngoài ra, chúng ta có thể không cần dùng pa mà dùng ngay a là 1 con trỏ. Hoặc ta có thể nhập 1 cách tương tự như mảng 2 chiều bình thường như sau.
3
Nhap a[0][0] = 4.23
Nhap a[0][1] = 5.7
Nhap a[0][2] = 1.2
Nhap a[1][0] = 8.6
Nhap a[1][1] = 3.456
Nhap a[1][2] = 12
4.23 5.70 1.20
8.60 3.46 12.00
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| #include #include int main() { double a[10][10], *pa; int n, m, i, j; pa = ( double *) a; printf ( "Nhap so hang va so cot: " ); scanf ( "%d %d" , &n, &m); for (i = 0 ; i < n; i++) { for (j = 0 ; j < m; j++) { printf ( "Nhap a[%d][%d] = " , i, j); scanf ( "%lf" , pa + i * 10 + j); } } for (i = 0 ; i < n; i++) { printf ( "\n" ); // xuong dong for (j = 0 ; j < m; j++) { printf ( "%-5.2lf" , *(pa + i * 10 + j)); } } return 0; } |
Các bạn chú ý là ta có thể viết a[i][j] nhưng không thể viết pa[i][j] vì theo khai báo thì a là mảng 2 chiều nên ta có thể viết như vậy còn pa là 1 con trỏ và khi ta gán pa = a thì ta đã ngầm định coi a là mảng 1 chiều. Vì vậy nếu có thì chúng ta cũng chỉ được phép viết pa[i10+j] (lấy giá trị) và &pa[i10+j] (lấy địa chỉ).
b. Mảng các con trỏ
Mảng con trỏ là một mảng chứa tập hợp các con trỏ cùng một kiểu.Float *a[10]; // khai báo một mảng con trỏ. Gồm 10 con trỏ: a[0], a[1], …a[9]; là 10 con trỏ.
Liên hệ với mảng 2 chiều thì ta có nhận xét sau: Mỗi hàng của mảng 2 chiều ta coi như 1 mảng 1 chiều. Mà mỗi con trỏ thì lại có mối quan hệ với 1 mảng 1 chiều, ta có hình vẽ:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| #include #include int main() { double a[10][10], *pa[10]; int n, m, i, j; printf ( "Nhap so hang va so cot: " ); scanf ( "%d %d" , &n, &m); for (i = 0 ; i < n; i++) { pa[i] = a[i]; // con tro thu i tro den hang thu i for (j = 0 ; j < m; j++) { printf ( "Nhap a[%d][%d] = " , i, j); scanf ( "%lf" , &pa[i][j]); } } for (i = 0 ; i < n; i++) { printf ( "\n" ); // xuong dong for (j = 0 ; j < m; j++) { printf ( "%-5.2lf" , pa[i][j]); } } return 0; } |
Các ví dụ ở trên chúng ta đều xét khi mà khai báo mảng a[][] nên không cần cấp phát bộ nhớ cho con trỏ, bây giờ muốn cấp phát bộ nhớ cho con trỏ với mảng 2 chiều giống như cấp phát ở mảng 1 chiều thì ta làm như sau:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| #include #include int main() { double **pa; int n, m, i, j; printf ( "Nhap so hang va so cot: " ); scanf ( "%d %d" , &n, &m); // cap phat n o nho cho n con tro (n hang) pa = ( double **) malloc (n * sizeof ( double )); for (i = 0 ; i < n; i++) { // cap phat m o nho cho moi con tro (moi hang) pa[i] = ( double *) malloc (m * sizeof ( double )); for (j = 0 ; j < m; j++) { printf ( "Nhap a[%d][%d] = " , i, j); scanf ( "%lf" , &pa[i][j]); } } for (i = 0 ; i < n; i++) { printf ( "\n" ); // xuong dong for (j = 0 ; j < m; j++) { printf ( "%-5.2lf" , pa[i][j]); } } return 0; } |
0 nhận xét:
Đăng nhận xét