You are on page 1of 27

Kỹ thuật lập trình

Bài 6: Tệp tin

TS. Nguyễn Hiếu Cường


Bộ môn CNPM, Khoa CNTT, Trường ĐH GTVT
Email: cuonggt@gmail.com

Hà Nội, 2022
Nội dung chính của môn học

1. Các khái niệm cơ bản trong ngôn ngữ C


2. Hàm và tổ chức chương trình

3. Hàm và mảng

4. Đệ quy

5. Xử lý chuỗi ký tự

6. Thao tác trên các tệp tin

7. Tệp lưu cấu trúc

8. Cấp phát bộ nhớ

9. Danh sách liên kết

2
Khái niệm tệp tin

 Tác dụng của tệp tin (files)


 Tồn tại lâu dài trên các thiết bị lưu trữ
 Dữ liệu vào và kết quả ra trên tệp tin
 Các loại hàm xử lý tệp tin
 Hàm cấp 1: Chỉ có dịch vụ đọc/ghi một dãy byte, không xử lý theo
từng loại dữ liệu
 Hàm cấp 2: Dựa trên các hàm cấp 1, chậm hơn nhưng dễ dùng hơn,
và có dịch vụ truy xuất cho từng loại dữ liệu
 Các loại tệp
 Nhị phân (binary file): truy xuất theo từng byte
 Văn bản (text file): truy xuất theo từng ký tự

3
Các hàm xử lý tệp tin

 Các hàm dùng cho cả 2 kiểu tệp (nhị phân và văn bản)
 fopen Mở tệp

 fclose Đóng tệp

 fcloseall Đóng tất cả các tệp đang mở

 fflush Xóa vùng đệm

 feof Xác định đã kết thúc tệp chưa

 fputc / fgetc Ghi/đọc một ký tự

4
Các hàm xử lý tệp tin

 Các hàm chỉ dùng cho tệp văn bản


 fprintf / fscanf Ghi / đọc dữ liệu theo khuôn dạng

 fputs / fgets Ghi / đọc một chuỗi ký tự

 Các hàm chỉ dùng cho tệp nhị phân


 fwrite / fread Ghi / đọc các mẫu tin (theo byte)

 putw / getw Ghi / đọc một số nguyên

5
Mở tệp

FILE *fopen(const char *tên_tệp, const char *kiểu_tệp)


 Mở tệp, nếu thành công hàm trả về con trỏ kiểu FILE ứng với tệp vừa mở
KiÓu ý nghÜa
"r" "rt" Më mét tÖp ®Ó ®äc theo kiÓu v¨n b¶n. TÖp cÇn
tån t¹i nÕu kh«ng sÏ cã lçi.
"w" "wt" Më mét tÖp míi ®Ó ghi theo kiÓu v¨n b¶n.
NÕu tÖp ®· tån t¹i nã bÞ xo¸.
"a" "at" Më mét tÖp ®Ó ghi bæ xung theo kiÓu v¨n
b¶n. NÕu tÖp ch-a tån t¹i th× t¹o tÖp míi.
"rb" Më mét tÖp ®Ó ®äc theo kiÓu nhÞ ph©n. TÖp
cÇn tån t¹i nÕu kh«ng sÏ cã lçi.
"wb" Më mét tÖp míi ®Ó ghi theo kiÓu nhÞ ph©n.
NÕu tÖp ®· tån t¹i nã bÞ xo¸.
"ab" Më mét tÖp ®Ó ghi bæ xung theo kiÓu nhÞ
ph©n. NÕu tÖp ch-a tån t¹i th× t¹o tÖp míi.
"r+" "r+t" Më mét tÖp ®Ó ®äc/ghi theo kiÓu v¨n b¶n. TÖp
cÇn tån t¹i nÕu kh«ng sÏ cã lçi.

6
Ví dụ: đọc và ghi tệp văn bản
// Đọc một dãy số từ tệp input.txt (dòng đầu là số phần tử, trên dòng
// tiếp theo là dãy số. Hãy in dãy ra màn hình và vào tệp output.txt.
#include<stdio.h>
int main() {
FILE *f;
int n, i, a[20];
f= fopen("input.txt", "rt"); // Mở để đọc
fscanf(f, "%d", &n); // Đọc số phần tử từ tệp f
for(i=1; i<=n; ++i)
fscanf(f, "%d", &a[i]); // Đọc từng phần tử từ tệp
for(i=1; i<=n; ++i)
printf("%d ", a[i]); // Ghi từng phần tử ra màn hình
f= fopen("output.txt", "wt"); // Mở để ghi
fprintf(f, "%d\n", n); // Ghi số phần tử vào tệp f
for(i=1; i<=n; ++i)
fprintf(f, "%d ", a[i]); // Ghi từng phần tử vào tệp f
}
7
Các hàm đọc/ghi tệp văn bản

 Đọc dữ liệu từ tệp văn bản


