Đọcghiđồngthờitrêntệp 13.1. Lớp fstream Để đọcghiđồngthờitrên tệp, chúng ta sử dụng lớp fstream. Lớp fstream thừa kế các phương thức của các lớp ofstream và ifstream. Ngoài ra lớp fstream có các hàm tạo và phương thức sau: 1. Hàm tạo: fstream() ; // Không đối dùng để tạo một đối tượng fstream (dòng nhập-xuất), chưa gắn với tệp. 2. Hàm tạo: fstream(const char *fn, int mode, int prot = filebuf::openprot); dùng để tạo một đối tượng fstream, mở tệp có tên fn và gắn đối tượng vừa tạo với tệp được mở. + Tham số fn cho biết tên tệp. + Tham số mode quy định các kiểu truy nhập và có thể là tổ hợp của các giá trị sau: ios::binary đọc-ghi theo kiểu nhị phân (mặc định theo kiểu văn bản). ios::out ghi tệp, nếu tệp đã có thì nó bị xoá ios::in đọctệp ios::app ghi bổ sung vào cuối tệp ios::ate chuyển con trỏ tệp về cuối sau khi mở ios::trunc xoá nội dung của tệp nếu nó tồn tạI ios::nocreate nếu tệp chưa có thì không làm gì (bỏ qua) ios::noreplace nếu tệp đã có thì không làm gì (bỏ qua) Chú ý: + Tham số mode không có giá trị mặc định. + Tham số thứ ba prot quy định cấp bảo vệ của dòng tin, tham số này có thể bỏ qua vì nó đã được gán một giá trị mặc định. 3. Hàm tạo: fstream(int fd); dùng để tạo một đối tượng fstream và gắn nó với một tệp có chỉ số fd đang mở. (Để mở và lấy chỉ số (số hiệu) tệp có thể dùng hàm _open, xem cuốn Kỹ thuật Lập trình C của tác giả) 4. Hàm tạo: fstream(int fd, char *buf, int n); dùng để tạo một đối tượng fstream , gắn nó với một tệp có chỉ số fd đang mở và sử dùng một vùng nhớ n byte do buf trỏ tới làm bộ đệm. 5. Phương thức: void open(const char *fn, int mode, int prot = filebuf::openprot); dùng để mở tệp có tên fn và gắn nó với đối tượng fstream. Các tham số của phương thức có cùng ý nghĩa như trong hàm tạo thứ 2. Chú ý: Tham số mode không có giá trị mặc định. 13.2. Các cách đọc-ghi đồngthờitrêntệp Có 2 cách chính sau: + Cách 1: Dùng hàm tạo 2 để xây dựng một dòng nhập-xuất, mở một tệp để đọc-ghi và gắn tệp với dòng nhập-xuất. Sau đó dùng toán tử nhập >> , toán tử xuất >> và các phương thức nhập, xuất để nhập, xuất dữ liệu ra dùng nhập-xuất vừa tạo (như đối với cácdòng chuẩn cin và cout). Ví dụ: fstream f(“DU_LIEU”, ios::in | ios::out) ; + Cách 2: Dùng hàm tạo 1 để xây dựng một dòng nhập-xuất. Sau đó dùng phương thức open để mở một tệp cụ thể (để đọc và ghi) và cho gắn với dòng nhập-xuất vừa xây dựng. Khi không cần làm việc với tệp này nữa, chúng ta có thể dùng phương thức close để chấm dứt mọi ràng buộc giữa dòng nhập-xuất và tệp. Sau đó có thể gắn dòng nhập-xuất với tệp khác. Theo cách này, có thể dùng một dòng nhập-xuất (đối tượng fstream) để đọc-ghi dữ liệu từ nhiều tệp khác nhau. Ví dụ: fstream f; f.open(“DU_LIEU”, ios::in | ios::out) ; 13.3. Di chuyển con trỏ tệp 13.3.1. Để di chuyển con trỏ tệptrêndò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 long teelp() ; cho biết vị trí hiện tại của con trỏ tệp. 13.3.2. Để di chuyển con trỏ tệptrêndò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 420 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 long teelg() ; cho biết vị trí hiện tại của con trỏ tệp. 13.3.3. Để di chuyển con trỏ tệptrêndòng nhập-xuất, chúng ta có thể sử dụng cả 6 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á. //CT7_13.CPP // ghi - đọcđồngthờ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: " ; cin >> ttep; f.open(ttep,ios::out|ios::in|ios::noreplace); if (f.bad()) 422 { 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 << " \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(); } 424 . 13.2. Các cách đọc- ghi đồng thời trên tệp Có 2 cách chính sau: + Cách 1: Dùng hàm tạo 2 để xây dựng một dòng nhập-xuất, mở một tệp để đọc- ghi và gắn tệp. Đọc ghi đồng thời trên tệp 13.1. Lớp fstream Để đọc ghi đồng thời trên tệp, chúng ta sử dụng lớp fstream. Lớp fstream thừa kế các phương thức của các