Mảng 2 chiều trong C#
Khóa học lập trình C# căn bản
Danh sách bài học
Mảng 2 chiều trong C#
Dẫn nhập
Ở các bài học trước, chúng ta đã cùng nhau tìm hiểu về MẢNG MỘT CHIỀU TRONG C#. Hôm nay chúng ta sẽ cùng tìm hiểu về mảng hai chiều trong C#.
Nội dung
Để đọc hiểu bài này tốt nhất các bạn nên có kiến thức cơ bản về các phần:
- CẤU TRÚC CƠ BẢN MỘT CHƯƠNG TRÌNH TRONG C# console application
- BIẾN và KIỂU DỮ LIỆU trong C#
- TOÁN TỬ TRONG C#
- CÂU ĐIỀU KIỆN TRONG C#
- CẤU TRÚC CƠ BẢN VÒNG LẶP
- CẤU TRÚC CƠ BẢN CỦA HÀM TRONG C#
Trong bài học này, chúng ta sẽ cùng tìm hiểu các vấn đề:
- Khai báo, khởi tạo mảng 2 chiều trong C#
- Sử dụng mảng 2 chiều trong C#
Khai báo, khởi tạo mảng 2 chiều trong C#
Khai báo mảng 2 chiều
Mảng 2 chiều được hình dung như một bảng có m dòng và n cột với một số đặc trưng sau:
- Mảng 2 chiều mang những đặc trưng cơ bản của một mảng bình thường (đặc trưng về mảng đã trình bày trong bài MẢNG 1 CHIỀU TRONG C#)
- Các phần tử trong mảng 2 chiều được truy xuất thông qua 2 chỉ số phần tử (tạm gọi là chỉ số dòng và chỉ số cột)
- Hình ảnh minh họa mảng 2: Giả sử ta có mảng A có 5 dòng và 8 cột
- Các dòng và các cột được đánh số từ 0 và tăng dần. Mỗi phần tử là giao nhau của dòng và cột tương ứng đồng thời ta sử dụng chỉ số dòng cột đó để truy xuất đến phần tử của mảng 2 chiều.
- Ví dụ: A[1, 2] là cách truy xuất đến phần tử ở dòng thứ 2 cột thứ 3 (do chỉ số được đánh số từ 0)
Cú pháp:
<kiểu dữ liệu> [ , ] <tên mảng>;
Trong đó:
- <kiểu dữ liệu> là kiểu dữ liệu của các phần tử trong mảng.
- Cặp dấu [ , ] là ký hiệu cho khai báo mảng 2 chiều.
- <tên mảng> là tên của mảng, cách đặt tên mảng cũng như cách đặt tên biến (quy tắc đặt tên biến đã trình bày trong BIẾN TRONG C#).
Để sử dụng được mảng ta phải khởi tạo giá trị hoặc cấp phát vùng nhớ cho mảng.
Cấp phát vùng nhớ
Được thực hiện thông qua toán tử new (đã trình bày trong bài TOÁN TỬ TRONG C#). Lưu ý là khi cấp phát vùng nhớ cho mảng 2 chiều ta cần chỉ ra số dòng và số cột tối đa của mảng.
Ví dụ:
/*
* Khai báo mảng 2 chiều kiểu string và có tên là Kteam.
* Sau đó thực hiện cấp phát vùng nhớ với số dòng là 2 và số cột là 3.
*/
string[,] Kteam = new string[2, 3];
Sau khi mảng được cấp phát vùng nhớ thì các phần tử trong mảng sẽ mang giá trị mặc định:
- Đối với số nguyên là 0
- Đối với số thực là 0.0
- Đối với kiểu ký tự là ‘’ (ký tự rỗng)
- Đối với kiểu tham chiếu là null
Chúng ta có thể khởi tạo giá trị khác mà chúng ta mong muốn ngay khi cấp phát vùng nhớ bằng cú pháp sau:
<kiểu dữ liệu>[,] <tên mảng> = new <kiểu dữ liệu>[]
{
{ <giá trị dòng 1 cột 1>, …, <giá trị dòng 1 cột n> },
…
{ <giá trị dòng m cột 1>, …, <giá trị dòng m cột n> }
};
- Vì đây là mảng 2 chiều nên chúng ta sẽ không khởi tạo giống mảng 1 chiều được mà phải khởi tạo giá trị theo từng dòng một. Xem từng dòng là một mảng 1 chiều và khởi tạo như mảng 1 chiều.
- Các giá trị khởi tạo nằm trong cặp dấu ngoặc ngọn {} và cách nhau bởi dấu phẩy.
- Chúng ta không cần cung cấp số dòng và số cột tối đa mà trình biên dịch sẽ tự đếm xem bạn đã khởi tạo bao nhiều dòng và mỗi dòng bao nhiêu giá trị rồi xem nó như số dòng số cột tối đa.
Khởi tạo giá trị
Cú pháp:
<kiểu dữ liệu>[,] <tên mảng> =
{
{ <giá trị dòng 1 cột 1>, …, <giá trị dòng 1 cột n> },
…
{ <giá trị dòng m cột 1>, …, <giá trị dòng m cột n> }
};
Ví dụ:
int[,] IntArray =
{
{1, 2},
{3, 4},
{5, 6}
};
Về bản chất thì cách này trình biên dịch vẫn xem xét số phần tử khởi tạo và cấp phát vùng nhớ cho biến mảng sau đó thực khởi tạo giá trị cho các phần tử trong mảng. Nhưng cách viết này có vẻ nhanh và gọn hơn so với cách cấp phát vùng nhớ rồi mới khởi tạo giá trị.
Tóm lại, cũng như mảng 1 chiều, mảng 2 chiều cũng có 3 cách khai báo và khởi tạo sau:
- Khai báo và cấp phát vùng nhớ
string[,] Array = new string[2, 3];
- Khai báo, cấp phát và khởi tạo giá trị cho mảng
string[,] Kteam = new string[,]
{
{ "HowKteam", "Free Education" },
{ “HowKteam.com”, “Share to be better” }
};
- Khởi tạo giá trị cho mảng
int[] IntArray =
{
{1, 2},
{3, 4},
{5, 6}
};
Sử dụng mảng 2 chiều
Tương tự như mảng 1 chiều, kiểu mảng 2 chiều cũng có thể dùng làm:
- Kiểu dữ liệu cho biến.
- Kiểu trả về cho hàm.
- Tham số truyền vào cho hàm.
- Các phần tử của mảng được truy xuất thông qua chỉ số dòng và chỉ số cột (chỉ số dòng viết trước, chỉ số cột viết sau ngăn cách nhau bởi dấu ,) và cặp dấu []. Có thể xem các phần tử của mảng như là các biến đơn và thao tác như thao tác với biến bình thường.
// Khai báo, cấp phát và khởi tạo mảng 2 chiều kiểu string và tên là Kteam
int[,] Kteam =
{
{1, 2},
{3, 4},
{5, 6}
};
/*
* Vì chỉ số phần tử được đánh số từ 0 nên muốn truy xuất đến phần tử dòng 1 cột 2 của mảng
thì chỉ số dòng là 0 và chỉ số cột là 1
*/
Console.WriteLine(Kteam[0, 1]);
Một số thuộc tính và phương thức đặc trưng của mảng 2 chiều:
Còn rất nhiều thuộc tính và phương thức khác, mình chỉ giới thiệu một số cái hay dùng còn lại các bạn có thể tự khám phá.
Cách duyệt mảng 2 chiều:
Ý tưởng:
- Tương tự như ý tưởng duyệt mảng 1 chiều (đã trình bày trong bài MẢNG MỘT CHIỀU TRONG C#)
- Nhưng do mảng 2 chiều có 2 chỉ số là chỉ số dòng và chỉ số cột nên chúng ta cần 2 vòng lặp lồng vào nhau.
Ví dụ:
int[,] IntArray = new int [9, 10];
/*
* Sử dụng 2 vòng for lồng vào nhau để duyệt mảng 2 chiều
* Vòng lặp ngoài là vòng lặp duyệt mỗi dòng của của mảng 2 chiều
* Với mỗi dòng thì vòng lặp trong là vòng lặp duyệt các phần tử trên dòng đó (duyệt từng cột trên dòng hiện tại)
*/
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 10; j++)
{
/*
* Với cách duyệt này thì IntArray[i, j] sẽ là phần tử hiện tại mình đang xét
* Code xử lý sẽ viết ở đây
*/
}
}
Hình ảnh minh họa:
- Cách duyệt này sẽ duyệt tuần tự các dòng trong mảng 2 chiều, ở mỗi dòng sẽ duyệt từ đầu dòng đến cuối dòng. Bạn hoàn toàn có thể duyệt theo ý mình bằng cách thay đổi giá trị trong vòng lặp.
- Ví dụ sau sẽ duyệt theo cột. Tức là duyệt tuần tự từng cột rồi ở mỗi cột duyệt từ trên xuống dưới.
/*
* Duyệt mảng 2 chiều theo cột
* Các bạn để ý sự thay đổi trong 2 vòng lặp
*/
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 9; j++)
{
/*
* Lưu ý là các phần tử được truy xuất là IntArray[j, i] thay vì IntArray[i, j]
* Code xử lý
*/
}
}
- Để ý là cả 2 cách duyệt mình đều vi phạm 1 điều mà ở phần duyệt mảng 1 chiều của bài trước mình đã trình bày. Đó là nên sử dụng hàm trả về số dòng, số cột thay vì viết cứng một con số cụ thể.
- Lúc này hàm GetLength(<số chiều>) thực sự phát huy tác dụng. Các bạn cùng xem nhé:
/*
* Như đã trình bày ở phần trước thì:
* GetLength(0) sẽ trả về số dòng của mảng 2 chiều
* GetLength(1) sẽ trả về số cột của mảng 2 chiều
*/
for (int i = 0; i < IntArray.GetLength(0); i++)
{
for (int j = 0; j < IntArray.GetLength(1); j++)
{
// Code xử lý
}
}
Ví dụ chương trình sử dụng mảng 2 chiều
Ta thử xét 1 ví dụ đơn giản đó là viết chương trình cho phép nhập vào giá trị số nguyên cho 1 mảng 2 chiều bất kỳ sau đó in ra màn hình mảng đã nhập kèm theo tổng tất cả các giá trị trong mảng.
Chương trình minh họa:
Console.Write(" Moi ban nhap so dong cua mang: ");
int Rows = int.Parse(Console.ReadLine());
Console.Write(" Moi ban nhap so cot cua mang: ");
int Columns = int.Parse(Console.ReadLine());
// Tạo 1 mảng 2 chiều với số dòng và số cột đã nhập
int[,] IntArray = new int[Rows, Columns];
/*
* Duyệt mảng để nhập giá trị cho các phần tử
* Ở đây mình muốn minh họa cách sử dụng mảng nên mình bỏ qua các bước kiểm tra dữ liệu mà ép kiểu trực tiếp
* Điều này có thể gây lỗi khi nhập sai nên các bạn hãy cải tiến chương trình này cho đầy đủ nhé!
*/
for (int i = 0; i < IntArray.GetLength(0); i++)
{
for (int j = 0; j < IntArray.GetLength(1); j++)
{
Console.Write(" Moi ban nhap phan tu IntArray[{0}, {1}] = ", i, j);
IntArray[i, j] = int.Parse(Console.ReadLine());
}
}
/*
* In mảng 2 chiều đã nhập ra màn hình
* Để tính tổng các giá trị trong mảng ta chỉ cần duyệt qua các phần tử và cộng chúng lại với nhau
* Tận dụng lúc duyệt mảng để in giá trị ta sẽ thực hiện tính tổng luôn để tránh phải duyệt lại mảng thêm lần nữa.
*/
int Sum = 0;
Console.WriteLine("\n Mang ban vua nhap la: ");
for (int i = 0; i < IntArray.GetLength(0); i++)
{
for (int j = 0; j < IntArray.GetLength(1); j++)
{
Console.Write(IntArray[i, j] + " ");
Sum = Sum + IntArray[i, j];
}
// Sau khi in xong mỗi dòng ta thực hiện xuống dòng rồi mới in tiếp
Console.WriteLine();
}
Console.WriteLine(" Tong cac gia tri trong mang: " + Sum);
Kết quả sau khi chạy chương trình trên:
Kết luận
Nội dung bài này giúp các bạn nắm được:
- Khai báo, khởi tạo mảng 2 chiều trong C#.
- Sử dụng mảng 2 chiều trong C#.
Bài sau chúng ta sẽ tìm hiểu về MẢNG NHIỀU CHIỀU TRONG C#.
Cảm ơn các bạn đã theo dõi bài viết. Hãy để lại bình luận hoặc góp ý của mình để phát triển bài viết tốt hơn. Đừng quên “Luyện tập – Thử thách – Không ngại khó”.
Tải xuống
Tài liệu
Nhằm phục vụ mục đích học tập Offline của cộng đồng, Kteam hỗ trợ tính năng lưu trữ nội dung bài học Mảng 2 chiều trong C# dưới dạng file PDF trong link bên dưới.
Ngoài ra, bạn cũng có thể tìm thấy các tài liệu được đóng góp từ cộng đồng ở mục TÀI LIỆU trên thư viện Howkteam.com
Đừng quên like và share để ủng hộ Kteam và tác giả nhé!
Thảo luận
Nếu bạn có bất kỳ khó khăn hay thắc mắc gì về khóa học, đừng ngần ngại đặt câu hỏi trong phần bên dưới hoặc trong mục HỎI & ĐÁP trên thư viện Howkteam.com để nhận được sự hỗ trợ từ cộng đồng.
Nội dung bài viết
Khóa học
Bạn mới bắt đầu học lập trình? Bạn đang muốn học thêm ngôn ngữ lập trình mới? C# là lựa chọn hoàn hảo để đáp ứng các nhu cầu trên.
Ngôn ngữ C# là một ngôn ngữ mới, cấu trúc rõ ràng, dễ hiểu và dễ học. C# thừa hưởng những ưu việt từ ngôn ngữ Java, C, C++ cũng như khắc phục được những hạn chế của các ngôn ngữ này. C# là ngôn ngữ lập trình hướng đối tượng được phát triển bởi Microsoft, được xây dựng dựa trên C++ và Java.
Khoá học lần này sẽ mang đến toàn bộ những kiến thức cơ bản về C#. Chào mừng các bạn đã đến với khoá học LẬP TRÌNH C# CƠ BẢN của Kteam.
using System.Text;
namespace CS
{
internal class Program
{
static void Main(string[] args)
{
Console.OutputEncoding = Encoding.UTF8;
#region
bool checkRows, checkColumns;
int N, M;
do
{
do
{
Console.Write("Mời bạn nhập số dòng mảng: ");
string Rows = Console.ReadLine();
checkRows = int.TryParse(Rows, out N);
Console.Write("Mời bạn nhập số cột mảng: ");
string Columns = Console.ReadLine();
checkColumns = int.TryParse(Columns, out M);
if (!checkRows || !checkColumns || N <= 0 || M <= 0)
{
Console.WriteLine("Vui lòng nhập số nguyên dương!!!\n");
}
else Console.WriteLine();
}while (N <= 0 || M <= 0);
} while (!checkRows || !checkColumns);
int i = 0;
int j = 0;
bool checkA;
int[,] arrayA = new int[N, M];
while (i < N)
{
j = 0;
while (j < M)
{
Console.Write("Phần tử của [{0},{1}]: ", i, j);
string strA = Console.ReadLine();
checkA = int.TryParse(strA, out arrayA[i, j]);
if (!checkA)
{
Console.WriteLine("Vui lòng nhập số nguyên của giá trị phần tử!\n");
}
else j++;
}
i++;
}
int sum = 0;
Console.WriteLine("\nMảng có phần tử là:");
do
{
i = 0;
while (i < N)
{
j = 0;
while (j < M)
{
Console.Write(arrayA[i, j] + " ");
sum += arrayA[i, j];
j++;
}
Console.WriteLine();
i++;
}
} while (false);
Console.WriteLine("\nTổng giá trị của mảng là: " + sum);
#endregion
Console.ReadKey();
}
}
}
public static int getvalidinput(string message)
{
int value;
bool isValid;
do
{
Console.Write(message);
isValid = int.TryParse(Console.ReadLine(), out value);
if (!isValid)
Console.WriteLine("Vui long nhap so nguyen");
} while (!isValid);
return value;
}
public static void m2c()
{
int m = getvalidinput("Nhap so dong: ");
int n = getvalidinput("Nhap so cot: ");
int[,] a = new int[m, n];
int s = 0;
for (int i = 0; i < a.GetLength(0); i++)
{
for (int j = 0; j < a.GetLength(1); j++)
{
do
{
Console.Write("a[{0}, {1}] = ", i, j);
} while (!int.TryParse(Console.ReadLine(), out a[i, j]));
s += a[i, j];
}
Console.WriteLine();
}
for (int i = 0; i < a.GetLength(0); i++)
{
for (int j = 0; j < a.GetLength(1); j++)
{
Console.Write("\t{0}", a[i, j]);
}
Console.WriteLine();
}
Console.WriteLine("Tong cac phan tu = {0}", s);
}
static void Main(string[] args)
{
m2c();
Console.ReadKey();
}
int m, n;
bool kt;
do
{
Console.Write("Nhap so dong: ");
kt = int.TryParse(Console.ReadLine(), out m);
if (!kt)
Console.WriteLine("Vui long nhap so dong la so");
} while (!kt);
do
{
Console.Write("Nhap so cot: ");
kt = int.TryParse(Console.ReadLine(), out n);
if (!kt)
Console.WriteLine("Vui long nhap so cot la so");
} while (!kt);
int[,] a = new int[m, n];
for (int i = 0; i < a.GetLength(0); i++)
{
for (int j = 0; j < a.GetLength(1); j++)
{
do
{
Console.Write("a[{0}, {1}] = ", i, j);
kt = int.TryParse(Console.ReadLine(), out a[i, j]);
if (!kt)
Console.WriteLine("Vui long nhap phan tu la so");
} while (!kt);
}
}
int s = 0;
for (int i = 0; i < a.GetLength(0); i++)
{
for (int j = 0; j < a.GetLength(1); j++)
{
Console.Write("\t{0}", a[i, j]);
s += a[i, j];
}
Console.WriteLine();
}
Console.WriteLine("Tong cac phan tu = {0}", s);
}
int Rows;
int Columns;
NhapLai:
Console.Write("Moi ban nhap so cot: ");
string Cot = Console.ReadLine();
Console.Write("Moi ban nhap so hang: ");
string Hang = Console.ReadLine();
if (int.TryParse(Cot, out Columns) == false || int.TryParse(Hang, out Rows) == false)
{
Console.WriteLine("sai du lieu");
goto NhapLai;
}
else {
Console.WriteLine("So hang {0} , So cot {1}", Rows, Columns);
int[,] IntArray = new int[Rows, Columns];
Nhapdulieu:
int nhap;
for (int i = 0; i < IntArray.GetLength(0); i++)
{
for (int j = 0; j < IntArray.GetLength(1); j++)
{
Console.Write("Moi ban nhap phan tu {0} {1} : ", i, j);
string NhapString = Console.ReadLine();
if (int.TryParse(NhapString,out nhap) == false)
{
Console.WriteLine("nhap sai du lieu vui long nhap lai");
goto Nhapdulieu;
}
else
{
IntArray[i, j] = nhap;
}
}
}
int sum = 0;
Console.WriteLine(" Mang ban vua nhap la :");
for (int i = 0; i < IntArray.GetLength(0); i++)
{
for (int j = 0; j< IntArray.GetLength(1); j++)
{
Console.Write(IntArray[i, j] + " ");
sum += IntArray[i,j];
}
Console.WriteLine();
}
Console.WriteLine(" Tong cac gia tri trong mang la : " + sum);
int Max;
Max = IntArray[0, 0];
for (int i = 0; i < IntArray.GetLength(0); i++)
{
for (int j = 0; j < IntArray.GetLength(1); j++)
{
if (Max < IntArray[i,j])
{
Max = IntArray[i, j];
}
}
}
Console.WriteLine("Gia tri lon nhat trong mang la : " + Max);
Console.WriteLine(" cac so chan trong mang la : ");
for (int i = 0; i < IntArray.GetLength(0); i++)
{
for (int j = 0; j < IntArray.GetLength(1); j++)
{
if (IntArray[i, j] % 2 == 0)
{
Console.Write(IntArray[i, j] + " ");
}
}
Console.WriteLine();
}
Console.Write("Nhap Hang can tim: ");
int TimHang = int.Parse(Console.ReadLine());
Console.Write("Nhap Cot can tim: ");
int TimCot = int.Parse(Console.ReadLine());
for (int i = 0; i < IntArray.GetLength(0); i++)
{
for (int j = 0; j < IntArray.GetLength(1); j++)
{
if (i == TimCot && j == TimHang)
{
Console.Write("Ma tran can tim la : " + IntArray[i, j]);
}
}
Console.WriteLine();
}
}