Con trỏ mảng 2 chiều trong c | Laptrinhcanban.com

Con trỏ mảng 2 chiều trong c

Cùng tìm hiểu về con trỏ mảng 2 chiều trong c. Bạn sẽ biết con trỏ mảng 2 chiều trong c là gì, cách sử dụng con trỏ mảng 2 chiều khi cấp phát bộ nhớ động cho mảng hai chiều trong C, cách sử dụng hàm malloc mảng 2 chiều trong c để cấp phát bộ nhớ, cách khai báo mảng 2 chiều bằng con trỏ trong c, cũng như cách sử dụng con trỏ mảng 2 chiều trong hàm và trong struct sau bài học này.

Con trỏ mảng 2 chiều trong c

Trong bài Con trỏ trong C là gì chúng ta đã biết, con trỏ trong C là một biến được dùng để lưu trữ địa chỉ của dữ liệu trong bộ nhớ máy tính.

Mảng 2 chiều cũng là một loại dữ liệu trong C, và do đó, chúng ta cũng có thể sử dụng con trỏ để lưu trữ địa chỉ và qua đó thao tác với mảng 2 chiều. Chúng ta gọi con trỏ sử dụng trong mảng 2 chiều là con trỏ mảng 2 chiều trong c, và sử dụng nó để truy cập vào địa chỉ của mảng trong bộ nhớ, khai báo cũng như lấy giá trị các phần tử trong nó.

Con trỏ mảng 2 chiều đặc biệt hữu ích khi chúng ta cần thao tác với mảng 2 chiều được tạo ra bằng cách cấp phát bộ nhớ động.

Cấp phát bộ nhớ động cho mảng hai chiều trong C

Trong các bài trước, chúng ta đã học cách xử lý các mảng 2 chiều với kích thước và độ dài cố định, nghĩa là số hàng và số cột trong mảng sẽ luôn luôn cố định, và mảng cũng chiếm một vùng bộ nhớ trong máy tính với một số byte nhất định. Các mảng như vậy được lưu trong bộ nhớ tĩnh, và chúng ta không thể thay đổi kích thước của mảng kiểu này sau khi tạo chúng.

Tuy nhiên khi sử dụng mảng 2 chiều trong C, kích thước của mảng không phải là lúc nào cũng cần phải cố định. Cũng có những lúc chúng ta muốn xóa đi một số hàng, số cột không cần thiết, và cũng có khi chúng ta muốn thêm phần tử vào mảng bằng cách thêm hàng và cột. Khi đó, thay vì mảng có kích thước cố định thì chúng ta cần phải dùng tới mảng có kích thước tự động thay đổi theo số hàng, số cột và số phần tử trong mảng.

Để có thể tự động thay đổi kích thước mảng như vậy, chúng ta cần cấp phát bộ nhớ động cho mảng hai chiều trong C, thông qua một hàm có sẵn là hàm malloc mảng 2 chiều trong c . Và để thao tác với bộ nhớ động được tạo ra bằng hàm này, chúng ta sẽ cần dùng tới con trỏ trong mảng 2 chiều.

Chú ý là khi sử dụng hàm malloc mảng 2 chiều trong c này, chúng ta cần phải giải phóng bộ nhớ sau khi đã sử dụng xong bộ nhớ động được cấp phát. Chúng ta sẽ sử dụng tới một hàm có sẵn là hàm free để thực hiện việc này.

Hai hàm trên đều được tích hợp trong header file 「stdlib.h」, do đó chúng ta phải ghi tên file này vào đầu chương trình để có thể sử dụng chúng.

Khai báo mảng 2 chiều bằng con trỏ trong c

Có hai phương pháp khai báo mảng 2 chiều bằng con trỏ trong c, một là xử lý nó như một mảng 2 chiều và hai là coi nó như một mảng 1 chiều để xử lý.

Khai báo mảng 2 chiều trong C dưới dạng con trỏ trong mảng 2 chiều

Trước tiên là cách xử lý mảng đã cho dưới dạng mảng 2 chiều. Trong trường hợp này, để truy cập vào từng hàng trong mảng 2 chiều, chúng ta cần 1 địa chỉ, và 1 con trỏ để lưu giữ địa chỉ đó. Do vậy, với một mảng có [y] hàng trong nó, chúng ta sẽ cần chuẩn bị một số lượng [y] con trỏ để có thể lưu giữ địa chỉ của chúng.

Để xử lý [y] con trỏ này, chúng ta cũng cần chuẩn bị một mảng mẹ để lưu giữ địa chỉ của các con trỏ này lại. Và để truy cập vào mảng mẹ này từ bộ nhớ, chúng ta cũng cần 1 địa chỉ trỏ đến nó, và 1 con trỏ để lưu giữ địa chỉ đó.

