Bài giảng Kỹ thuật lập trình Chương 1 Mảng một chiều cung cấp cho người học các kiến thức Khái niệm kiểu dữ liệu mảng một chiều, khai báo, các thao tác nhập xuất mảng, kỹ thuật tìm kiếm, liệt kê giá trị trong mảng, kỹ thuật xóa, chèn, chuỗi ký tự và các thao tác xử lý cơ bản.
Trang 3KHÁI NIỆM VÀ KHAI BÁO
3
Trang 5Khai báo
<KDL> < Tên mảng > [< Số phần tử tối đa của mảng>] ;
Nhằm thuận tiện cho việc viết chương trình, ta nên định nghĩa hằng số MAX
ở đầu chương trình – là kích thước tối đa của mảng - như sau:
Trang 7Truy xuất giá trị
TênMảng [vị trí cần truy xuất]
Trang 9THAO TÁC NHẬP VÀ XUẤT
9
Trang 10 Nhập a[i], với 0 ≤ i ≤ n-1
Trang 13Phát sinh ngẫu nhiên giá trị nguyên
• Sử dụng thư viện hàm <time.h> và <stdlib.h>
• Dùng hàm srand() trong hàm main() trước khi gọi hàm
phát sinh: để khởi tạo bộ giá trị ngẫu nhiên
• Dùng hàm rand()%k để phát sinh số ngẫu nhiên: có giá trị
từ 0 đến k-1
Trang 14Ví dụ: Chương trình tạo mảng số nguyên
có giá trị ngẫu nhiên từ 1 đến MAX
void NhapKichThuoc ( int & n );
void PhatSinh ( int a [], int n );
void XuatMang ( int a [], int n );
Trang 18XUẤT CÓ ĐIỀU KIỆN
18
Trang 19for (int i = 0; i<n; i++)
if (a[i] thỏa điều kiện)
Xuất a[i];
}
Trang 20for (int i = 0; i<n; i++)
if (a[i] thỏa điều kiện so với x)
Xuất a[i];
}
Trang 21Ví dụ 1: Liệt kê các phần tử có giá trị chẵn trong mảng số nguyên
void LietKeChan(int a[], int n)
Ví dụ 2: Liệt kê các phần tử có giá trị lớn hơn x trong mảng số nguyên
void LietKeLonHonX(int a[], int n, int x )
Trang 22Ví dụ 3: Chương trình nhập vào mảng một chiều số nguyên a, kích thước n In ra các phần tử có giá trị lớn hơn x có trong mảng
#define MAX 100
void NhapKichThuoc(int &n);
void NhapMang(int a[], int n);
void XuatMang(int a[], int n);
void LietKeLonHonX(int a[], int n, int x);
void NhapKichThuoc(int &n)
printf(“Nhap phan tu tai vi tri %d: “, i);
scanf(“%d”, &a[i]);
Trang 25Bài tập tại lớp
Cho mảng số nguyên a, gồm n phần tử, viết chương trình
gồm các hàm thực hiện các yêu cầu sau:
1 Nhập vào kích thước mảng (0<n<=100), nếu nhập không
thỏa miền giá trị thì cho phép người dùng nhập lại
2 Nhập các giá trị vào mảng một chiều a
3 Xuất các phần tử là bội số của 5 trong mảng a
4 Xuất các phần tử là số nguyên tố trong mảng a
5 Hàm main() để gọi thực hiện các yêu cầu từ 1 đến 4
Trang 26THAO TÁC ĐẾM SỐ LƯỢNG
26
Trang 27for (int i = 0; i<n; i++)
if (a[i] thỏa điều kiện)
d++;
return d;
Trang 28for (int i = 0; i<n; i++)
if (a[i] thỏa điều kiện so với x)
d++;
return d;
}
Trang 29Ví dụ 1: Đếm các phần tử có giá trị là số nguyên tố trong mảng số nguyên
int DemSNT(int a[], int n) {
int d = 0;
for (int i = 0; i<n; i++) {
if (LaSNT(a[i]) ==1) {
d++;
} } return d;
Trang 31Ví dụ 3: Chương trình nhập vào mảng một chiều số nguyên a, kích thước
n Đếm số lượng các phần tử là số nguyên tố có trong mảng
#define MAX 100
void NhapKichThuoc(int &n);
void NhapMang(int a[], int n);
void XuatMang(int a[], int n);
int LaSNT(int k);
int DemSNT(int a[], int n);
void NhapKichThuoc(int &n){
prinft(“Nhap vao kich thuoc mang: “);
scanf(“%d”, &n);
}
void NhapMang (int a[], int n){
for (int i = 0; i < n; i ++) {
printf(“Nhap phan tu tai vi tri %d: “, i);
scanf(“%d”, &a[i]);
} }
Trang 32int DemSNT(int a[], int n) {
int d = 0;
for (int i = 0; i<n; i++)
if (LaSNT(a[i]) ==1) d++;
Trang 35THAO TÁC TÌM KIẾM
35
Trang 36Đã tìm thấy tại
vị trí 5
Đã hết mảng
Trang 37(nếu x không xuất hiện trong mảng trả về -1)
int TimVTX(int a[], int n, int x)
Trang 39Giả sử cần tìm vị trí phần tử nhỏ nhất trong dãy
số sau ?
Trang 40Bước 1: Giả sử vị trí phần tử nhỏ nhất là 1 (vtmin), phần tử này có giá trị 10
vtmin
40
Trang 41Bước 2: So sánh giá trị tại vtmin với tất cả giá trị tại vị trí còn lại (từ 2 đến 8), nếu có phần tử nào nhỏ hơn phần tử tại vtmin thì cập nhật lại vtmin
vtmin
5 nhỏ hơn 10 nên cập nhật
vị trí min
10
10
41
Trang 421 2 3 3 4 3 5 9 6 7 8
9
2 2
15 15 1
1
Bước 2: So sánh giá trị tại vtmin với tất cả giá trị tại vị trí còn lại (từ 2 đến 8), nếu có phần tử nào nhỏ hơn phần tử tại vtmin thì cập nhật lại vtmin
vtmin
7 lớn hơn 5 nên không cập nhật vị trí min
Trang 431 2 3 3 4 3 5 9 6 7 8
9
2 2
15 15 1
1
Bước 2: So sánh giá trị tại vtmin với tất cả giá trị tại vị trí còn lại (từ 2 đến 8), nếu có phần tử nào nhỏ hơn phần tử tại vtmin thì cập nhật lại vtmin
vtmin
3 nhỏ hơn 5 nên cập nhật
Trang 441 2 3 3 4 3 5 9 6 7 8
9
2 2
15 15 1
1
Bước 2: So sánh giá trị tại vtmin với tất cả giá trị tại vị trí còn lại (từ 2 đến 8), nếu có phần tử nào nhỏ hơn phần tử tại vtmin thì cập nhật lại vtmin
vtmin
9 lớn hơn 3 nên không cập nhật vị trí min
Trang 451 2 3 4 5 6 7 8
9
9
2 2
15 15
Bước 2: So sánh giá trị tại vtmin với tất cả giá trị tại vị trí còn lại (từ 2 đến 8), nếu có phần tử nào nhỏ hơn phần tử tại vtmin thì cập nhật lại vtmin
vtmin
1 nhỏ hơn 3 nên cập nhật
45
Trang 461 2 3 4 5 6 7 8
9
9
2 2
Bước 2: So sánh giá trị tại vtmin với tất cả giá trị tại vị trí còn lại (từ 2 đến 8), nếu có phần tử nào nhỏ hơn phần tử tại vtmin thì cập nhật lại vtmin
vtmin
15 lớn hơn 1 nên không cập nhật vị trí min
15 15 1
1
46
Trang 471 2 3 4 5 6 7 8
9 9
Bước 2: So sánh giá trị tại vtmin với tất cả giá trị tại vị trí còn lại (từ 2 đến 8), nếu có phần tử nào nhỏ hơn phần tử tại vtmin thì cập nhật lại vtmin
15 15
2 lớn hơn 1 nên không cập nhật vị trí min
2
2 1
1
47
Trang 50THAO TÁC TÍNH TOÁN
50
Trang 53Ví dụ 1: Tính tổng các phần tử có giá trị lẻ trong mảng trong
Trang 54Ví dụ 2: Tính giá trị trung bình các phần tử có giá trị âm trong mảng số nguyên
float TrungBinhAm(int a[], int n)
Trang 55SẮP XẾP MẢNG THEO THỨ TỰ
55
Trang 56Mẫu phương thức sắp thứ tự tăng:
void SapTang(<KDL> a[], int n)
Trang 57THAO TÁC KIỂM TRA GIÁ TRỊ MẢNG
CÓ THỎA ĐIỀU KIỆN
57
Trang 58Kiểm tra tồn tại
Kiểm tra xem mảng có tồn tại một phần tử thỏa điều kiện
nào đó cho trước hay không?
tìm phần tử thỏa điều kiện để kết luận
Trả về:
• 1 nếu có phần tử thỏa điều kiện
• 0 nếu không có phần tử nào thỏa điều kiện
Trang 59Kiểm tra tồn tại
int KiemTraTonTaiXXX(<KDL> a[], int n)
{
for (int i = 0; i<n; i++)
if (a[i] thỏa điều kiện)
return 1;
return 0; //Không có phần tử nào thỏa điều kiện
}
Trang 60Kiểm tra tồn tại
Kiểm tra xem mảng số nguyên có tồn tại số lẻ không?
int KiemTraTonTaiLe(int a[], int n)
Trang 61Kiểm tra với mọi phần tử
• Kiểm tra tất cả các phần tử thỏa điều kiện nào đó cho trước
tìm phần tử không thỏa điều kiện để kết luận mảng không thỏa điều kiện
Trả về:
• 0 nếu gặp phần tử không thỏa điều kiện
• 1 nếu không có phần tử nào không thỏa điều kiện
Tìm phủ định của điều kiện cho trước kết luận 0
Trang 62Kiểm tra với mọi phần tử
int KiemTraXXX(<KDL> a[], int n)
{
for (int i = 0; i<n; i++)
if (a[i] không thỏa điều kiện)
return 0;
return 1;
}
Trang 63Kiểm tra với mọi phần tử
Kiểm tra xem mảng số nguyên có toàn bộ là giá trị âm không?
int KiemTraToanAm(int a[], int n)
Trang 64Bài tập
Cho mảng số nguyên kích thước n Viết các hàm sau:
1 Kiểm tra xem mảng có chứa số nguyên tố không?
2 Kiểm tra xem mảng có thứ tự tăng dần hay không?
3 Kiểm tra xem mảng có chẵn lẻ xen kẽ không?
4 Kiểm tra xem mảng có âm dương xen kẽ không?
Trang 651 Kiểm tra xem mảng có chứa số nguyên
tố không?
/*Kiem tra k co phai la so nguyen to khong?
* Neu la so nguyen to thi tra ve 1
* Nguoc lai tra ve 0
*/
int LaSNT( int k);
/*Kiem tra xem mang a co chua so nguyen to khong?
* Neu co thi tra ve 1
* Nguoc lai tra ve 0
*/
int CoTonTaiSNT( int a[], int n);
Trang 682 Kiểm tra mảng có thứ tự tăng dần?
Trang 693 Kiểm tra chẵn lẻ xen kẽ?
Trang 704 Kiểm tra âm dương xen kẽ
Trang 71THAO TÁC CHÈN
71
Trang 729 111
72
Trang 75Chèn phần tử vào mảng
BT: Hãy viết hàm chèn phần tử có giá trị x vào vị trí k cho trước trong mảng số nguyên a kích thước n theo mẫu sau:
void ChenX(int a[], int &n, int x, int k);
75
Trang 77Bài tập áp dụng
Hãy viết hàm chèn phần tử có giá trị x vào sau phần tử có giá trị nhỏ nhất có trong mảng số nguyên a, kích thước n (giả sử mảng không có giá trị trùng nhau)
Trang 80THAO TÁC XÓA
80
Trang 86Bài tập áp dụng
Hãy viết hàm xóa phần tử x (nếu có) trong mảng số nguyên a, kích thước n (giả sử mảng không có giá trị trùng nhau)
Gợi ý:
1 Viết hàm tìm vị trí phần tử có giá trị x
2 Viết hàm xoá phần tử x (sử dụng hàm
Trang 89CHUỖI KÝ TỰ
89
Trang 90Khái niệm
• Chuỗi ký tự là trường hợp đặc biệt của mảng 1 chiều,
là một dãy các phần tử, mỗi phần tử có kiểu ký tự
• Hằng ký tự được đặt trong cặp nháy đơn Ví dụ: ‘a’,
‘1’, ‘ ’ (Ký tự trắng – giữa cặp dấu nháy ‘ phải có 1 khoảng trắng )
• Hằng chuỗi được đặt trong cặp nháy kép Ví dụ: “ho va
ten”, “123”, “” (Chuỗi rỗng – không có khoảng trắng )
90
Trang 91Khái niệm
• Chuỗi ký tự được kết thúc bằng ký tự ‘\0’ (giá trị 0)
Do đó khi khai báo độ dài của chuỗi luôn luôn khai báo dư 1 phần tử để chứa ký tự ‘\0’.
• Ví dụ: Chuỗi “NGUYEN VAN A” được lưu
Chuỗi gồm 13 ký tự
91
‘N’ ‘G’ ‘U’ ‘Y’ ‘E’ ‘N’ ‘ ‘ ‘V’ ‘A’ ‘N’ ‘ ‘ ‘A’ ‘\0’
Trang 92Khai báo chuỗi
char < Tên chuỗi > [< Số ký tự tối đa>] ;
Ví dụ: char str[25];
Ý nghĩa khai báo 1 mảng kiểu ký tự tên là str có 25 phần tử (như vậy có thể lưu tối đa 24 ký tự vì phần tử thứ 24 đã chứa ký tự kết thúc chuỗi ‘\0’ )
Trang 96Xuất chuỗi – string.h
• Cú pháp : int puts (const char *s);
Trang 97Các hàm xử lý chuỗi - <string.h>
1 Tính độ dài chuỗi: strlen
2 Sao chép chuỗi: strcpy, strncpy
3 Nối chuỗi: strcat, strncat
4 So sánh chuỗi: strcmp, strncmp, stricmp, strnicmp
5 Tìm kiếm: strchr, strstr
6 Tách chuỗi: strtok
7 Đổi thành chữ in HOA: strupr
8 Đổi thành chữ in thường: strlwr
Trang 98Tính độ dài của chuỗi
int strlen(char *s);
• Ví dụ:
char *str = "Borland International";
printf("Do dai str = %d\n", strlen(str));
Kết quả: Do dai str = 21
Trang 99Bài tập ví dụ - tính độ dài chuỗi
1 Viết hàm đếm số ký tự trắng trong chuỗi
2 Viết hàm in ra màn hình chuỗi theo thứ tự đảo ngược
3 Viết hàm tìm xem ký tự ch có trong chuỗi không? Nếu
có cho biết vị trí xuất hiện đầu tiên của ch
4 Viết hàm kiểm tra xem chuỗi có đối xứng hay không?
5 Viết hàm đổi tất cả các ký tự có trong chuỗi thành chữ
HOA (không dùng hàm strupr)
Trang 1012 In ra màn hình chuỗi theo thứ tự ngược
void XuatChuoiNguoc(char *s)
Trang 102Bài tập làm thêm – tính độ dài chuỗi
1 Viết hàm tra xem trong chuỗi có ký tự số hay không nếu có tách
Trang 103Sao chép chuỗi
• Sao chép nội dung chuỗi scr vào chuỗi dest
strcpy(char *dest, const char *scr);
Trang 104Sao chép chuỗi
• Chép n ký tự từ chuỗi scr sang dest
strncpy(char *dest, const char *scr, int n);
Trang 106Nối chuỗi
• Nối n ký tự đầu tiên của chuỗi s2 vào sau chuỗi s1
strncat(char *s1, char *s2, int n);
Trang 107So sánh chuỗi
• So sánh 2 chuỗi s1 và s2 theo nguyên tắc thứ tự từ điển
Phân biệt chữ hoa và thường
int strcmp(char *s1, char *s2);
• Trả về:
• 0: nếu s1 bằng s2
• >0: nếu s1 lớn hơn s2
• <0: nếu s1 nhỏ hơn s2
Trang 108 Kết quả: Chuoi s1 lon hon chuoi s2
Trang 110So sánh chuỗi
• So sánh chuỗi s1 và s2 nhưng không phân biệt hoa
int stricmp(char *s1, char *s2);
Trang 111So sánh chuỗi
• So sánh n ký tự đầu tiên của s1 và s2, không phân biệt hoa
int strnicmp(char *s1, char *s2, int n);
Trang 112Tìm ký tự trong chuỗi
• Tìm sự xuất hiện đầu tiên của ký tư c trong chuỗi s
char *strchr(char *s, char c);
• Trả về:
NULL: nếu không có
Con trỏ đến ký tự c xuất hiện trong s: nếu tìm thấy
Trang 114Tìm chuỗi con
• Tìm sự xuất hiện đầu tiên của chuỗi s2 trong chuỗi s1
char *strstr(char *s1, char *s2);
• Trả về:
NULL: nếu không có
Ngược lại: Con trỏ vào chuỗi s2 xuất hiện trong s1
Trang 115Tìm chuỗi con
• Ví dụ:
Kết quả: Vi tri xuat hien cua s2: 13
char *s1 = "Borland International";
Trang 116Tách chuỗi
char *strtok(char *s1, char *s2);
• Nếu s2 có xuất hiện trong s1: Tách chuỗi s1 thành 2
chuỗi: Chuỗi đầu là những ký tự cho đến khi gặp s2 đầu tiên, chuỗi sau là những ký tự còn lại của s1 sau khi đã
bỏ đi s2 xuất hiện trong s1
• Nếu s2 không xuất hiện trong s1 thì kết quả vẫn là s1
Trang 118Bài tập tách chuỗi
1 Viết hàm đếm xem một chuỗi cho trước có bao nhiêu
từ (các từ cách nhau bằng khoảng trắng)
2 Viết hàm đảo ngược các từ
3 Viết hàm tách các từ phân biệt và in ra màn hình (các
từ các nhau bởi dấu chấm câu hoặc khoảng trắng)
4 Viết hàm kiểm tra xem chuỗi có tuần hoàn hay không?
5 Viết hàm đổi những ký tự đầu tiên của mỗi từ thành chữ in
HOA
Trang 119Đổi sang chữ in HOA
• Đổi chuỗi str thành chuỗi in HOA
Trang 120Đổi sang chữ in thường
• Đổi chuỗi str thành chuỗi in thường
Trang 121Q&A