You are on page 1of 67

Đại Học Sư Phạm Tp.

Hồ Chí Minh

CẤU TRÚC DỮ LIỆU 2

Chương 01: SẮP XẾP NGOẠI


Đề cương môn học: CTDL2
• Chương 1: Sắp xếp ngoại
• Chương 2: Bảng băm (Hash Table)
• Chương 3: Cây 2-3-4, B – cây
• Chương 4:Cây Đỏ Đen (Red Black Tree)

CTDL2 – Lương Trần Hy Hiến 2


Giới thiệu
• Mục tiêu:
– Bài toán kinh điển: Sắp xếp và tìm kiếm
– Đặc trưng của SX trên file: Bài toán trộn
– TT tìm kiếm cơ bản: Tuần tự, nhị phân
– TT sắp xếp: Trộn trực tiếp, trộn tự nhiên, trộn n-
đường cân bằng, trộn đa pha
– Đánh giá thuật toán
• Các nội dung chính:
– Thuật toán và cài đặt các phương pháp sắp xếp

CTDL2 – Lương Trần Hy Hiến 3


Chương 1: SẮP XẾP NGOẠI
• Phương pháp trộn Run
• Phương pháp trộn tự nhiên
• Phương pháp trộn đa lối cân bằng
• Phương pháp trộn đa pha

CTDL2 – Lương Trần Hy Hiến 4


Các PP sắp xếp – Vấn đề???
Vì sao phải xây dựng thuật toán sắp xếp trên
file?
• Thao tác cơ bản trong SX là hoán vị
• Thực hiện hoán vị trên cùng 1 file  Tần
suất thao tác lên trên 1 vùng đĩa quá lớn
 Không an toàn.
• SX ngoại không thích hợp với hoán vị  Sử
dụng phương pháp trộn.

CTDL2 – Lương Trần Hy Hiến 5


Bài toán trộn
• Cho trước 2 (hay nhiều) dãy đã sắp thứ tự:
A[1], A[2], A[3], …, A[N]
B[1], B[2], B[3], …, B[M]
• Kết hợp các dãy đã cho thành một dãy mới C
được sắp.

CTDL2 – Lương Trần Hy Hiến 6


Thuật toán trộn 1 – Trộn từng phần tử
int nCurrA = 1;
int nCurrB = 1;
A[N+1] = MAX_VALUE; // phần tử lính canh
B[M+1] = MAX_VALUE; // phần tử lính canh
for (int nCurrC=1; nCurrC <= N+M; nCurrC++)
if (A[nCurrA] < B[nCurrB]) {
C[nCurrC] = A[nCurrA];
nCurrA++;
}
else {
C[nCurrC] = B[nCurrB];
nCurrB++;
}

CTDL2 – Lương Trần Hy Hiến 7


T.toán trộn 2 – Trộn dãy phần tử được sắp
int nCurrA = 1;
int nCurrB = 1;
while (nCurrA <= N && nCurrB <= M)
{
if (A[nCurrA] < B[nCurrB])
C[nCurrC] = A[nCurrA];
else
C[nCurrC] = B[nCurrB];
nCurrC++;
}
// Xét phần tử còn lại của dãy A
for ( ; nCurrA <= N; nCurrA++) {
C[nCurrC] = A[nCurrA];
nCurrC++;
}
// Xét phần tử còn lại của dãy B
for ( ; nCurrB <= M; nCurrB++) {
C[nCurrC] = B[nCurrB];
nCurrC++;
}
CTDL2 – Lương Trần Hy Hiến 8
1. Phương pháp trộn trực tiếp
• Khái niệm:
– Run là một dãy liên tiếp các phần tử được sắp
thứ tự.
Ví dụ: 2 4 7 12 55 là một Run.
– Chiều dài Run chính là số phần tử trong Run.
Chẳng hạn Run ở ví dụ trên có chiều dài là 5.

CTDL2 – Lương Trần Hy Hiến 9