Lưu ý con trỏ dùng để lưu địa chỉ của mảng mẹ do dùng để lưu giữ địa chỉ của các con trỏ của hàng, nên chúng ta cần sử dụng nó dưới dạng con trỏ của con trỏ. Bạn có thể tìm hiểu chi tiết về kiểu con trỏ này trong bài: Con trỏ của con trỏ trong C.

Và để có thể tự động thay đổi kích thước mảng thì các mảng sử dụng ở đây đều được tạo bằng cách cấp phát bộ nhớ động cho mảng.

Và sau đây là chương trình khai báo mảng 2 chiều trong C dưới dạng con trỏ trong mảng 2 chiều:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
int y , x;
printf("Nhap so hang va so cot cua mang 2 chieu: ");
scanf("%d", &y);
scanf("%d", &x);
//Khai báo con trỏ của con trỏ
int **nums1;

/*Cấp phát bộ nhớ động cho 1 mảng mẹ gồm y phần tử,
để chứa địa chỉ tương ứng của y hàng trong mảng 2 chiều cần tạo*/
/*Gán địa chỉ mảng mẹ vào con trỏ nums1*/
nums1 = malloc(sizeof(int *) * y);

/*Cấp phát bộ nhớ động cho y mảng con, mỗi mảng gồm x phần tử,
để chứa x phần tử tương ứng trong từng hàng của mảng 2 chiều cần tạo*/
/*Gán địa chỉ của các mảng này vào phần tử của mảng mẹ*/
for(int i = 0; i < y; i++) {
nums1[i] = malloc(sizeof(int) * x);
}

/*Truy cập và gán giá trị lần lượt vào các phần tử của y mảng con đã tạo ở trên,
thông qua đia chỉ của chúng được gán trong con trỏ*/
printf("\nNhap phan tu: \n");
for(int i = 0; i < y; i++) {
for(int j = 0; j < x; j++) {
scanf("%d",&nums1[i][j]);//Gán giá trị nhập từ bàn phím vào phần tử
}
}

//In và kiểm tra mảng 2 chiều vừa khai báo
printf("Mang 2 chieu vua nhap\n");
for(int i = 0; i < y; i++) {
for(int j = 0; j < x; j++) {
printf("%d ", nums1[i][j]);
}
printf("\n");
}

// Giải phóng các bộ nhớ đã dùng để lưu các phần tử sau khi đã tạo mảng
for(int i = 0; i < y; i++) {
free(nums1[i]);
}
// Giải phóng bộ nhớ đã dùng để lưu địa chỉ mảng sau khi đã tạo mảng
free(nums1);

return 0;
}

Kết quả chương trình như sau:

Nhap so hang va so cot cua mang 2 chieu: 4 3

Nhap phan tu:
7 8 9
2 3 1
0 9 2
8 5 4
Mang 2 chieu vua nhap
7 8 9
2 3 1
0 9 2
8 5 4

Khai báo mảng 2 chiều trong C dưới dạng con trỏ trong mảng 1 chiều

Phương pháp thứ 2 để khai báo mảng 2 chiều bằng con trỏ trong c, đó chính là coi mảng 2 chiều đó như là 1 mảng 1 chiều.

Để coi mảng 2 chiều như một mảng 1 chiều, dữ liệu ở cuối hàng trước đó sẽ được sắp xếp bên cạnh dữ liệu ở đầu hàng tiếp theo và chúng được kết nối theo thứ tự.

Và chúng ta cũng chỉ cần sử dụng tới 1 con trỏ mà thôi.

Và sau đây là ví dụ khai báo mảng 2 chiều trong C dưới dạng con trỏ trong mảng 1 chiều.

#include <stdio.h>
#include <stdlib.h>

int main(void) {
int y , x;
printf("Nhap so hang va so cot cua mang 2 chieu: ");
scanf("%d", &y);
scanf("%d", &x);

int *nums2;
//Cấp phát bộ nhớ động cho 1 mảng gồm y×x phần tử
//Gán địa chỉ mảng trên vào con trỏ nums2
nums2 = malloc(sizeof(int) * x * y);

for(int i = 0; i < y; i++) {
for(int j = 0; j < x; j++) {
scanf("%d",&nums2[i * x + j]);//Gán giá trị nhập từ bàn phím vào phần tử
}
}

//In và kiểm tra mảng 2 chiều vừa khai báo
printf("Mang 2 chieu vua nhap\n");
for(int i = 0; i < y; i++) {
for(int j = 0; j < x; j++) {
if(j < x -1) {
printf("%d ", nums2[i * x + j]);
} else {
printf("%d\n", nums2[i * x + j]);
}
}
}

// Giải phóng bộ nhớ
free(nums2);

return 0;
}

Kết quả chương trình như sau:

Nhap so hang va so cot cua mang 2 chieu: 2 3
1 2 3
2 3 4
Mang 2 chieu vua nhap
1 2 3
2 3 4

