CodeGym /Các khóa học /C# SELF /Làm quen với mảng

Làm quen với mảng

C# SELF
Mức độ, Bài học
Có sẵn

1. Mảng — là container chứa các phần tử

Chắc bạn từng nghe máy tính có thể xử lý lượng thông tin khổng lồ. Câu lệnh điều kiện (if-else) và vòng lặp (for, while) đúng là giúp được phần nào. Nhưng chỉ thế thì chưa đủ, vì dữ liệu xử lý cần phải lưu ở đâu đó nữa.

Cho trường hợp này, trong C# cũng như hầu hết các ngôn ngữ lập trình khác, có một thứ cực kỳ tiện là mảng (Array). Người ta còn gọi nó là bảng (table) nữa.

Mảng — là một object đặc biệt, nơi bạn có thể lưu không chỉ một giá trị mà là nhiều giá trị cùng lúc.

Arrays (Array) C#

Nếu trước đây mình so sánh biến với cái hộp (để lưu một giá trị nào đó), thì mảng giống như cái hộp được chia thành nhiều ngăn nhỏ bên trong. Mỗi ngăn trong “hộp-mảng” đều có số thứ tự riêng. Đánh số thì tất nhiên bắt đầu từ 0 rồi...

Hoặc bạn có thể tưởng tượng thêm một ví dụ nữa. So sánh nhà riêng với chung cư. Nhà riêng thì một gia đình ở, còn chung cư thì chia thành nhiều căn hộ. Nếu muốn gửi thư cho gia đình ở nhà riêng, bạn chỉ cần ghi địa chỉ nhà. Còn gửi thư cho gia đình ở chung cư thì phải ghi địa chỉ nhà và số căn hộ.

Vậy nên, biến-mảng giống như biến-chung cư. Nó không chỉ lưu một giá trị mà là nhiều giá trị. Trong biến này có nhiều căn hộ (ô nhớ), mỗi ô có thể truy cập bằng số thứ tự (index) của nó.

Để làm vậy, sau tên biến bạn chỉ cần ghi số index trong dấu ngoặc vuông. Cực kỳ đơn giản luôn:


array[chỉ_số] = giá_trị;
Gán giá trị cho ô trong mảng theo chỉ số

Ở đây array là tên biến-mảng, chỉ_số là số thứ tự của ô trong mảng, còn giá_trị là giá trị bạn muốn gán cho ô đó.

Nhưng trước hết, hãy xem cách tạo mảng đã nhé.

2. Tạo mảng phần tử trong C#

Tạo mảng phần tử trong C#

Giả sử chương trình của bạn cần lưu 100 số nguyên ở đâu đó. Chắc chắn mảng là lựa chọn hợp lý. Vậy tạo nó như nào?

Nếu chỉ cần lưu một số nguyên, bạn dùng kiểu int, còn nếu muốn lưu 100 số nguyên, chắc chắn bạn cần mảng kiểu int. Đây là code tạo mảng đó:

int[] array = new int[100];
Tạo mảng gồm 100 số nguyên

Cùng phân tích xem dòng này có gì nhé.

Như bạn đoán, bên trái dấu bằng là khai báo biến tên array kiểu int[]. Sau kiểu int là dấu ngoặc vuông, ám chỉ rằng “hộp” kiểu này có thể chứa nhiều giá trị.

Bên phải dấu bằng là “tạo object” (từ khóa new) gồm 100 phần tử (ô nhớ) kiểu int. Cũng không khó lắm nhỉ.

Nếu muốn tạo mảng 20 ô để lưu số thực, code sẽ như này:

double[] vals = new double[20];
Tạo mảng gồm 20 số thực

Số ô trong mảng gọi là kích thước mảng hoặc độ dài mảng. Vì khả năng lưu nhiều giá trị nên mảng còn được gọi là container.

Lưu ý quan trọng: kích thước container của mảng không thể thay đổi sau khi tạo.

Bạn có thể tạo mới mảng khác, nhưng không thể đổi độ dài của mảng đã tạo.

3. Làm việc với các ô trong mảng

Làm việc với các ô trong mảng

Ok, tạo mảng thì biết rồi, vậy làm việc với nó thế nào cho đúng?

