BÁO CÁO LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG Tìm hiểu về vào ra với tệp nhị phân (binary file)

21 417 0
BÁO CÁO LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG Tìm hiểu về vào ra với tệp nhị phân (binary file)

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

MỤC LỤC I. Mở đầu: 1 Khái niệm về tệp: 2 1. Mở tệp 2 2. Vào ra tệp nhị phân bằng hàm read() và write() 2 I. I. Mở đầu: Một số đặc điểm chung về tệp Khái niệm về tệp: Tệp là một dãy các phần tử cùng kiểu được sắp xếp một cách tuần tự. Tệp dữ liệu được lưu trữ ở bộ nhớ ngoài dưới một tên nào đó. Tệp tập hợp trong nó một số phần tử dữ liệu có cùng cấu trúc giống như mảng nhưng khác mảng là số phần tử của tệp chưa được xác định. Trong C++, khi thao tác với một tệp dữ liệu cần thực hiện các bước sau: - Mở tệp tin - Thực hiện các thao tác đọc, ghi trên tệp đang mở - Đóng tệp tin Để thực hiện các thao tác liên quan đến tệp dữ liệu, C++ cung cấp một thư viện <fstream.h> chứa các lớp và các hàm phục vụ cho các thao tác này. Do vậy, trong quá trình làm việc với tệp tin, chúng ta cần khai báo chỉ thị dùng thư viện ngay từ đầu chương trình như sau: #include<fstream.h> II. Nội dung. 1. Tìm hiểu về vào/ra với tệp nhị phân (binary file) 1. Mở tệp Để mở một tệp tin dưới chế độ nhị phân, ta dùng cú pháp sau: Fstream <Tên_biến_tệp>(Tên_tệp>, ios::binary); Khi đó, các thao tác đọc ghi tên biến tệp được thực hiện theo đơn vị byte theo kích thước các bản ghi (cấu trúc) được ghi trong tệp. Ví dụ: khi ta muốn mở tệp tin baitho.txt dưới chế độ nhị phân thì ta khai báo như sau: Fstream MyBaiTho(“baitho.txt”, ios::binary); 2. Vào ra tệp nhị phân bằng hàm read() và write() a) Ghi vào tệp nhị phân bằng hàm write() Các bước thực hiện để ghi dữ liệu vào một tệp nhị phân như sau: - Mở tệp tin theo chế độ để ghi nhị phân bằng đối tượng fstream: fstream <tên_biến_tệp>(tên_tệp_tin>, ios::out | ios::binary); - Ghi dữ liệu vào tệp bằng hàm “write()”: <tên_biến_tệp>.write(char* <dữ liệu>, int <kích thước dữ liệu>); - Đóng tệp tin bằng lệnh close(): <tên_biến_tệp>.close(); Trong đó, thao tác write nhận hai tham số đầu vào như sau: - Tham số thứ nhất là con trỏ kiểu char trỏ đến vùng dữ liệu cần ghi vào tệp. Vì con trỏ bắt buộc có kiểu char nên khi muốn ghi dữ liệu có kiểu khác vào tệp, ta dùng hàm chuyển kiểu: Reinterpret_cast<char *>(<dữ liệu>); - Tham số thứ hai là kích cỡ dữ liệu được ghi tệp. Kích cỡ này được tính theo byte, nên thông thường ta dùng toán tử: Sizeof(<kiểu dữ liệu>); * Chú ý: - Khi muốn đọc, ghi các dữ liệu có cấu trúc (struct) vào tệp thì ta phải dùng ở chế độ đọc/ghi tệp nhị phân mà không thể dùng chế độ đọc/ghi ở chế độ văn bản. - Khi đọc/ghi dữ liệu có kiểu cấu trúc, để toán tử sizeof() thực hiện chính xác thì các thành viên cấu trúc không được là kiểu con trỏ. Vì toán tử sizeof() đối với con trỏ chỉ cho kích cỡ của con trỏ mà không cho kích cỡ thật của vùng dữ liệu mà con trỏ trỏ tới. b) Đọc dữ liệu từ tệp nhị phân bằng hàm read() Các bước thực hiện để ghi dữ liệu vào một tệp nhị phân như sau: - Mở tệp tin theo chế độ để đọc tệp nhị phân bằng đối tượng fstream: fstream <tên_biến_tệp>(tên_tệp_tin>, ios::in | ios::binary); - Để mở tệp theo chế độ nhị phân và ghi bổ sung vào tệp chúng ta có thể làm một trong 2 cách sau: +C.1. Khai báo theo mẫu sau: fstream <tên_biến_tệp>(tên_tệp_tin>, ios::in | ios::binary | ios::app );//ở đây app nghĩa là append (ghi bổ sung) + C.2. Tạo đối tượng tệp Fstream f; Sau đó dùng hàm open() để mở tệp: f.open("sv.dl",ios::binary | ios::app); Ngoài ra bạn có thể ghi tệp nhị phân dưới nhiều chế độ khác nhau như đã nói ở mục 3 trong phần I. - Đọc dữ liệu vào tệp bằng hàm “read()”: <tên_biến_tệp>.read(char* <dữ liệu>, int <kích thước dữ liệu>); - Đóng tệp tin bằng lệnh close(): <tên_biến_tệp>.close(); 2. Vào ra trực tiếp với bộ nhớ Các hàm truy nhập theo địa chỉ phân đoạn a. Hàm pokeb: Gửi một ký tự vào bộ nhớ. + Nguyên mẫu trong dos.h như sau: void pokeb(unsigned seg, unsigned off, char value); + Công dụng: Gửi giá trị ký tự value vào bộ nhớ tại địa chỉ phân đoạn seg:off b. Hàm peekb: Nhận một ký tự từ bộ nhớ. + Nguyên mẫu trong dos.h như sau: char peekb(unsigned seg, unsigned off); + Công dụng: Nhận một byte tại địa chỉ phân đoạn seg:off c. Hàm poke: Gửi một số nguyên vào bộ nhớ. + Nguyên mẫu trong dos.h như sau: void poke(unsigned seg, unsigned off, int value); + Công dụng: Gửi giá trị nguyên value vào bộ nhớ tại địa chỉ phân đoạn seg:off d. Hàm peek: Nhận một số nguyên từ bộ nhớ. +Nguyên mẫu trong dos.h như sau: int peek(unsigned seg, unsigned off); + Công dụng: Nhận một word tại địa chỉ phõn đoạn seg:off e. Hàm movedata: Sao các byte. + Nguyên mẫu trong mem.h như sau: void movedata(unsigned seg_gui, unsigned off_gui, unsigned seg_nhan, unsigned off_nhan, int n); + Công dụng: Sao n byte từ seg_gui:off_gui đến seg_nhan:off_nhan Bộ nhớ màn hình văn bản a. Cách biểu diễn ký tự trong bộ nhớ màn hình Bộ nhớ màn hình văn bản bắt đầu từ địa chỉ : (0xb800:0x0000) Khi đưa một ký tự vào vùng nhớ màn hình, thỡ nó sẽ hiện lên màn hình. Mỗi ký tự trên màn hình chiếm 2 byte trong bộ nhớ màn hình: byte đầu chứa mã ASCII, byte thứ hai biểu diễn mầu hiển thị gọi là byte thuộc tính. Các bit của byte thuộc tính: B7B6B5B4B3B2B1B0 được chia làm 3 nhóm: + Nhóm 1 gồm bit B7 biểu thị sự nhấp nháy. Nếu B7=0 thì ký tự không nhấp nháy, nếu B7=1 thì ký tự sẽ nhấp nháy. + Nhóm 2 gồm các bit B6, B5 và B4. Các bit này chứa được một số nguyên từ 0 đến 7 và biểu thị 8 mầu nền của ký tự. + Nhóm 3 gồm các bit B3, B2, B1 và B0. Các bit này chứa được một số nguyên từ 0 đến 15 và biểu thị 16 mầu của ký tự. b. Trang màn hình Mỗi trang màn hình gồm 80x25 ký tự, do đó cần 80x25x2=4000 byte bộ nhớ. Thực tế mỗi trang màn hình được phân bố 4096 = 0x1000 byte. Như vậy 4 trang màn hình được phân bố như sau: + Trang màn hình thứ 0 bắt đầu từ địa chỉ 0xB800:0x0000 + Trang màn hình thứ 1 bắt đầu từ địa chỉ 0xB800:0x1000 + Trang màn hình thứ 2 bắt đầu từ địa chỉ 0xB800:0x2000 + Trang màn hình thứ 3 bắt đầu từ địa chỉ 0xB800:0x3000 c. Chọn trang hiển thị Tại mỗi thời điểm chỉ có thể hiển thị được một trong 4 trang màn hình. Để hiển thị trang màn hình thứ t (t=0,1,2,3) chúng ta sử dụng chức năng 5 của ngắt 0x10 theo mẫu sau: union REGS v,r; v.h.ah = 5 ; // Chức năng 5 v.h.al = t ; // Số hiệu trang màn hình cần hiển thị int86(0x10, &v, &r); // Thực hiện ngắt 0x10 Chuyển đổi địa chỉ a. Để chuyển từ địa chỉ thực sang địa chỉ phân đoạn ta dùng các macro: unsigned FP_SEG(địa_chỉ_thực) unsigned FP_OFF(địa_chỉ_thực) b. Để chuyển từ địa chỉ phân đoạn sang địa chỉ thực ta dựng macro: void far *MK_FP(seg,off) Ví dụ 1. Sau khi thực hiện các câu lệnh: char buf[100]; unsigned ds,dx; ds = FP_SEG(buf); dx = FP_OFF(buf); thì ds:dx chứa địa chỉ của mảng buf. Ví dụ 2. Sau khi thực hiện các câu lệnh: char far *pchar; pchar = (char far*)MK_FP(0xb800:0); thì pchar trỏ tới địa chỉ đầu của bộ nhớ màn hình. Khi đó ta có thể sử dụng các lệnh gán để truy nhập trực tiếp tới bộ nhớ màn hình. 3. Cách sử dụng hàm thành viên để đọc/ghi đối tượng ra tệp Cách khai báo một thành viên là hàm trong một lớp có thể dùng hai dạng chính sau: + Mô tả trực tiếp trong định nghiã của lớp mà hàm là thành viên [virtual] int + Mô tả sau bên ngoài sau định nghĩa của lớp mà hàm là thành viên Hàm thành viên có chức năng điều hành và chức năng khai báo là thành viên được công nhận hiển nhiên của một lớp. Chúng ta có thể khai báo một hàm thành viên ở trạng thái tĩnh, gọi là hàm thành viên tĩnh. Một hàm thành viên không được khai báo tĩnh thì được gọi là một hàm thành viên (nonstatic). Giả sử bạn tạo một đối tượng có tên là X của một lớp A có một hàm thành viên là F( ). Nếu bạn gọi hàm XF( ) thì từ khóa trong thân hàm F( ) là địa chỉ của X. Định nghĩa hàm thành viên trong phạm vi bao quanh lớp. Phần thân của hàm thành viên được phân tích sau khi khai báo lớp để các thành viên của lớp có thể được sử dụng trong phần thân của hàm thành viên. Ngay cả khi, nếu định nghĩ các chức năng của thành viên xuất hiện trước khi khai báo rằng thành viên trong danh sách thành viên lớp. Khi hàm add( ) được gọi trong ví dụ sau đây. Các biến dữ liệu a, b, c có thể sử dụng trong phần thân của add( ) class x { public: int add() // inline member function add {return a+b+c;}; private: int a,b,c; }; Bạn có thể định nghĩa một hàm thành viên bên trong các lớp được định nghĩa. Hoặc bạn có thể định nghĩa ở bên ngoài nếu bạn thực sự đã khai báo( nhưng chưa định nghĩa) hàm thành viên trong định nghĩa lớp. Một hàm thành viên xác định các thành viên trong danh sách lớp được gọi là một hàm thành viên nội tuyến. Trong ví dụ trên thì add( ) là một hàm thành viên nội tuyến. Nếu bạn định nghĩa một hàm thành viên bên ngoài lớp thì nó phải xuất hiện trong một phạm vi không gian tên kèm theo các định nghĩa lớp. Bạn phải hội đủ điều kiện tên hàm thành viên sử dụng scope resolution (::) . 4. Cách sử dụng hàm thành viên tĩnh để đọc/ghi nhiều đối tượng của cùng một lớp ra tệp Hàm thành viên tĩnh được viết theo một trong hai cách: - Dùng từ khoá static đặt trước định nghĩa hàm thành phần viết bên trong định nghĩa lớp. - Nếu hàm thành phần xây dựng bên ngoài định nghĩa lớp, thì dùng từ khoá static đặt trước khai báo hàm thành phần bên trong định nghĩa lớp. Không cho phép dùng từ khoá static đặt trước định nghĩa hàm thành phần viết bên ngoài định nghĩa lớp. Các đặc tính của hàm thành viên tĩnh: - Hàm thành viên tĩnh là chung cho toàn bộ lớp và không lệ thuộc vào một đối tượng cụ thể, nó tồn tại ngay khi lớp chưa có đối tượng nào. - Lời gọi hàm thành viên tĩnh như sau: Tên lớp :: Tên hàm thành viên tĩnh(các tham số thực sự) - Vì hàm thành viên tĩnh là độc lập với các đối tượng, nên không thể dùng hàm thành viên tĩnh để xử lý dữ liệu của các đối tượng trong lời gọi phương thức tĩnh. Nói cách khác không cho phép truy nhập các thuộc tính (trừ thuộc tính tĩnh) trong thân hàm thành viên tĩnh. Đoạn chương trình sau minh họa điều này: class HDBH { private: int shd; char *tenhang; double tienban; static int tshd; static double tstienban; public: static void in() { cout <<”\n” << tshd; cout << ”\n” << tstienban; cout <<”\n”<< tenhang //loi cout <<”\n” << tienban; //loi } }; Ví dụ 3.12 #include <iostream.h> #include <conio.h> class A { int m; static int n; //n la bien tinh public: void set_m(void) { m= ++n;} void show_m(void) { cout << "\n Doi tuong thu:" << m << endl; } static void show_n(void) { cout << " m = " << n << endl; } }; int A::n=1; //khoi gan gia tri ban dau 1 cho bien tinh n void main() { clrscr(); A t1, t2; t1.set_m(); t2.set_m(); A::show_n(); A t3; t3.set_m(); A::show_n(); t1.show_m(); t2.show_m(); t3.show_m(); getch(); } Kết quả chương trình trên là: m = 3 m = 4 Doi tuong thu : 2 Doi tuong thu : 3 Doi tuong thu : 4 5. Kỹ thuật đọc/ghi các đối tượng của các lớp khác nhau ra cùng một tệp C++ cung cấp 4 dòng tin chuẩn để làm việc với bàn phím và màn hình. Muốn nhập xuất lên tệp chúng ta cần tạo các dòng tin mới (khai báo các đối tượng Stream) và gắn chúng với một tệp cụ thể. C++ cung cấp 3 lớp sream để làm điều này, đó là các lớp: Ofstream dùng để tạo các dòng xuất (ghi tệp) Ifstream dùng để tạo các dòng nhập (đọc tệp) Ftream dùng để tạo các dòng nhập, dòng xuất hoặc dòng nhập/xuất. Ghi dữ liệu lên tệp + Dùng lớp oftream để tạo một dòng xuất và gắn nó với một cụ thể. Khi đó việc xuất dữ liệu ra dòng này cũng đồng nghĩa với việc ghi dữ liệu lên tệp + Thực hiện xuất dữ liệu ra dòng xuất vừa tạo như thể xuất dữ liệu ra dòng chuẩn cout Lớp ofstream thừa kế các phương thức của các lớp ios và ostream. Nó cũng kế thừa phương thức: Close Của lớp ftreambase [...]... chương trình: Đề bài: Chương trình quản lý nhân sự của một trường đại học Có 3 loại nhân sự với các thông tin như sau: Cán bộ quản lý có họ tên, ngày sinh, chức vụ; Giáo viên có họ tên, ngày sinh, các môn học giảng dạy; Nhân viên phục vụ có họ tên, ngày sinh Trong chương trình có cài đặt hàm thành viên đọc/ghi đối tượng ra tệp, hàm thành viên tĩnh đọc/ghi tất cả các đối tượng nhân sự ra cùng một tệp #include . một tệp nhị phân như sau: - Mở tệp tin theo chế độ để đọc tệp nhị phân bằng đối tượng fstream: fstream <tên_biến _tệp& gt;(tên _tệp_ tin>, ios::in | ios::binary); - Để mở tệp theo chế độ nhị phân. quá trình làm việc với tệp tin, chúng ta cần khai báo chỉ thị dùng thư viện ngay từ đầu chương trình như sau: #include<fstream.h> II. Nội dung. 1. Tìm hiểu về vào/ra với tệp nhị phân (binary. Ghi vào tệp nhị phân bằng hàm write() Các bước thực hiện để ghi dữ liệu vào một tệp nhị phân như sau: - Mở tệp tin theo chế độ để ghi nhị phân bằng đối tượng fstream: fstream <tên_biến _tệp& gt;(tên _tệp_ tin>,

Ngày đăng: 14/04/2015, 09:00

Từ khóa liên quan

Mục lục

  • I. Mở đầu:

    • Khái niệm về tệp:

    • 1. Mở tệp

    • 2. Vào ra tệp nhị phân bằng hàm read() và write()

Tài liệu cùng người dùng

Tài liệu liên quan