Sử dụng con trỏ mảng 2 chiều trong hàm

Ngoài cách sử dụng trực tiếp con trỏ trong mảng 2 chiều như Kiyoshi đã hướng dẫn ở trên, chúng ta cũng có thể sử dụng nó như là đối số trong một hàm, hoặc là thành viên trong kiểu struct.

Sau đây là ví dụ sử dụng con trỏ mảng 2 chiều trong hàm C:

#include <stdio.h>
#include <stdlib.h>

void init_2d_array(int *arr, int x, int y) {
for(int i = 0; i < y; i++) {
for(int j = 0; j < x; j++) {
arr[i * x + j] = i * x + j; // Khởi tạo giá trị trong mảng
}
}
}

int main(void) {
int x = 3, y = 5;

int *nums;
//Cấp phát bộ nhớ động cho 1 mảng gồm y×x phần tử
//Gán địa chỉ mảng trên vào con trỏ nums
nums = malloc(sizeof(int) * x * y);

init_2d_array(nums, 5, 3);

for(int i = 0; i < y; i++) {
for(int j = 0; j < x; j++) {
if(j < x - 1) {
printf("%d ", nums[i * x + j]);
} else {
printf("%d\n", nums[i * x + j]);
}
}
}

// Giải phóng bộ nhớ
free(nums);

return 0;
}

Kết quả:

0 1 2
3 4 5
6 7 8
9 10 11
12 13 14

Trong chương trình trên chúng ta đã tạo hàm init_2d_array() để khai báo mảng 2 chiều bằng con trỏ trong c. Đối số của hàm này là một con trỏ, cũng như kích thước hàng và cột của mảng 2 chiều cần khai báo.

Lại nữa, con trỏ nums được sử dụng để lưu giữ địa chỉ của các phần tử có trong mảng 2 chiều được tạo ra bằng cách cấp phát bộ nhớ động, thông qua hàm marloc() trong C.

Sử dụng con trỏ mảng 2 chiều trong struct

Ngoài cách sử dụng trực tiếp con trỏ trong mảng 2 chiều như Kiyoshi đã hướng dẫn ở trên, chúng ta cũng có thể sử dụng nó như là đối số trong một hàm, hoặc là thành viên trong kiểu struct.

Sau đây là ví dụ sử dụng con trỏ mảng 2 chiều trong struct:

#include <stdio.h>
#include <stdlib.h>

typedef struct str{
int x;
int y;
int *arr;
} number;

void init_2d_array_struct(number *num) {
for(int i = 0; i < num->y; i++) {
for(int j = 0; j < num->x; j++) {
num->arr[i * num->x + j] = i * num->x + j; // Khởi tạo struct
}
}
}

int main(void) {
// Khởi tạo và khai báo struct
number num;
num.x = 3;
num.y = 5;
// Cấp phát bộ nhớ động cho 1 mảng gồm y×x phần tử
num.arr = malloc(sizeof(int) * num.x * num.y);

init_2d_array_struct(&num);

for(int i = 0; i < num.y; i++) {
for(int j = 0; j < num.x; j++) {
if(j < num.x - 1) {
printf("%d ", num.arr[i * num.x + j]);
} else {
printf("%d\n", num.arr[i * num.x + j]);
}
}
}

// Giải phóng bộ nhớ
free(num.arr);

return 0;
}

Kết quả:

0 1 2
3 4 5
6 7 8
9 10 11
12 13 14

Trong ví dụ trên thì chúng ta khai báo kiểu struct trong c với [x] là số phần tử trong một hàng và [y] là số hàng có trong struct. Con trỏ [arr] ở đây được dùng để lưu giữ địa chỉ của các dữ liệu có trong mảng 2 chiều cần tạo.

Hàm init_2d_array_struct() sử dụng địa chỉ của struct đã tạo (&num), và thực hiện gán các giá trị vào struct đã khai báo.

Lại nữa, con trỏ arr được sử dụng để lưu giữ địa chỉ của các phần tử có trong mảng 2 chiều được tạo ra bằng cách cấp phát bộ nhớ động, thông qua hàm marloc() trong C.

Tổng kết

Trên đây Kiyoshi đã hướng dẫn bạn về cách sử dụng con trỏ mảng 2 chiều trong c rồi. Để nắm rõ nội dung bài học hơn, bạn hãy thực hành viết lại các ví dụ của ngày hôm nay nhé.

Và hãy cùng tìm hiểu những kiến thức sâu hơn về C trong các bài học tiếp theo.

HOME>> >>

Profile
きよしです!笑

Tác giả : Kiyoshi (Chis Thanh)

Kiyoshi là một cựu du học sinh tại Nhật Bản. Sau khi tốt nghiệp đại học Toyama năm 2017, Kiyoshi hiện đang làm BrSE tại Tokyo, Nhật Bản.