Nội dung
Lương Trần Hy Hiến
Khoa Toán – Tin học
Đại học Sư phạm TPHCM
Mảng
khai báo
cấu trúc, thao tác
Xâu ký tự
tạo xâu, nhập, xuất
một số hàm xâu
Một số thuật toán sắp xếp và tìm kiếm
1
Mảng
2
Mảng(2)
Tập các phần tử thuộc cùng một kiểu dữ liệu
Được sắp xếp liên tục trong bộ nhớ
Công dụng
Dùng để lưu các đối tượng có cùng chung một kiểu và
ý nghĩa sử dụng
kích thước là cố định
Có thể đánh chỉ số và truy cập theo thứ tự ngẫu
nhiên
Phân loại
lo i
Mảng 1 chiều
Mảng 2 chiều
C/C++: chỉ số luôn bắt đầu từ 0
Phân loại:
Khai báo
Cách sử dụng
Các thao tác cơ bản trên mảng
Mảng 1 chiều
Mảng 2 chiều
Mảng n chiều
3
4
Mảng (3)
Khai báo mảng:
Ví dụ
0
1
Mảng 1 chiều:
Kiểu Tên-mảng[số phần tử];
Ý nghĩa: <Tên-mảng> là một
mảng có <số phần tử> kiểu
<Kiểu>. Phần tử đầu tiên nằm
ở vị trí thứ 0. Phần tử cuối
cùng nằm ở vị trí
tử> - 1.
Lưu ý: số phần tử trong câu
khai báo mảng phải là một
hằng số hoặc một biểu thức
của các hằng số.
…
SPT-2
SPT-1
…
•Ví dụ:
•int A[10]; // mảng A có 10
phần tử kiểu nguyên
•double mangthuc[100]; mảng
mangthuc có 100 phần tử kiểu
thực
void main()
{
int c[12];
for (int i=0; i<12; i++) {
cin >> c[i];
}
}
•const int MAX = 100;
double mangthuc[MAX];
5
6
Khai báo mảng
void main()
{
int a[12];
t b[] = {
{2,
, 3, 5, 7};
};
int
int c[5] = {2, 4, 8, 16};
int d[2] = {1, 2, 3}; // compile error
int m[5], i;
…
}
7
8
Mảng là tham số
Kích thước mảng không cần biết trước
void main()
{
int n, max = 0;
cin >> n;
int a[n];
for (int i=0; i
cin >> a[i];
if (a[max] < a[i]) max = i;
}
if (n > 0)
cout << "max number = " << a[max];
}
Có thể truyền mảng là tham số cho một hàm
Như là tham chiếu (nhận sự thay đổi)
Hàm cần phải biết kích thước của mảng
thông qua một tham số phụ
thông qua giá trị kết thúc mảng
9
Ví dụ: copy mảng
10
Mảng 1 chiều
void arrayCopy(int a[], int b[], int size)
{
for (int i=0; i
b[i] = a[i];
[i]
}
Các thao tác thường gặp trên mảng một chiều:
Qui ước mảng:
int A[100]; // mảng có thể chứa tối đa 100 phần tử
int n; // số phần tử thật sự sẽ sử dụng
Các thao tác trên mảng m
một
ột chiều thườ
th ờng
ng đi kèm với một vòng
for
Nhập một dãy (giả sử đã nhập n)
for (int i = 0 ; i < n ; i++)
{
cout << “Nhập vào phần tử thứ “ << i << “ của mảng: “;
cin >> A[i];
}
11
12
Mảng 1 chiều
int linearSearch(int, int [], int);
void main()
{
int a[100], key;
…
cin >> key;
cout << linearSearch(key,
linearSearch(key a,
a 100);
}
Bài toán: Tìm vị trí X trên mảng a đang có N
thành phần.
Giải pháp: Tìm tuần tự
int linearSearch(int k, int m[], int size)
{
for (int i=0; i< size; i++) {
if (k == m[i]) return i;
}
return -1;
}
13
Mảng 1 chiều
14
Mảng – Thêm X vào cuối dãy
Xuất dãy
// định dạng độ rộng để xuất #include<iomanip>
for (int i = 0 ; i < n ; i++)
cout << setw(6)<
Thêm 15 vào (a, 7)
Thêm một phần tử v vào cuối dãy
0
1
2
3
4
5
6
12
2
8
5
1
6
4
7
A[n++] = v;
Thêm một phần tử v vào đầu dãy
for (int i = n ; i > 0 ; i--)
A[i] = A[i-1];
A[0] = v;
n++;
N=8
7
a[N] = X;
NX ++;
15
15
16
Sắp xếp dãy theo thứ tự tăng dần:
Mảng 1 chiều
Interchange Sort
Thêm một phần tử v vào vị trí thứ k của dãy
for (int i = n ; i > k ; i--)
A[i] = A[i-1];
A[k] = v;
n++;
Xóa phần tử nằm tại vị trí thứ k của dãy
n--;
for (int i = k ; i < n ; i++)
A[i] = A[i+1];
17
for (int i = 0 ; i < (n – 1) ; i++)
{
for (int j = i + 1 ; j < n ; j++)
if (A[j] < A[i])
{
int temp = A[j];
A[j] = A[i];
A[i] = temp;
}
}
23
Tìm Min
int min = A[0];
for (int i = 1 ; i < n ; i++)
if (A[i] < min)
min = A[i];
cout << “Phần tử nhỏ nhất là: “ << min;
Tính tổng
int tong = 0;
for (int i = 0 ; i < n ; i++)
tong += A[i];
Tính trung bình cộng
Tìm Max
int max = A[0];
for (int i = 1 ; i < n ; i++)
if (A[i] > max)
max = A[i];
cout << “Phần tử lớn nhất là: “ << max;
int tong = 0;
for (int i = 0 ; i < n ; i++)
tong += A[i];
double TBC = tong * 1.0 / n;
24
25
Bài tập
Viết các hàm tính giá trị lớn nhất, giá trị nhỏ nhất,
giá trị trung bình của một mảng số nguyên.
Đảo ngược dãy
for (int i = 0 ; i < n / 2; i++)
{
int temp = A[i];
A[i] = A[n – i – 1];
A[n – i – 1] = temp;
}
26
Mảng 2 chiều
0
1
…
27
Mảng 2 chiều
SC-1
0
Khai báo mảng:
Kiểu Tên-mảng[số dòng][số cột];
Ý nghĩa: <Tên-mảng> là một ma
trận có <số dòng> dòng và
cột> cột. Phần tử đầu tiên nằm ở
vị trí dòng thứ 0, cột thứ 0. Phần
tử cuối cùng nằm ở vị trí dòng
<số dòng> - 1 và cột <số cột> 1.
Lưu ý: số dòng, số cột phải là một
hằng số hoặc một biểu thức của
các hằng số.
int a[7][7];
int b[2][3] = { {2, 4, 6}, {3, 5, 7} };
1
Mảng 2 chiều:
…
SD-1
•Ví dụ:
int A[10][5]; // ma trận
10 dòng, 5 cột
const int MAXX = 10;
const int MAXY = 5;
int A[MAXX][MAXY];
{
for (int i=0; i<2; i++){
for (int j=0; j<3; j++)
cout << b[i][j]<<“\t”;
cout << endl;
}
Bản chất là mảng một chiều
28
29
Mảng 2 chiều
Các thao tác thường gặp trên mảng hai chiều:
Xuất ma trận
Qui ước mảng:
int A[100][100]; // mảng có thể chứa tối đa 100x100 phần tử
int m, n; // số dòng và số cột thật sự sẽ sử dụng
Các thao tác trên mảng hai chiều thường đi kèm với hai vòng for
Nhập m
một
ột dãy (giả s
sử
ử đã nhập m, n)
for (int i = 0 ; i < m ; i++)
{
for (int j = 0 ; j < n ; j++)
{
cout << “Nhập phần tử tại dòng “ << i << “ cột “ << j << “ của mảng: “;
cin >> A[i][j];
}
30
}
//setw(6); // định dạng độ rộng để xuất
for (int i = 0 ; i < m ; i++)
{
for (int j = 0 ; j < n ; j++)
cout << setw(6)<< A[i][j];
cout << endl;
}
31
Thêm một dòng v vào cuối ma trận
Xóa dòng thứ k
for (int j = 0 ; j < n ; j++)
A[m][j] = v[j];
m++;
m--;
for (int i = k ; i < m ; i++)
{
for (int j = 0 ; j < n ; j++)
A[i][j] = A[i+1][j];
}
Thêm một dòng v vào vị trí dòng thứ k
for (int i = m ; i > k ; i++)
{
for (int j = 0 ; j < n ; j++)
A[i][j] = A[i-1][j];
}
for (int j = 0 ; j < n ; j++)
A[k][j] = v[j];
m++;
32
33
Chuỗi - Xâu ký tự
Mảng các ký tự
char name[30];
char str[] = ”hello”;
Tìm kiếm vị trí phần tử mang giá trị x
int dem = 0;
for (int i = 0 ; i < m ; i++)
{
for (int j = 0 ; j < n ; j++)
if (A[i][j] == x)
{
cout << “Vị trí dòng “ << i << “ cột “ << j << endl;
dem++;
}
}
if (dem == 0)
cout << “Phần tử ” << x << “ không có trong ma trận.”;
Trong C/C++ xâu kết thúc bằng ký tự \0.
kích thước bộ nhớ và độ dài có nghĩa là khác
nhau.
str
char last_name[6]
= "Minor";
char other[]
= "Tony Blurt";
#include <iostream>
using namespace std;
int main()
{
char other[] = "Tony Blurt";
"Blurt" sẽ không
được in ra
cout<
other[4] = '\0';
first_name
'J'
'o'
'h'
'n'
0
last_name
'M'
'i'
'n'
'o'
'r'
other
'T'
'o' ‘n’
'y'
32 'B'
'n' 'u'
o \0
35
char characters[7] = "No null";
32
l
Lưu ý: kết thúc chuỗi
char first_name[5] = { 'J', 'o', 'h', 'n', '\0' };
'N' 'o'
l
34
Chuỗi ký tự - Ví dụ
characters
h e
cout<
0
'l'
'l'
'u'
'l'
0
'r'
't'
Tony Blurt
Tony
return 0;
0
}
other
36
'T' 'o' ‘n’ 'y' 32 'B' 'l'
'u' 'r'
't'
0
37
Khai báo, nhập/xuất xâu
Tham số là xâu ký tự
#include <iostream>
using namespace std;
#include <cstring>
void main()
{
char s1[] = ”Hello”;
char s2[] = ”What’s your name?”;
char name[30];
cout << s1 << endl << s2 << endl;
cin >> name;
cout << name << ”, welcome!”;
}
Về cơ bản như mảng
Như là tham số biến
Có phần tử kết thúc xâu nên thường không cần
truyền kích thước
38
39
Một số hàm thư viện xâu
void stringCopy(char s1[], char s2[])
{
int i = 0;
while (s1[i] > 0) {
s2[i] = s1[i];
i++;
}
s2[i] = 0;
}
40
Sử dụng thư viện cstring (thư viện C++)
#include <cstring>
Một số hàm
strlen(s) : trả lại
l i kích thước
th ớc xâu s
strcpy(s1, s2) : copy s2 vào s1
strcmp(s1, s2) : so sánh, nếu bằng thì kết quả là 0; có
phân biệt IN HOA – in thường
stricmp(s1, s2) : so sánh, nếu bằng thì kết quả là 0;
không phân biệt IN HOA – in thường
strupr(s): Đổi toàn bộ các ký tự của chuỗi thành IN HOA
strlwr(s): Đổi toàn bộ các ký tự của chuỗi thành in thường41
Chuỗi ký tự – ví dụ strcpy
Chuỗi ký tự – Một số hàm thư viện
#include <iostream>
using namespace std;
int main()
{
char s[]
[] = "Tony
y Blurt";
;
char s2[100], *s3;
Gán nội dung chuỗi:
o Chép toàn bộ chuỗi source sang chuỗi dest:
int strcpy(char *dest, const char
*src);
o Chép tối đa n ký tự từ source sang dest:
Tony Blurt
To123Blurt
Blurt
strcpy(s2, s);
cout<
strncpy(s2 + 2, "12345", 3);
cout<
s3 = strdup(s + 5);
cout<
return 0;
int strncpy(char *dest,
const char *src, int n);
Tạo chuỗi mới từ chuỗi đã có:
char *strdup(const char *src);
42
}
43
Chuỗi ký tự – ví dụ strtok
Chuỗi ký tự – Một số hàm thư viện
#include <iostream>
Nối chuỗi:
char *strcat(char *dest,
const char *src);
#define SEPARATOR "., "
int main()
{
char s[]= "Thu strtok: 9,123.45";
char *p;
Tách chuỗi:
char *strtok(char *s,
const char *sep);
Thu
strtok:
9
123
45
p = strtok(s, SEPARATOR);
while (p != NULL)
{
cout<
p = strtok(NULL, SEPARATOR);
}
return 0;
Trả về địa chỉ của đoạn đầu tiên. Muốn tách
đoạn kế tiếp tham số thứ nhất sẽ là NULL
44
}
45
Chuỗi ký tự – ví dụ tìm kiếm
Chuỗi ký tự – Một số hàm thư viện
#include <iostream>
using namespace std;
int main()
{
char s[]= "Thu tim kiem chuoi";
char *p;
Tìm một ký tự trên chuỗi:
char *strchr(const char *s, int
c);
Tìm một đoạn ký tự trên chuỗi:
char *strstr(const char *s1,
const char *s2);
p = strchr(s, 'm');
cout<
p = strstr(s, "em");
cout<
return 0;
46
#include <iostream.h>
#include <iostream.h>
void StrIns(char *s, char *sub)
{
int len = strlen(sub);
memmove(s + len, s, strlen(s)+1);
strncpy(s, sub, len);
}
123 Thu chen
int main()
123 Thu 45chen
{
char s[]= "Thu chen";
}
47
}
Chuỗi ký tự – xóa một đoạn ký tự
Chuỗi ký tự – chèn một đoạn ký tự
StrIns(s, "123");
StrIns(s + 8, "45");
return 0;
m kiem chuoi
em chuoi
void StrDel(char *s, int n)
{
memmove(s, s + n, strlen(s+n)+1); xoa 12345
}
xoa 45
int main()
{
char s[]= "Thu xoa 12345";
StrDel(s, 4);
StrDel(s + 4, 3);
return 0;
cout<
cout<
cout<
cout<
}
48
49
Mảng xâu
char
Bài tập
Viết hàm tạo xâu nghịch đảo: nhận tham số là
xâu, tạo xâu nghịch đảo của chính xâu đó và ghi
kết quả vào chính xâu tham số vào.
Viết hàm kiểm tra một
m t xâu ký tự
t có nằm trong
một xâu ký tự khác hay không.
names[100][30];
for (int i=0; i<100; i++) {
cin >> names[i];
cout << strlen(names[i]);
}
50
Tự thực hành
Thao tác thành thạo với mảng một chiều
Cài đặt các hàm sắp xếp và tìm kiếm
Thao tác với xâu ký tự
nhập xuất, tạo hằng xâu
sử dụng các hàm thư viện copy, so sánh,…
53
52