Giáo trình C - Chương 3: Nhập và xuất dữ liệu

Tr-ớc đây chúng ta đã xét việc nhập dữ liệu từ bàn phím. Trong nhiều tr-ờng

hợp thực tế , để thuận lợi , chúng ta phải nhập dữ liệu từ các tập tin trên đĩa . Các hàm th-

viện của C cho phép truy cập tập tin và chia là 2 cấp khác nhau :

- các hàm cấp 1 là các hàm ở cấp thấp nhất , truy cập trực tiếp đến các tập tin trên

đĩa.C không cung cấp vùng nhớ đệm cho các hàm này

- các hàm cấp 2 là các hàm truy xuất tập tin cao hơn , do chúng đ-ợc C cung cấp

vùng nhớ đệm

 Đối với các hàm cấp 1 , tập tin đ-ợc xem là khối các byte liên tục do đó khi muốn

truy cập mẫu tin cụ thể thì phải tính toán địa chỉ của mẫu tin và nh-vậy công việc vất vả

hơn . Ngoài ra phải cung cấp vùng nhớ đệm cho kiểu đọc ghi này. Đối với các hàm cấp hai

công việc nhẹ nhàng hơn do :

- trình biên dịch tự động cung cấp vùng kí ức đệm cho chúng

- có thể truy xuất các mẫu tin mà không gặp khó khăn nh-với các hàm cấp 1

Trong C , các thông tin cần thiết cho các hàm xuất nhập cấp 2 đ-ợc đặt trong tập tin

stdio.h còn các thông tin về hàm nhập xuất cấp 1 thì ở trong tập tin io.h

pdf24 trang | Chuyên mục: C/C++ | Chia sẻ: dkS00TYs | Lượt xem: 1911 | Lượt tải: 0download
Tóm tắt nội dung Giáo trình C - Chương 3: Nhập và xuất dữ liệu, để xem tài liệu hoàn chỉnh bạn click vào nút "TẢI VỀ" ở trên
tập tin 
ngẫu nhiên là : 
 rewind() : di chuyển con trỏ tập tin về đầu tập tin 
 Cú pháp : void rewind(FILE *fp); 
 fseek() : di chuyển con trỏ tập tin về vị trí mong muốn 
 Cú pháp : int fseek(FILE *fp , long sb , int xp) 
 fp - con trỏ tập tin 
 sb - số byte cần di chuyển 
38
 xp - vị trí xuất phát mà việc dịch chuyển đ−cợ bắt đầu từ đó . xp có thể có các 
giá trị sau : 
 xp=SEEK_SET hay 0 : xuất páht từ đầu tập tin 
 xp=SEEK_CUR hay 1 : xuất phát từ vị trí con trỏ hiện tại 
 xp=SEEK_END hay 2 : xuất páht từ cuối tập tin 
 ftell() : cho biết vị trí hiện tại của con trỏ tập tin 
Ta xét ch−ơng trình ví dụ sau : 
Ch−ơng trình 3-19 : 
#include 
#include 
#include 
void main() 
 { 
 struct nguoi { 
 char ten[30]; 
 int so; 
 float cao; 
 }nv; 
 int recno; 
 FILE *fp; 
 long int offset; 
 clrscr(); 
 if ((fp=fopen("nhanvien.rec","r"))==NULL) 
 { 
 printf("Khong mo duoc file\n"); 
 getch(); 
 exit(1); 
 } 
 printf("Ban muon doc ban ghi thu may : "); 
 scanf("%d",&recno); 
 recno--; 
 offset=recno*sizeof(nv); 
 if (fseek(fp,offset,0)!=0) 
 { 
 printf("Khong di chuyen duoc con tro file toi do\n"); 
 getch(); 
 exit(1); 
 } 
 fread(&nv,sizeof(nv),1,fp); 
 printf("Ten :%s\n",nv.ten); 
 printf("Ma nhan vien : %3d\n",nv.so); 
 printf("Chieu cao :%4.2f\n",nv.cao); 
 getch(); 
 } 
Đ5. Lỗi vào ra 
 Nói chung , khi mở tập tin thành công ta có thể ghi lên nó . Tuy nhiên , nhiều tr−ờng 
