You are on page 1of 72

Trường ĐHCN Việt - Hung

Khoa CNTT

NHẬP MÔN LẬP TRÌNH


Nguyễn Thị Thu Thủy

Chương 6:
MẢNG và CHUỖI KÍ TỰ

1
&&
VC
VC
BB
BB
Nội dung

1 Mảng 1 chiều

2 Mảng nhiều chiều

NMLT - Mảng một chiều 2


&&
VC
VC
BB
BB
Đặt vấn đề

 Ví dụ
 Chương trình cần lưu trữ 3 số nguyên?
=> Khai báo 3 biến int a1, a2, a3;
 Chương trình cần lưu trữ 100 số nguyên?
=> Khai báo 100 biến kiểu số nguyên!
 Người dùng muốn nhập n số nguyên?
=> Không thực hiện được!
 Giải pháp
 Kiểu dữ liệu mới cho phép lưu trữ một dãy
các số nguyên và dễ dàng truy xuất.
NMLT - Mảng một chiều 3
&&
VC
VC
BB
BB
1. Mảng 1 chiều

 Khái niệm mảng


 Là một kiểu dữ liệu có cấu trúc do người lập
trình định nghĩa.
 Biểu diễn một dãy các biến có cùng kiểu dữ
liệu. Ví dụ: dãy các số nguyên, dãy các ký
tự…
 Kích thước được xác định ngay khi khai báo
và không bao giờ thay đổi.
 NNLT C luôn chỉ định một khối nhớ liên tục
cho một biến kiểu mảng.
NMLT - Mảng một chiều 4
&&
VC
VC
BB
BB
1.1.Khai báo biến mảng

 Tường minh (cụ thể)


<kiểu dữ liệu > <tên biến mảng>[<số phần tử>];

• Lưu ý
• Phải xác định <số phần tử> cụ thể (hằng) khi khai báo.
(VD khai báo: int a[ ]=> Lỗi)
• Bộ nhớ sử dụng = <tổng số phần tử>*sizeof(<kiểu cơ sở>)
• Bộ nhớ sử dụng phải ít hơn 64KB (65535 Bytes)
• Một dãy liên tục có chỉ số từ 0 đến <tổng số phần tử>-1
(Nếu ta có mảng a có khai báo int a[20] thì các phần tử của
nó có thứ tự (chỉ số) từ 0 đến 19)
NMLT - Mảng một chiều 5
&&
VC
VC
BB
BB
Khai báo biến mảng

• Ví dụ: khai báo 1 biến mảng tên là Mang1chieu có


kiểu dữ liệu của các phần tử là int, số phần tử là 10

int Mang1Chieu[10];
0 1 2 3 4 5 6 7 8 9

Mang1Chieu

• Khai báo mảng A gồm 20 ki tự:


char A[20];

NMLT - Mảng một chiều 6


&&
VC
VC
BB
BB
1.1. Khai báo biến mảng
 Khai báo không tường minh
 Không tường minh (thông qua khai báo kiểu:
định nghĩa 1 kiểu dữ liệu mới, sử dụng kiểu
này để khai báo biến)
typedef <kiểu cơ sở> <tên kiểu mảng>[<số phần tử>];
typedef <kiểu cơ sở> <tên kiểu mảng>[<N1>]…[<Nn>];
//Sử dụng kiểu dữ liệu định nghĩa ở trên để khai báo biến:
<tên kiểu mảng> <tên biến mảng>;

• Ví dụ
typedef int Mang1Chieu[10]; //ĐN kiểu DL mới tên Mang1Chieu
typedef int Mang2Chieu[3][4]; //ĐN kiểu DL mới tên Mang2Chieu
//Sử dụng 2 kiểu Dl này để khai báo các biến m1, m2, m3, m4,m5
Mang1Chieu m1, m2, m3;
Mang2Chieu m4, m5;
NMLT - Mảng một chiều 7
&&
VC
VC
BB
BB
1.2. Số phần tử của mảng
 Phải xác định cụ thể số phần tử ngay lúc khai
báo, không được sử dụng biến hoặc hằng
thường (hằng phải được khai báo bằng #define
không được khai báo bằng const)
int n1 = 10; int a[n1]; //báo lỗi vì sd biến để khai báo số pt mảng
const int n2 = 20; int b[n2]; //báo lỗi vì sd hằng thường

 Nên sử dụng chỉ thị tiền xử lý #define để định


