CÁC HÀM XỬ LÝ TẬP TIN

Một phần của tài liệu giáo trình lập trình C (Trang 324 - 338)

SỬ DỤNG HÀM TRONG C

CHƯƠNG 8 QUẢN LÝ TẬP TIN

8.5 CÁC HÀM XỬ LÝ TẬP TIN

Khi một tập tin được mở để đọc ở dạng nhị phân, một số nguyên có giá trị tương đương với EOF có thể được đọc. Trong trường hợp này, quá trình đọc sẽ cho rằng đã đến cuối tập tin, mặc dù chưa đến cuối tập tin thực sự. Một hàm feof() có thể được dùng để giải quyết những trường hợp này. Nguyên mẫu của hàm feof()như sau:

int feof (FILE *fp);

Trong đó fp là con trỏ kiểu FILE, trỏ đến tập tin nhị phân đã được mở bằng

lệnh fopen().

Hàm feof() trả về giá trị khác 0 nếu đã đến cuối tập tin. Ngược lại, sẽ trả về giá trị

0. Hàm này

rất hữu dụng trong việc đọc dữ liệu nhị phân và thường được sử dụng kết hợp với

các vòng lặp

while/do while:

While (!

feof(fp)){ //

Đọc dữ liệu }

Hoặc

do{

// Đọc dữ liệu }While (!

feof(fp));

Chương trình sau đây sẽ sử dụng hàm feof() để kiểm tra xem đã đọc đến cuối file test_feof.data hay chưa và hiện ra thông báo nếu việc đọc dữ liệu có lỗi.

Ví dụ 8.12:

#include<stdio.h>