int fscanf(FILE *fp, char *đặc_tả, danh_sách_đối)
 Tương tự như hàm scanf, nhưng thay vì đọc từ bàn phím thì đọc từ tệp fp
 Hàm trả về giá trị là số trường (số phần tử) đã đọc được

 Ghi dữ liệu vào tệp văn bản


int fprintf(FILE *fp, char *đặc_tả, danh_sách_đối)
 Tương tự như hàm printf, nhưng thay vì ghi lên màn hình thì ghi vào tệp fp
 Nếu ghi thành công thì hàm trả về giá trị nguyên bằng số byte ghi lên tệp,
ngược lại trả về EOF

8
Các hàm đọc/ghi ký tự

 Đọc một ký tự từ tệp


int fgetc(FILE *fp)
 Đọc một ký tự từ fp, kết quả có thể lưu vào một biến ký tự (kiểu char) hoặc
biến nguyên (kiểu int, là mã ASCII của ký tự được đọc)

 Ghi một ký tự vào tệp


int fputc(char ch, FILE *fp)
int fputc(int ch, FILE *fp)
 Ghi lên tệp fp một ký tự ch (nếu ch là char) hoặc ký tự có mã ASCII bằng ch
(nếu ch là int)
 Nếu thành công thì trả về mã ký tự được ghi, ngược lại trả về EOF

9
Các hàm đọc/ghi chuỗi

 Đọc một chuỗi ký tự từ tệp


char *fgets(char *s, int n, FILE *fp)
 Đọc một chuỗi ký tự từ fp, ghi vào s, n là độ dài max của dãy cần đọc

 Ghi một chuỗi ký tự vào tệp


int fputs(const char *s, FILE *fp)
 Ghi chuỗi s lên tệp fp (không ghi ‘\0’).
 Nếu thành công trả về ký tự cuối cùng được ghi, ngược lại trả về EOF

10
Ví dụ (đọc từng ký tự từ tệp)

#include <stdio.h>
int main () {
FILE *fp;
int c;
int n = 0;
fp = fopen("input.txt","rt");
if(fp == NULL) {
perror("Xay ra loi khi mo input.txt !!!");
return(-1);
}
do {
c = fgetc(fp);
if(feof(fp))
break ;
printf("%c", c);
} while(1);
}

11
Đọc tệp văn bản

 Mảng một chiều


f= fopen("input.txt", "rt");
fscanf(f, "%d", &n);
for(i=1; i<= n; ++i)
fscanf(f, "%f", &a[i]);

 Mảng hai chiều


f= fopen("input.txt", "rt");
fscanf(f, "%d%d", &m, &n);
for(i=1; i<= m; ++i)
for(j=1; j<= n; ++j)
fscanf(f, "%f", &a[i][j]);

12
Ví dụ

1. Dữ liệu của một dãy số được lưu trong tệp input.txt có: dòng đầu là
số phần tử, dòng tiếp theo là giá trị các phần tử. Hãy đọc dữ liệu từ
input.txt, tính các giá trị lớn nhất và trung bình cộng của dãy. Ghi vào
tệp output.txt: dòng đầu là dãy số trên, mỗi dòng tiếp theo là các kết
quả vừa tính được.

2. Đọc dữ liệu của ma trận được lưu trong một tệp văn bản matran.txt,
gồm: dòng đầu lưu số hàng, số cột, trên mỗi dòng tiếp theo lưu một
hàng của ma trận. In vào một tệp văn bản (tên tệp nhập từ bàn phím)
+ Ma trận trên dưới dạng bảng và
+ Dòng cuối cùng là các giá trị lớn nhất của các phần tử của ma trận đó.

13
Đọc tệp văn bản

 Mảng một chiều


f= fopen("input.txt", "rt");
fscanf(f, "%d", &n);
for(i=1; i<= n; ++i)
fscanf(f, "%f", &a[i]);

 Mảng hai chiều


