SỬ DỤNG HÀM TRONG C
CHƯƠNG 8 QUẢN LÝ TẬP TIN
8.3 CÁC TẬP TIN VĂN BẢN
Hàm fopen() mở một stream để sử dụng và liên kết một tập tin với stream đó.
Con trỏ kết hợp với tập tin được trả về từ hàm fopen(). Trong hầu hết các trường hợp, tập tin đang mở là một tập tin trên đĩa. Nguyên mẫu của hàm fopen() là:
FILE *fopen (const char *filename, const char *mode);
Trong đó filename là tên của một tập tin cần mở, có thể chứa đầy đủ cả đường dẫn tập tin, mode là chế độ mở tập tin (xác định cách thức tập tin được mở).
Chế độ Ý nghĩa
R Mở một tập tin văn bản để đọc W Tạo mới một tậptin để ghi
a Mở một tập tin văn bản đã có và ghi thêm dữ liệu vào cuối tập tin r+ Mở một tập tin văn bản để đọc/ghi
w+ Mở/tạo một tập tin văn bản để đọc/ghi a+f Nối hoặc tạo một tập tin văn bản để đọc/ghi
Bảng 8. 2: Các chế độ mở tập tin văn bản
Nếu mở tập tin thành công, hàm fopen() sẽ trả về một con trỏ đến tập tin vừa mở. Ngược lại, nếu việc mở tập tin có lỗi thì một con trỏ NULL được trả về.
Chương trình sau đây sẽ mở một tập tin nhị phân có tên “Output.txt” trên ổ đĩa Cđể ghi và thông báo ra màn hình nếu việc mở file không thành công.
Ví dụ 8.1:
#inlude
<stdio.
h> int main(){
FILE *fo;
fo =
fopen("C:\\Output.txt",
"w+"); if ("fo != NULL"){
printf("The file is already for writing!");
/*Thực hiện các thao tác ghi dữ liệu
vào file*/
Retun 0;
} else{
printf("Can not open file!");
return 1;
} }
Nếu một tập tin được mở để ghi, bất kỳ một tập tin nào có cùng tên và đang
mở sẽ bị ghi
đè lên. Vì khi một tập tin được mở ở chế độ ghi, thì một tập tin mới được tạo ra.
Nếu muốn nối
thêm các mẫu tin vào tập tin đã có, thì nó phải được mở với chế độ nối (‘a’). Nếu một tập tin
154
được mở ở chế độ đọc và nó không tồn tại, hàm sẽ trả về lỗi. Nếu một tập tin
được mở để
đọc/ghi, nó sẽ không bị xóa nếu đã tồn tại. Tuy nhiên, nếu nó không tồn tại, thì nó sẽ được tạo ra.
Theo chuẩn ANSI, tám tập tin có thể được mở tại một thời điểm. Tuy vậy, hầu hết các trình biên dịch C và môi trường đều cho phép mở nhiều hơn tám tập tin.
8.3.2 Đóng một tập tin văn bản
Vì số lượng tập tin có thể mở tại một thời điểm bị giới hạn, việc đóng một tập tin khi không còn sử dụng là một điều quan trọng. Thao tác này sẽ giải phóng tài nguyên và làm giảm nguy cơ vượt quá giới hạn đã định. Đóng một stream cũng sẽ làm sạch và chép vùng đệm kết hợp của nó ra ngoài (một thao tác quan trọng để tránh mất dữ liệu) khi ghi ra đĩa. Hàm fclose() đóng một stream đã được mở bằng hàm fopen(). fclose() ghi bất kỳ dữ liệu nào còn lại trong vùng đệm của đĩa vào tập tin. Nguyên mẫu của hàm như sau:
int fclose (FILE *fp);
Trong đó fp là một con trỏ tập tin. Hàm fclose() trả về giá trị 0 nếu đóng file thành công. Ngược lại, trả về giá trị khác 0. Hàm fclose() sẽ thất bại nếu không tìm thấy ổ đĩa chứa file cần ghi hoặc đĩa bị đầy, không thể ghi thêm dữ liệu. Ví dụ:
file *fp;
main {
fclose(fp);
}
Ngoài ra, có thể dùng hàm fcloseall() để đóng cùng một lúc nhiều stream đang mở. Hàm này trả về số stream đã đóng hoặc EOF nếu có phát hiện lỗi. Ví dụ:
int status = fcloseall();
if (status==EOF)
printf(“Can not close
all file”);
else
printf(“The number of closed files: %d”,status);
8.3.3 Hàm fprintf()
Hàm fprintf() được sử dụng để ghi dữ liệu vào file, nguyên tắc hoạt động của hàm này tương tự như hàm printf(). Nguyên mẫu của fprintf()như sau:
int fprintf (FILE *fp, const char * <Chuỗi định dạng> , <Danh sách đối số>);
Trong đó fp là con kiểu FILE, trỏ đến tập tin đã được bằng lệnh fopen()mở với
chế độ mở
để ghi dữ liệu (w/w+/a), chuỗi định dạngđược qui định giống như đối với hàm
fprintf (xem
phần 1.5.2 - chương 1), danh sách đối số chính là danh sách giá trị của các đối số
sẽ được ghi
vào file.
Chương trình sau đây sẽ mở lại file output.txt ở trên (xem ví dụ 8.1)
và sử dụng
hàmfprint() để ghi dữ liệu vào file.
155
Ví dụ 8.2:
#include
<stdio.h
> int
main(){
F I L E
* f o
; i n t i
= 1 0
;
doublefp = 1.5;
chars[] = "Hello!";
fo =
fopen("C:\\Output.txt",
"w+"); if ("fo == NULL"){
printf("Can not open file!");
return 1;
} fprintf( fo, "%s", s);
fprintf( fo,
"%d\n", i);
fprintf( fo,
"%f\n", fp);
fclose( fo );
}
Sau khi ghi xong, file output.txt sẽ có nội dung như sau:
Hello 10
1.500000 8.3.4 Hàm fscanf()
Hàm fscanf()là hàm được sử dụng để đọc dữ liệu từ file vào các biến trong
chương trình,
hàm này được sử dụng rất phổ biến trong khi làm việc với file văn bản. Nguyên
mẫu của hàm
như sau:
int fscanf (FILE *fp, const char *<Chuỗi định dạng> , <Danh sách đối
số>);
Trong đó fp là con trỏ kiểu FILE, trỏ đến tập tin đã được mở bằng lệnh fopen()với chế độ để đọc dữ liệu (r/r+), chuỗi định dạng được qui định giống như
đối với hàm scanf (xem phần 1.5.3 -
chương 1), danh sách đối số chính là danh sách biến được gán các giá trị đọc được từ file.
Hàm fscanf() trả về số trường được đọc và gán giá trị thành công. Giá trị trả
về không bao
gồm những trường đã được đọc nhưng chưa được gán. Giá trị trả về bằng 0 nếu
không có
trường nào được gán. Nếu việc đọc có lỗi hoặc đã đến cuối file trước khi đọc dữ
liệu thì giá trị
trả về là EOF.
Chương trình sau đây sử dụng lệnh scanf() để đọc ra các dữ liệu đã được lưu trong file output.txt ở trên.
Ví dụ 8.3:
#includ e<stdio .h>
intmain () {
F I L E
* f i
; i n t x
;
doublef;
charstr[100];
fi =
fopen("C:\\Output.txt",
"r"); if (fi == NULL){
printf("Can not open file to read!"); return 1;
}
156
fscanf( fi,
"%s", str);
fscanf( fi,
"%d", &x);
fscanf( fi,
"%lf", &f);
fclose( fi );
printf("The reading contents:\n");
printf(" str = %s, x = %d, f=%f\n", str, x, f);
}
Kết quả thực hiện chương trình như sau:
The reading contents:
str = Hello!, x = 10, f = 1.500000 8.3.5 Hàm fputc()
Hàm fputc() được sử dụng để ghi các ký tự vào tập tin. Nguyên mẫu của hàm là:
int fputc (int ch, FILE *fp);
Trong đó ch là ký tự được ghi vào tập tin, fp là con trỏ kiểu FILE, trỏ đến tập tin đã được bằng lệnh fopen() mở với chế độ mở để ghi dữ liệu (w/w+/a).
Hàm fputc() trả về một giá trị nguyên, xác định mã của ký tự được ghi thành công hoặc giá trị EOF nếu có việc ghi bị lỗi.
Chương trình sau đây sẽ mở một file test.txt ở ổ đĩa C với chế độ mở file để ghi, sau đó sử dụng hàm fputc() để ghi lần lượt các ký tự của một chuỗi ký tự cho trước vào file.
Ví dụ 8.4:
#includ e<stdio .h>
int main( v oid ){
FILE
*fi;
intx;
fi =
fopen("C:\\test.txt",
"w"); if (fi == NULL){
printf("Can not open file to read!");
}
char str[] = "This is a test of fputc!!\n"; for (inti=0;
i<strlen(str); i++){
x = fputc( str[i], fi);
if (x == EOF){
printf("Error in writing!");
fclose(fi);
return 1;
}
} fclose(fi);
}
Sau khi ghi dữ liệu xong, tập tin test.txt sẽ có nội dung như sau:
This is a test of fputc!!
8.3.6 Hàm fgetc()
Hàm fgetc() được dùng để đọc các ký tự từ một tập tin đã được mở. Nguyên
mẫu của hàm
như sau:
int fgetc (FILE *fp);
157
Trong đó fp là con trỏ kiểu FILE, trỏ đến tập tin đã được mở bằng lệnh fopen()với chế độ để đọc (r). Hàm fgetc() trả về ký tự kế tiếp của vị trí hiện hành trong stream input, và tăng con trỏ định vị trí bên trong tập tin lên. Ký tự đọc được là một ký tự kiểu unsigned char và được chuyển thành kiểu int. Nếu đã đến cuối tập tin, fgetc() trả về EOF.
Chương trình sau đây sẽ mở file test.txt ở trên với chế độ để đọc, sau đó sử dụng lệnh fgetc() để đọc lần lượt các ký và hiển thị ra màn hình.
Ví dụ 8.5:
#includ e<stdio .h>
intmain (){
FI LE
*f o;
in tx
;
charstr[100];
fo =
fopen("C:\\Test.txt",
"r"); if (fo == NULL){
printf("Can not open file to read!"); return 1;
}
do{ x = fgetc(fo)
;
printf("%
c",x); } while (x!
=EOF);
fclose(fo } );
Kết quả thực hiện của chương trình như sau:
This is a test of fputc!!
Chú ý, để đọc một tập tin văn bản từ đầu đến cuối, ta sử dụng cấu trúc
lặp có dạng:
Do{ ch = fgetc(fp);
}while (ch != EOF);
8.3.7 Hàm fputs()
Hàm fputs() làm việc giống như hàm fputc().Điểm khác biệt duy nhất giữa chúng là hàm fputs() cho phép ghi toàn bộ chuỗi ký tự vào tập tin, trong khi fputc() chỉ cho phép ghi từng ký tự một. Nguyên mẫu của hàm này như sau:
int fputs (const char *str, FILE *fp);
Trong đó str là chuỗi kýtự được ghi vào tập tin, fp là con kiểu FILE, trỏ đến
tập tin đã
được bằng lệnh fopen() mở với chế độ mở để ghi dữ liệu (w/w+/a). Hàm sẽ trả về
một giá trị
nguyên dương nếu việc ghi thành công. Ngược lại, giá trị EOF sẽ được trả về nếu
có lỗi. Xem
xét ví dụ sau đây.
Ví dụ 8.6:
#includ e<stdio .h>
intmain ( void ){ FILE
*fi;
fi =
fopen("C:\\testps.txt",
"w"); if (fi == NULL){
printf("Can not open file to read!");
158
return 1;
}
fputs( "Hello world from fputs.\n", fi); fclose(fi);
}
Sau khi thực hiện xong, chương trình sẽ tạo ra một tập tin có tên testps.txt ở ổ
đĩa C có nội
dung là:
Hello world from fputs.
8.3.8 Hàm fgets()
Nhược điểm của hàm fscanf()là không đọc được những chuỗi kýtự có chứa
dấu cách -
space (dấu cách được coi là dấu phân tách giữa giá trị của các đối số). Để khắc phục điều này có thể sử dụng dụng hàm fgets().Hàm fgets()được sử dụng để đọc một chuỗi kýtự từ một file đã được mở. Nguyên mẫu của hàm như sau:
char *fgets (char *str, int n, FILE *fp);
Trong đó, str lưu chuỗi ký tự đọc được, n là số kýtự cần đọc, fp là con trỏ kiểu FILE, trỏ đến tập tin đã được bằng lệnh fopen() mở với chế độ để đọc (r).
Hàm fgets()sẽ đọc một chuỗi từ vị trí con trỏ tập tin hiện hành cho đến khi đọc
được một
ký tự sang dòng mới hoặc sau khi đã đọc được (n- 1) ký tự.Nếu đọc được một ký
tự sang dòng
mới, ký tự này được xem như là một phần của chuỗi. Chuỗi kết quả sẽ kết thúc
bằng ký tự
NULL (‘\0’). Hàm trả về một con trỏ trỏ đến chuỗi đọc được nếu thành công hoặc
NULL nếu
xảy ra lỗi.
Chương trình sau đây sẽ mở file testps.txt ở trên với chế độ để đọc (r), sau đó sử dụng hàm fgets() để đọc và hiển thị chuỗi kýtự đã được lưu trong file ra màn hình.
Ví dụ 8.7:
#includ e<stdio .h>
intmain ( void ){
FILE
*fo;
charline[100];
fo =
fopen("C:\\testps.txt",
"r"); if (fo == NULL){
printf("Can not open file to read!"); return 1;
}
if( fgets( line, 100, fo) == NULL)
printf( "fgets error\n" );
else
printf( "%
s", line);
fclose(fo);
}
Kết quả thực hiện của chương trình là chuỗi kí tự sau được hiển thị ra màn hình.
Hello world from fputs.
159