hợp không mở đ−ợc tập tin nh−ng ta không biết lỗi do đâu . Để xác định llõi ta dùng hàm 
39
ferror() . Hàm này có đối số là con trỏ tập tin . Hàm sẽ có giá trị không nếu không có lỗi gì . 
Ng−ợc lại hàm cho giá trị khác không . Ta cũng có thể dùng hàm perror() để chỉ nội dung 
lỗi . 
Ch−ơng trình 3-20 : 
#include 
#include 
#include 
#include 
void main() 
 { 
 FILE *fp; 
 char name[40],numstr[10]; 
 int code; 
 float height; 
 int n,i; 
 clrscr(); 
 fp=fopen("a:\newfile.txt","w"); 
 printf("Cho so nguoi can nhap : "); 
 gets(numstr); 
 n=atoi(numstr); 
 for (i=0;i<n;i++) 
 { 
 printf("Nhap ten : "); 
 gets(name); 
 printf("Nhap ma so : "); 
 gets(numstr); 
 code=atoi(numstr); 
 printf("Nhap chieu cao : "); 
 gets(numstr); 
 height=atof(numstr); 
 fprintf(fp,"%s %d %f",name,code,height); 
 if (ferror(fp)) 
 { 
 perror("Loi ghi file "); 
 getch(); 
 exit(1); 
 } 
 } 
 fclose(fp); 
 } 
 Sau lỗi do ta ghi , trình biên dịch sẽ thông báo lỗi cụ thể trong câu “ Loi ghi file : no 
such file ỏ directory” 
Đ6. Vào ra ở mức hệ thống 
1.Các tập tin tiêu đề và biến chuẩn : Trong cách vào ra ở mức hệ thống , ta phải khởi tạo 
bộ đệm rồi đặt dữ liệu vào đó tr−ớc ghi hay đọc . Vào ra ở mức hệ thống có lợi ở chỗ l−ợng 
mã ít hơn vào ra chuẩn và tốc độ sẽ nhanh hơn . Để dùng các hàm cấp 1 ta phải cần các tập 
tin tiêu đề sau : 
40
 io.h - chứa các prototype của các hàm cấp 1 
 fcntl.h - chứa các định nghĩa quyền truy cập 
 sys/stat.h - chá các định nghĩa thuộc tính 
 dó.h - chứa các thuộc tính theo DOS 
2. Tóm tắt các hàm : creat - tạo tập tin mới 
 _creat - tạo tập tin mới theo kiểu nhị phân 
 open - mở tập tin 
 _open - mở tập tin đã tồn tại 
 close và _close - đóng tập tin 
 chmod - thay đổi thuộc tính của tập tin 
 _chmode - thay đổi thuộc tính của tập tin theo kiểu DOS 
 perror - thông báo lỗi (stdlib.h) 
 write - ghi một dãy các byte 
 read - đọc một dãy các byte 
 lseek - dùng di chuyển con trỏ vị trí 
3. Đọc tập tin theo cách vào ra hệ thống : Ta có ch−ơng trình đọc tập tin từ đĩa và hiển thị 
lên màn hình theo cách vào ra hệ thống . 
Ch−ơng trình 3-21 : 
#include 
#include 
#include 
#include 
#include 
#define BUFFSIZE 512 
char buff[BUFFSIZE]; 
void main(int argc,char *argv[]) 
 { 
 int inhandle,bytes,i; 
 clrscr(); 
 if (argc!=2) 
 { 
 printf("Dang "); 
 getch(); 
 exit(1); 
 } 
 if ((inhandle=open(argv[1],O_RDONLY|O_BINARY))<0) 
 { 
 printf("Khong mo duoc file\n"); 
 getch(); 
 exit(1); 
 } 
 while ((bytes=read(inhandle,buff,BUFFSIZE))>0) 
 for (i=0;i<bytes;i++) 
 putch(buff[i]); 
 close(inhandle); 
 } 
4. Khởi tạo bộ đệm : Trong ch−ơng trình ta phải định nghĩa bộ đệm bằng phát biểu 
 #define BUFFSIZE 512 
 char buff[BUFFSIZE] 
41
Nhờ đó ta đọc đ−ợc dữ liệu từ đĩa vào bộ đệm buff . Với DOS , kích th−ớc bộ đệm nên chọn 
là bội số của 512. 
5. Mở một tập tin : Cũng giống nh− vào ra bằng hàm cấp 2 , ta phải mở tập tin tr−ớc khi 
đọc hay ghi bằng phát biểu : 
 inhandle=open(argv[1],O_RDONLY | O_BINARY); 
