13.4. Ví dụ
Ví dụ 1. Trong Đ12 đã viết chương trình xác định độ dài của tệp TC.EXE. Dưới đây là một phương án khác đơn giản hơn:
fstream f(“TC.EXE”); f.seekg(0,ios::end); do_dai = f.teelg();
Ví dụ 2. Chương trình dưới đây sẽ nhập danh sách n thí sinh từ bàn phím và ghi lên tệp. Sau đó đưa con trỏ tệp về đầu tệp và bắt đầu đọc dữ liệu thí sinh từ tệp để in ra màn hình. Thông tin thí sinh gồm: Họ tên, tỉnh hoặc thành phố cư trú, số báo danh, các điểm toán lý hoá.
//CT7_13.CPP // ghi - đọc đồng thời #include <iostream.h> #include <iomanip.h> #include <fstream.h> #include <conio.h> #include <stdlib.h> #include <ctype.h> #include <stdio.h> void main() {
char ht[25], ttinh[21], ttep[40]; int sobd,stt ;
float dt, dl, dh, td; fstream f;
cout << "\nTen tep: " ; 422
cin >> ttep;
f.open(ttep,ios::out|ios::in|ios::noreplace); if (f.bad())
{
cout << "\nTep " << ttep << " da ton tai"; cout << "\nCo ghi de? - C/K";
int ch=getch(); if (toupper(ch)=='C') { f.close(); f.open(ttep,ios::out|ios::in|ios::trunc) ; } else exit(1); } stt=0 ; f << setprecision(1) << setiosflags(ios::showpoint); while(1) { ++stt;
cout << "\nNhap thi sinh thu: " << stt ;
cout << "\nHo ten (neu rong thi ket thuc nhap) : "; cin.ignore();
cin.getline(ht,25); if (ht[0]==0) break;
cout << "Tinh - thanh pho: "; cin.getline(ttinh,21);
cout << "SoBD, diem toan, diem ly, diem hoa: " ; cin >> sobd >> dt>> dl >> dh ;
td = dt + dl + dh ; if (stt>1) f << endl;
f << setw(24) << ht << setw(20) << ttinh ; f << endl << setw(6) << sobd
<< setw(6) << dt << setw(6) << dl << setw(6) << dh << setw(6) << td ; } f.seekg(0); stt=0; clrscr();
cout << "\nDanh sach thi sinh\n"; cout << setprecision(1) << setiosflags(ios::showpoint); while(1) { f.getline(ht,25).getline(ttinh,21); if (f.eof()) break; ++stt; f >> sobd >> dt >> dl >> dh >> td; f.ignore(); 424
cout << "\nThi sinh thu: " << stt ; cout << "\nHo ten: "<< ht;
cout << " \nTinh - thanh pho: " << ttinh; cout << "\nSo bao danh: " << sobd;
cout << "\nDiem toan, ly, hoa va tong diem: " <<setw(6)<< dt << setw(6) <<dl << setw(6) << dh << setw(6) << td ;
}
f.close();
cout << "\n Hoan thanh"; getch();
}
Đ 14. Xử lý lỗi
Khi làm việc với tệp không phải mọi việc đều trôi chẩy mà thường xẩy ra nhiều điều trục trặc, chẳng hạn: 1. Mở một tệp để đọc nhưng tệp không tồn tại.
2. Đọc dữ liệu nhưng con trỏ tệp đã ở cuối tệp 3. Ghi dữ liệu nhưng hết không gian đĩa (đĩa đầy).
4. Tạo tệp nhưng đia hỏng, hoặc đĩa cấm ghi hoặc đĩa đầy. 5. Dùng tên tệp không hợp lệ
6. Định thực hiện một thao tác nhưng tệp lại không được mở ở mode phù hợp để thực hiện thao tác đó.
Tóm lại khi làm việc với tệp thường gặp nhiều lỗi khác nhau, nếu không biết cách phát hiện xử lý thì chương trình sẽ dẫn đến rối loạn hoặc cho kết quả sai. Trong lớp ios của C++ có nhiều phương thức cho phép phát hiện lỗi khi làm việc với tệp. Đó là:
1. Phương thức
int eof() ;
Nếu con trỏ tệp đã ở cuối tệp mà lại thực hiện một lệnh đọc dữ liệu thì phương thức eof() trả về giá trị khác không, trái lại phương thức có giá trị bằng 0.
2. Phương thức
int fail() ;
Phương thức fail() trả về giá trị khác không nếu lần nhập xuất cuối cùng có lỗi, trái lại phương thức có giá trị bằng 0.
3. Phương thức
int bad() ;
Phương thức bad() trả về giá trị khác không khi một phép nhập xuất không hợp lệ hoặc có lỗi mà chưa phát hiện được, trái lại phương thức có giá trị bằng 0.
4. Phương thức
int good() ;
Phương thức good() trả về giá trị khác không nếu mọi việc đều tốt đẹp ( không có lỗi nào xẩy ra). Khi có một lỗi nào đó thì phương thức có giá trị bằng 0.
5. Phương thức
void clear() ;
dùng để tắt tất cả các bit lỗi.
Ví dụ 1. Khi mở tệp để đọc cần kiểm tra xem tệp có tồn tại không. Để làm điều đó, chúng ta có thể dùng đoạn chương sau:
char ten_tep[40] ;
cout << “\n Cho biết tên tệp: “ ; cin >> ten_tep ;
ifstream f(ten_tep); if (f.bad())
{ 426
cout << “\n Tệp << ten_tep << “không tồn tại” ; exit(1) ;
}
Ví dụ 2. Khi tạo tệp mới để ghi cần kiểm tra xem có tạo được tệp hay không. Để làm điều đó, chúng ta có thể dùng đoạn chương sau:
char ten_tep[40] ;
cout << “\n Cho biết tên tệp: “ ; cin >> ten_tep ;
ofstream f(ten_tep); if (f.bad())
{
cout << “\n Không tạo được tệp << ten_tep ; exit(1) ;
}
Ví dụ 3. Để xác định độ dài của tệp, có thể dùng phương thức eof() và thuật toán sau: + Đọc một byte (chú ý phải đọc theo kiểu nhị phân)
+ Nếu việc đọc thành công ( eof()=0 ) thì cộng thêm một vào bộ đếm. Nếu việc đọc không thành ( eof() != 0 ) thì kết thúc vùng lặp.
Thuật toán trên được thể hiện bằng đoạn chương trình sau: ifstream f(ten_tep, ios::in | ios::binary) ;
long dem = 0 ; char ch; while (1) { f.get(ch) ; if (!eof()) dem++ ; else break; }
Đ 15. Nhập xuất nhị phân 15.1. Chọn kiểu nhập xuất nhị phân
Kiểu nhập xuất mặc định là văn bản. Để chọn kiểu nhập xuất nhị phân, thì trong tham số mode (của hàm tạo dạng 2 và phương thức open) cần chứa giá trị:
ios::binary
Ví dụ muốn mở tệp “DSTS.DL” để đọc-ghi theo kiểu nhị phân và gắn tệp với dòng nhập-xuất fs , ta dùng câu lệnh sau:
fstream fs(“DSTS.DL” , ios::in | ios::out | ios::binary) ;