Bài giảng C căn bản - Chương 1: Kỹ thuật xử lý Mảng và Con trỏ
Mảng (array) là một dãy các phần tử có cùng kiểu dữ liệu được đặt liên tiếp trong bộ nhớ.
Mỗi phần tử được xác định bởi một chỉ số biểu thị vị trí của phần tử trong mảng.
Số lượng phần tử trong mảng được gọi là kích thước của mảng.
Kích thước của mảng là cố định và phải được xác định trước.
g
long TongUocSo(int n)
{
long S; int i;
S = 0;
for (i = 1; i <n; i++)
if(n%i ==0)
S = S + i;
return S;
}
7
1.1. Khái niệm Mảng
long TichUocSo(int n)
{ long P; int i;
P = 1;
for (i = 1; i <n; i++)
if(n%i ==0)
P = P * i;
return P;
}
int SoHoanChinh(int n)
{
return ( TongUocSo(n )== TichUocSo(n ));
}
8
1.1. Khái niệm Mảng
Đếm các số a[1], a[2], , a[n] thõa điều kiện
count = 0;
Lặp i = 1, 2, 3, , n
Nếu a[i ] thõa điều kiện thì
Count = count + 1;
Cuối lặp .
Ví dụ : Đếm số phần tử dương , số phần tử âm , số phần tử bằng 0 trong mảng số nguyên a có n phần tử .
9
1.1. Khái niệm Mảng
void Demso(int a[], int n, int & demduong , int&demam , int & demkhong )
{ int i;
demduong =0; demam = 0; demkhong = 0;
for (i = 0; i < n; i++)
{
if ( a[i ]>0) ( demduong )++;
if ( a[i ]<0) ( demam )++;
if(a[i ]==0) ( demkhong )++;
}
}
10
1.1. Khái niệm Mảng
Tìm phần tử đầu tiên trong mảng a thõa điều kiện
j = -1, i = 1;
Lặp ( trong khi (i<=n) và (j = -1))
Nếu a[i] thõa điều kiện thì
j = i;
Cuối nếu.
i = i+1;
Cuối lặp.
Ví dụ : Tìm phần tử âm đầu tiên trong mảng a mà có tận cùng bằng 6.
11
1.1. Khái niệm Mảng
int AmTanCung6(int a[], int n)
{
i = 0;
j = -1;
while (i < n && j ==-1)
{
if(a[i]<0 && -a[i] %10 ==6)
j = i;
i++;
}
re turn j;
}
12
1.1. Khái niệm Mảng
Tìm tất cả các phần tử mảng a thõa điều kiện
m = 0;
Lặp i = 1, 2, 3, , n
Nếu ( a[i ] thõa điều kiện thì )
b[m] = a[i];
m = m + 1;
Cuối nếu.
Cuối lặp.
Ví dụ: Tìm tất cả các phần tử chỉ xuất hiện một lần trong mảng số nguyên a, n phần tử.
13
1.1. Khái niệm Mảng
int Dem(int a[], int n, int x)
{
int i, kq = 0;
for(i = 0; i < n ; i++)
if(a[i] == x)
kq = kq + 1;
return kq;
}
14
1.1. Khái niệm Mảng
void XuatHien01Lan(int a[], int n, int b[], int&m )
{
m = 0;
for(i = 0; i < n; i++)
if(Dem(a, n, a[i]) == 1)
{
b[m] = a[i]
m = m + 1;
}
}
15
1.1. Khái niệm Mảng
Tìm phần tử lớn nhất, nhỏ nhất
Bước 1: Chọn một phần tử xo và gán min := xo
Bước 2: Lặp (cho đến khi chọn hết các phần tử của S)
Chọn phần tử kế tiếp x, nếu min > x thì gán min := x;
Ví dụ: Hãy tìm phần tử âm lớn nhất có tận cùng là 6 trong mảng a
16
1.1. Khái niệm Mảng
void MaxAmTanCung6 ( int a[], int n)
{ int i, j;
int max;
j = AmTanCung6(a, n);
if (j ==-1) return 0;
else
{
max = a[j];
for (i = j+1; i < n; i++)
if(a[i ]<0&&(-a[i]%10==6))
if (max < a[i ])
max = a[i ];
}
return max;
}
17
1.1. Khái niệm Mảng
Sắp xếp mảng thõa một điều kiện ( giữ nguyên vị trí các phần tử khác )
Lặp i = 1, 2, , n -1
Lặp j = i +1, i + 2, , n
Nếu ( a[i ], a[j ] thõa điều kiện ) thì
Nếu a[i ] > a[j ] thì
x = a[i];
a[i] = a[j];
a[j]= x;
Cuối nếu.
Cuối lặp j.
Cuối lặp i.
18
1.2. Mảng hai chiều
Khai báo mảng 2 chiều kiểu int gồm 10 dòng , 10 cột : int A[10][10];
Khai báo mảng 2 chiều kiểu float gồm 10 dòng , 10 cột : float b[10][10];
int A[3][4] = { {2,3,9,4} , {5,6,7,6} , {2,9,4,7} };
A[0][0] = 2; A[0][1] = 3;
A[1][1] = 6; A[1][3] = 6;
Khi nhập liệu cho mảng hai chiều , nếu là mảng các số nguyên thì ta nhập liệu theo cách thông thường . Nhưng nếu là mảng các số thực thì ta phải thông qua biến trung gian .
19
1.2. Mảng hai chiều
Duyệt các phần tử của mảng .
// Duyệt từng dòng từ trên xuống dưới .
for(i = 0; i< so_dong ; i++)
for(j = 0; j < so_cot ; j++)
{
// Xử lý a[i][j ];
}
// Duyệt từng cột từ trái qua phải
for(j = 0; j < so_cot ; j++)
for(i = 0; i< so_dong ; i++)
{
// Xử lý a[i][j ];
}
20
1.2. Mảng hai chiều
Duyệt các phần tử nằm trên cùng một dòng hay trên cùng một cột .
// Duyệt các phần tử trên dòng thứ k (0 <=k < so_dong )
for (i = 0; i < so_cot ; i++)
{
// Xử lý phần tử a[k][i ];
}
// Duyệt các phần tử trên cột thứ k (0 <=k < so_cot )
for (i = 0; i < so_dong ; i++)
{
// Xử lý phần tử a[i][k ];
}
21
1.2. Mảng hai chiều
Duyệt các phần tử trên đường chéo của ma trận vuông
// Duyệt các phần tử trên đường chéo chính .
for (i = 0; i < n; i++)
{
// Xử lý phần tử a[i][i];
}
// Duyệt các phần tử trên đường chéo phụ .
for (i = 0; i < n; i++)
{
// Xử lý phần tử a[n-1-i][i];
}
22
1.3. Con trỏ
Ta xét dòng khai báo sau :
int *p;
Dòng này cho bi ết bi ến p đư ợc khai báo là m ột con trỏ ki ểu int , đ ịa chỉ c ủa ki ểu dữ li ệu số nguyên . D ấu * không ph ải là m ột ph ần c ủa bi ến p, int * có nghĩa là con trỏ ki ểu int.
Cú pháp khai báo như sau : * ;
23
Địa chỉ & ô nhớ
Bộ nhớ
Địa chỉ ô nhớ
0xA00h
ĐỊA CHỈ Ô NHỚ DÙNG ĐỂ QUẢN LÝ Ô NHỚ TRONG BỘ NHỚ.
0xA01h
0xAFFh
.
.
24
POINTER
int x;
int *p;
p
0xA04h
x = 5;
p = 0xA04h;
p = &x;
Dùng biến con trỏ (pointer) để lưu giữ các giá trị địa chỉ .
x
5
p = &x;
Khai báo : * ;
Ví dụ : int * p;
25
POINTER
*p = *p + 2;
*p =
x =
x = 6
*p = 8
int x;
int *p;
p
0xA04h
x = 5;
p = &x;
Nếu gán con trỏ p = &x thì :
6
5
6
*p x
*p và biến x cùng sử dụng chung một ô nhớ
8
8
26
Ví dụ 1
int main()
{
int i;
int j;
int *p;
p = &i;
*p = 5;
j = i;
printf (“%d %d %d ”, i, j, *p);
return 0;
}
i
j
p
5 5 5
int i;
int j;
int *p;
p = &i;
*p = 5;
5
5
j = i;
printf (“%d %d %d ”, i, j, *p);
return 0;
5
27
Ví dụ 2
int main()
{
int i;
int *p;
printf(“%d %d \n”, p, &i);
p = &i;
printf(“%d % d\n”,p,&i );
return 0;
}
i
0xA06h
p
852 2566
2566 2566
int i;
int *p;
printf(“%d %d \n”, p, &i);
printf(“%d % d\n”,p,&i );
p = &i;
p = &i;
return 0;
28
Ví dụ 3
void swap(int *a, int *b)
{
int tmp ;
tmp = *a;
*a = *b;
*b = tmp ;
}
int main()
{
int a, b;
a = 5;
b = 10;
swap(&a , &b);
printf(“%d,%d”,a , b);
return 0;
}
int a, b;
0xA06h
0xA08h
a
b
a = 5;
5
5
b = 10;
10
10
swap(&a , &b);
void swap(int *a, int *b)
int tmp ;
tmp
tmp = *a;
5
5
*a = *b;
*b = tmp ;
5
10
10
10 5
printf(“%d,%d”,a , b);
0xAA0h
return 0;
5
29
Ví dụ 4
void tinh ( int * a, int * b)
{
(*a) ++;
*a = *a + *b;
(*b) ++;
*b = *b + *a;
}
int main()
{
int * pa , * pb ;
int x = 10;
pa = &x;
pb = &x;
tinh(pa , &x);
printf(“%d%d%d ”, x, *pa, * pb );
tinh(pa , pb );
x++;
printf(“%d%d%d ”, x, *pa, * pb );
return 0;
}
int * pa , * pb ;
pa
pb
int x = 10;
x
pa = &x;
pb = &x;
tinh(pa , &x);
void tinh ( int * a, int * b)
(*a) ++;
11
10
*a = *a + *b;
22
(*b) ++;
23
*b = *b + *a;
46
printf(“%d%d%d ”, x, *pa, * pb );
46 46 46
tinh(pa , pb );
void tinh ( int * a, int * b)
(*a) ++;
47
*a = *a + *b;
94
(*b) ++;
95
*b = *b + *a;
190
x++;
191
printf(“%d%d%d ”, x, *pa, * pb );
191 191 191
return 0;
30
POINTER
Pointer là một biến mà trỏ đến một ô nhớ .
int x = 5;
int *p;
5
Pointer lưu trữ địa chỉ bộ nhớ của một ô nhớ .
p = &x;
p
0xA04h
p = 0xA04h
*p = 5
p = &x;
p = &x;
31
array & pointer
Lưu ý:
5
4
3
6
8
12
16
24
10
9
a[0]
a[1]
a[2]
a[6]
a[3]
a[7]
a[4]
a[8]
a[5]
a[9]
a
int a[10] ={5, 4, 3, 6, 8, 12, 16, 24, 10, 9};
int *pa;
pa
pa = a;
pa + 8;
pa = pa + 8;
& a[i ] (a + i)
pa + i & a[i ]
pa[i ] *(pa + i)
32
Ví dụ 5
int main()
{ int a[10] ={5, 4, 3, 6, 8, 12, 16, 24, 10, 9};
int * pa ;
int x;
pa = &a[0];
x = *pa;
printf(“%d ”, x);
pa++;
x = *pa;
printf(“%d ”, x);
pa = pa + 5;
x = *pa;
printf(“%d ”, x);
return 0 ; }
x
pa
int a[10] ={5, 4, 3, 6, 8, 12, 16, 24, 10, 9};
int * pa ;
int x;
pa = &a[0];
x = *pa;
5
printf(“%d ”, x);
5
pa++;
x = *pa;
4
printf(“%d ”, x);
4
pa = pa + 5;
x = *pa;
16
printf(“%d ”, x);
16
return 0 ;
5
4
3
6
8
12
16
24
10
9
a[0]
a[1]
a[2]
a[6]
a[3]
a[7]
a[4]
a[8]
a[5]
a[9]
a
33
array & pointer
M ảng không ph ải là m ột bi ến ( ta không thể th ực hi ện a = pa và a++ )
5
4
3
6
8
12
16
24
10
9
a[0]
a[1]
a[2]
a[6]
a[3]
a[7]
a[4]
a[8]
a[5]
a[9]
a
pa
pa = a
pa = a
pa++
pa++
Pointer là m ột bi ến (ta có thể th ực hi ện : pa = a và pa ++)
34
MỘT SỐ LƯU Ý
Ph ải kh ởi t ạo đ ịa chỉ ô nhớ cho con trỏ (pointer) trư ớc khi sử d ụng .
int * p;
*p = *p + 2;
p
int * p;
int x = 5;
p = x;
p
Không đư ợc gán m ột giá trị cho con trỏ.
5
x
35
MỘT SỐ LƯU Ý
Sử d ụng p++ t ức là con trỏ p tham chi ếu đ ến ô nhớ ti ếp theo .
int * p;
p = &x;
p
int * p, *q, *r;
int x;
r = p + q;
p
Không đư ợc th ực hi ện các phép toán (+, *, /) trên hai con trỏ.
int x = 2;
p ++;
p = &x; q = &x;
Lưu ý: Phép toán trừ hai con trỏ (p – q) v ẫn th ực hi ện đư ợc .
K ết quả c ủa : p – q = ? ( Bài t ập )
36
TỔNG KẾT
Phân bi ệt gi ữa đ ịa chỉ và ô nhớ .
Cách qu ản lý ô nhớ c ủa con trỏ.
Toán tử đ ịa chỉ (&) và n ội dung (*).
Phân bi ệt sự khác nhau gi ữa m ảng và con trỏ.
Lưu ý m ột số l ỗi khi sử d ụng con trỏ.
37
BÀI TẬP
int * Func ()
{
int x;
int * p;
x = 2;
p = &x;
return p;
}
int main()
{
int * q;
q = Func ();
printf(“%d ”, *q);
return 0;
}
Tìm l ỗi sai c ủa chương trình trên và s ửa l ại cho đúng .
38
BÀI TẬP
int * p;
int x;
p = &x;
Con trỏ p sẽ lưu giữ giá trị đ ịa chỉ c ủa bi ến x.
Đ ịa chỉ c ủa bi ến con trỏ p là gì ?
Làm cách nào để qu ản lý đư ợc đ ịa chỉ c ủa bi ến con trỏ p ?
39
Q&A
40
File đính kèm:
bai_giang_c_can_ban_chuong_1_ky_thuat_xu_ly_mang_va_con_tro.ppt