Gần như giống với biến thường, chỉ khác là sau tên biến-mảng phải ghi số ô (index) bạn muốn thao tác.

Các ô trong mảng luôn đánh số từ 0. Nếu mảng có 10 phần tử thì index là 0..9, nếu mảng có 200 phần tử thì là 0..199. Cứ thế mà suy ra.

Ví dụ:

int[] a = new int[10];	// Tạo mảng 10 phần tử kiểu int.

a[2] = 4;				// Gán giá trị 4 cho ô có index 2.

a[7] = 9;				// Gán giá trị 9 cho ô có index 7.

a[9] = a[2] + a[5];		// Gán tổng giá trị ở ô 2 (là 4) và ô 5 (là 0) cho ô 9. 

Sau khi chạy đoạn code trên, bộ nhớ sẽ như này:

Working with int array cells

Cột bên trái (màu xám) là số thứ tự (index) của các ô. Trong các ô lưu giá trị đã gán: 4, 9 và 4. Ngay sau khi tạo, các ô trong mảng đều được gán bằng 0.

Lưu ý. Tất cả các ô trong mảng đều cùng kiểu dữ liệu. Nếu tạo mảng kiểu string, thì chỉ lưu được chuỗi thôi. Kiểu dữ liệu của mảng được xác định khi tạo. Không thể đổi kiểu dữ liệu hoặc độ dài mảng sau này.

4. Mảng trong bộ nhớ

Các hình minh họa trước hơi chưa chính xác lắm.

Khi tạo mảng (cũng như khi tạo string), bộ nhớ sẽ cấp phát hai vùng: một cho mảng (container), một cho biến lưu địa chỉ của nó. Hình dưới đây minh họa rõ hơn:

Arrays in memory

Màu xanh lá là mảng 10 phần tử kiểu int và biến kiểu int[] lưu địa chỉ (tham chiếu) của mảng kiểu int trong bộ nhớ.

Để so sánh, màu xanh dương là biến thường kiểu int lưu giá trị 199.

Trông cũng giống cách lưu string trong bộ nhớ nhỉ?

Chuẩn luôn, string đó. Và cũng như với string, “biến kiểu mảng” có thể gán cho nhau:

int[] a = new int[10];		// Tạo mảng 10 phần tử kiểu int.

a[2] = 4;					// Gán giá trị 4 cho ô 2.
a[7] = 9;					// Gán giá trị 9 cho ô 7.

int[] b = a;				// Biến b lưu địa chỉ giống biến a.
                            // Giờ a và b cùng trỏ đến một object-mảng trong bộ nhớ.

a[9] = b[2] + a[7];			// Gán tổng giá trị ở ô 2 (4) và ô 7 (9) cho ô 9. 

Object-mảng vẫn nằm nguyên chỗ cũ, còn biến a và b đều lưu cùng một địa chỉ (tham chiếu) đến object đó. Xem hình minh họa:

Arrays in memory 2

5. Làm việc với mảng chi tiết hơn

Bạn có thể tạo mảng từ bất kỳ kiểu nào. Chỉ cần sau tên kiểu ghi thêm dấu ngoặc vuông. Cú pháp tổng quát như sau:

kiểu[] tên = new kiểu[số_lượng];
Cú pháp chuẩn để tạo mảng

Ở đây kiểu là kiểu phần tử (ô) của mảng mà bạn sẽ lưu. tên là tên biến để bạn truy cập mảng, còn số_lượng là số ô trong mảng.

Ví dụ trên là cú pháp chuẩn: vừa tạo biến-mảng vừa tạo object-mảng. Thực ra hai bước này tách riêng cũng được:


kiểu[] tên;
tên = new kiểu[số_lượng];
        
Tạo biến và mảng riêng biệt

Và còn một điểm quan trọng nữa

Chỉ số mảng và số lượng phần tử mảng có thể là biến hoặc cả biểu thức.

Ví dụ:

int n = 100;
int[] a = new int[n];			// 	Tạo mảng n phần tử

int n = 100;
int[] a = new int[n * 2 + 3];	// 	Tạo mảng 203 phần tử

int n = 100;
int[] a = new int[n];
a[n-1] = 2;					// a[99] = 2;
a[n-2] = 3;					// a[98] = 3;
a[n/5] = a[n-1] + a[n-2];	// a[20] = a[99] + a[98];