nghĩa số phần tử mảng
#define n1 10
#define n2 20
int a[n1]; //  int a[10];
int b[n1][n2]; //  int b[10][20];

NMLT - Mảng một chiều 8


&&
VC
VC
BB
BB
1.3. Khởi tạo giá trị cho mảng lúc khai báo

 Gồm các cách sau


 Khởi tạo giá trị cho mọi phần tử của mảng
(Liệt kê tất cả các giá trị, đặt cách nhau dấu ,
trong cặp dấu {}
int a[4] = {2912, 1706, 1506, 1904};
0 1 2 3

a 2912 1706 1506 1904


 Khởi tạo giá trị cho một số phần tử đầu mảng (ko liệt
kê hết giá trị của tất cả các pt, các phần tử thiếu giá
trị ở cuối mảng tự động gán giá trị =0)
int a[4] = {2912, 1706}; 0 1 2 3
a 2912 1706 0 0 9
NMLT - Mảng một chiều
&&
VC
VC
BB
BB
1.3. Khởi tạo giá trị cho mảng lúc khai báo

 Gồm các cách sau


 Khởi tạo giá trị 0 cho mọi phần tử của mảng
int a[4] = {0};
0 1 2 3

a 0 0 0 0
 Tự động xác định số lượng phần tử
int a[] = {2912, 1706, 1506, 1904};

0 1 2 3

a 2912 1706 1506 1904

NMLT - Mảng một chiều 10


&&
VC
VC
BB
BB
1.4. Truy xuất đến một phần tử

 Thông qua chỉ số (Số thứ tự của pt trong mảng )


<tên biến mảng>[<cs1>][<cs2>]…[<csn>];
<tên biến mảng>[<chỉ số>] //mảng 1 chiều
 Ví dụ
 Cho mảng như sau 0 1 2 3

int a[4];
 Các truy xuất
• Hợp lệ: a[0], a[1], a[2], a[3]
• Không hợp lệ: a[-1], a[4], a[5], …
=> Cho kết quả thường không như mong muốn!

NMLT - Mảng một chiều 11


&&
VC
VC
BB
BB
1.5. Gán dữ liệu kiểu mảng

 Không được sử dụng phép gán thông thường 2


mảng cho nhau mà phải gán trực tiếp giữa các
phần tử tương ứng
<biến mảng đích> = <biến mảng nguồn>; //sai
<biến mảng đích>[<chỉ số thứ i>] = <giá trị>;

 Ví dụ
#define MAX 3 //ĐN 1 hằng số tên là MAX có giá trj là 3
typedef int MangSo[MAX]; //ĐN 1 kiểu dữ liệu tên MangSo
MangSo a = {1, 2, 3}, b; // Khao báo biến a là 1 MangSo, gán trị
cho mảng a, khai báo 1 biến b là 1 MangSo
b = a; // Sai do ko thể gán 2 mảng cho nhau
for (int i = 0; i < MAX; i++)
b[i] = a[i]; NMLT - Mảng một chiều 12
&&
VC
VC
BB
BB
Một số lỗi thường gặp

 Khai báo không chỉ rõ số lượng phần tử


 int a[]; => int a[100];
 Khởi tạo cách biệt với khai báo
 int a[4]; a = {2912, 1706, 1506, 1904};
=> int a[4] = {2912, 1706, 1506, 1904};
 Chỉ số mảng không hợp lệ
 int a[4];
 a[-1] = 1; a[10] = 0;

NMLT - Mảng một chiều 13


&&
VC
VC
BB
BB
1.6. Truyền mảng cho hàm

 Truyền mảng cho hàm


 Tham số kiểu mảng trong khai báo hàm giống
như khai báo biến mảng
void SapXepTang(int a[100];
 Tham số kiểu mảng truyền cho hàm chính là địa
chỉ của phần tử đầu tiên của mảng
• Có thể bỏ số lượng phần tử hoặc sử dụng con trỏ.
• Mảng có thể thay đổi nội dung sau khi thực hiện hàm.

void SapXepTang(int a[]);


void SapXepTang(int *a);

NMLT - Mảng một chiều 14


&&
VC
VC
BB
BB
1.6. Truyền mảng cho hàm

 Truyền mảng cho hàm


 Số lượng phần tử thực sự truyền qua biến khác
void SapXepTang(int a[100], int n);
void SapXepTang(int a[], int n);
void SapXepTang(int *a, int n);
 Lời gọi hàm
void NhapMang(int a[], int &n);
void XuatMang(int a[], int n);
void main()
{
int a[100], n;
NhapMang(a, n);
XuatMang(a, n);
} NMLT - Mảng một chiều 15
&&
VC
VC
BB
BB
1.7. Một số bài toán cơ bản

 Viết chương trình:


-Khai báo 1 mảng số nguyên a tối đa 30 phần tử
-Nhập một số n<30
-Nhập n số nguyên vào cho các phần tử của
mảng a
-In ra mảng các số nguyên vừa nhập được

double a[30];

int a;

NMLT - Mảng một chiều 16


&&
VC
VC
BB
BB
1.7. Một số bài toán cơ bản

- Nhập một số n<30


(*)Làm
Nhập 1 số N;
Trong khi (N>30)||(N<=0) quay lại (*)

double a[30];

int a;

NMLT - Mảng một chiều 17


&&
VC
VC
BB
BB
1.7. Một số bài toán cơ bản
- Khai báo 1 mảng số nguyên a tối đa 30 phần tử
int Ptu[30] ; // Kiểu DL: int, Tên biến: Ptu
// int mang [30];
-Nhập một số n<30 // tự viết …dùng do…while
-Nhập n số nguyên vào cho các phần tử của mảng a
+ i=0;
(*) Làm: nhập 1 số nguyên cho biến a[i]; tăng i++
+ Trong khi i<n thì quay lại (*)
i=0;
do{
for(i=0;i<n;i++) cout<<“nhap 1 so”; cin>>a[i];
{ cout<<“nhap 1 so”; i++;
cin>>a[i]; } while(i<n);
}

NMLT - Mảng một chiều 18


&&
VC
VC
BB
BB
1.7. Một số bài toán cơ bản

- In ra mảng các số nguyên vừa nhập được


+ i=0;
(*)làm: in phần tử thứ i của mảng a (phần tử a[i])
Tăng i lên i:++
Trong khii (i<n) thì lặp lại (*)
Þi=0
do{ cout<<“\nphan tu thu:”<<i<<“=“ <<a[i];
i++;
for(i=0;i<n;i++)
} while(i<n) cout<<“\nphan tu thu:”<<i<<“=“ <<a[i];

NMLT - Mảng một chiều 19


&&
VC
VC
BB
BB
1.7. Một số bài toán cơ bản

 Viết hàm thực hiện từng yêu cầu sau


 Nhập mảng
 Xuất mảng
 Tìm kiếm một phần tử trong mảng
 Kiểm tra tính chất của mảng
 Tách mảng / Gộp mảng
 Tìm giá trị nhỏ nhất/lớn nhất của mảng
 Sắp xếp mảng giảm dần/tăng dần
 Thêm/Xóa/Sửa một phần tử vào mảng

NMLT - Mảng một chiều 20


&&
VC
VC
BB
BB
Nhập mảng

 Yêu cầu
 Cho phép nhập mảng a, số lượng phần tử n
 Ý tưởng
 Cho trước một mảng có số lượng phần tử là MAX.
 Nhập số lượng phần tử thực sự n của mảng.
 Nhập từng phần tử cho mảng từ chỉ số 0 đến n – 1.

0 1 2 3 n -4 1 MAX - 1

… … …

NMLT - Mảng một chiều 21


&&
VC
VC
BB
BB
Hàm Nhập Mảng

void NhapMang(int a[], int &n)


{
cout<<“Nhap so luong phan tu n: ";
cin>>n;

for (int i = 0; i < n; i++)


{
cout<<“Nhap phan tu thu: ”<<i;
cin>>a[i];
}
}

NMLT - Mảng một chiều 22


&&
VC
VC
BB
BB
Xuất mảng

 Yêu cầu
 Cho trước mảng a, số lượng phần tử n. Hãy xuất nội
dung mảng a ra màn hình.
 Ý tưởng
 Xuất giá trị từng phần tử của mảng từ chỉ số 0 đến n-1.

0 1 2 n-1 MAX - 1

… … …

NMLT - Mảng một chiều 23


&&
VC
VC
BB
BB
Hàm Xuất Mảng

void XuatMang(int a[], int n)


{
cout<<“Noi dung cua mang la: ";

for (int i = 0; i < n; i++)


cout<<“ ”<<a[i];

cout<<“\n";
}

NMLT - Mảng một chiều 24


&&
VC
VC
BB
BB
Tìm kiếm một phần tử trong mảng

 Yêu cầu
 Tìm xem phần tử x có nằm trong mảng a kích thước n
hay không? Nếu có thì nó nằm ở vị trí đầu tiên nào.
 Ý tưởng
 Xét từng phần của mảng a. Nếu phần tử đang xét bằng
x thì trả về vị trí đó. Nếu kô tìm được thì trả về -1.

x vị trí = 1

0 1 2 n-1 MAX - 1

a x b … x … …

NMLT - Mảng một chiều 25


&&
VC
VC
BB
BB
Hàm Tìm Kiếm (dùng while)

int TimKiem(int a[], int n, int x)


{
int vt = 0;

while (vt < n && a[vt] != x)


vt++;

if (vt < n)
return vt;
else
return -1;
}

NMLT - Mảng một chiều 26


&&
VC
VC
BB
BB
Hàm Tìm Kiếm (dùng for)

int TimKiem(int a[], int n, int x)


{
for (int vt = 0; vt < n; vt++)
if (a[vt] == x)
return vt;

return -1;
}

NMLT - Mảng một chiều 27


&&
VC
VC
BB
BB
Kiểm tra tính chất của mảng

 Yêu cầu
 Cho trước mảng a, số lượng phần tử n. Mảng a có
phải là mảng toàn các số nguyên tố hay không?
 Ý tưởng
 Cách 1: Đếm số lượng số ngtố của mảng. Nếu số
lượng này bằng đúng n thì mảng toàn ngtố.
 Cách 2: Đếm số lượng số không phải ngtố của mảng.
Nếu số lượng này bằng 0 thì mảng toàn ngtố.
 Cách 3: Tìm xem có phần tử nào không phải số ngtố
không. Nếu có thì mảng không toàn số ngtố.

NMLT - Mảng một chiều 28


&&
VC
VC
BB
BB
Hàm Kiểm Tra (Cách 1)

int KiemTra_C1(int a[], int n)


{
int dem = 0;

for (int i = 0; i < n; i++)


if (LaSNT(a[i]) == 1) // có thể bỏ == 1
dem++;

if (dem == n)
return 1;
return 0;
}

NMLT - Mảng một chiều 29


&&
VC
VC
BB
BB
Hàm Kiểm Tra (Cách 2)

int KiemTra_C2(int a[], int n)


{
int dem = 0;

for (int i = 0; i < n; i++)


if (LaSNT(a[i]) == 0) // Có thể sử dụng !
dem++;

if (dem == 0)
return 1;
return 0;
}

NMLT - Mảng một chiều 30


&&
VC
VC
BB
BB
Hàm Kiểm Tra (Cách 3)

int KiemTra_C3(int a[], int n)


{
for (int i = 0; i < n ; i++)
if (LaSNT(a[i]) == 0)
return 0;

return 1;
}

NMLT - Mảng một chiều 31


&&
VC
VC
BB
BB
Tách các phần tử thỏa điều kiện

 Yêu cầu
 Cho trước mảng a, số lượng phần tử na. Tách các số
nguyên tố có trong mảng a vào mảng b.
 Ý tưởng
 Duyệt từ phần tử của mảng a, nếu đó là số nguyên tố
thì đưa vào mảng b.

NMLT - Mảng một chiều 32


&&
VC
VC
BB
BB
Hàm Tách Số Nguyên Tố

void TachSNT(int a[], int na, int b[], int &nb)


{
nb = 0;

for (int i = 0; i < na; i++)


if (LaSNT(a[i]) == 1)
{
b[nb] = a[i];
nb++;
}
}

NMLT - Mảng một chiều 33


&&
VC
VC
BB
BB
Tách mảng thành 2 mảng con

 Yêu cầu
 Cho trước mảng a, số lượng phần tử na. Tách mảng
a thành 2 mảng b (chứa số nguyên tố) và mảng c
(các số còn lại).
 Ý tưởng
 Cách 1: viết 1 hàm tách các số nguyên tố từ mảng a
sang mảng b và 1 hàm tách các số không phải
nguyên tố từ mảng a sang mảng c.
 Cách 2: Duyệt từ phần tử của mảng a, nếu đó là số
nguyên tố thì đưa vào mảng b, ngược lại đưa vào
mảng c.

NMLT - Mảng một chiều 34


&&
VC
VC
BB
BB
Hàm Tách 2 Mảng

void TachSNT2(int a[], int na,


int b[], int &nb, int c[], int &nc)
{
nb = 0;
nc = 0;

for (int i = 0; i < na; i++)


if (LaSNT(a[i]) == 1)
{
b[nb] = a[i]; nb++;
}
else
{
c[nc] = a[i]; nc++;
}
}
NMLT - Mảng một chiều 35
&&
VC
VC
BB
BB
Gộp 2 mảng thành một mảng

 Yêu cầu
 Cho trước mảng a, số lượng phần tử na và mảng b
số lượng phần tử nb. Gộp 2 mảng trên theo tứ tự đó
thành mảng c, số lượng phần tử nc.
 Ý tưởng
 Chuyển các phần tử của mảng a sang mảng c
=> nc = na
 Tiếp tục đưa các phần tử của mảng b sang mảng c
=> nc = nc + nb

NMLT - Mảng một chiều 36


&&
VC
VC
BB
BB
Hàm Gộp Mảng

void GopMang(int a[], int na, int b[], int nb,


int c[], int &nc)
{
nc = 0;

for (int i = 0; i < na; i++)


{
c[nc] = a[i]; nc++; // c[nc++] = a[i];
}

for (int i = 0; i < nb; i++)


{
c[nc] = b[i]; nc++; // c[nc++] = b[i];
}
}

NMLT - Mảng một chiều 37


&&
VC
VC
BB
BB
Tìm giá trị lớn nhất của mảng

 Yêu cầu
 Cho trước mảng a có n phần tử. Tìm giá trị lớn nhất
trong a (gọi là max)
 Ý tưởng
 Giả sử giá trị max hiện tại là giá trị phần tử đầu tiên a[0]
 Lần lượt kiểm tra các phần tử còn lại để cập nhật max.

max 8
7
?

0 1 2 n–1 MAX - 1

7 2 8 … 8 … …

NMLT - Mảng một chiều 38


&&
VC
VC
BB
BB
Hàm tìm Max

int TimMax(int a[], int n)


{
int max = a[0];

for (int i = 1; i < n; i++)


if (a[i] > max)
max = a[i];

return max;
}

NMLT - Mảng một chiều 39


&&
VC
VC
BB
BB
Sắp xếp mảng thành tăng dần

 Yêu cầu
 Cho trước mảng a kích thước n. Hãy sắp xếp mảng a
đó sao cho các phần tử có giá trị tăng dần.
 Ý tưởng
 Sử dụng 2 biến i và j để so sánh tất cả cặp phần tử
với nhau và hoán vị các cặp nghịch thế (sai thứ tự).

tạm 5
8

0 1 2 n–1 MAX - 1

5
1 1
5 8
6 … 6
8 … …

40
i j j j j NMLT - Mảng một chiều
&&
VC
VC
BB
BB
Hàm Sắp Xếp Tăng

void SapXepTang(int a[], int n)


{
int i, j;

for (i = 0; i < n – 1; i++)


{
for (j = i + 1; j < n; j++)
{
if (a[i] > a[j])
HoanVi(a[i], a[j]);
}
}
}

NMLT - Mảng một chiều 41


&&
VC
VC
BB
BB
Thêm một phần tử vào mảng

 Yêu cầu
 Thêm phần tử x vào mảng a kích thước n tại vị trí vt.
 Ý tưởng
 “Đẩy” các phần tử bắt đầu tại vị trí vt sang phải 1 vị trí.
 Đưa x vào vị trí vt trong mảng.
 Tăng n lên 1 đơn vị.
x chèn?

0 1 2 3 n–1 n MAX - 1

a b c … z … …

NMLT - Mảng một chiều 42


vt
&&
VC
VC
BB
BB
Hàm Thêm

void Them(int a[], int &n, int vt, int x)


{
if (vt >= 0 && vt <= n)
{
for (int i = n; i > vt; i--)
a[i] = a[i - 1];

a[vt] = x;
n++;
}
}

NMLT - Mảng một chiều 43


&&
VC
VC
BB
BB
Xóa một phần tử trong mảng

 Yêu cầu
 Xóa một phần tử trong mảng a kích thước n tại vị trí vt
 Ý tưởng
 “Kéo” các phần tử bên phải vị trí vt sang trái 1 vị trí.
 Giảm n xuống 1 đơn vị.

xóa?

0 1 2 n-1 n–1 MAX - 1

a x b … z … …

NMLT - Mảng một chiều 44


vt
&&
VC
VC
BB
BB
Hàm Xóa

void Xoa(int a[], int &n, int vt)


{
if (vt >= 0 && vt < n)
{
for (int i = vt; i < n – 1; i++)
a[i] = a[i + 1];

n--;
}
}

NMLT - Mảng một chiều 45


&&
VC
VC
BB
BB
2. Mảng 2 chiều

Ma Trận

0 1 … n-1 0 … n-1

0 0
Am,n An


m-1 n-1

NMLT - Mảng hai chiều 46


&&
VC
VC
BB
BB
Ma Trận

0 … n-1 0 … n-1 0 … n-1

0 0 0
An


n-1 n-1 n-1

dòng = cột dòng > cột dòng < cột

0 … n-1 0 … n-1 0 … n-1

0 0 0
An


n-1 n-1 n-1

dòng + cột = n-1 dòng + cột > n-1 dòng + cột < n-1
NMLT - Mảng hai chiều 47
&&
VC
VC
BB
BB
2.1. Khai báo biến mảng 2 chiều

 Cú pháp
 Tường minh
<kiểu cơ sở> <tên biến>[<N1>][<N2>];

 Không tường minh (thông qua kiểu)


typedef <kiểu cơ sở> <tên kiểu>[<N1>][<N2>];
N1, N2: số lượng phần tử mỗi chiều

<tên kiểu> <tên biến>;


<tên kiểu> <tên biến 1>, <tên biến 2>;

NMLT - Mảng hai chiều 48


&&
VC
VC
BB
BB
2.1. Khai báo kiểu mảng 2 chiều

 Ví dụ

typedef int MaTran[3][4];

0 1 2 3

Kiểu MaTran 1

NMLT - Mảng hai chiều 49


&&
VC
VC
BB
BB
2. Mảng 2 chiều

 Ví dụ
int Mang2Chieu[3][4];

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

Mang2Chieu 0
1

NMLT - Mảng một chiều 50


&&
VC
VC
BB
BB
2.1. Khai báo biến mảng 2 chiều

 Ví dụ
 Tường minh
int a[10][20], b[10][20];
int c[5][10];
int d[10][20];
 Không tường minh (thông qua kiểu)
typedef int MaTran10x20[10][20];
typedef int MaTran5x10[5][10];

MaTran10x20 a, b;
MaTran11x11 c;
MaTran10x20 d;

NMLT - Mảng hai chiều 51


&&
VC
VC
BB
BB
2.2. Truy xuất đến một phần tử

 Thông qua chỉ số


<tên biến mảng>[<giá trị cs1>][<giá trị cs2>]

 Ví dụ 0 1 2 3

 Cho mảng 2 chiều như sau 0

1
int a[3][4];
2
 Các truy xuất
• Hợp lệ: a[0][0], a[0][1], …, a[2][2], a[2][3]
• Không hợp lệ: a[-1][0], a[2][4], a[3][3]

NMLT - Mảng hai chiều 52


&&
VC
VC
BB
BB
2.3. Gán dữ liệu kiểu mảng

 Không được sử dụng phép gán thông thường


mà phải gán trực tiếp giữa các phần tử
<biến mảng đích> = <biến mảng nguồn>; //sai
<biến mảng đích>[<giá trị cs1>][giá trị cs2] =
<giá trị>;
 Ví dụ
int a[5][10], b[5][10];

b = a; // Sai
int i, j;
for (i = 0; i < 5; i++)
for (j = 0; j < 10; j++)
b[i][j] = a[i][j];
NMLT - Mảng hai chiều 53
&&
VC
VC
BB
BB
2.4. Truyền mảng cho hàm

 Truyền mảng cho hàm


 Tham số kiểu mảng trong khai báo hàm giống
như khai báo biến mảng
void NhapMaTran(int a[50][100]);
 Tham số kiểu mảng truyền cho hàm chính là địa
chỉ của phần tử đầu tiên của mảng
• Có thể bỏ số lượng phần tử chiều thứ 2 hoặc con trỏ.
• Mảng có thể thay đổi nội dung sau khi thực hiện hàm.

void NhapMaTran(int a[][100]);


void NhapMaTran(int (*a)[100]);

NMLT - Mảng hai chiều 54


&&
VC
VC
BB
BB
2.5. Truyền mảng cho hàm

 Truyền mảng cho hàm


 Số lượng phần tử thực sự truyền qua biến khác
void XuatMaTran(int a[50][100], int m, int n);
void XuatMaTran(int a[][100], int m, int n);
void XuatMaTran(int (*a)[100], int m, int n);
 Lời gọi hàm
void NhapMaTran(int a[][100], int &m, int &n);
void XuatMaTran(int a[][100], int m, int n);
void main()
{
int a[50][100], m, n;
NhapMaTran(a, m, n);
XuatMaTran(a, m, n);
} NMLT - Mảng hai chiều 55
&&
VC
VC
BB
BB
2.6. Một số bài toán cơ bản

 Viết chương trình con thực hiện các yêu cầu sau
 Nhập mảng
 Xuất mảng
 Tìm kiếm một phần tử trong mảng
 Kiểm tra tính chất của mảng
 Tính tổng các phần tử trên dòng/cột/toàn ma
trận/đường chéo chính/nửa trên/nửa dưới
 Tìm giá trị nhỏ nhất/lớn nhất của mảng
…

NMLT - Mảng hai chiều 56


&&
VC
VC
BB
BB
Nhập Ma Trận

 Yêu cầu
 Cho phép nhập mảng a, m dòng, n cột
 Ý tưởng
 Cho trước một mảng 2 chiều có dòng tối đa là MAXD,
số cột tối đa là MAXC.
 Nhập số lượng phần tử thực sự m, n của mỗi chiều.
 Nhập từng phần tử từ [0][0] đến [m-1][n-1].

NMLT - Mảng hai chiều 57


&&
VC
VC
BB
BB
Hàm Nhập Ma Trận

void NhapMaTran(int a[][MAXC], int &m, int &n)


{
cout<<Nhap so dong, so cot cua ma tran: ";
cin>>m>>n;

int i, j;
for (i=0; i<m; i++)
for (j=0; j<n; j++)
{
cout<<Nhap a[“<<i<<“][“<j<<“]:”;
cin>>a[i][j];
}
}

NMLT - Mảng hai chiều 58


&&
VC
VC
BB
BB
Xuất Ma Trận

 Yêu cầu
 Cho phép nhập mảng a, m dòng, n cột
 Ý tưởng
 Xuất giá trị từng phần tử của mảng 2 chiều từ dòng
có 0 đến dòng m-1, mỗi dòng xuất giá giá trị của cột 0
đến cột n-1 trên dòng đó.

NMLT - Mảng hai chiều 59


&&
VC
VC
BB
BB
Hàm Xuất Ma Trận

void XuatMaTran(int a[][MAXC], int m, int n)


{
int i, j;
for (i=0; i<m; i++)
{
for (j=0; j<n; j++)
cout<<“ “<< a[i][j];

cout<<“\n";
}
}

NMLT - Mảng hai chiều 60


&&
VC
VC
BB
BB
Tìm kiếm một phần tử trong Ma Trận

 Yêu cầu
 Tìm xem phần tử x có nằm trong ma trận a kích
thước mxn hay không?
 Ý tưởng
 Duyệt từng phần của ma trận a. Nếu phần tử đang
xét bằng x thì trả về có (1), ngược lại trả về không có
(0).

NMLT - Mảng hai chiều 61


&&
VC
VC
BB
BB
Hàm Tìm Kiếm

int TimKiem(int a[][MAXC], int m, int n, int x)


{
int i, j;
for (i=0; i<m; i++)
for (j=0; j<n; j++)
if (a[i][j] == x)
return 1;
return 0;
}

NMLT - Mảng hai chiều 62


&&
VC
VC
BB
BB
Kiểm tra tính chất của mảng

 Yêu cầu
 Cho trước ma trận a kích thước mxn. Ma trận a có
phải là ma trậntoàn các số nguyên tố hay không?
 Ý tưởng
 Cách 1: Đếm số lượng số ngtố của ma trận. Nếu số
lượng này bằng đúng mxn thì ma trận toàn ngtố.
 Cách 2: Đếm số lượng số không phải ngtố của ma
trận. Nếu số lượng này bằng 0 thì ma trận toàn ngtố.
 Cách 3: Tìm xem có phần tử nào không phải số ngtố
không. Nếu có thì ma trận không toàn số ngtố.

NMLT - Mảng hai chiều 63


&&
VC
VC
BB
BB
Hàm tính tổng trên dòng

int TongDong(int a[][MAXC], int m, int n, int d)


{
int j, tong;

tong = 0;

for (j=0; j<n; j++) // Duyệt các cột


tong = tong + a[d][j];

return tong;
}

NMLT - Mảng hai chiều 64


&&
VC
VC
BB
BB
Hàm tính tổng trên cột

int TongCot(int a[][MAXC], int m, int c)


{
int i, tong;

tong = 0;

for (i=0; i<m; i++) // Duyệt các dòng


tong = tong + a[i][c];

return tong;
}

NMLT - Mảng hai chiều 65


&&
VC
VC
BB
BB
Hàm tính tổng đường chéo chính

int TongDCChinh(int a[][MAXC], int n)


{
int i, tong;

tong = 0;

for (i=0; i<n; i++)


tong = tong + a[i][i];

return tong;
}

NMLT - Mảng hai chiều 66


&&
VC
VC
BB
BB
Hàm tính tổng trên đường chéo chính

int TongTrenDCChinh(int a[][MAXC], int n)


{
int i, j, tong;

tong = 0;

for (i=0; i<n; i++)


for (j=0; j<n; j++)
if (i < j)
tong = tong + a[i][j];

return tong;
}

NMLT - Mảng hai chiều 67


&&
VC
VC
BB
BB
Hàm tính tổng dưới đường chéo chính

int TongTrenDCChinh(int a[][MAXC], int n)


{
int i, j, tong;

tong = 0;

for (i=0; i<n; i++)


for (j=0; j<n; j++)
if (i > j)
tong = tong + a[i][j];

return tong;
}

NMLT - Mảng hai chiều 68


&&
VC
VC
BB
BB
Hàm tính tổng trên đường chéo phụ

int TongDCPhu(int a[][MAXC], int n)


{
int i, tong;

tong = 0;

for (i=0; i<n; i++)


tong = tong + a[i][n-i-1];

return tong;
}

NMLT - Mảng hai chiều 69


&&
VC
VC
BB
BB
Tìm giá trị lớn nhất của Ma Trận

 Yêu cầu
 Cho trước ma trận a, kích thước mxn. Tìm giá trị lớn
nhất trong ma trận a (gọi là max)
 Ý tưởng
 Giả sử giá trị max hiện tại là giá trị phần tử đầu tiên a[0]
[0]
 Lần lượt kiểm tra các phần tử còn lại để cập nhật max.

NMLT - Mảng hai chiều 70


&&
VC
VC
BB
BB
Hàm tìm Max

int TimMax(int a[][MAXC], int m, int n)


{
int i, j, max;

max = a[0][0];

for (i=0; i<m; i++)


for (j=0; j<n; j++)
if (a[i][j] > max)
max = a[i][j];

return max;
}

NMLT - Mảng hai chiều 71


&&
VC
VC
BB
BB
ÔN TẬP

Sinh viên truy cập vào link sau để làm bài kiểm tra
ôn tập chương 6:
https://docs.google.com/forms/d/e/
1FAIpQLSdjF6uNM8uVs6e_yQKoOSys-O9a4wJgFV-
KXR6Z5SxN_N0Aww/viewform?usp=sf_link

72

You might also like