Khái niệm
Mảng thực chất là một biến được cấp phát bộ nhớ liên tục và bao gồm nhiều biến thành phần.
Các thành phần của mảng là tập hợp các biến có cùng kiểu dữ liệu và cùng tên. Do đó để truy xuất các biến thành phần, ta dùng cơ chế chỉ mục (chỉ số).
Khai báo mảng
Cú pháp:
< Kiểu_mảng> < Tên_mảng > [ < Số_phần_tử_tối_đa> ] ;
Trong đó:
Kiểu_mảng: đây là kiểu của mảng, là tên một kiểu dữ liệu đã tồn tại, có thể là kiểu chuẩn hoặc kiểu dữ liệu do người lập trình định nghĩa .
Tên_mảng: là tên của mảng, do người lập trình đặt, theo quy tắc về tên của C/C++.
Số_phần_tử: là hằng (hoặc biểu thức hằng) nguyên, dương là số phần tử của mảng.
Ví dụ:
int a[10]; // Khai báo mảng a, có số phần tử tối đa là 10, kiểu dữ liệu của mảng a là int.
float MT[20]; //Khai báo mảng MT, có số phần tử tối đa là 20, kiểu dữ liệu của mảng MT là float.
Truy xuất đến các phần tử của mảng
Cú pháp :tên_mảng [chỉ_số]
Ví dụ: a[1], MT[3];
chỉ_số là số thứ tự của phần tử trong mảng, các phần tử của mảng được đánh chỉ số bắt đầu từ 0. Với mảng có n phần tử thì các phần tử của nó có chỉ số là 0, 1,..,n-1.
Khởi tạo mảng
Kiểu_mảng tên_mảng [ số_phần_tử ] = {gt_0, gt_1,..,gt_k};
hoặc
Kiểu_mảng tên_mảng [ ] = {gt_0, gt_1,..,gt_k};
Trong đó các thành phần Kiểu_mảng , tên_mảng, số_phần_tử như trong phần khai báo mảng. gt_0, gt_1,.., gt_k là các giá trị khởi đầu (gọi là bộ khởi đầu) cho các phần tử tương ứng của mảng, tức là gán tuần tự các giá trị trong bộ khởi đầu cho các phần tử của mảng từ trái qua phải.
Trong dạng thứ nhất, số giá trị trong bộ khởi đầu chỉ có thể <= số phần tử của mảng (k ≤ số_phần_tử). Khi đó những phần tử mảng thừa ra (không có giá trị khởi đầu) sẽ tự động được gán bằng 0 (trong trường hợp mảng số, nếu là con trỏ sẽ là NULL (rỗng) ).
Ví dụ:
int a[3] ={ 1, 3, 4}; thì giá trị của a[0] là 1, a[1] là 3, a[2] là 4.
int b[5] ={1,2}; thì giá trị của b[0] là 1, b[1] là 2, b[3]=b[4] là 0.
với mảng các ký tự hoặc xâu ký tự thì có hai cách khởi đầu như sau:
char c[4] ={‘a’,’b’,’c’ }; // c[0] là ‘a’, c[1] là ‘b’, c[2] là ‘c’, c[3] là ‘\0’
char s[10] =”ABC”; // tương đương với char s[10] ={‘A’,’B’,’C’,’\0’}
(nếu số giá trị trong bộ khởi đầu > số phần tử mảng chương trình dịch sẽ báo lỗi)
Trong dạng thứ hai, chúng ta không xác định số phần tử của mảng, trong trường hợp này chương trình biên dịch sẽ tự động xác định kích thước (số phần tử) của mảng theo số giá trị trong bộ khởi đầu.
Ví dụ:
int a[] ={1,3,4};
thì a là mảng có 3 phần tử, giá trị của a[0] là 1, a[1] là 3, a[2] là 4.
Ví dụ 1: Viết chương trình nhập vào một mảng A có n phần tử kiểu nguyên, n<=20, n được nhập từ bàn phím. In các phần tử của mảng theo trật tự xuôi, ngược (theo trật tự chỉ số).
#include<iostream.h>
main()
{
const max = 20;
int n, i, a[max];
do {
cout<<"Nhap vao so phan tu cua mang: "; cin>>n;
}
while (n < 1 || n > max);
cout<<"Nhap vao mang a: "<<endl;
for (i = 0; i<n; i++)
cin>>a[i];
cout<<"Cac phan tu mang theo TT xuoi la: ";
for (i = 0; i<n; i++)
cout<<a[i]<<"\t";
cout<<endl;
cout<<"Cac phan tu mang theo TT nguoc la: ";
for (i = n-1;i>=0; i--)
cout<<a[i]<<"\t";
return 0;
}
Ví dụ 2: Nhập vào 2 mảng A và B, có số phần tử tối đa là 10. Tính tổng của A và B.
//Tinh tong cua C = A + B
#include<iostream.h>
main()
{
const max = 10;
int n, i, a[max], b[max], c[max];
do {
cout<<"Nhap vao so phan tu cua mang: "; cin>>n;
}
while (n < 1 || n > max);
cout<<"Nhap vao so PT mang a: "<<endl;
for (i = 0; i<n; i++)
cin>>a[i];
cout<<"Nhap vao so PT mang b: "<<endl;
for (i = 0; i<n; i++)
cin>>b[i];
cout<<"Tong C = A + B = ";
for (i = 0; i< n; i++)
c[i] = a[i] + b[i];
for (i = 0; i<n; i++)
cout<<c[i]<<"\t";
return 0;
}
Dùng mảng làm tham số
Vào một lúc nào đó có thể chúng ta cần phải truyền một mảng tới một hàm như là một tham số. Trong C++, việc truyền theo tham số giá trị một khối nhớ là không hợp lệ, ngay cả khi nó được tổ chức thành một mảng. Tuy nhiên chúng ta lại được phép truyền địa chỉ của nó, việc này cũng tạo ra kết quả thực tế giống thao tác ở trên nhưng lại nhanh hơn nhiều và hiệu quả hơn.
Để có thể nhận mảng là tham số thì điều duy nhất chúng ta phải làm khi khai báo hàm là chỉ định trong phần tham số kiểu dữ liệu cơ bản của mảng, tên mảng và cặp ngoặc vuông trống.
Ví dụ, hàm sau:
void procedure (int arg[])
nhận vào một tham số có kiểu "mảng của char" và có tên arg. Để truyền tham số cho hàm này một mảng được khai báo:
int myarray [40];
chỉ cần gọi hàm như sau:
procedure (myarray);
Ví dụ 1:
#include <iostream.h>
void printarray (int arg[], int length)
{
for (int n=0; n<length; n++)
cout << arg[n] << " ";
cout << "\n";
}
int main ()
{
int firstarray[] = {5, 10, 15};
int secondarray[] = {2, 4, 6, 8, 10};
printarray (firstarray,3);
printarray (secondarray,5);
return 0;
}
Ví dụ 2: Tính tổng C = A + B
#include <iostream.h>
void nhapmang(int a[], int n);
void inmang(int a[], int n);
void tong(int A[],int B[],int C[],int n);
void main()
{
const int max = 20;
int A[max], B[max],C[max];
int n;
do {
cout<<"\nNhap so phan tu mang = ";
cin>>n;
}
while(n<1 || n>max);
cout<<"\nNhap A \n";
nhapmang(A,n);
cout<<"\nNhap B \n";
nhapmang(B,n);
tong(A,B,C,n);
cout<<"\nmang A: ";
inmang(A,n);
cout<<"\nmang B: ";
inmang(B,n);
cout<<"\nmang C: ";
inmang(C,n);
}
void nhapmang(int a[], int n){
int i;
cout<<"\nNhap mang co so phan tu: "<<n;
for(i=0; i<n; i++)
{
cout<<"\nPhan tu thu"<<"["<<i<<"]";
cin>>a[i];
}
}
void inmang(int a[], int n){
int i;
for(i=0; i<n; i++)
cout<<a[i];
}
void tong(int A[],int B[],int C[],int n){
int i;
for (i = 0; i<n; i++)
C[i]=A[i]+B[i];
}
Mảng hai chiều
Định nghĩa
Mảng hai chiều có thể hiểu như bảng gồm các dòng các cột, các phần tử thuộc cùng một kiểu dữ liệu nào đó. Mảng hai chiều được định nghĩa như sau.
Cú pháp:
Kiểu_mảng tên_mảng [sd][sc];
Trong đó:
- Kiểu_mảng: đây là kiểu của mảng, là tên một kiểu dữ liệu đã tồn tại, có thể là kiểu chuẩn hoặc kiểu dữ liệu do người lập trình định nghĩa.
- Tên_mảng: là tên của mảng, do người lập trình đặt, theo quy tắc về tên của C/C++.
- sd, sc: là hằng (hoặc biểu thức hằng) nguyên, dương tương ứng là số dòng và số cột mảng, số phần tử của mảng sẽ là sd*sc.
Ví dụ:
int a[2][5]; // a là mảng số nguyên có 2 dòng, 5 cột (có 10 phần tử).
float D[3][10]; // D là mảng số thực có 3 dòng, 10 cột (có 30 phần tử).
char DS[5][30]; // DS là mảng kí tự có 5 dòng, 30 cột.
Truy xuất các phần tử của mảng hai chiều
Một phần tử của mảng 2 chiều được xác định qua tên (tên của mảng) và chỉ số dòng, chỉ số cột của nó trong mảng theo cú pháp sau:
tên_mảng [csd][csc]
Với csd là số nguyên xác định chỉ số dòng và csc là số hiệu cột cũng như trong mảng 1 chiều các chỉ số được tính từ 0. Tức là 0 ≤csd ≤sd-1 và 0≤csc≤sc-1.
Khởi tạo giá trị mảng hai chiều
Các phần tử mảng hai chiều cũng có thể được khởi đầu giá trị theo cú pháp (4 dạng sau):
+ Kiểu_mảng tên_mảng [sd][sc]={{kđ_dòng_1},{ kđ_dòng_2},..,{ kđ_dòng_k}};
+ Kiểu_mảng tên_mảng [ ][sc] = {{kđ_dòng_1},{ kđ_dòng_2},..,{ kđ_dòng_k}};
+ Kiểu_mảng tên_mảng [sd][sc] = { gt_1, gt_2,...,gt_n };
+ Kiểu_mảng tên_mảng [ ][sc] = { gt_1, gt_2,...,gt_n };
Dạng 1: có k bộ giá trị sẽ được gán cho k dòng đầu tiên của mảng (k ≤ sd ), với mỗi dòng (được coi như mảng một chiều) được khởi tạo giá trị như mảng một chiều:
dòng thứ nhất được khởi đầu bởi {kđ_dòng_1}, dòng thứ hai được khởi đầu bởi {kđ_dòng_1},.., dòng thứ k được khởi đầu bởi {kđ_dòng_k}. Yêu cầu k ≤ sd, ngược lại chương trình sẽ báo lỗi.
Các dòng cuối của mảng nếu không có bộ khởi đầu tương ứng thì sẽ được tự động gán giá trị 0 (hoặc NULL nếu là con trỏ).
Dạng 2: (không xác định số dòng) chương trình dịch sẽ tự động ấn định số dòng của mảng bằng số bộ khởi đầu ( = k), sau đó thực hiện khởi đầu như dạng 1.
Dạng 3: n giá trị trong bộ khởi đầu được gán cho các phần tử mảng theo cách: sc giá trị đầu tiên trong các giá trị khởi đầu (gt_1,..,gt_sc) được gán tuần tự cho các phần tử của dòng thứ nhất trong mảng, sc phần tử kế tiếp sẽ gán cho các phần tử ở dòng thứ 2,... nếu phần tử nào của mảng không có giá trị khởi đầu sẽ được gán 0 (con trỏ là NULL) - với điều kiện n ≤ sd*sc, ngược lại là lỗi.
Dạng 4: số dòng của mảng sẽ được chương trình tự tính theo số giá trị trong bộ khởi đầu theo công thức sd = (n/sc) +1, và khởi đầu như dạng 3.
Ví dụ 1: int a[3][2] = {{1,2},{3},{4,5}}; thì các phần tử của a như sau:
a[0][0]=1, a[0][1]=2, a[1][0]=3, a[1][1]= 0, a[2][0]=4,a[2][1]=5;
Ví dụ 2: int b[ ][2] = {{1,2},{3},{4,5}};
thì là mảng 3 dòng, 2 cột các phần tử của b như sau:
b[0][0]=1, b[0][1]=2, b[1][0]=3,b[1][1]= 0, b[2][0]=4,b[2][1]=5;
Ví dụ 3: int c[ ][2] = {1,2,3,4,5};
thì số dòng của c là mảng 5/2 +1 =3 dòng, các phần tử của a như sau:
c[0][0]=1, c[0][1]=2, c[1][0]=3,c[1][1]= 4, b[2][0]=5,b[2][1]=0;
Viết chương trình nhập vào mảng A(n, m) với 1<=n,m<=5 các số nguyên.
Yêu cầu:
+ In mảng A ra màn hình.
+ In ra màn hình các phần tử chẵn của mảng.
+ In ra màn hình các phần tử lẻ của mảng.
#include<iostream.h>
main()
{
const max = 5;//Kich thuoc toi da
int a[max][max];
int n,m,i,j;
do {
cout<<"Nhap so dong cua mang = ";cin>>n;
cout<<"Nhap so cot cua mang = "; cin>>m;
}
while (n<1 || n>max || m<1 || m>max);
cout<<"Nhap cac gia tri cua mang: "<<endl;
for (i = 0; i<n; i++)
for (j = 0; j<m; j++)
{
cin>>a[i][j];
}
cout<<"Cac PT cua mang la: "<<" ";
for (i = 0; i<n; i++)
{
cout<<endl;
for (j = 0; j<m; j++)
cout<<a[i][j]<<" ";
}
cout<<"\n Cac PT chan cua mang la: ";
for (i = 0; i<n; i++)
for (j = 0; j<m; j++)
{
if (a[i][j] % 2 == 0)
cout<<a[i][j]<<"\t";
}
cout<<"\n Cac PT le cua mang la: ";
for (i = 0; i<n; i++)
for (j = 0; j<m; j++)
{
if (a[i][j] % 2 != 0)
cout<<a[i][j]<<"\t";
}
}