275
Chƣơng 5
MẢNG VÀ CON TRỎ
Ngoài các kiểu dữ liệu cơ bản (số nguyên, số thực, ký tự), trong ngôn
ngữ lập trình C cho phép ngƣời lập trình viên thể tạo ra các kiểu dữ
liệu mới. Trong Chƣơng 5, các vấn đề sau đây sẽ đƣợc đề cập đến:
- Mảng một chiều mảng hai chiều: Khai báo, cách thức truy cập
các phần tử trong mảng, một số dạng bài tập với mảng một chiều và mảng
hai chiều.
- Con tr: Định nghĩa, khai báo con trỏ, c phép toán với biến con trỏ,
mối quan h gia con tr và mảng, s dụng con trcấp pt b nh đng.
- Chuỗi tự: Khai báo, các phép toán trên chuỗi, một số dạng bài
tập vận dụng xử lý đối với chuỗi.
5.1. MẢNG
5.1.1. Mng mt chiu
Mng mt chiu là tp hp các thành phn cấu trúc (thƣờng đƣợc
gi là các phn t mng) có th đƣợc truy cp riêng l bng cách ch định
v trí ca mt thành phn vi giá tr ch s duy nht. Mng phải đƣợc khai
báo trƣớc khi chúng có th đƣợc s dụng trong chƣơng trình.
5.1.1.1. Khai báo mng
Cú pháp:
data_Type arrayName [ arraySize ];
Trong đó:
data_Type: kiu giá tr ca các phn t mng, th kiu d
liệu cơ bản nhƣ kiểu s nguyên, s thc, ký t, chui, v.v. hoặc cũng
th là kiu d liu có cấu trúc nhƣ kiểu bn ghi, v.v.
arrayName: tên đƣợc đặt cho mng, cách thc đặt tên biến mng
giống nhƣ định danh.
arraySize: kích thƣớc ca mảng, luôn đƣợc đặt trong cp du [].
Ví d 5.1
Cho khai báo sau đây:
int a[5];
276
Khai báo mt mng có tên là a, s ng phn t ca mng là 5, kiu
d liu ca mi phn t trong mng a s nguyên. Ch s các phn t
ca mảng đƣợc đánh từ 0 đến 4. Hình nh minh ha ca mng mt chiu:
a[0]
a[1]
a[2]
a[3]
a[4]
Lƣu ý:
th khai báo khi to giá tr mảng ban đu. Khi to mng rt
đơn giản trong lp trình C. c giá tr khi tạo đƣợc đặt trong du ngoc
nhọn trong khai báo đƣợc đặt sau du bng sau tên mảng. Dƣới đây là
mt d khai báo khi to mt mng gồm năm phần t kiu int.
Mảng cũng có thể đƣc khi to sau khi khai báo.
Ví d 5.2
int a[5] = {13, -6, 9, 45, 7};
Không cn thiết phải xác định kích thƣớc ca mng trong quá trình
khi tạo, nhƣ ví d 5.3 sau đây:
Ví d 5.3
int a[] = {13, -6, 9, 45, 7};
Trong trƣờng hp này, trình biên dịch xác định kích thƣớc ca mng
bng cách tính s ng phn t ca mng:
a[0]
a[1]
a[2]
a[3]
a[4]
13
-6
9
45
7
Điu này rt hữu ích kích thƣớc ca mng th đƣợc kim soát
bng cách thêm hoc xóa các phn t khi to khỏi định nghĩa không
cần điều chỉnh kích thƣớc.
Nếu kích thƣớc mảng đƣợc xác định trƣớc, tức đƣợc cp phát b nh
theo s phn t đã khai báo, nhƣng chỉ mt s phn t trong mảng đƣợc
khi tạo, khi đó các phần t còn li s cha giá tr 0. Vi cách thc khai
báo nhƣ vậy rt thích hợp trong trƣờng hp phi x lý vi mng ln.
Ví d 5.4
Cho khai báo: int a[2000] = {13, 9};
Vi khai báo trên, a[0] = 13, a[1] = 9, a[2] = 0,…, a[1999] = 0.
5.1.1.2. Truy cp các phn t ca mng
Trong C, mảng đƣợc truy cp và x lý giống nhƣ các biến.
Cú pháp:
277
arrayName(index);
Trong đó:
arrayName: Tên biến mng
index: Ch s phn t truy cp;
Ví d 5.5
Câu lnh chèn giá tr vào phn t th 3 trong mng a:
scanf(“%d”, &a[2]);
Câu lnh in giá tr ca phn t t 3 trong mng a:
printf(“%d”, a[2]);
Trong C, mng truy cp cp nht bng ch s mng. Nếu mng
n phn t, thì ch s ca mảng đƣợc gán t 0 đến n - 1. Không ging
nhƣ ngôn ngữ Java, khi ch s mng nm ngoài phm vi t 0,, n - 1,
đƣợc x lý ngoi l trong cp lnh try…catch, mng trong C th
không hin th bt k mt cnh báo nào nếu ch s mng ngoài gii hn
đƣợc truy cập. Thay vào đó, trình biên dch th truy cp các phn t
ngoài phạm vi, do đó dẫn đến các li nghiêm trng v thi gian thc hin
chƣơng trình.
Để gim bớt các “rủi ro” các vấn đề liên quan đến ch s ca mng,
biu thức sizeof() thƣờng đƣc s dụng để x lý vòng lp trong mng.
Chúng ta th s dng mt marco s dng biu thức sizeof() để tìm s
ng phn t ca mảng, marco y các tên khác nhau nhƣ
“lengthof()”, “MY_ARRAY_SIZE()”, hoặc “NUM_ELEM()”,
“SIZEOF_STATIC_ARRAY()” , v.v.
Ví d 5.6
Cho đoạn chƣơng trình sau đây:
1
#include <stdio.h>
2
int main()
3
{
4
int i;
5
int a[] = {13, -6, 9, 45, 7};
6
for (i = 0; i < sizeof(a)/sizeof(int); i++)
7
{
8
printf("%d\t", a[i]);
278
9
}
10
return 0;
11
}
Kết qu chƣơng trình:
13 -6 9 45 7
Lƣu ý trong dụ trên, kích thƣớc ca mảng không đƣc ch định
ràng. Trình biên dch biết kích thƣớc ca 5 5 giá tr trong danh
sách khi to. Thêm mt giá tr b sung vào danh sách s khiến
kích thƣớc thành 6 do biu thc sizeof trong vòng lp for, s t
động điều chỉnh theo thay đổi này. Thc hành lp trình tt là khai báo mt
kích thƣớc thay đổi và lƣu trữ s ng phn t trong mảng trong đó.
size = sizeof (tên_mng) / sizeof (kiu_d_liu_mng)
5.1.1.3. Các dng bài tp mng mt chiu
Dng 1: Nhp và hin th mng mt chiu
a. Nhp mng
Cách 1:
Nhp tng phn t ca mng.
Để nhp các phn t ca mng, ta thc hiện nhƣ sau:
- Nhp tng phn t ca mng s dng mt vòng lp
- Xây dng mt hàm nhap() có kiu void, không tr v giá tr, truyn
vào hai tham s là tên biến mng và s ng phn t ca mng.
Cách 2: Sinh ngu nhiên các phn t ca mng, s dng hàm rand()
để sinh ra các giá tr ngu nhiên.
Cú pháp hàm rand():
int rand(void)
m rand() không nhn tham s vào, tr v mt giá tr ngu nhiên
trong phm vi t 0 đến RAND_MAX. Trong đó, RAND_MAX một
hng s giá tr mặc định (đƣợc định nghĩa trong thƣ viện “stdlib.h”,
thông thƣờng RAND_MAX = 32767)
b. Hin th mng
Để hin th c phn t ca mng, ta thc hiện nhƣ sau:
- S dng mt vòng lặp để hin th các phn t ca mng.
- Xây dng mt hàm hienthi() có kiu void, truyn vào hai tham s
tên biến mng và s ng phn t ca mng.
279
Ví d 5.7
Viết chƣơng trình nhập vào mt mng gm n s nguyên (n là s phn
t ca mảng, đƣợc nhp t bàn phím) và hin th các phn t ra màn hình,
mi phn t cách nhau độ dài phím tab.
Phác tho li gii
Xây dng 2 hàm:
- m nhap(): S dng mt vòng lp for nhp tng phn t ca mng.
- m hienthi(): S dng mt vòng lp for, hin th các phn t ca mng.
Chƣơng trình:
1
#include <stdio.h>
2
void nhap(int a[], int n) {
3
for (int i = 0; i < n; i++) {
4
printf("Gia tri phan tu a[%d]=", i);
5
scanf("%d", &a[i]); }
6
}
7
void hienthi(int a[], int n)
8
{
9
printf("Hien thi cac phan tu cua mang :\n");
10
for(int i=0; i < n; i++)
11
printf("%4d", a[i]);
12
}
13
int main(){
14
int a[1000];
15
int n;
16
printf("Nhap so phan tu cua mang =");
17
scanf("%d", &n);
18
nhap(a, n);
19
hienthi(a,n);
20
return 0;
21
}
Kết qu chƣơng trình: