để di chuyển con trỏ tệp trên dòng xuất, chúng ta sử dụng các phương thức sau
(của lớp ostream) :
1. Phương thức: ostream& seekp(long n) ;
sẽ chuyển con trỏ tệp tới vị trắ (byte) thứ n (số thứ tự các byte tắnh từ 0). 2. Phương thức: ostream& seekp(long offset, seek_dir dir) ;
sẽ chuyển con trỏ tệp tới vị trắ offset kể từ vị trắ xuất phát dir. Giá trị của offset có thể âm, còn dir có thể nhận một trong các giá trị sau:
ios::beg xuất phát từ ựầu tệp ios::end xuất phát từ cuối tệp
ios::cur xuất phát từ vị trắ hiện tại của con trỏ tệp 3. Phương thức teelp() ;
cho biết vị trắ hiện tại của con trỏ tệp.
để di chuyển con trỏ tệp trên dòng nhập, chúng ta sử dụng các phương thức sau
(của lớp istream):
4. Phương thức: istream& seekg(long n) ;
sẽ chuyển con trỏ tệp tới vị trắ (byte) thứ n (số thứ tự các byte tắnh từ 0) 5. Phương thức: istream& seekg(long offset, seek_dir dir) ;
sẽ chuyển con trỏ tệp tới vị trắ offset kể từ vị trắ xuất phát dir. Giá trị của offset có
thể âm, còn dir có thể nhận một trong các giá trị sau: ios::beg xuất phát từ ựầu tệp
ios::end xuất phát từ cuối tệp
ios::cur xuất phát vị trắ hiện tại của con trỏ tệp 6. Phương thức: teelg() ;
cho biết vị trắ hiện tại của con trỏ tệp.
để di chuyển con trỏ tệp trên dòng nhập-xuất, chúng ta có thể sử dụng cả sáu
phương thức nêu trên.
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á.
// ghi - ựọc ựồng thời #include <iostream.h> #include <iomanip.h> #include <fstream.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: " ; 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();
cout << "\nThi sinh thu: " << stt ; cout << "\nHo ten: "<< ht;
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"; }
ậ 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:
+ Mở một tệp ựể ựọc nhưng tệp không tồn tại. + đọc dữ liệu nhưng con trỏ tệp ựã ở cuối tệp + Ghi dữ liệu nhưng hết không gian ựĩa (ựĩa ựầy).
+ Tạo tệp nhưng ựĩa hỏng, hoặc ựĩa cấm ghi hoặc ựĩa ựầy. + Dùng tên tệp không hợp lệ
+ đị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: 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: 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: 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: 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: 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())
{
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) ;