30/09/2018, 17:25

Truy xuất mảng 2 chiều trong C và C++

Có rất nhiều người sử dụng mảng 2 chiều mà chưa thực sự hiểu về nó.
Ví dụ: int array[m][n],
Tức là mảng có m phần tử, mỗi phần tử trong m phần tử có n phần tử con (chiếm 4 byte trong RAM).
Trong giáo trình của một thầy trường đh KHTN biên soạn, có 2 nhận xét như sau:

  1. "- Mảng 2 chiều là mảng mà mỗi phần tử là 1 mảng 1 chiều,
  • Vị trí của các phần tử trong mảng 2 chiều được xác định thông qua chỉ số hàng và chỉ số cột"
    Mỗi phần tử là 1 mảng 1 chiều rồi thì “vị trị các phần tử trong mảng 1 chiều được xác định …” chứ sao lại ví trí các phần tử trong mảng 2 chiều: Đây là cái SAI thứ NHẤT.
  1. " Mảng 2 chiều có m hàng và n cột thì phần tử a [ i ] [ j ] TƯƠNG ĐƯƠNG a [ i * n + j ]" : Đây là cái SAI thứ HAI
    Điều này chỉ đúng cho con trỏ (int* pointer) nếu nó trỏ tới mảng 2 chiều thôi chứ dùng tên mảng là sai hoàn toàn. Vì:
  • Tên mảng 2 chiều nó như một con trỏ, con trỏ này nó trỏ tới vùng nhớ có giá trị n4byte chứ không đơn giản trỏ tới vùng nhớ 4byte như con trỏ int thông thường.
    Rất mong m.n đọc bài kĩ và cho ý kiến!
Nguyễn Hữu Điền viết 19:30 ngày 30/09/2018

Tài liệu nào vậy bạn?

... viết 19:32 ngày 30/09/2018
  1. " Mảng 2 chiều có m hàng và n cột thì phần tử a [ i ] [ j ] TƯƠNG ĐƯƠNG a [ i * n + j ]" : Đây là cái SAI thứ HAI

Bạn dùng như thế nào mà sai?

Đinh Việt Thắng viết 19:29 ngày 30/09/2018

Tài liệu do thầy tự biên soạn thành slide,

Đinh Việt Thắng viết 19:39 ngày 30/09/2018

Bạn dùng như thế nào mà sai?

đây, nếu nó tương đương bản lấy đoạn đơn giản này về chạy xem có đúng không?

#include <stdio.h>


int main()
{
		int a[2][3] = 
		{
		{1,2,3},
		{4,5,6}
		};
		int i,j;
		for ( i = 0; i < 2; i++)
		{
			for ( j = 0; j < 3; j++)
			{
				printf("%d ", a[i*3+j]);
			}
		}	
}
viết 19:26 ngày 30/09/2018

cái này là do câu cú tiếng Việt thôi.

  1. ý của tác giả là mảng 2 chiều là mảng 1 chiều bao gồm 1 hoặc nhiều mảng 1 chiều. Ở đây nếu coi mảng 2 chiều là mảng 1 chiều của mảng thì mỗi phần tử của mảng 2 chiều là mảng 1 chiều. Nhưng thực tế chả ai quan tâm cái phần tử mảng 1 chiều này cả, người ta quan tâm tới từng ô trong mảng 2 chiều. Mỗi ô này được xác định thông qua chỉ số hàng và cột. Gọi mỗi ô là phần tử trong mảng 2 chiều thì cũng có lý. Nói chung là từ ngữ tiếng Việt mà hiểu ý tác giả thôi.

  2. cái này lại 1 lần nữa tác giả gộp ngắn gọn lại a[i][j] thì a là con trỏ tạm gọi là con trỏ 2 cấp, trong khi a[i*n + j] thì rõ ràng a là con trỏ 1 cấp. Đáng lẽ tốn thêm vài dòng ép kiểu để giải thích, vẽ vài tấm hình để giải thích thì tác giả lại bỏ qua.

ví dụ cái code trên thì chỉ cần thêm 1 dòng int* b = (int*) a; rồi sửa a[…] thành b[…] là được:

#include <stdio.h>

int main()
{
    int a[2][3] = { {1,2,3}, {4,5,6} };
    int i, j;
    int* b = (int*) a;
    for (i = 0; i < 2; i++)
        for (j = 0; j < 3; j++)
            printf("%d ", b[i*3+j]);
    return 0;
}

ý tác giả ở đây là do bộ nhớ chỉ có 1 chiều, muốn có mảng 2 chiều thì phải ép/xếp thành 1 chiều, mỗi hàng liên tiếp nhau. Như vậy ta truy cập theo kiểu [i*n + j] là hoàn toàn đúng. Vẽ thêm cái hình

[x......x+3][x+4....x+7][x+8...x+11][x+12..x+15][x+16..x+19][x+20..x+23]
(phần tử b0)(phần tử b1)(phần tử b2)(phần tử b3)(phần tử b4)(phần tử b5)
[integer_11][integer_12][integer_13][integer_21][integer_22][integer_23]
 ^a[0]                               ^a[1]                   a[1][2]
                                                             b[1*3+2] hay b[5]

rồi tốn thêm mấy dòng giải thích nữa là được

Đinh Việt Thắng viết 19:32 ngày 30/09/2018

Nhưng thực tế chả ai quan tâm cái phần tử mảng 1 chiều này cả

Bạn nói rất đúng, m đồn ý hết ngoài câu này.
Việc quan tâm tới phần tử là mảng 1 chiều trong mảng 2 chiều rất quan trọng chứ không phải không, cần phải hiểu rõ trỏ tời từng phần tử mảng 1 chiều trong mảng 2 chiều ntn:
Ví dụ:
bạn muốn nhập tên của sinh viên chẳng hạn, mỗi 1 tên sẽ lưu vào 1 hàng của mảng 2 chiều ( tức là phần tử mảng 1 chiều)
Thử hỏi nếu không hiểu rõ và biết cách truy xuất đến phần tử 1 chiều trong mảng 2 chiều thì bạn nhập và lưu ntn?

lâm phúc tài viết 19:28 ngày 30/09/2018

mình thấy nó giống câu cú thôi, cơ mà cái sai thứ 2 thì chắc bạn nói đúng rồi, đang là mảng tĩnh thì sao sài con trỏ vứt vô vậy được.
còn con trỏ khi nói vậy cũng ko đúng vì có 1 số sách khi tạo mảng hai chiều bằng con trỏ thì tạo trước 1 mảng con trỏ sau đó mỗi con trỏ tạo một mảng 1 chiều thì khi truy xuất từng phần tử cũng y chang mảng tĩnh.
Túm lại, mấy cáu này cũng đừng quan trọng quá vì khi coi bản chất thì lấy mấy cuốn như programing for c ấy ra đọc nó mới chính xác

Bài liên quan
0