Một mảng lưu trữ một tập hợp tuần tự có kích thước cố định của các phần tử cùng loại. Một mảng được sử dụng để lưu trữ một tập hợp dữ liệu, nhưng thường hữu ích hơn khi nghĩ về một mảng là một tập hợp các biến cùng loại được lưu trữ tại các vị trí bộ nhớ liền kề.
Thay vì khai báo các biến riêng lẻ, chẳng hạn như number0, number1, ... đến number99, bạn có thể khai báo một mảng numbers và sử dụng numbers[0], numbers[1] và ..., numbers[99] để biểu thị cho các biến riêng lẻ ở trên. Một phần tử cụ thể trong một mảng được truy cập bởi một chỉ mục.
Tất cả các mảng bao gồm các vị trí bộ nhớ liền kề. Địa chỉ thấp nhất tương ứng với phần tử đầu tiên và địa chỉ cao nhất cho phần tử cuối cùng.
datatype[] arrayName;
Giải thích:
Ví dụ:
double[] balance;
Việc khai báo một mảng không khởi tạo mảng trong bộ nhớ. Khi biến mảng được khởi tạo, bạn có thể gán giá trị cho mảng đó.
Mảng là một kiểu tham chiếu, vì thế bạn cần sử dụng từ khóa new trong C# để tạo một thể hiện của mảng đó. Ví dụ:
double[] balance = new double[10];
Bạn có thể gán giá trị cho các phần tử mảng riêng biệt bởi sử dụng chỉ số mảng, như:
double[] balance = new double[10];
balance[0] = 123.0;
Bạn có thể gán giá trị cho mảng tại thời điểm khai báo mảng, như sau:
double[] balance = { 123.0, 456.69, 789.0};
Bạn cũng có thể tạo và khai báo một mảng, như sau:
int[] marks = new int[6] { 90, 98, 92, 97, 95, 99 };
Bạn cũng có thể bỏ qua kích cỡ mảng, như:
int[] marks = new int[] { 90, 98, 92, 97, 95, 99 };
Bạn có thể sao chép một biến mảng vào trong biến mảng khác. Trong tình huống này, cả biến mảng mới và biến mảng nguồn đều trỏ tới cùng vị trí bộ nhớ:
int[] marks = new int[] { 90, 98, 92, 97, 95, 80 };
int[] score = marks;
Khi bạn tạo một mảng, trình biên dịch C# ngầm định gắn giá trị mặc định cho từng phần tử của mảng phụ thuộc vào kiểu mảng. Ví dụ, với một mảng int, thì tất cả phần tử được gắn giá trị là 0.
Một phần tử được truy cập bởi chỉ mục mảng. Điều này được thực hiện bởi việc đặt vị trí của phần tử bên trong dấu ngoặc vuông ở sau tên mảng. Ví dụ:
double salary = balance[3];
Ví dụ sau minh họa khái niệm về khai báo, gán và truy cập mảng trong C# đã đề cập ở trên:
using System;
namespace ArrayApplication
{
class MyArray
{
static void Main(string[] args)
{
int[] numbers = new int[10];
for (int i = 0; i < 10; i++)
{
numbers[i] = i + 100;
}
for (int j = 0; j < 10; j++)
{
Console.WriteLine("Element[{0}] = {1}", j, numbers[j]);
}
Console.ReadKey();
}
}
}
Kết quả khi chạy chương trình trên:
Element[0] = 100
Element[1] = 101
Element[2] = 102
Element[3] = 103
Element[4] = 104
Element[5] = 105
Element[6] = 106
Element[7] = 107
Element[8] = 108
Element[9] = 109
Trong bài Vòng lặp trong C# mình đã trình bày về vòng lặp foreach, nếu bạn chưa biết vòng lặp foreach thì nên đọc bài viết này trước. Dùng vòng lặp foreach duyệt mảng như sau:
using System;
namespace ArrayApplication
{
class MyArray
{
static void Main(string[] args)
{
int[] numbers = new int[10];
for (int i = 0; i < 10; i++)
{
numbers[i] = i + 100;
}
int j = 0;
foreach (int item in numbers)
{
Console.WriteLine("Element[{0}] = {1}", j, item);
j++;
}
Console.ReadKey();
}
}
}
Kết quả khi chạy đoạn mã trên:
Element[0] = 100
Element[1] = 101
Element[2] = 102
Element[3] = 103
Element[4] = 104
Element[5] = 105
Element[6] = 106
Element[7] = 107
Element[8] = 108
Element[9] = 109
Có một số khái niệm quan trọng sau đây liên quan đến mảng cần phải hiểu rõ ràng đối với lập trình viên C#:
Khái niệm | Miêu tả |
---|---|
Mảng đa chiều | C# hỗ trợ mảng đa chiều. Mẫu đơn giản nhất của mảng đa chiều là mảng hai chiều |
Mảng răng cưa | C# hỗ trợ mảng đa chiều, mà là mảng của các mảng |
Truyền mảng cho phương thức | Bạn có thể truyền cho phương thức một con trỏ tới một mảng bằng việc xác định tên mảng mà không cần chỉ số của mảng |
Mảng tham số | Được sử dụng để truyền một số lượng tham số chưa biết trước tới một phương thức |
Lớp Array | Được định nghĩa trong namespace System, nó là lớp cơ sở cho tất cả mảng, và cung cấp các thuộc tính và phương thức để làm việc với mảng |
C# hỗ trợ các mảng đa chiều. Các mảng đa chiều cũng được gọi là mảng hình chữ nhật. Bạn có thể khai báo một mảng chuỗi hai chiều như sau:
string[,] name;
Hoặc, một mảng các biến int 3 chiều, như sau:
int[,,] name;
Mẫu đơn giản nhất của mảng đa chiều là mảng hai chiều. Một mảng hai chiều về bản chất là danh sách của các mảng một chiều.
Một mảng 2 chiều có thể được nghĩ như là một bảng, có x hàng và y cột. Dưới đây là một mảng hai chiều có 3 hàng và 4 cột.
Như vậy, mỗi phần tử trong mảng a được định danh bởi một tên phần tử trong kiểu mẫu a[i][j], với a là tên mảng và i, j là các chỉ số được xác định duy nhất mỗi phần tử trong mảng a.
Các mảng đa chiều có thể được khởi tạo bởi chỉ định các giá trị trong dấu móc vuông cho mỗi hàng. Sau đây là một mảng với 3 hàng và 4 cột.
int[,] a = new int [3,4]
{
{0, 1, 2, 3}, /* initializers for row indexed by 0 */
{4, 5, 6, 7}, /* initializers for row indexed by 1 */
{8, 9, 10, 11} /* initializers for row indexed by 2 */
};
Các phần tử mảng hai chiều được truy cập bằng cách sử dụng các chỉ số, đó là chỉ mục hàng và chỉ mục cột. Ví dụ:
int val = a[2,3];
Lệnh trên sẽ truy cập vào phần tử ở hàng 3 và cột 4 của mảng. Bạn có thể kiểm tra lại nó trong sơ đồ trên. Bây giờ chúng ta xem xét ví dụ dưới đây, chúng tôi đã sử dụng các vòng lặp lồng vào nhau để xử lý một mảng hai chiều:
using System;
namespace ArrayApplication
{
class MyArray
{
static void Main(string[] args)
{
int[,] a = new int[5,2] {{0,0}, {1,2}, {2,4}, {3,6}, {4,8}};
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 2; j++)
{
Console.WriteLine("a[{0},{1}] = {2}", i, j, a[i,j]);
}
}
Console.ReadKey();
}
}
}
Đây là kết quả khi chạy chương trình trên:
a[0,0]: 0
a[0,1]: 0
a[1,0]: 1
a[1,1]: 2
a[2,0]: 2
a[2,1]: 4
a[3,0]: 3
a[3,1]: 6
a[4,0]: 4
a[4,1]: 8
Một mảng răng cưa là một mảng của các mảng. Bạn có thể khai báo một mảng răng cưa có tên scores có kiểu int như sau:
int[][] scores;
Khai báo một mảng, không tạo mảng trong bộ nhớ:
int[][] scores = new int[5][];
for (int i = 0; i < scores.Length; i++)
{
scores[i] = new int[4];
}
Bạn có thể khởi tạo một mảng răng cưa như sau:
int[][] scores = new int[2][]
{
new int[]{92,93,94},
new int[]{85,66,87,88}
};
Trong đó, scores là một mảng của hai mảng integer: trong đó, scores[0] là một mảng 3 integer và scores[1] là một mảng 4 integer.
using System;
namespace ArrayApplication
{
class MyArray
{
static void Main(string[] args)
{
int[][] a = new int[][]
{
new int[]{0,0},
new int[]{1,2},
new int[]{2,4},
new int[]{3,6},
new int[]{4,8}
};
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 2; j++)
{
Console.WriteLine("a[{0}][{1}] = {2}", i, j, a[i][j]);
}
}
Console.ReadKey();
}
}
}
Đây là kết quả khi chạy chương trình trên:
a[0][0]: 0
a[0][1]: 0
a[1][0]: 1
a[1][1]: 2
a[2][0]: 2
a[2][1]: 4
a[3][0]: 3
a[3][1]: 6
a[4][0]: 4
a[4][1]: 8
Bạn có thể truyền một mảng như là một tham số phương thức trong C#. Dưới đây là ví dụ minh họa khái niệm này:
using System;
namespace ArrayApplication
{
class MyArray
{
double GetAverage(int[] arr, int size)
{
int sum = 0;
for (int i = 0; i < size; i++)
{
sum += arr[i];
}
double avg = (double)sum / size;
return avg;
}
static void Main(string[] args)
{
MyArray app = new MyArray();
int[] balance = new int[] {1000, 2, 3, 17, 50};
double avg = app.GetAverage(balance, balance.Length);
Console.WriteLine("Average value is: {0} ", avg);
Console.ReadLine();
}
}
}
Kết quả khi chạy chương trình:
Average value is: 214.4
Đôi khi, trong khi khai báo một phương thức, bạn không chắc chắn về số lượng đối số được truyền dưới dạng tham số. Các mảng tham số trong C# sẽ giúp giải quyết vấn đề này.
Ví dụ sau đây minh họa điều này:
using System;
namespace ArrayApplication
{
class ParamArray
{
public int AddElements(params int[] arr)
{
int sum = 0;
foreach (int i in arr)
{
sum += i;
}
return sum;
}
}
class TestClass
{
static void Main(string[] args)
{
ParamArray app = new ParamArray();
int sum = app.AddElements(512, 720, 250, 567, 889);
Console.WriteLine("The sum is: {0}", sum);
Console.ReadKey();
}
}
}
Kết quả khi chạy chương trình trên:
The sum is: 2938
Lớp Array là lớp cơ sở cho tất cả các mảng trong C#. Nó được định nghĩa trong namespace System. Lớp Array cung cấp các thuộc tính và phương thức khác nhau để làm việc với mảng.
Bảng sau đây mô tả một số thuộc tính được sử dụng phổ biến nhất của lớp Array:
STT | Thuộc tính | Mô tả |
---|---|---|
1 | IsFixedSize | Cho biết Array có kích thước cố định hay không. |
2 | IsReadOnly | Cho biết Array chỉ đọc. |
3 | Length | Tổng số phần tử của Array (integer) |
4 | LongLength | Tổng số phần tử của Array (long) |
5 | Rank | Lấy số chiều của Array |
Bảng sau đây mô tả một số phương thức được sử dụng phổ biến nhất của lớp Array:
STT | Phương thức | Mô tả |
---|---|---|
1 | Clear | Thiết lập một dãy các phần tử trong Array về 0, về false hoặc về null, phụ thuộc vào kiểu phần tử |
2 | Copy(Array, Array, Int32) | Sao chép một dãy các phần tử từ một Array bắt đầu từ phần tử đầu tiên và paste chúng vào trong Array khác bắt đầu tại phần tử đầu tiên. Độ dài (length) được xác định là một integer (32 bit) |
3 | CopyTo(Array, Int32) | Sao chép tất cả phần tử của Array một chiều hiện tại tới Array một chiều đã xác định bắt đầu tại chỉ mục mảng đích đến đã cho. Chỉ mục được xác định là một integer (32 bit) |
4 | GetLength | Lấy một số integer (32 bit) mà biểu diễn số phần tử trong chiều đã xác định của Array |
5 | GetLongLength | Lấy một số integer (64 bit) mà biểu diễn số phần tử trong chiều đã xác định của Array |
6 | GetLowerBound | Lấy giới hạn thấp hơn của chiều đã xác định trong Array |
7 | GetType | Lấy kiểu của instance (sự thể hiện) hiện tại (được kế thừa từ Object) |
8 | GetUpperBound | Lấy giới hạn ở trên của chiều đã xác định trong Array |
9 | GetValue(Int32) | Lấy giá trị tại vị trí đã xác định trong mảng một chiều. Chỉ mục được xác định là số integer (32) |
10 | IndexOf(Array, Object) | Tìm kiếm object đã cho và trả về chỉ mục về sự xuất hiện đầu tiên bên trong cả mảng một chiều đó |
11 | Reverse(Array) | ngược dãy phần tử trong cả mảng một chiều đó |
12 | SetValue(Object, Int32) | Thiết lập giá trị cho phần tử tại vị trí đã cho trong mảng một chiều. Chỉ mục được xác định là một số integer (32 bit) |
13 | Sort(Array) | Sắp xếp các phần tử trong cả mảng một chiều bởi sử dụng IComparable implementation của mỗi phần tử của mảng đó |
14 | ToStringk | Trả về một chuỗi mà biểu diễn object hiện tại (được kế thừa từ Object) |
Để có danh sách đầy đủ các thuộc tính và phương thức của lớp Array, bạn tham khảo tài liệu của Microsoft về C#.
using System;
namespace ArrayApplication
{
class MyArray
{
static void Main(string[] args)
{
int[] list = { 34, 72, 13, 44, 25, 30, 10 };
int[] temp = list;
Console.Write("Original Array: ");
foreach (int i in list)
{
Console.Write(i + " ");
}
Console.WriteLine();
// reverse the array
Array.Reverse(temp);
Console.Write("Reversed Array: ");
foreach (int i in temp)
{
Console.Write(i + " ");
}
Console.WriteLine();
//sort the array
Array.Sort(list);
Console.Write("Sorted Array: ");
foreach (int i in list)
{
Console.Write(i + " ");
}
Console.WriteLine();
Console.ReadKey();
}
}
}
Kết quả khi chạy chương trình trên:
Original Array: 34 72 13 44 25 30 10
Reversed Array: 10 30 25 44 13 72 34
Sorted Array: 10 13 25 30 34 44 72
Bạn có muốn xem bài viết tiếp theo không? Nó ở dưới đây nè.
Bạn có thể vui lòng tắt trình chặn quảng cáo ❤️ để hỗ trợ chúng tôi duy trì hoạt động của trang web.
Trong loạt bài này, tôi sẽ xem xét một số
Ngôn ngữ C# đã bật các bộ tăng áp liên
Trong bài viết này, chúng ta sẽ tìm hiểu lớp tiện ích ZipFile trong C#, cách nén tập tin và thư mục, cùng với giải nén tập tin zip.
Bài viết này sẽ giới thiệu cách đơn giản nhất mà tôi đã tìm thấy để đọc và ghi file Excel bằng C# sử dụng ExcelMapper.