Chương 10. Mảng, con trỏ và xâu ký tự
Học phần: LẬP TRÌNH CƠ BẢN
Tài liệu tham khảo
Kỹ thuật lập trình C: cơ sở và nâng cao, Phạm
Văn Ất, Nhà xuất bản KHKT – Chương 6
The C programming language 2nd Edition,
Brian Kernighan and Dennis Ritchie, Prentice
Hall Software Series – Chương 4
The C programming language 2nd Edition,
Brian Kernighan and Dennis Ritchie, Prentice
Hall Software Series – Chương 5
2
Nội dung
Mảng một chiều
Mảng hai chiều
Con trỏ và phép toán trên con trỏ
Khai báo con trỏ
Phép gán con trỏ
Truy xuất giá trị qua con trỏ
Con trỏ và mảng
Cấp phát vùng nhớ cho con trỏ
Xâu ký tự
3
Khái niệm
Khởi tạo
Các thao tác trên xâu ký tự
PHẦN 1. MẢNG MỘT CHIỀU VÀ NHIỀU CHIỀU
4
Mảng một chiều
Khái niệm
Khai báo
Truy xuất dữ liệu
5
Dữ liệu kiểu mảng
Khái niệm
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. Ví dụ:
dãy các số ngun, 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.
6
Khai báo biến mảng (tường minh)
Tường minh
<kiểu cơ sở> <tên biến mảng>[<số phần tử>];
<kiểu cơ sở> <tên biến mảng>[<N1>][<N2>]…[<Nn>];
<N1>, …, <Nn> : số lượng phần tử của mỗi chiều.
Lưu ý
Phải xác định <số phần tử> cụ thể (hằng) khi khai báo.
Mảng nhiều chiều: <tổng số phần tử> = N1*N2*…*Nn
Bộ nhớ sử dụng = <tổng số phần tử>*sizeof(<kiểu cơ sở>)
Một dãy liên tục có chỉ số từ 0 đến <tổng số phần tử>-1
7
Khai báo biến mảng (tường minh)
Ví dụ
int Mang1Chieu[10];
0
1
2
3
4
5
6
7
8
9
3
4
5
6
7
8
9
Mang1Chieu
int Mang2Chieu[3][4];
0
Mang2Chieu 0
1
2
8
1
2
10 11
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
int n1 = 10; int a[n1];
const
= thị
20;tiền
intxử
b[n2];
Nên
sử int
dụngn2chỉ
lý #define để định nghĩa số
phần tử mảng
#define n1 10
#define n2 20
int a[n1];
int b[n1][n2];
9
// int a[10];
// int b[10][20];
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
int a[4] = {2912, 1706, 1506, 1904};
a
0
1
2
3
2912
1706
1506
1904
Khởi tạo giá trị cho một số phần tử đầu mảng
int a[4] = {2912, 1706};
a
10
0
1
2
3
2912
1706
0
0
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};
a
0
1
2
3
0
0
0
0
Tự động xác định số lượng phần tử
int a[] = {2912, 1706, 1506, 1904};
a
11
0
1
2
3
2912
1706
1506
1904
Truy xuất đến một phần tử
Thông qua chỉ số
<tên biến mảng>[<gt cs1>][<gt cs2>]…[<gt csn>]
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 thường không như mong muốn!
12
Ví dụ
Nhập mảng có n phần tử kiểu ngun, in ra các phần tử của mảng
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
13
#include <stdio.h>
#define MAX 1000
main()
{
int ary[MAX];
int i,n;
printf(“Nhap n = ”);
scanf(“%d”,&n);
for(i=0; i
{
printf(“\n Enter value: %d : ”, i+1);
scanf(“%d”,&ary[i]);
}
for(i=0; i
ary[i]);
}
Ví dụ
Nhập 2 mảng có n phần tử kiểu ngun, tính và in ra mảng tổng
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
14
#include <stdio.h>
#define MAX 1000
void main()
{
int ary1[MAX], ary2[MAX], sum[MAX];
int i,n;
printf(“Nhap n = ”);scanf(“%d”,&n);
for(i=0; i
{
printf(“\n Enter value: %d : ”, i+1);
scanf(“%d”,&ary1[i]);
}
for(i=0; i
{
printf(“\n Enter value: %d : ”, i+1);
scanf(“%d”,&ary2[i]);
}
for(i=0; i
for(i=0; i
}
Mảng hai chiều
(Tự đọc)
Khái niệm
Khai báo
Truy xuất dữ liệu
15
Ma Trận
0
1
… n-1
0
0
m-1
16
An
…
…
Am,n
0
n-1
… n-1
Ma Trận
0
… n-1
0
0
…
…
n-1
dòng > cột
… n-1
0
0
dòng < cột
… n-1
0
0
…
…
…
n-1
n-1
dòng + cột > n-1
… n-1
0
n-1
dòng + cột = n-1
… n-1
0
n-1
0
17
0
n-1
dòng = cột
An
… n-1
…
An
0
dòng + cột < n-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>];
<tên kiểu> <tên biến>;
<tên kiểu> <tên biến 1>, <tên biến 2>;
18
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;
19
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>]
0
Ví dụ
Cho mảng 2 chiều như sau
int a[3][4];
20
0
1
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]
1
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ử
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];
21
Ví dụ
Nhập mảng có n dịng, m cột các phần tử kiểu nguyên, in các phần tử
của mảng ra màn hình
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
22
#include <stdio.h>
#define MAX 1000
void main()
{
int a[MAX][MAX];
int i,n,m;
//Nhap mang
printf(“Nhap n = ”);scanf(“%d”,&n);
printf(“Nhap m = ”);scanf(“%d”,&m);
for (i=0; i
for (j=0; j
{
printf(“Nhap a[%d][%d]: ”, i, j);
scanf(“%d”, &a[i][j]);
}
Ví dụ
Nhập mảng có n dịng, m cột các phần tử kiểu nguyên, in các phần tử của
mảng ra màn hình (tiếp)
16.
17.
18.
19.
20.
21.
23
// In cac phan tu cua mang
for (i=0; i
{
for (j=0; j
printf(“\n”);}
}
Ví dụ
Nhập 2 mảng A, B có n dịng, m cột các phần tử kiểu nguyên, tính và
in
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
24
các phần tử của mảng C = A + B
#include <stdio.h>
#define MAX 1000
void main(){
int a[MAX][MAX], b[MAX][MAX], c[MAX][MAX];int i,n,m;
//Nhap 2 mang
printf(“Nhap n = ”);scanf(“%d”,&n);
printf(“Nhap m = ”);scanf(“%d”,&m);
for (i=0; i
for (j=0; j
printf(“Nhap a[%d][%d]: ”, i, j);
scanf(“%d”, &a[i][j]); }
for (i=0; i
for (j=0; j
printf(“Nhap a[%d][%d]: ”, i, j);
scanf(“%d”, &a[i][j]); }
Ví dụ
Nhập 2 mảng A, B có n, m cột các phần tử kiểu nguyên, tính và in các
phần tử của mảng C = A + B (tiếp)
16.
17.
18.
19.
20.
21.
22.
23.
24.
25
// Tinh cac phan tu cua mang C
for (i=0; i
for (j=0; j
c[i][j] = a[i][j] + b[i][j];
// In cac phan tu cua mang C
for (i=0; i
{
for (j=0; j
printf(“\n”);}
}