Biểu thức này thiết lập sự liên lạc giữa tập tin và hệ điều hành . Trong biểu thức ta cần một 
hằng lag oflag là dấu hiệu cho biết mức độ dùng tập tin . 
oflag ý nghĩa 
O_APPEND Đặt con trỏ ở cuối tập tin 
O_CREAT Tạo tập tin mới để ghi(không có hiệu quả nếu tập tin đã có ) 
O_RDONLY Mở một tập tin để chỉ đọc 
O_RDWR Mở một tập tin để chỉ đọc hay ghi 
O_TRUNC Mở và cắt bỏ bớt tập tin 
O_WRONLY Mở tập tin để ghi 
O_BINARY Mở tập tin kiểu nhị phân 
O_TEXT Mở tập tin kiểu văn bản 
6. Danh số của tập tin : Trong vào ra chuẩn , con trỏ tập tin sẽ nhận đ−ợc ngay khi gọi hàm 
fopen() còn trong nhập xuất bằng hàm cấp 1 ta nhậ đ−ợc giá trị nguyên gọi là danh số của 
tập tin . Đây là số gán cho một tập tin cụ thể để tham chiếu đến tập tin này . Nếu hàm open() 
cho ta giá trị -1 nghĩa là danh số không đúng và phát sinh lỗi . 
7. Đọc tập tin vào bộ đệm : Để đọc tập tin vào bộ đệm ta dùng lệnh : 
 byte = read(inhandle , buff , BUFSIZE); 
Hàm này có 3 đối số : danh số của tập tin , địa chỉ của bộ đệm và số byte cực đại cần đọc . 
Giá trị của hàm read() chỉ ra số byte đã đọc đ−ợc . 
8. Đóng tập tin : Để đóng tập tin ta dùng lệnh 
 close(inhandle); 
9. Thông báo lỗi : Khi hàm open() cho giá trị -1 , nghĩa là có lỗi . Dạng lỗi sẽ đ−ợc đọc 
bằng perror() . Ta có ch−ơng trình ví dụ 
Ch−ơng trình 3-22 : 
#include 
#include 
#include 
#include 
#include 
#define BUFFSIZE 512 
char buff[BUFFSIZE]; 
void main(int argc,char *argv[]) 
 { 
 int inhandle,bytes,i; 
 clrscr(); 
 if (argc!=2) 
 { 
 printf("Dang "); 
 getch(); 
 exit(1); 
 } 
 if ((inhandle=open(argv[1],O_RDONLY|O_BINARY))<0) 
42
 { 
 perror("Khong mo duoc file\n"); 
 getch(); 
 exit(1); 
 } 
 while ((bytes=read(inhandle,buff,BUFFSIZE))>0) 
 for (i=0;i<bytes;i++) 
 putch(buff[i]); 
 close(inhandle); 
 } 
10. Thao tác trên bộ đệm : Việc đ−a tập tin vào bộ đệm có lợi là cho phép truy cập trên bộ 
đệm thay vì trên tập tin . Làm nh− vậy nhanh hơn truy cập trên đĩa . 
Ch−ơng trình sau cho phép tìm một từ trong một tập tin văn bản . 
Ch−ơng trình 3-23 : 
#include 
#include 
#include 
#include 
#include 
#include 
#define BUFFSIZE 1024 
char buff[BUFFSIZE]; 
void main(int argc,char *argv[]) 
 { 
 int inhandle,bytes; 
 void search(char *,int); 
 clrscr(); 
 if (argc!=3) 
 { 
 printf("Dang "); 
 getch(); 
 exit(1); 
 } 
 if ((inhandle=open(argv[1],O_TEXT))<0) 
 { 
 printf("Khong mo duoc file %s\n",argv[1]); 
 getch(); 
 exit(1); 
 } 
 while ((bytes=read(inhandle,buff,BUFFSIZE))>0) 
 search(argv[2],bytes); 
 close(inhandle); 
 printf("Khong tim thay"); 
 getch(); 
 } 