int main( void ){

intcount, total = 0;

charbuffer [100];

FILE *fo;

fo =

fopen("C:\\test_feof.data","

rb"); if( fo == NULL ){

printf("Can not open file!"); exit(

1 );

while( !feof( fo )){ }

count = fread( buffer, sizeof( char ), 100, fo );

if( count==0 ) { printf("Read error" );

break;

}

total += count;

}

printf( "Number of bytes read =

%d\n", total ); fclose( fo );

}

164

8.5.2 Hàm rewind()

Hàm rewind()được sử dụng để đặt lại con trỏ định vị trí bên trong tập tin về đầu tập tin. Nó lấy con trỏ tập tin làm đối số. Nguyên mẫu của hàmrewind()như sau:

void rewind( FILE *stream);

Chương trình sau đây sẽ tạo/mở một file có tên là test_rewind.out ở ổ đĩa C, với chế độ đọc/ghi để ghi 2 số nguyên vào file. Sau đó sẽ sử dụng hàm rewind() để định vị con trỏ về đầu tập tin, đọc ngược trở lại dữ liệu từ file và hiển thị ra màn hình .

Ví dụ 8.13:

#includ e<stdio .h>

intmain () {

FILE *fi;

intx=10, y=-20;

fi = fopen("C:\\test_rewind.out","w+");

if( fi != NULL ) {

fprintf( fi, "%d %d", x, y);

printf( "The values written are: %d and

%d\n", x, y); rewind(fi);

fscanf( fi, "%d %d", &x, &y);

printf( "The values read are: %d and

%d\n", x, y); fclose( fi);

} }

Kết quả thực hiện của chương trình như sau:

The values written are:

10 and -20

The values read are: 10 and -20

8.5.3 Hàm ferror()

Hàm ferror() xác định liệu một thao tác trên tập tin có sinh ra lỗi hay không.

Nguyên mẫu của hàm là:

int ferror(FILE * fp) ;

Trong đó fp là một con trỏ tập tin hợp lệ. Hàm trả về một giá trị khác 0 nếu xảy ra lỗi trong các thao tác trên tập tin, ngược lại, trả về giá trị 0.

Chương trình sau đây sẽ sử dụng hàm ferror() để thay cho đoạn mã tự kiểm tra lỗi đọc dữ liệu ở ví dụ 8.7.

Ví dụ 8.14:

#include<stdio.h>

intmain( void ){

intcount,

total = 0;

charbuffer [100];

FILE *fo;

fo =

fopen("C:\\test_feof.data","

rb"); if( fo == NULL ){

printf("Can not open file!");

165

exit( 1 );

}

while( ! feof( fo ) )

{ count = fread( buffer, sizeof( char ), 100, fo );

if( ferror(fo) ) { perror( "Read error" );

break;

}

total += count;

}

printf( "Number of bytes read =

%d\n", total ); fclose( fo );

}

8.5.4 Hàm remove()

Hàm remove() được sử dụng để xóa một tập tin đã được tạo ra và lưu trên đĩa cứng. Nguyên mẫu của hàm remove() như sau:

int remove(const char *filename);

Trong đó filename là tên file cần xóa. Hàm remove() trả về giá trị 0 nếu xóa thành công, ngược lại, trả về giá trị khác 0.

Chương trình sau đây cho phép người dùng nhập vào một tên file cần xóa. Nếu xóa thành công chương trình sẽ hiện thông báo ra màn hình, nếu gặp một lỗi nào đó trong khi xóa file thì một thông báo sẽ được hiển thị ra stream lỗi chuẩn (stderr).

Ví dụ 8.15:

#include

<stdio.h

>

int main(voi d) {

char buffer[101];

printf("Name of file to

delete: ");

gets_s(buffer, 100);

if(remove(buffer) == 0)

printf("File %s

deleted.\n", buffer);

else

fprintf(stderr, "Error deleting the file %s.\n", buffer);

}

8.5.5 Hàm rename()

Hàm rename() được sử dụng để đổi tên một tập tin đã được tạo ra và lưu trên ổ đĩa cứng. Nguyên mẫu của hàm như sau:

int rename(const char *old_name, const char *new_name);

Trong đó old_name là tên cũ và new_name là tên mới của tập tin. Cần chú ý

rằng phải đóng tập tin trước khi gọi hàm rename(), không thể đổi tên một tập tin nếu nó đang mở. Hàm trả về giá trị 0 nếu đổi tên thành công, ngược lại một giá trị khác 0 sẽ được trả về. Xét ví dụ sau.

Ví dụ 8.16:

#includ e<stdio .h>

intmain (void)

166

{ char old_name[101], new_name[101];

printf("Current filename: ");

gets(old_name);

printf("New filename: ");

gets(new_name);

if(rename(old_name, new_name) == 0)

printf("Successful rename!"; else

fprintf(stderr, "Error renaming %s.\n", old_name);

}

Chương trình trên cho phép người dùng nhập vào các tên cũ và mới của một tập tin, sau đó sử dụng hàm rename()để đổi tên cũ thành tên mới cho tập tin đó.

8.5.6 Hàm fflush()

Thông thường, các tập tin xuất chuẩn được trang bị vùng đệm. Điều này có nghĩa là kết xuất cho tập tin được thu thập trong bộ nhớ và không thật sự hiển thị cho đến khi vùng đệm đầy. Nếu một chương trình bị treo hay kết thúc bất thường, một số ký tự vẫn còn nằm trong vùng đệm. Kết quả là chương trình có vẻ như kết thúc sớm hơn là nó thật sự đã làm. Hàm fflush() sẽ giải quyết vấn đề này, nó sẽ làm sạch vùng đệm và chép những gì có trong vùng đệm ra ngoài. Hành động làm sạch tùy theo kiểu tập tin. Một tập tin được mở để đọc sẽ có vùng đệm nhập trống, trong khi một tập tin được mở để ghi thì vùng đệm xuất của nó sẽ được ghi vào tập tin. Hàm fflush() có nguyên mẫu như sau:

int fflush(FILE * fp);

Trong đó fp là một con trỏ tập tin hợp lệ. Hàm fflush() sẽ ghi nội dung của bất kỳ vùng đệm dữ liệu nào vào tập tin kết hợp với fp. Hàm fflush(), không có đối số, sẽ làm sạch tất cả các tập tin đang mở để xuất.

Hàm sẽ trả về giá trị 0 nếu vùng đệm được làm sạch thành công. Giá trị 0 cũng được trả về trong trường hợp tập tin không có vùng đệm hoặc được mở với chế độ chỉ đọc. Nếu việc làm sạch vùng đệm không thành công, hàm sẽ trả về giá trị EOF.

Hàm fflush() cũng thường xuyên được sử dụng để làm sạch bộ đệm nhập chuẩn (stdin) trong trường hợp các kýtự hoặc chuỗi kýtự được nhập ngay sau khi nhập các giá trị số. Trong những trường hợp này, nếu không có thao tác làm sạch bộ đệm thì dấu xuống dòng (enter) sau mỗi giá trị số sẽ được gán cho các biến kýtự, chuỗi kýtự cần nhập ngay sau đó. Vì vậy, nó sẽ bỏ qua không yêu cầu nhập giá trị cho các biến này.

Chương trình sau đây sẽ sử dụng hàm fflush() để làm sạch bộ đệm nhập chuẩn trong khi nhập dữ liệu từ bàn phím.

Ví dụ 8.17:

#includ e<stdio

.h>

int main(vo id) {

intx;

doubled;

charch, str[80];

167

printf("\nEnter an integer number: "); scanf("%d",&x);

fflush(stdin);

printf("\nEnter a character: ");

scanf("%c",&ch);

printf("\nEnter a double

number: ");

scanf("%lf",&d);

fflush(stdin);

printf("\nEnter a string: ");

gets(str);

printf("\n--- ---\n"); printf("%d\n",x);

printf("%

c\n",ch);

printf("%

lf\n",d);

printf("%

s\n",str)

;getch();

}

Nếu không có lệnh làm sạch bộ đệm fflush() ở phía trước thì các câu lệnh nhập kýtự ch và nhập chuỗi str có thể sẽ bị bỏ qua.

8.5.7 Hàm ftell()

Để lần theo vị trí nơi mà các thao tác nhập/xuất đang diễn ra, một con trỏ được duy trì trong cấu trúc FILE. Mỗi khi một ký tự được đọc ra hay ghi vào một stream, con trỏ kích hoạt hiện hành được tăng lên. Hầu hết các hàm nhập xuất đều tham chiếu đến con trỏ này, và cập nhật nó sau các thủ tục nhập hoặc xuất trên stream.

Hàm ftell() được sử dụng để xác định vị trí của con trỏ tập tin hiện hành.

Nguyên mẫu của hàm như sau:

long int ftell(FILE *fp);

Trong đó fp là một con trỏ tập tin hợp lệ. Hàm ftell() trả về một giá trị kiểu

long int xác

định vị trí của con trỏ tập tin hiện hành tính từ đầu tập tin trong stream đã cho.

Xét ví dụ sau

đây.

Ví dụ 8.18:

#includ e<stdio .h>

int main( v oid ){

FILE

*fo;

longpos;

charstr[100];

fo =

fopen("c:\\test_ftell.data","

rb"); if (fo!=NULL) {

// Move the pointer by reading data: fread( str, sizeof( char ), 100, fo); // Get position after read:

pos = ftell(fo);

printf("Position after read:

%ld\n",pos); fclose(fo);

} }

168

Chương trình trên mở một tập tin nhị phân có tên test_ftell.data trên ổ đĩa C, với chế độ để đọc. Đầu tiên, chương trình sẽ đọc 100 kýtự từ tập tin, sau đó sử dụng hàm ftell() để xác định vị trí con trỏ tập tin hiện hành và hiển thị giá trị đó ra màn hình.

8.5.8 Hàm fseek()

Hàm fseek() được sử dụng để định lại vị trí của con trỏ tập tin hiện hành dời đi một số byte tính từ đầu, từ vị trí hiện hành hay từ cuối stream là tùy vào vị trí được qui định khi gọi hàm fseek(). Nguyên mẫu của hàm fseek() là:

int fseek( FILE *fp, long offset, int origin );

Trong đó fp là một con trỏ tập tin hợp lệ, offset là số byte cần di chuyển vượt

qua vị trí tập

tin được cho bởi tham số origin. Tham số originchỉ định vị trí bắt đầu tìm kiếm và

phải có giá

trị là 0, 1 hoặc 2, biễu diễn cho 3 hằng ký hiệu (được định nghĩa trong stdio.h) như trong Bảng

8. 4:

Origin Vị trí tập tin

SEEK_SET hoặc 0 Đầu tập tin

SEEK_CUR hoặc 1 Vị trí con trỏ của tập tin hiện hành SEEK_END hoặc 2 Cuối tập tin

Bảng 8. 4: Các hằng giá trị của tham số origin.

Hàm fseek() trả về giá trị 0 nếu thành công và giá trị khác 0 nếu thất bại. Xem xét chương trình ví dụ sau:

Ví dụ 8.19:

#includ e<stdio .h>

int main( v oid) { FILE

*fi;

char line[

100];

int resul t;

fi =

fopen("C:\\test_fseek.txt",

"w+"); if (fi==NULL){

printf( "The file fseek.txt was not opened\n" ); return 1;

}

fprintf( fi, "Begins here: This is the first line.\n" ); result = fseek( fi, 13L, SEEK_SET);

if( result ) perror( "Fseek failed" );

else{

printf("File pointer is set to middle of the line\n" ); fgets( line, 100, fi );

printf( "%s", line );

}fclose( fi );

}

Chương trình trên sẽ mở một tập tin có tên là test_fseek.txt trên ổ đĩa C và

ghi vào file

chuỗi kýtự "Begins here: This is the first line.\n", sau đó sử dụng hàm fseek()

để dịch

chuyển con trỏ tập tin hiện hành 13 byte tính từ đầu tập tin. Do kiểu kýtự có kích

thước 1 byte

nên sau khi dịch chuyển 13 byte, con trỏ tập tin hiện hành sẽ trỏ tới vị trí của kýtự thứ 14 được

169

lưu trong tập tin (kýtự ‘T’) và hàm fprintf() sẽ đọc từ vị trí đó cho đến khi gặp

dấu xuống

dòng.

Kết quả thực hiện của chương trình như sau:

File pointer is set to middle of the line This is the first line.

8.5.9 Các stream chuẩn

Mỗi chương trình C chạy trên DOS được hệ điều hành cung cấp 5 stream đặc biệt là:  Nhập chuẩn (stdin).

 Xuất chuẩn (stdout).

 Lỗi chuẩn(stderr).

 Máy in chuẩn (stdprn).

 Thiết bị hỗ trợ chuẩn (stdaux) .

Trong đó, stdin, stdout và stderr được gán mặc định cho các thiết bị nhập/xuất

chuẩn của

hệ thống, stdprn được gán cho cổng in song song đầu tiên và stdaux được gán cho

cổng nối

tiếp đầu tiên. Chúng được định nghĩa như là các con trỏ cố định kiểu FILE, vì vậy

chúng có

thể được sử dụng ở bất kỳ nơi nào mà việc sử dụng con trỏ FILE là hợp lệ. Chúng

cũng có thể

được chuyển một cách hiệu quả cho các stream hay thiết bị khác mỗi khi cần định hướng lại.

170

Một phần của tài liệu giáo trình lập trình C (Trang 324 - 338)

Tải bản đầy đủ (DOCX)

(339 trang)
w