1. Phương pháp trộn trực tiếp
• Giải thuật:
– Giải thuật sắp xếp tập tin bằng phương pháp
trộn Run có thể tóm lược như sau:
Input: f0 là tập tin cần sắp thứ tự
Ouput: f0 là tập tin đã được sắp thứ tự
Gọi f1, f2 là 2 tập tin trộn.
Trong đó f0, f1, f2 có thể là các tập tin văn bản
thường (text file) hay các tập tin nhị phân.

CTDL2 – Lương Trần Hy Hiến 10


1. Phương pháp trộn trực tiếp
• Bước 1:
– Giả sử các phần tử trên f0 là:
24 12 67 33 58 42 11 34 29 31
– Khởi tạo f1, f2 rỗng.
– Thực hiện phân bố m=1 phần tử từ f0 lần lượt
vào f1, f2:
f1: 24 67 58 11 29
f2: 12 33 42 34 31
– Trộn f1,f2 vào f0
f0: 12 24 33 67 42 58 11 34 29 31

CTDL2 – Lương Trần Hy Hiến 11


1. Phương pháp trộn trực tiếp
• Bước 2:
– Phân bố m=2 *m = 2 phần tử từ f0 vào f1, f2
f0: 12 24 33 67 42 58 11 34 29 31
f1: 12 24 42 58 29 31
f2: 33 67 11 34
– Trộn f1, f2 thành f0:
f0: 12 24 33 67 11 34 42 58 29 31

CTDL2 – Lương Trần Hy Hiến 12


1. Phương pháp trộn trực tiếp
• Bước 3:
– Tương tự bước 2, phân bố m= 2 * m = 4 phần
tử từ f0 vào f1, f2
f0: 12 24 33 67 11 34 42 58 29 31
f1: 12 24 33 67 29 31
f2: 11 34 42 58
– Trộn f1, f2 thành f0:
f0: 11 12 24 33 34 42 58 67 29 31

CTDL2 – Lương Trần Hy Hiến 13


1. Phương pháp trộn trực tiếp
• Bước 4: Phân bố m=2 * m = 8 phần tử lần
lượt từ f0 vào f1, f2.
f1: 11 12 24 33 34 42 58 67
f2: 29 31
– Trộn f1, f2 thành f0:
f0: 11 12 24 29 31 33 34 42 58 67
• Bước 5: Lặp lại tương tự các bước trên cho
tới khi chiều dài m của run cần phân bố lớn
hơn chiều dài n của f0 thì dừng.

CTDL2 – Lương Trần Hy Hiến 14


Cài đặt thuật toán
m=1
while (m < số phần tử của f0)
{
Chia[Distribute] m phần tử của f0 lần lượt
cho f1, f2
Trộn[Merge] f1, f2 lần lượt vào f0
M=M*2
}

CTDL2 – Lương Trần Hy Hiến 15


Đánh giá
• Đánh giá:
– Cần ít nhất N không gian trống trên đĩa để hoạt động.
– Số bước log2N (vì mỗi lần xử lý 1 dãy tăng gấp 2)
– Mỗi bước:
• Distribute: Copy N lần
• Merge: Copy N lần, so sánh N/2 lần
– Tổng cộng:
• Copy: 2N * log2N
• So sánh: N/2 * log2N
• Hạn chế:
– Không tận dụng được dữ liệu đã được sắp bộ phận
– Độ dài dãy con xử lý ở bước k <= 2k

CTDL2 – Lương Trần Hy Hiến 16


2. Phương pháp trộn tự nhiên
Giải thuật:
• Trong phương pháp trộn ở mục 1, giải thuật
chưa tận dụng được chiều dài cực đại của
các Run trước khi phân bố  chưa tối ưu.
• Đặc điểm của PP trộn tự nhiên là tận dụng
chiều dài “tự nhiên” của các Run ban đầu;
nghĩa là thực hiện việc trộn các Run có độ
dài cực đại với nhau cho tới khi dãy chỉ còn
1 Run duy nhất  dãy đã được sắp.

CTDL2 – Lương Trần Hy Hiến 17