Vượt quá giới hạn mảng

Lưu ý, nếu bạn thử truy cập ô mảng với chỉ số không tồn tại (ở đây là mọi số nguyên ngoài 0..99), chương trình sẽ bị lỗi IndexOutOfRangeException — chỉ số vượt quá giới hạn mảng.

6. Độ dài mảng

Như ví dụ trước, bạn có thể tạo biến kiểu mảng rồi sau đó gán giá trị (tham chiếu đến object-mảng) ở đâu đó trong code. Thậm chí như này:

int[] array;			//	Tạo biến-mảng kiểu int[]
if (a < 10)				// Nếu biến a nhỏ hơn 10,
   array = new int[10];	// thì tạo mảng 10 phần tử.
else					// Ngược lại
   array = new int[20];	// tạo mảng 20 phần tử 

Vậy làm sao biết mảng này có bao nhiêu phần tử?

Mảng có thuộc tính đặc biệt (biến) — length. Để lấy độ dài mảng, dùng biểu thức:

array.Length;
Lấy độ dài mảng qua thuộc tính Length

Ở đây array là tên biến-mảng, Length là tên thuộc tính của object-mảng. Không thể thay đổi giá trị thuộc tính Length: bạn có thể gán nó cho biến khác, nhưng không thể gán giá trị cho nó (chương trình sẽ không biên dịch được đâu).

Có thể tiếp tục ví dụ trên như sau:

int[] array;			//	Tạo biến-mảng kiểu int[]
if (a < 10)				// Nếu biến a nhỏ hơn 10,
   array = new int[10];	// thì tạo mảng 10 phần tử.
else					// Ngược lại
   array = new int[20];	// tạo mảng 20 phần tử 

for (int i = 0; i < array.Length; i++)	// Lặp qua tất cả phần tử mảng: từ 0 đến array.Length - 1
{
   Console.WriteLine(array[i]);
}

7. Một số sự thật về mảng trong C#

Tóm lại, đây là những điều bạn cần nhớ về mảng:

  • Sự thật 1. Mảng gồm nhiều ô nhớ.
  • Sự thật 2. Truy cập từng ô bằng số thứ tự (index).
  • Sự thật 3. Tất cả các ô cùng kiểu dữ liệu.
  • Sự thật 4. Giá trị khởi tạo cho tất cả ô là 0 và null (nếu ô lưu địa chỉ), false (cho kiểu bool).
  • Sự thật 5. string[] list — chỉ là khai báo biến: container (object-mảng) chưa được tạo. Muốn dùng phải tạo mảng (container) rồi gán vào biến này, sau đó mới dùng được. Xem ví dụ dưới.
  • Sự thật 6. Khi tạo object-mảng (container), phải chỉ rõ độ dài — số ô trong mảng. Làm bằng lệnh: new TypeName[n];
  • Sự thật 7. Độ dài mảng lấy qua thuộc tính .Length.
  • Sự thật 8. Sau khi tạo mảng, không thể đổi kiểu phần tử hoặc số lượng phần tử.
string s;				// s bằng null
string[] list;			// list bằng null

list = new string[10];	// Biến list lưu tham chiếu đến object – mảng string 10 phần tử.
int n = list.Length;	// n bằng 10

list = new string[0];	// Giờ list chứa mảng 0 phần tử. 
                        // Có mảng nhưng không lưu được phần tử nào.

list = null;
Console.WriteLine(list[1]); // Sẽ bị lỗi chương trình — chương trình dừng đột ngột. 
                            // list chứa tham chiếu rỗng — null

list = new string[10];
Console.WriteLine(list[10]);	// Sẽ bị lỗi — vượt quá giới hạn mảng.
//	Nếu list có 10 phần tử/ô, thì index hợp lệ là: 0 1 2 3 4 5 6 7 8 9 — tổng cộng 10 số. 	
2
Nhiệm vụ
C# SELF, mức độ, bài học
Đã khóa
Tạo và in ra mảng số nguyên
Tạo và in ra mảng số nguyên
2
Nhiệm vụ
C# SELF, mức độ, bài học
Đã khóa
Tổng các phần tử của mảng
Tổng các phần tử của mảng
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION