www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
Nhập Môn Lập Trình
Mảng Hai Chiều – Con Trỏ
www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
Road Map
Mảng Đa Chiều
Khái Niệm Mảng Đa Chiều
Giải Thích Mảng 2 Chiều
Khai báo, duyệt, khởi tao, nhập/xuất mảng 2 chiều
Con Trỏ (Pointer)
Khái niệm về Con trỏ
Các toán tử
Con trỏ và mảng 1 chiều
Con trỏ và mảng 2 chiều
Con trỏ và chuỗi
www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
www.hoasen.edu.vn
3
Khái Niệm Mảng Đa Chiều
- Mảng đa (nhiều) chiều là mảng mà những phần tử
của nó được xác định bởi nhiều chỉ số.
- Mảng 2 chiều là mảng nhiều chiều đơn giản và sử
dụng nhiều nhất.
- Mảng 2 chiều giống như một bảng, gồm nhiều dòng
và nhiều cột
www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
4
0 1 2 3 4
0 5 7 9 2 3
1 1 5 7 4 6
2 1 8 9 0 3
3 2 5 6 3 4
Chỉ số
cột
m[2][3]
i và j là số nguyên
chỉ số
dòng
Mảng 2 chiều:
Một nhóm các phần tử có
cùng kiểu, chung tên.
Các phần tử được xác
Định bằng chỉ số dòng
và chỉ số cột.
GIẢI THÍCH MẢNG 2 CHIỀU
www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
GIẢI THÍCH MẢNG 2 CHIỀU
float rain[5][12];
float rain[5][12]; /* array of 5 arrays of 12 floats */
float rain[5] [12]; /* rain: array of 5 somethings */
float rain[5] [12]; /* somethings = an array of 12 floats */
rain[0], the first element of rain, is an array of 12 float values.
So are rain[1], rain[2], rain[3], and rain[4].
If rain[0] is an array, its first element is rain[0][0], its second
element is rain[0][1], and so on.
Rain is a five-element array of 12-element arrays of float, rain[0] is
an array of 12 floats, and rain[0][0] is a float.
To access, say, the value in row 2, column 3, use rain[2][3].
(Remember, array counting starts at 0, so row 2 is the third row.)
www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
GIẢI THÍCH MẢNG 2 CHIỀU
www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
www.hoasen.edu.vn
7
DataType mt[ maxRow] [maxColumn] ;
int r, c ; // Số dòng và cột hiện thời
#define maxRow1 20
#define maxCol1 50
int m1 [maxRow1] [maxCol1];
int r1, c1;
const int maxRow2=30;
const int maxCol2=60;
long m2 [maxRow2] [maxCol2];
int r2, c2;
char m3 [20] [25];
int r3, c3;
Khai báo mảng 2 chiều
www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
www.hoasen.edu.vn
8
m 0 1 2 3 4
0 5 7 9 2 3
1 2 5 7 4 6
2 1 8 9 0 3
3 2 5 6 3 4
col=5
row=4
for (int i=0;i<row; i++)
{ for (int j=0;j<col;j++) Xử lý m[i][j];
Những thao tác khác;
}
// Tổng phần tử mảng
S=0;
for (int i=0;i<row, i++)
{ for (int j=0;j<col;j++)
S+= m[i][j];
}
//Xuất mảng
for (int i=0;i<row, i++)
{ for (int j=0;j<col;j++) printf(“%3d”,m[i][j]);
printf(“\n”);
}
Duyệt mảng 2 chiều
www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
www.hoasen.edu.vn
9
#include <conio.h>
#include <stdio.h>
void main()
{ int mt1[2][3] = {1,2,3,4,5,6};
int mt2[2][3] = {{2,1,4},{4,7,6}};
int i,j; clrscr();
printf("mang 1\n");
for (i=0;i<2;i++)
{ for(j=0; j<3; j++) printf("%4d",mt1[i][j]);
printf("\n");
}
printf("mang 2\n");
for (i=0;i<2;i++)
{ for(j=0; j<3; j++) printf("%4d",mt2[i][j]);
printf("\n");
}
getch();
}
Khởi tạo
mảng
Khởi tạo mảng 2 chiều
www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
www.hoasen.edu.vn
10
Nhập/xuất mảng 2 chiều
Nhập mảng 2 chiều: sử dụng 2 vòng lặp for
Ví dụ nhập mảng số nguyên 2 chiều có N hàng và M cột
for (int i=0; i<N; i++)
{
for (j=0; j<M; j++)
{
printf(“A[%d][%d]:”,i,j);
scanf(“%d”,&A[i][j]);
}
}
www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
www.hoasen.edu.vn
11
Nhập/xuất mảng 2 chiều
Xuất mảng 2 chiều: sử dụng 2 vòng lặp for
Ví dụ xuất mảng số nguyên 2 chiều có N hàng và M cột
for (int i=0; i<N; i++)
{
for (j=0; j<M; j++)
{
printf(“%3d”,A[i][j]);
}
printf(“\n”);
}
www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
www.hoasen.edu.vn
12
Viết chương trình nhập 1 mảng số nguyên 2 chiều với N hàng và
M cột. Thực hiện các công việc sau:
- In mảng 2 chiều ra màn hình
-
Tìm tổng các phần tử trong mảng.
- Liệt kê các phần tử chia hết cho 7.
- Tìm tổng các phần tử nằm trên đường viền của mảng
- Tìm cột có tích Max.
- Tìm dòng có nhiều số chính phương nhất
-
Hoán vị thành mảng MxN
-
Chuyển thành mảng 1 chiều rồi sắp xếp tăng dần
BÀI TẬP
www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
Road Map
Mảng Đa Chiều
Khái Niệm Mảng Đa Chiều
Giải Thích Mảng 2 Chiều
Khai báo, duyệt, khởi tao, nhập/xuất mảng 2 chiều
Con Trỏ (Pointer)
Khái niệm về Con trỏ
Các toán tử
Con trỏ và mảng 1 chiều
Con trỏ và mảng 2 chiều
Con trỏ và chuỗi
www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
Khái niệm về Con trỏ
Con trỏ là một biến chứa địa chỉ vùng nhớ của một biến khác
Con trỏ được sử dụng trong chương trình để truy cập bộ nhớ
và vận dụng các bộ nhớ
Chúng ta đã sử dụng các địa chỉ bộ nhớ như là tham số cho
hàm scanf()
scanf(“%d”, &value): lưu 1 giá trị (được nhập) vào 1 địa chỉ cụ thể
trong bộ nhớ
value là biến và &value là địa chỉ
14
www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
Biến con trỏ
Khai báo: type *name;
type: một kiểu dữ liệu hợp lệ bất kỳ (int, long, char …)
name: tên của biến con trỏ
Ví dụ: int i, *p;
Gán giá trị:
p = &i; /* “referring” chỉ đến địa chỉ I */
p = 0;
P = NULL; /* tương đương với p = 0; */
15
www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
Các toán tử con trỏ
Hai toán tử đặc biệt được dùng với con trỏ: * và &
Toán tử &: trả về "địa chỉ của"
var2 = &var1; /* lấy địa chỉ vùng nhớ của biến var1 gán cho var2 */
/*VD: var1 có giá trị 100 và dùng vùng nhớ 302 */
/* để lưu giá trị này. Vậy var2 sẽ có giá trị 302 */
Toán tử *:
Dùng bổ xung với toán tử &
trả về giá trị chứa trong vùng nhớ mà vùng nhớ này được trỏ bởi giá
trị của biến con trỏ (tại địa chỉ)
tmp = *var2; /* tmp có giá tri 100 */
16
www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
Addressing and Dereferencing
int a, b, *p; → Complier to allocate space in memory for 2 int and
a pointer to int
a b p
a = b = 7;
p = &a;
a b p
17
? ?
?
7 7
www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
Addressing and Dereferencing
Bây giờ, chúng ta có thể dùng con trỏ p truy cập giá trị chứa trong
biến a
Điều này được thực hiện qua “dereference” của toán tử *
p là con trỏ, *p có giá trị của biến con trỏ “chỉ” đến
printf("*p = %d\n", *p); // 7 sẽ được in ra
( p points to a, and a has value 7, the dereferenced value of p is 7,
and that is what gets printed)
18
www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
Addressing and Dereferencing
*p = 3; → The object pointed to by p is assigned the value of 3
printf(“a = %d\n", a); /* 3 sẽ được in ra */
a b p
19
3 7
www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
Sử dụng con trỏ
Để trả về nhiều hơn một giá trị từ một hàm
Thuận tiện hơn trong việc truyền các mảng và chuỗi từ một hàm
đến một hàm khác
Sử dụng con trỏ để làm việc với các phần tử của mảng thay vì truy
xuất trực tiếp vào các phần tử này
Để cấp phát bộ nhớ động và truy xuất vào vùng nhớ được cấp phát
này (dynamic memory allocation)
20
www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
int i = 3, j = 5, *p = &i, *q = &j, *r;
double x;
Expression Equivalent exp Value
p == &i p == (&i) 1
p = i + 7 p = (i + 7) /* Không cho phép */
* * & p *(*(&p)) 3
r = & x r = (&x) /* Không cho phép */
7 * * p / * q + 7 (((7 * (*p))) / (*q)) + 7 11
* (r = &j) *= * p (* (r = (&j))) *= (*p) 15
Phép tính số trên con trỏ
21
Chỉ có thể thực hiện phép cộng trừ trên con trỏ
www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
Con trỏ và mảng 1 chiều
An array name by itself is an address or pointer value
Pointers and arrays are almost identical in term of how they are
used to assess memory
Differences:
A pointer is a variable that takes addresses as value
An array name is a particular fixed address that can be thought of as a
constant pointer
When an array is declared, the complier must allocate a base address and a
sufficient amount of storage to contain all elements of the array.
The base address of the array is the initial location in memory where the
array is stored
22
www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
Con trỏ và mảng 1 chiều
int a[100], *p; → memory bytes numbered 300, 304, 308, …,
696 to be the addresses of a[0], a[1], a[2], …, a[99]
p = a; and p = &a[0]; → are equivalent and would assign 300 to p
a = p; ++a; a += 2; → Không cho phép (illegal)
23
www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
Con trỏ và mảng 1 chiều
Truy cập địa chỉ các phần tử mảng:
array[100] ; // array mảng 1 chiều có 100 phần tử
địa chỉ của phần tử đầu tiên trong mảng: &array[0] hay array
địa chỉ của phần tử thứ hai trong mảng: &array[1] hay array + 1
Tổng quát, địa chỉ của phần tử thứ i trong mảng: &array[i+1]
hay array + i
→ array[i] và *(array +i) đều biểu diễn nội dung của địa chỉ
đó, nghĩa là, giá trị của phần tử thứ i trong mảng array
24
www.hoasen.edu.vn
Cùng Đại học Hoa Sen xây dựng tương lai
Con trỏ và mảng 1 chiều
Chương trình sau đây biểu diễn mối quan hệ giữa các phần tử
mảng và địa chỉ của chúng
#include<stdio.h>
void main()
{
static int array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int i;
for (i = 0; i < 10; i ++)
{
printf(“i=%d , array[i]=%d , *(array+i)= %d “, i, array[i], *(array+i));
printf(“&array[i] = %X , array + i = %X”, &array[i], array + i);
// %X gives unsigned hexadecimal
}
}
25