2. Phương pháp trộn tự nhiên
Giải thuật:
Trong khi số Run của F0 > 1
Phân bố F0 vào F1, F2 theo các Run tự nhiên.
Trộn các Run của F1, F2 vào F0.
Hết trong khi
do {
- [Distribute] Chia xoay vòng dữ liệu của file F0 cho
F1 và F2, mỗi lần 1 run cho đến khi file F0 hết
nDemRunF0 = 0;
- [Merge] Trộn từng cặp run của F1 và F2 tạo thành
run mới trên F0
} while (nDemRunF0 > 1);
CTDL2 – Lương Trần Hy Hiến 18
2. Phương pháp trộn tự nhiên
• Ví dụ: F0: 1 2 9 8 7 6 5
• Bước 1:
– F1: 1 2 9 7 5
– F2: 8 6
– F0: 1 2 8 9 6 7 5
• Bước 2:
– F1: 1 2 8 9 5
– F2: 6 7
– F0: 1 2 6 7 8 9 5
CTDL2 – Lương Trần Hy Hiến 19
2. Phương pháp trộn tự nhiên
• Ví dụ(tt)
• Bước 3:F0: 1 2 6 7 8 9 5
– F1: 1 2 6 7 8 9
– F2: 5
– F0: 1 2 5 6 7 8 9
• Bước 4: Dừng vì F0 chỉ có 1 Run.

CTDL2 – Lương Trần Hy Hiến 20


3. Phương pháp trộn đa lối cân bằng
• Thuật toán sắp xếp ngoài cần 2 giai đoạn:
Phân phối và trộn.
– Giai đoạn nào làm thay đổi thứ tự?
– Chi phí cho giai đoạn phân phối?
• Rút ra kết luận:
– Thay vì thực hiện 2 giai đoạn, ta chỉ cần thực
hiện 01 giai đoạn trộn.
• Tiết kiệm ½ chi phí Copy.
• Cần số lượng file trung gian gấp đôi.

CTDL2 – Lương Trần Hy Hiến 21


3. Phương pháp trộn đa lối cân bằng
• Chi phí sắp xếp ngoài tỉ lệ với số bước thực hiện:
– Nếu mỗi bước cần N thao tác copy
– Nếu dùng 2 file trung gian cần log2N bước  cần N *
log2N thao tác copy.
– Để giảm số bước  Phân bố số Run nhiều hơn 2 file
trung gian.
– Nếu dùng n file trung gian: cần lognN bước  cần N *
lognN thao tác copy.
• Rút ra kết luận:
– Dùng nhiều file trung gian để giảm số bước.
– Tiết kiệm thao tác copy bằng cách thực hiện 1 giai đoạn
– Sử dụng 2*n file trung gian:
• n file nguồn
• n file đích

CTDL2 – Lương Trần Hy Hiến 22


3. Phương pháp trộn đa lối cân bằng
Thuật toán:
• B1: Gọi tập nguồn S = {f1, f2, …, fn}
Gọi tập đích D = {g1, g2, …, gn}
Chia xoay vòng dữ liệu của file F0 cho các file thuộc
tập nguồn, mỗi lần 1 Run cho tới khi F0 hết.
• B2: Trộn từng bộ Run của các file thuộc tập nguồn
S, tạo thành Run mới, mỗi lần ghi lên các file thuộc
tập đích D.
• B3: Nếu (số Run trên các file của D > 1) thì:
– Hoán vị vai trò tập nguồn (S) và tập đích (D).
– Quay lại B2
Ngược lại kết thúc thuật toán.

CTDL2 – Lương Trần Hy Hiến 23