f= fopen("input.txt", "rt");
fscanf(f, "%d%d", &m, &n);
for(i=1; i<= m; ++i)
for(j=1; j<= n; ++j)
fscanf(f, "%f", &a[i][j]);

 Nếu không có thông tin kích thước thì đọc thế nào?

14
Ví dụ

 Một dãy số được lưu trong tệp dayso.txt, các phần tử cách nhau bởi ít
nhất một dấu cách. Hãy đọc dữ liệu từ dayso.txt, tính trung bình cộng
của dãy (không có thông tin về số phần tử của dãy).

while (!feof(f))
{
...

15
Ví dụ (dùng hàm feof)

#include<stdio.h>
int main()
{
FILE *f;
float a[50];
int n = 0;
f= fopen("dayso.txt", "rt");
while(!feof(f))
{
fscanf(f, "%f", &a[n]);
n++;
}
}

16
Ví dụ

1. Dữ liệu của một dãy số được lưu trong tệp dayso1.txt có: dòng đầu là
số phần tử, dòng tiếp theo là giá trị các phần tử. Hãy đọc dữ liệu từ
dayso.txt, tính các giá trị trung bình cộng và trung vị của dãy. Ví dụ:
2, 3, 6, 5, 1  trung bình cộng (mean) = 3.4; trung vị (median)= 3.

2. Dữ liệu của một dãy số được lưu trong tệp dayso2.txt (chú ý: không
có thông tin số phần tử). Hãy đọc dữ liệu từ dayso2.txt, tính các giá
trị max và min của dãy.

17
Các hàm đọc/ghi tệp kiểu nhị phân

 Ghi dữ liệu vào tệp


int fwrite(void *p, int size, int n, FILE *f)
 p: con trỏ trỏ tới vùng nhớ chứa dữ liệu cần ghi
 size: kích thước mẫu tin (tính theo byte)
 n: số mẫu tin cần ghi
 f: con trỏ tệp
 Hàm trả về giá trị là số mẫu tin ghi được
 Đọc dữ liệu từ tệp
int fread(void *p, int size, int n, FILE *f)
 p: con trỏ trỏ tới vùng nhớ chứa dữ liệu đọc được
 size: kích thước mẫu tin (tính theo byte)
 n: số mẫu tin cần ghi
 f: con trỏ tệp
 Hàm trả về giá trị là số mẫu tin đọc được

18
Ví dụ (dùng fwrite, fread)

 Sao chép tệp


#include<stdio.h>
int main(){
int n;
char t1[15], t2[15], c[1000];
FILE *f1, *f2;
printf("\nTep nguon: "); gets(t1);
printf("\nTep dich: "); gets(t2);
f1= fopen(t1, "rb");
if(f1 == NULL)
printf("Tep khong ton tai");
f2= fopen(t2, "wb");
while((n = fread(c,1,1000,f1))>0)
fwrite(c,1,n,f2);
fclose(f1); fclose(f2);
}
19
Viết hàm đọc/ghi dãy số

 Hàm đọc dãy số từ tệp


void doc_day(FILE *f, float *a, int *n);

 Hàm ghi dãy số vào tệp


void ghi_day(FILE *f, float *a, int n);

20
Ví dụ (Hàm đọc/ghi dãy số)

1. Viết hàm đọc một dãy số từ tệp (tên tệp nhập từ bàn phím), có cấu
trúc như sau: dòng đầu là số phần tử, trên dòng tiếp theo là các phần
tử của dãy số.
 Viết hàm ghi các phần tử có giá trị >10 vào một tệp khác.
 Áp dụng trong hàm main()

2. Dữ liệu của một dãy số nguyên được lưu trong tệp input.txt, có dạng:
dòng đầu là số phần tử, dòng tiếp theo là giá trị các phần tử.
 Viết hàm đọc một dãy số nguyên từ tệp input.txt
 Viết hàm xác định một số có phải số nguyên tố không, nếu số đó là
số nguyên tố thì hàm trả về 1, ngược lại trả về 0.
 Viết hàm main() để sử dụng các hàm trên: Đọc một dãy số nguyên
từ tệp văn bản, in ra màn hình các số nguyên tố từ dãy đó.

21
Hàm đọc ma trận tệp

22
Ví dụ (Hàm đọc/ghi ma trận)

1. Cho tệp văn bản (tên tệp nhập từ bàn phím) chứa các phần tử của
một ma trận thực cấp m*n, có dạng như sau: Dòng đầu chứa các số
nguyên m và n (giữa hai số m và n có ít nhất một dấu cách). Dòng
thứ i+1 (i=1, 2,.., m) chứa các phần tử của hàng thứ i của ma trận
(giữa các phần tử có ít nhất một dấu cách). Hãy:
 Viết hàm đọc ma trận từ tệp.
 Viết hàm ghi ma trận dưới dạng bảng vào một tệp khác.

23
Tóm tắt (đọc/ghi tệp)

 Đọc một dãy số từ tệp (dòng đầu lưu số phần tử của dãy, dòng tiếp
theo lưu dãy số)
 Hàm đọc một dãy số từ tệp

 Đọc một dãy điểm từ tệp (dòng đầu lưu số điểm, mỗi dòng tiếp theo
lưu tọa độ của một điểm)
 Hàm đọc một dãy điểm từ tệp

 Đọc một ma trận từ tệp (dòng đầu lưu số hang và số cột, mỗi dòng
tiếp theo lưu một hàng của ma trận)
 Hàm đọc một ma trận từ tệp

 Đọc dữ liệu khi không có thông tin về số lượng


 Ghi dữ liệu vào tệp

24
Bài tập

1. Dữ liệu của một dãy số được lưu trong tệp input.txt có: dòng đầu là
số phần tử, dòng tiếp theo là giá trị các phần tử. Hãy đọc dữ liệu từ
input.txt, tính các giá trị trung bình cộng và trung vị của dãy. Ghi vào
tệp output.txt: dòng đầu là dãy số trên, mỗi dòng tiếp theo là các kết
quả vừa tính được.

2. Dữ liệu của một dãy điểm được lưu trong tệp (tên tệp nhập từ bàn
phím), có dạng: dòng đầu là số điểm, trên mỗi dòng tiếp theo là tọa
độ của một điểm. Hãy đọc dữ liệu từ tệp trên và đếm số điểm nằm
bên trên trục hoành.

3. Đọc dữ liệu của ma trận được lưu trong một tệp văn bản input.txt:
dòng đầu lưu số hàng, số cột, các dòng tiếp theo mỗi dòng lưu một
hàng của ma trận. In vào tệp output.txt ma trận trên dưới dạng bảng,
và dòng cuối cùng là trung bình cộng của các phần tử của ma trận.

25
Bài tập

4. Dữ liệu một dãy số nguyên được lưu trong tệp (tên tệp nhập từ bàn
phím) có dạng: dòng đầu là số phần tử, dòng tiếp theo là giá trị các
phần tử. Hãy viết hàm đọc dữ liệu từ tệp trên và tính ước số chung
lớn nhất của các số nguyên đó.

5. Dữ liệu về các hệ số của đa thức P(x) được lưu trong tệp (tên tệp
nhập từ bàn phím) có dạng: dòng đầu là hệ số của đa thức n, dòng
tiếp theo là giá trị các hệ số a0, a1, …, an. Hãy đọc dữ liệu từ tệp và
tính giá trị đa thức và đạo hàm đa thức tại x = t (với t là một số
thực nhập từ bàn phím).

26
Bài tập

6. Cho tệp văn bản (tên tệp nhập từ bàn phím) chứa toạ độ của một
dãy n điểm. Tệp có dạng: Dòng đầu chứa số điểm, mỗi dòng tiếp
theo chứa toạ độ x, y của một điểm. Hãy viết các hàm: Đọc toạ độ
dãy điểm từ tệp; Tính tổng khoảng cách của các điểm đến trục
hoành; Trong số các đoạn thẳng có đầu mút là các điểm nói trên,
tìm một đoạn thẳng có độ dài lớn nhất.

7. Cho tệp văn bản (tên tệp nhập từ bàn phím) chứa các phần tử của
một ma trận nguyên m hàng, n cột. Tệp có dạng: Dòng đầu chứa
các số nguyên m và n, trên mỗi dòng tiếp theo là một hàng của
ma trận. Hãy viết chương trình: Đọc ma trận từ tệp; Tính tích các
phần tử chẵn của ma trận; Tìm phần tử chẵn nhỏ nhất của ma trận
và cho biết vị trí của phần tử đó; Xác định xem những cột nào có
tổng các giá trị là chẵn.

27

You might also like