void search(char *cau,int buflen) 
 { 
43
 char *p,*ptr; 
 ptr=buff; 
 while ((ptr=memchr(ptr,cau[0],buflen))!=NULL) 
 if (memcmp(ptr,cau,strlen(cau))==0) 
 { 
 printf("Tu xuat hien lan dau trong cau tai vi tri %d:\n",ptr-buff+1); 
 for (p=ptr;p<ptr+strlen(cau);p++) 
 putch(*p); 
 exit(1); 
 } 
 else 
 ptr++; 
 } 
11. Hàm dùng bộ đệm : Hàm search() là ch−ơng trình con minh hoạ cách dùng bộ đệm . Ta 
có một hàm memchr() dạng : 
 ptr = memchr(ptr , cau[0] , buflen); 
Hàm này dùng để tìm vị trí của kí tự cau[0] trong chuỗi chỉ bởi ptr và độ f\dài của phần cần 
tìm trong bộ đệm là buflen . Ch−ơng trình sẽ truyền argv[2] cho cau . Hàm này cho giá trị 
NULL khi không tìm thấy kí tự cần tìm . Ng−ợc lại nó sẽ cho địa chỉ của kí tự đã tìm thấy 
trong bộ đệm . Việc so sánh các chuỗi cau và chuỗi ptr đ−ợc tiến hành nhờ hàm memcmp 
trong câu lệnh : 
 if ((memcmp(ptr,cau,strlen(cau))==0) 
Hàm này cũng có 3 đối số là : chuỗi thu nhất ptr , chuỗi thu hai cau và đo dai can so sanh 
strlen(cau) 
12. Ghi lên tập tin : Ghi thông tin lên tập tin phức tạp hơn đọc từ tập tin . Ta có ch−ơng 
trình ví dụ sau dùng để chép từ một tập tin này sang tập tin khác. 
Ch−ơng trình 3-24 : 
#include 
#include 
#include 
#include 
#include 
#include 
#define BUFFSIZE 4096 
char buff[BUFFSIZE]; 
void main(int argc,char *argv[]) 
 { 
 int inhandle,outhandle,bytes; 
 clrscr(); 
 if (argc!=3) 
 { 
 printf("Dang "); 
 getch(); 
 exit(1); 
 } 
 if ((inhandle=open(argv[1],O_RDWR|O_BINARY))<0) 
 { 
44
 printf("Khong mo duoc file %s\n",argv[1]); 
 getch(); 
 exit(1); 
 } 
 if ((outhandle=open(argv[2],O_CREAT|O_WRONLY|O_BINARY,S_IWRITE))<0) 
 { 
 printf("Khong mo duoc file %s\n",argv[2]); 
 getch(); 
 exit(1); 
 } 
 while ((bytes=read(inhandle,buff,BUFFSIZE))>0) 
 write(outhandle,buff,bytes); 
 close(inhandle); 
 close(outhandle); 
 printf("Da chep xong"); 
 getch(); 
 } 
 Trong ví dụ trên ta mở một lúc 2 tập tin với danh số là inhamdle và outhandle Biểu 
thức mở tập tin nguồn không có gì đặc biệt còn biểu thức mở tập tin đích có dạng : 
outhandle = open(argv[2] ,O_CREAT | O_WRONLY | O_BINARY , S_IWRITE) 
với O_CREAT để tạo tập tin trên đĩa 
 O_WRONLY để chỉ ghi lên tập tin 
 O_BINARY để mở tập tin theo kiểu nhị phân 
Khi mở tập tin với O_CREAT , đối thứ 3 của open() là một trong 3 trị : 
 S_IWRITE : chỉ cho phép ghi lên tập tin 
 S_IREAD : chỉ cho phép đọc từ tập tin 
 S_IWRITE | S_IREAD : cho phép đọc và ghi lên tập tin 
Để dùng các trị này phải khai báo #include sau khai báo 
#include . Hàm write() có đối t−ơng tự nh− read() . Trong vòng lặp while hàm 
read() báo số byte đọc đ−ợc qua biến bytes và hàm write() sẽ biết số bytes cần ghi vào tập 
tin đích . Trong ch−ơng trình ta dùng bộ đệm với kích th−ớc khá lớn để ch−ơng trình chạy 
nhanh . 

File đính kèm:

  • pdfGiao_Trinh_C_Chuong3.pdf
Tài liệu liên quan