3. Phương pháp trộn đa lối cân bằng
Ví dụ:
• fInput: U Q N M K I H F D C B, N=3
// Phân phối (lần 1)
f1: U M H C
f2: Q K F B
f3: N I D
// Trộn (lần 1)
g1: N Q U B C
g2: I K M
g3: D F H
// Trộn (lần 2)
f1: D F H I K M N Q U
f2: B C
f3: NULL
// Trộn (lần 3)
g1: B C D F H I K M N Q U
g2: NULL
g3: NULL CTDL2 – Lương Trần Hy Hiến 24
3. Phương pháp trộn đa lối cân bằng
• Các ký hiệu:
– fInput: file dữ liệu gốc cần sắp xếp
– N: số phần tử trên file fInput
– n: số file trung gian trên mỗi tập nguồn/đích
– S: tập các file nguồn
– D: tập các file đích
– Sdd: tập các file nguồn đang còn run dở dang
– Str: tập các file nguồn chưa hết (!EOF), còn có thể tham gia vào quá
trình trộn
– “Lượt”: là 1 quá trình trộn run từ nguồn đ đích, một “luợt” kết thúc khi
mỗi file đích (trong tập D) nhận được 1 run
– Drun: tập các file đích đã nhận được run trong “lượt” hiện hành
• Suy diễn:
– S –Str: tập các file nguồn đã hết (EOF)
– Str –Sdd: tập các file nguồn chưa hết (!EOF), nhưng đã kết thúc run
hiện tại
– D – Drun: tập các file đích chưa nhận được run trong “lượt” hiện hành
CTDL2 – Lương Trần Hy Hiến 25
3. Phương pháp trộn đa lối cân bằng
Thuật toán chi tiết:
[Bước 1] S = {f1, f2, … , fn}
D = {g1, g2, … , gn}
// Chia xoay vòng dữ liệu của fInput cho các
file thuộc tập nguồn S
i = 1;
while (!feof(fInput)) {
Copy_1_Run(fInput, fi);
i = (i % n) + 1;
}
Str = S;
Drun = {};
nDemRun = 0;

CTDL2 – Lương Trần Hy Hiến 26


3. Phương pháp trộn đa lối cân bằng
[Bước 2]
a. Sdd = Str
b. Gọi dhh ∈ D –Drun là file đích hiện hành (sẽ được nhận run)
c. Đọc các phần tử xfi, fi ∈ Sdd
d. Gọi xf0 = MIN { xfi, fi ∈ Sdd}
e. Copy xf0 lên dhh
f. Nếu (file f0 hết) thì {
Str = Str – {f0}
Sdd = Sdd – {f0}
Nếu (Str == {}) thì { // Xong quá trình trộn N đ D
nDemRun++;
Goto [Bước 3]
}
ngược lại Nếu (Sdd <> {}) thì Goto [Bước 2.d]
ngược lại { // Sdd=={}: hết bộ run hiện hành
nDemRun++;
Drun = Drun + {dhh};
Nếu (Drun==D) thì Drun= {}; // Xong 1 “lượt”
Goto [Bước 2.a]
} CTDL2 – Lương Trần Hy Hiến 27
3. Phương pháp trộn đa lối cân bằng
ngược lại { // File f0 chưa hết
Nếu (!EOR(f0)) thì {
Đọc phần tử kế xf0 từ file f0;
Goto [Bước 2.d]
}
ngược lại { // Hết run hiện hành trên f0
Sdd = Sdd – {f0}
Nếu (Sdd <> {}) thì Goto [Bước 2.d]
ngược lại { // Sdd=={}: hết bộ run hiện hành
nDemRun++;
Drun = Drun + {dhh};
Nếu (Drun==D) thì Drun= {}; // Xong 1 “lượt”
Goto [Bước 2.a]
}
} // end of file f0 chưa hết
CTDL2 – Lương Trần Hy Hiến 28
3. Phương pháp trộn đa lối cân bằng
[Bước 3]
Nếu (nDemRun == 1) thì Kết thúc thuật toán
ngược lại {
Nếu (nDemRun < n) thì Str = Drun; // Không đủ n run
ngược lại Str = D;
Drun = {};
nDemRun = 0;
“Hoán vị tập S, D”
Goto [Bước 2]
}

CTDL2 – Lương Trần Hy Hiến 29


Trộn đa lối cân bằng
• Ví dụ: Cho dãy số sau
3 5 2 7 12 8 4 15 20 1 2 8 23 7 21 27
• Nhập :
f0 :3 5 2 7 12 8 4 15 20 1 2 8 23 7 21 27
• Xuất :
f0: 1 2 2 3 4 5 7 7 8 8 12 15 20 21 23 27

CTDL2 – Lương Trần Hy Hiến 30


Các bước tiến hành : chọn 6 file
3 5 2 7 12 8 4 15 20 1 2 8 23 7 21 27
Bước 0: đặt nh = 3
Bước 1:
Phân phối các run luân phiên vào f[1], f[2], f[3]
f1: 3 5 4 15 20
f2: 2 7 12 1 2 8 23
f3: 8 7 21 27

CTDL2 – Lương Trần Hy Hiến 31


Các bước tiến hành : chọn 6 file
Bước 2:
-Trộn các run của f[1], f[2], f[3] và luân phiên phân phối vào các
file g[1], g[2], g[3]
g1: 2 3 5 7 8 12
g2: 1 2 4 7 8 15 20 21 23 27
g3:
- Do số run sau khi trộn >1 nên tiếp tục trộn run từ g[1], g[2], g[3]
vào ngược trở lại f[1], f[2], f[3]
f1: 1 2 2 3 4 5 7 7 8 8 12 15 20 21 23 27
f2:
f3:
- Do số run trộn = 1 nên kết thúc thuật toán
CTDL2 – Lương Trần Hy Hiến 32
Bước 1
3 5 2 7 12 8 4 15 20 1 2 8 23 7 21 27

f1

f2

f3

CTDL2 – Lương Trần Hy Hiến 33


Bước 2

f1 3 5 4 15 20

f2 2 7 12 1 2 8 23

f3 8 7 21 27

3 2 8 7 5 12

g1

g2 1 2 4 7 8 15 20 21 23 27

g3

CTDL2 – Lương Trần Hy Hiến 34


Bước 2
g1 2 3 5 7 12

g2 1 2 6
4 78 15
8 18
15 20 21 23 27

g3

f1 1 2 2 3 4 5 7 7 8 8 12 15 20 21 23 27

f2
f3

CTDL2 – Lương Trần Hy Hiến 35


4. Phương pháp trộn đa pha
• Phương pháp trộn đa lối cân bằng các tập tin
chưa được sử dụng một cách có hiệu quả bởi
vì trong cùng một lần duyệt thì phân nửa số
tập tin luôn luôn giữ vai trò trộn (nguồn) và
phân nửa số tập tin luôn luôn giữ vai trò
phân phối (đích)  Cải tiến: Thay đổi vai trò
của các tập tin trong cùng một lần duyệt 
phương pháp trộn đa pha.

CTDL2 – Lương Trần Hy Hiến 36


4. Phương pháp trộn đa pha
Ta xét ví dụ sau với 3 tập tin f1, f2, f3
• Bước 1: Phân phối luân phiên các run ban đầu của f0 vào
f1 và f2
• Bước 2: Trộn các run của f1, f2 vào f3 . Giải thuật kết thúc
nếu f3 chỉ có một run
• Bước 3: Chép nửa run của f3 vào f1
• Bước 4: Trộn các run của f1 và f3 vào f2. Giải thuật kết
thúc nếu f2 chỉ có một run.
• Bước 5: Chép nửa số run của f2 vào f1. Lặp lại bước 2.
Phương pháp này còn có nhược điểm là mất thời gian sao
chép nửa số run của tập tin này vào tập tin kia. Việc sao
chép này có thể loại bỏ nếu ta bắt đầu với Fn run của tập
tin f1 và fn-1 run của tập tin f2, với fn và fn-1 là các số liên
tiếp trong dãy Fibonaci.

CTDL2 – Lương Trần Hy Hiến 37


4. Phương pháp trộn đa pha
• Ví dụ: Trường hợp n = 7, tổng số run ban đầu là
13 + 8 = 21 run
Pharse F1 F2 F3
0 1,1,1,1,1,1,1,1 1,1,1,1,1 Sort
1 1,1,1 2,2,2,2,2 Merge1
2 3,3,3 2,2 Merge2
3 5,5 3 Merge3
4 5 8 Merge4
5 13 Merge4
6 21 Merge6
CTDL2 – Lương Trần Hy Hiến 38
4. Phương pháp trộn đa pha
• Phase 0: Phân phối các run ban đầu
• Phase 1: Trộn 8 run của f1 và f2 vào f3
• Phase 2: Trộn 5 run của f1 và f3 vào f2
• Phase 3: Trộn 3 run của f2 và f3 vào f1
• Phase 4: Trộn 2 run của f1 và f2 vào f3
• Phase 5: Trộn 1 run của f1 và f3 vào f2
• Phase 6: Trộn 1 run của f2 và f3 vào f1

CTDL2 – Lương Trần Hy Hiến 39


ÔN TẬP
XỬ LÝ TẬP TIN VỚI C++
Cấu trúc

CTDL2 – Lương Trần Hy Hiến 41


Nội dung

1. Giới thiệu về tập tin


2. ofstream
– output file stream
– Lớp làm nhiệu vụ ghi dữ liệu ra file
3. ifstream
– input file stream
– Lớp làm nhiệm vụ đọc dữ liệu từ file
4. Một số thao tác khác với tập tin
5. fstream
– file stream
– Lớp làm cả nhiệm vụ đọc và ghi tập tin

CTDL2 – Lương Trần Hy Hiến 42


1. C++ File I/O

CTDL2 – Lương Trần Hy Hiến 43


1. Giới thiệu về tập tin

• Binary file được dùng để lưu trữ dữ liệu


dạng cấu trúc có kích thước cố định
– Khi ghi biến cấu trúc lên file sẽ ghi 1 khối có
kích thước cố định,
– Khi đọc từ file ra biến cấu trúc cũng đọc từ file
theo từng khối có kích thước cố định.
• Muốn lập trình với file cần phải biết dạng
lưu trữ cũng như ý nghĩa của dữ liệu trong
file.

CTDL2 – Lương Trần Hy Hiến 44


1. Giới thiệu về tập tin

• Input file : file có dữ liệu sẽ được


truy cập để đưa vào biến

• Output file: File sẽ chứa trị của biến


khi trị của biến được ghi vào

CTDL2 – Lương Trần Hy Hiến 45


2. ofstream
• Khai báo và mở tập tin để ghi dữ liệu
– ofstream <tên biến>;
– ofstream <tên biến>(<tên file>);
– Ví dụ: ofstream fout;
fout.open(“data.dat”);
hoặc ofstream fout(“data.dat”);
• Ghi dữ liệu chuẩn
– Tương tự như cout
– <tên biến> <toán tử xuất (<<)>
– Ví dụ: int a;
fout<<a;

CTDL2 – Lương Trần Hy Hiến 46


2. ofstream
• Ghi dữ liệu dạng nhị phân
– ostream& write(char* pch,int nCount);
– ostream& write(unsigned char* puch,int nCount);
– ostream& write(signed char* psch,int nCount);
– Giải thích tham số
• pch,puch,psch: con trỏ đến mảng ký tự lưu dữ liệu.
• nCount: số byte cần ghi
• Thường dùng để ghi toàn bộ một struct hoặc
một đối tượng ra file
• Đóng tập tin: sử dụng phương thức close();

CTDL2 – Lương Trần Hy Hiến 47


2. ofstream
• Ví dụ
Ghi dữ liệu của 5 phần tử số nguyên liên tiếp ra
file dạng nhị phân
---------------------------------------------------------
int a[10];
a[0]=65;a[1]=66;a[2]=97;a[3]=99;a[4]=67;
ofstream fout(“data.dat”);
int n=5;
fout.write((char*)a,n*sizeof(*a));
fout.close();
CTDL2 – Lương Trần Hy Hiến 48
3. ifstream
• Khai báo và mở tập tin để đọc dữ liệu
– ifstream <tên biến>;
– ifstream <tên biến>(<tên file>);
– Ví dụ: ifstream fin;
fin.open(“data.dat”);
hoặc ifstream fin(“data.dat”);
• Đọc dữ liệu chuẩn
– Tương tự như cin
– <tên biến> <toán tử nhập (>>)>
– Ví dụ: int a;
fin>>a;

CTDL2 – Lương Trần Hy Hiến 49


3. ifstream
• Đọc dữ liệu dạng nhị phân
– istream& read(char* pch, int nCount);
– istream& read(unsigned char* puch, int nCount);
– istream& read(signed char* psch, int nCount);
• Giải thích tham số
– pch,puch,psch: con trỏ đến mảng ký tự lưu dữ
liệu.
– nCount: số byte lớn nhất cần đọc
• Thường dùng để đọc một struct hoặc một
đối tượng từ file
• Đóng tập tin: sử dụng phương thức close();

CTDL2 – Lương Trần Hy Hiến 50


3. ifstream
• Ví dụ
Đọc dữ liệu của 5 phần tử số nguyên liên
tiếp đã ghi dạng nhị phân
-----------------------------------------------
int a[10];
ifstream fin(“data.dat”);
int n=5;
fin.read((char*)a,n*sizeof(*a));
fin.close();
CTDL2 – Lương Trần Hy Hiến 51
4. Một số thao tác khác với tập tin
• Lấy vị trí hiện tại của con trỏ tập tin
– Khi đọc
• Dùng hàm tellg();
• Ví dụ: long pos=fin.tellg();
– Khi ghi
• Dùng hàm tellp();
• Ví dụ: long pos=fout.tellp();

CTDL2 – Lương Trần Hy Hiến 52


4. Một số thao tác khác với tập tin
• Di chuyển con trỏ đến một vị trí trong tập
tin
– Khi đọc
• Dùng hàm seekg(long sobyte, ios::xx vtbd);
• Ví dụ: fin.seekg(0,ios::beg); //về đầu tập tin
– Khi ghi
• Dùng hàm seekp(long sobyte, ios::xx vtbd);
• Ví dụ: fout.seekp(0,ios::end); //đến cuối tập tin
– Hằng số
• ios::beg: di chuyển từ đầu tập tin
• ios::cur: di chuyển từ vị trí hiện tại của con trỏ
• ios::end: di chuyển từ cuối tập tin

CTDL2 – Lương Trần Hy Hiến 53


4. Một số thao tác khác với tập tin

long SizeOf(char *fileName)


{
long end,begin;
ifstream myfile(fileName);
begin = myfile.tellg();
myfile.seekg(0, ios::end); Tính kích thước
end = myfile.tellg(); của tập tin
myfile.close();
return end-begin;
}

CTDL2 – Lương Trần Hy Hiến 54


5. fstream
• Sử dụng đối tượng của lớp này có thể vừa
đọc vừa ghi dữ liệu trong cùng một tập tin
• is_open(): Trả về true nếu đang mở, false
nếu không mở.
• Mở tập tin vừa đọc vừa ghi dạng nhị phân
fstream f;
f.open(“data.dat”,ios::in|ios::out|ios::binary);
ios::in, ios::out, ios::app, ios::nocreate, …

CTDL2 – Lương Trần Hy Hiến 55


Làm việc với file bằng C

56
Khai báo mở tập tin để đọc/ghi dữ liệu

– Khai báo biến con trỏ tệp


FILE* <tên file>;
– Mở tệp
File * fopen(const char *<tên file>, const char
* <kiểu truy cập>);
– Ví dụ:
FILE *f;
f = fopen(“D:\\data.txt”,”r”); //mở tập tin để đọc dữ liệu.
f = fopen(“D:\\data.txt”,”w”); //mở tập tin để ghi dữ liệu.

CTDL2 – Lương Trần Hy Hiến 57


Một số kiểu truy cập

Kiểu truy cập Ý nghĩa

“r” Mở một tập tin đã có để đọc theo kiểu VB

“w” Mở một tập tin mới để ghi theo kiểu VB

“a” Mở một tập tin mới để ghi bổ sung theo kiểu VB

“rb” Mở một tập tin đã có để đọc theo kiểu nhị phân

“wb” Mở một tập tin mới để ghi theo kiểu nhị phân

“ab” Mở một tập tin mới để ghi bổ sung theo kiểu nhị phân

Lưu ý: Cần làm sạch vùng đệm trước khi chuyển từ đọc
sang ghi hoặc từ ghi sang đọc.

CTDL2 – Lương Trần Hy Hiến 58


Một số hàm khác
• Đóng file
int fclose(FILE * f);
• Đóng các file đang mở
int fcloseall(void);
• Làm sạch vùng đệm
int fflush(FILE* f);
• Kiểm tra cuối file
int feof(FILE *f) //trả về giá trị khác 0 nếu
gặp cuối tệp, ngược lại trả về 0.

CTDL2 – Lương Trần Hy Hiến 59


Các hàm nhập xuất ký tự
• Ghi ký tự lên file
int fputc(int ch, FILE *f)
Hàm ghi lên file f một ký tự có mã bằng
m = ch % 256
• Đọc ký tự từ file
int fgetc(int ch, FILE *f)

CTDL2 – Lương Trần Hy Hiến 60


Các hàm nhập xuất theo kiểu văn bản
• Ghi dữ liệu theo khuôn dạng lên file
int fprintf(FILE* f, const char * dk,… )
• Đọc dữ liệu từ file theo khuôn dạng
int fscanf(FILE* f, const char * dk,… )
• Ghi một chuỗi ký tự lên file
int fputs(const char* s, FILE *f)
• Đọc một dãy ký tự từ file
char fgets(const char* s, int n, FILE *f)
Việc đọc kết thúc khi:
- Hoặc đã đọc n-1 ký tự
- Hoặc gặp dấu xuống dòng
- Hoặc kết thúc tệp.

CTDL2 – Lương Trần Hy Hiến 61


Ví dụ - hàm fprintf
Chương trình tạo ra tệp văn bản text gồm 3 dòng với
nội dung:
Dong 1
Dong 2
Dong 3
-----------------------------------------------
FILE *f;
f =fopen(“D:\\text.txt”,”w”);
for(int i=0; i<2; i++)
fprintf(f,”Dong%2d\n”,i);
fclose(f);
CTDL2 – Lương Trần Hy Hiến 62
Ví dụ - hàm fscanf
Giả sử có một dãy số nguyên ghi trên tệp array.sl, giữa 2 số
có ít nhất 1 khoảng trống.
-----------------------------------------------

int c;
while(!feof(f))
{
fscanf(f, “%d”, &c);
printf(“%3d”,c);
}

CTDL2 – Lương Trần Hy Hiến 63


Ví dụ - hàm fputs
Chương trình nhập một dòng ký tự từ bàn phím và
ghi lên tệp “dongVB”
----------------------------------------------char s[256];
FILE *f;
f = fopen(“D:\\dongVB.txt”,”w”);
printf(“Nhap dong van ban: “);
gets(s);
fputs(d,f);
fclose(f);

CTDL2 – Lương Trần Hy Hiến 64


Ví dụ - hàm fgets
Chương trình đọc các dòng ký tự trên tệp “dongVB”
và in ra màn hình
----------------------------------------------

int i=0; char d[256];
while(!feof())
{
i++;
fgets(d, 256, f);
printf(“Dong %d: %s”,i,d);
}


CTDL2 – Lương Trần Hy Hiến 65
Các hàm nhập xuất theo kiểu nhị phân
• Ghi một số nguyên (2byte) lên file
int putw(int n, FILE *f)
• Đọc một số nguyên (2byte) lên file
int getw(FILE *f)
• Ghi một số mẫu tin lên file
int fwrite(void *ptr, int size, int n, FILE *f)
• Đọc một số mẫu tin từ file
int fread(void *ptr, int size, int n, FILE *f)
ptr: con trỏ trỏ tới vùng nhớ chứa dữ liệu đọc được
size: kích thước mẫu tin theo byte
n: số mẫu tin cần đọc
f: con trỏ tệp
CTDL2 – Lương Trần Hy Hiến 66
Câu hỏi và thảo luận

CTDL2 – Lương Trần Hy Hiến 67

You might also like