Tải bản đầy đủ (.pdf) (42 trang)

Nhập xuất C++ nâng cao

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (85.56 KB, 42 trang )




Chương 8

Nhập/Xuất C++ nâng cao











Tạo Bộ thao tác Nhập/Xuất


Nhập/Xuất File


Nhập/Xuất File nhò phân không đònh dạng


Các hàm Nhập/Xuất nhò phân


Truy cập ngẫu nhiên



Kiểm tra trạng thái Nhập/Xuất


Nhập/Xuất theo đơn đặt hàng và các File


Nhập/Xuất theo mảng




Chöông 8
Nhaäp / Xuaát C++

naâng cao




228


































Chương 8
Nhập / Xuất C++

nâng cao





229
I/ Tạo Bộ thao tác Nhập/Xuất

Ngoài bộ chèn và bộ chiết, có thể sửa đổi hệ thống nhập/xuất của C++ bằng cách
tạo ra bộ thao tác nhập/xuất tự tạo
. Nó có hai lý do :
* một bộ thao tác có thể hợp nhất một dãy các thao tác nhập/xuất thành một bộ thao
tác tự tạo.
* một bộ thao tác nhập/xuất tự tạo cần thiết khi nhập/xuất trên các thiết bò không
chuẩn (máy in đặc biệt hay hệ thống nhận dạng quang học) .

Có hai loại bộ thao tác, một dùng cho các stream nhập, một dùng cho các stream
xuất. Ngoài ra người ta còn phân thành hai nhóm :
bộ thao tác có tham số

bộ thao
tác không có tham số
, chúng khác nhau về cách tạo ra bộ thao tác. Việc tạo ra bộ
thao tác có tham số không thuộc phạm vi bài giảng này.


Dạng tổng quát của các
bộ thao tác xuất không có tham số
:

ostream &manip_name(ostream &stream)
{


// program codes
return stream
}

manip_name
tên của bộ thao tác được tạo ra

Lưu ý : bộ thao tác trên có đối số là một tham chiếu đến stream mà nó thao tác, khi
gọi bộ này, không được kèm theo tên bộ thao tác bất kỳ một đối số nào.



Dạng tổng quát của các
bộ thao tác nhập không có tham số
:

istream &manip_name(istream &stream)
{

// program codes
return stream
}

Chương 8
Nhập / Xuất C++

nâng cao





230
Một bộ thao tác nhập nhận một tham chiếu đến stream mà nó thao tác. Stream này
phải được trả về bởi bộ thao tác.

Ví dụ 1.1
Chương trình tạo ra bộ thao tác xuất setup(). Khi được gọi, bộ này sẽ
thiết lập độ rộng trường là 10, độ chính xác là 4 và dấu "* " là ký tự lấp đầy.
#include <iostream.h>

ostream &setup(ostream &stream)
{

stream.
width(10);

stream.
precision(4);

stream.
fill('*');

return
stream
;
}

int main()
{
cout <<

setup
<< 123.123456;
return 0;
}

Kết qủa chương trình
**123.1234


Ví dụ 1.2
Hai bộ thao tác atn() và note() đơn giản sau đây làm gọn hơn đoạn
chương trình in các từ hay đoạn câu hay lặp lại trong chương trình.

#include <iostream.h>
// Attention:
ostream &atn(ostream &stream)
{
stream << "Attention: ";
return stream;
}

Chương 8
Nhập / Xuất C++

nâng cao




231

// Please note:
ostream &note(ostream &stream)
{
stream << "Please Note: ";
return stream;
}

int main()
{
cout <<
atn
<< "High voltage circuit\n";
cout <<
note
<< "Turn off all lights\n";

return 0;
}


Ví dụ 1.3
Chương trình tạo bộ thao tác nhập getpass() thực hiện báo tiếng chuông
và thông báo đề nghò nhập mật khẩu.

#include <iostream.h>
#include <string.h>

// A simple input manipulator
istream &getpass(istream &stream)
{

cout << '\a'; // sound bell
cout << "Enter password: ";

return
stream
;
}

int main()
{
char pw[80];

do {
cin >>
getpass
>> pw;
Chương 8
Nhập / Xuất C++

nâng cao




232
} while (strcmp(pw, "password"));

cout << "Logon complete\n";

return 0;

}


Bài tập I

1. Hãy tạo một bộ thao tác mới tên là td() dùng để hiện giờ và ngày hiện tại của hệ
thống.

2. Hãy tạo một bộ thao tác mới tên làsethex() dùng để thiết lập các trạng thái để in
một số thập lục phân, đặt các cờ uppercase và showbase. Ngoài ra, hãy tạo một bộ
thao tác xuất tên là reset() để phục hồi lại trạng thái trước khi gọi sethex().

3. Hãy tạo một bộ thao tác mới tên là skipchar() dùng để đọc và bỏ qua mười ký tự
liên tiếp từ một stream nhập.



















Chương 8
Nhập / Xuất C++

nâng cao




233
II/ Nhập/Xuất File

1/ Khái niệm
Để sử dụng nhập/xuất file trong chương trình cần phải nạp file
fstream.h
. File này
đònh nghiã nhiều lớp gồm
ifstream
,
ofstream

fstream
. Ba lớp này được suy dẫn
từ hai lớp istream và ostream, và ios là lớp cơ sở của chúng. Do đó các lớp ifstream,
ofstream và fstream cũng có thể truy xuất đến tất cả các thao tác đã đònh nghóa trong
ios
.

Trong C++,

một file được mở bằng cách liên kết nó với một stream
. Có ba loại
stream
: nhập, xuất và nhập/xuất
. Trước khi mở file phải tạo ra stream tương ứng.

Để tạo một
stream nhập
, cần khai báo stream đó
thuộc lớp ifstream
.
Để tạo một
stream xuất
, cần khai báo stream đó
thuộc lớp ofstream
.
Đối với
stream thực hiện cả thao tác nhập và xuất
, cần khai báo stream đó
thuộc lớp
fstream
.

Ví dụ
ifstream
in
; // input stream
ofstream
out
; // output stream

fstream
io
; // input and output stream

2/ Mở file
a/ Sau khi tạo ra một stream, có thể
mở file gắn với stream đó bằng
hàm open()
.
Hàm này là hàm thành phần của ba stream nói trên, dạng tổng quát :
void
open
(const char
*filename
, int
mode
, int
access
);
filename
tên của file cần mở, có thể đi kèm với đường dẫn.
mode
xác đònh chế độ của file được mở.
access
xác đònh cách truy cập file


@ Các
giá trò nguyên của mode
, có thể là một hay nhiều giá trò (được kế thừa bởi

fstream.h)

Chế độ
ios::app
làm cho kết xuất được
thêm vào cuối của file
. Dùng cho các
file xuất.
Chương 8
Nhập / Xuất C++

nâng cao




234

Chế độ
ios::ate
cho phép
chuyển đến vò trí cuối file
ngay sau khi file được mở.
Lưu ý, mặc dù đang ở vò trí cuối file, các thao tác nhập/xuất vẫn có thể xuất
hiện ở bất cứ vò trí nào của file.

Chế độ
ios::in
xác đònh
file được mở là file nhập

. Chế độ
ios::out
xác đònh
file
được mở là file xuất
.

Tuy nhiên, việc tạo ra một stream bằng các khai báo nó thuộc lớp ifstream ngầm
đònh nó là một stream nhập, cũng như khai báo stream thuộc lớp ofstream ngầm
đònh nó là một stream xuất. Trong hai trường hợp trên, không cần phải xác đònh các
giá trò ios::in và ios::out khi mở file.


Chế độ
ios::binary
làm cho
file được mở ở chế độ nhò phân
.

Theo mặc đònh, tất cả các file được mở ở chế độ văn bản (text mode). Trong chế độ
văn bản, sẽ có một số trường hợp ký tự sẽ bò chuyển đổi. Ví dụ,
ký tự tạo dòng mới
(
'\n' ) sẽ được chuyển thành chuổi liên tiếp nhau của hai
ký tự xuống dòng
(carriage
return, mã 13), và thêm một dòng (line-feed, mã 10).

Khi hoạt động
ở chế độ nhò phân, sẽ không có bất kỳ một trường hợp chuyển đổi ký tự

nào
. Bất kỳ một file nào đều có thể hoạt động ở hai chế độ văn bản hay nhò phân.


Chế độ
ios::nocreate
làm cho việc gọi
hàm open()
bò thất bại nếu file được mở
là một file mới (chưa có sẵn trên điã). Còn
ios::noreplace
làm cho việc gọi
hàm
open()
bò thất bại nếu file được mở đã có sẵn trên điã.


Chế độ
ios::trunc
làm cho khi file có sẵn trùng tên với file được mở sẽ bò xoá
sạch nội dung.

Có thể sử dụng kết hợp hai hay nhiều chế độ ở trên bằng phép toán OR.

@ Các giá trò của đối số
access
xác đònh cách truy cập file.
Giá trò ngầm đònh của đối số này là
filebuf::openprot
(

filebuf
là lớp cha của các
lớp stream). Trong môi trường UNIX nó có giá trò 0x644 đối với các file thông
thường.

Trong môi trường DOS/WINDOWS giá trò của đối số access qui đònh mã thuộc tính
của file, bao gồm :
Chương 8
Nhập / Xuất C++

nâng cao




235


Thuộc tính Ý nghiã
0 Archive File bình thường : ghi / đọc (mặc đònh)
1 Read only File chỉ đọc
2 Hidden File ẩn
4 System File hệ thống
8 Save Thuộc tính lưu trữ


Có thể sử dụng kết hợp hai hay nhiều thuộc tính ở trên bằng phép toán OR.




Ví dụ đoạn chương trình sau minh hoạ việc mở file bình thường trong
DOS/WINDOWS
ofstream
out
; // khai báo stream xuất

out.open
("test.txt",
ios::out
, 0) ;

hoặc
out.open
("test.txt") ; // lời gọi ngắn gọn, thông thường.



Để mở file nhập/xuất, cần phải xác đònh cả hai chế độ ios::in và ios::out cho đối
số mode, được minh hoạ sau đây. Lưu ý, không có giá trò mặc đònh cho trường
hợp này.
fstream
mystream
; // khai báo stream xuất

mystream.open
("test.txt",
ios::in | ios::out
) ;

Nếu hàm open() không thực thi được, stream được trả về sẽ mang giá trò không. Do

đó, cần kiểm tra lại việc mở file có thành công hay không, trước khi truy xuất nó. Ví
dụ :
if(! mystream) {
cout << "Can't open file \n";
// handle error
}


b/ Dùng hàm tạo để mở file

Chương 8
Nhập / Xuất C++

nâng cao




236
Thông thường, không cần dùng hàm open() để mở file, vì các lớp
ifstream
,
ofstream

fstream

đã có sẵn các hàm tạo dùng để mở file một cách tự động.
Các
hàm tạo này có các đối số giống hệt như của hàm open(). Dạng thông thường
mở file


để nhập
:


ifstream
mystream("test.txt");

Cần kiểm tra lại việc mở file có thành công hay không, trước khi truy xuất nó.

3/ Đóng file
Dùng hàm void
close()
. Hàm này không có đối số và không trả về giá trò nào cả.
Ví dụ đóng một file đang gắn với stream mystream, cần gọi :

mystream.close()
;


Để kiểm tra tình trạng hết file dùng hàm eof()
int
eof()
;

Hàm trả về giá trò

0 khi đang ở tình trạng cuối file.
giá trò = 0 ngược lại.


Ví dụ
mystream.eof()
;


4/ Truy xuất nội dung trên file
Toán tử xuất << và toán tử nhập >> được sử dụng để truy xuất nội dung trên file,
cần phải thay các stream cin và cout bằng stream liên kết với file.

Thông tin lưu trên file
có cùng đònh dạng
như khi nó được trình bày trên màn hình.
Do đó, các
file tạo ra
bằng toán tử xuất << và các
file được đọc vào
bằng toán tử
nhập >> đều là các
file văn bản có đònh dạng
.


Ví dụ 2.1
Tạo một file xuất, ghi lên file, đóng file. Mở file đó như một file nhập,
đọc nội dung của file.

#include <iostream.h>
#include <fstream.h>
Chương 8
Nhập / Xuất C++


nâng cao




237
#include <iomanip.h>

int main()
{

ofstream fout
("test.txt"); // create output file

if(!fout) {
cout << "Cannot open output file.\n";
return 1;
}


fout <<
"Hello!\n";

fout <<
100 << ' ' << hex << 100 << endl;


fout.close()
;



ifstream fin
("test.txt"); // open input file

if(!fin) {
cout << "Cannot open input file.\n";
return 1;
}

char str[80];
int i, j;


fin >>
str >> i >> j;
cout << str << ' ' << i << ' ' << j << endl;


fin.close()
;

return 0;
}


Kết quả chương trình, nội dung trong file test.txt

Chương 8
Nhập / Xuất C++


nâng cao




238
Hello!
100 64


Ví dụ 2.2
Chương trình đọc từ bàn phím một chuổi ký tự, ghi lên file, đóng file.
Chương trình kết thúc khi nhập một dòng trống. Mở file đó như một file nhập, đọc
nội dung của file.

// WRITE.CPP
#include <iostream.h>
#include <fstream.h>
#include <iomanip.h>

int main(
int argc, char *argv[]
) // argc : số các tham số ,
// *argv[] : chứa nội dung các tham số
{
if(argc!=2) {
cout << "Usage: WRITE <filename> \n";
// argv[0] = '\<path>\WRITE.EXE'
// argv[1] = '<filename>'

return 1;
}


ofstream out(argv[1])
; // output file

if(!out) {
cout << "Cannot open output file.\n";
return 1;
}

char str[80];
cout << "Write strings to disk, '$' to stop\n";

do {
cout << ": ";
cin >> str;

out << str
<< endl;
Chương 8
Nhập / Xuất C++

nâng cao




239

} while (*str != '$');


out.close()
;
return 0;
}

Ví dụ 2.3
Chương trình sẽ sao chép một text file, trong đó các dấu khoảng cách
sẽ được thay bằng dấu '|'.

// CONVERT.CPP
// Convert spaces to |s.
#include <iostream.h>
#include <fstream.h>

int main(
int argc, char *argv[]
)
{
if(argc != 3) {
cout << "Usage: CONVERT <input> <output>\n";
return 1;
}

ifstream
fin(argv[1])
; // open input file to read
ofstream

fout(argv[2])
; // create output file to write

if(!fout) {
cout << "Cannot open output file.\n";
return 1;
}

if(!fin) {
cout << "Cannot open input file.\n";
return 1;
}

char ch;


fin.unsetf(ios::skipws)
; // do not skip spaces
Chương 8
Nhập / Xuất C++

nâng cao




240
while(!fin.eof()) {

fin >> ch

;
if(ch == ' ' ) ch = '|';
if(!fin.eof())
fout << ch
;
}

fin.close();
fout.close();
return 0;
}


Bài tập II

1. Viết chương trình sao chép một text file sang một file mới, đếm và in ra số ký tự
đã chép. Tại sao số lượng các ký tự này khác với số lượng các ký tự khi in file kết
quả ra màn hình.

2. Viết chương trình để ghi bảng dữ liệu sau đây vào một file có tên là phone.txt

Nguyễn Công Trứ 08.8980168
Phạm Ngũ Lão 04.2325678
Trần Nguyên Hãn 04.6781234

3. Viết chương trình đếm số lượng từ có trong một text file bất kỳ.











III/ Nhập/Xuất File nhò phân không đònh dạng
Việc nhập/xuất file nhò phân không đònh dạng
linh động hơn
nhập/xuất text file.
Chương 8
Nhập / Xuất C++

nâng cao




241

1/ Các hàm nhập/xuất cấp thấp

Đọc ghi từng ký tự
Dạng phổ biến của chúng :


istream &get
(char
&
ch);

ostream &put
(char ch);

Hàm get() đọc một ký tự từ stream tương ứng và gán ký tự đó vào nội dung của ch.
Hàm trả về một tham chiếu đến stream, nó sẽ là NULL nếu đến cuối file.

Hàm put() ghi (xuất) nội dung của ch ra một stream và trả về một stream.


Đọc ghi các khối dữ liệu nhò phân

istream &read
(unsigned char *
buf
, int
num
);
ostream &write
(const unsigned char *
buf
, int
num
);

Hàm read() đọc một số lượng
num
các byte từ stream tương ứng và ghi lên một vùng
đệm được trỏ bởi
buf
.


Hàm write() ghi một số lượng
num
các byte ở vùng đệm được trỏ bởi
buf
đến stream
tương ứng.

Nếu file được đọc hết trước khi đủ num ký tự, hàm read() hoàn tất bình thường và
vùng đệm chứa hết số ký tự của lần đọc cuối. Để biết lần cuối này có bao nhiêu ký
tự được đưa ra vùng đệm, dùng hàm gcount() có dạng

int gcount();

Hàm sẽ trả về giá trò là tổng số ký tự đọc được ở lần đọc cuối ngay trước khi hết file.

Lưu ý
: việc thiết lập chế độ
ios::binary
chỉ nhằm mục đích ngăn ngừa việc chuyển
đổi ký tự. Khi sử dụng các hàm nhập/xuất file nhò phân không đònh dạng, không cần
mở file ở chế độ
ios::binary.


Ví dụ 3.1
Chương trình xuất nội dung của một file bất kỳ ra màn hình

// PR.CPP
Chương 8

Nhập / Xuất C++

nâng cao




242
#include <iostream.h>
#include <fstream.h>

int main(
int argc, char *argv[]
)
{
char ch;

if(argc!=2) {
cout << "Usage: PR <filename>\n";
return 1;
}


ifstream in
(
argv[1]
,
ios::in | ios::binary
);


if(!in) {
cout << "Cannot open file.\n";
return 1;
}
while(!in.eof()) {

in.get(ch)
;
cout << ch;
}

in.close();
return 0;
}


Ví dụ 3.2
Chương trình ghi các ký tự lên một file cho đến khi người dùng nhập
vào ký tự '$' .

// WRITE.CPP
#include <iostream.h>
#include <fstream.h>
int main(
int argc, char *argv[]
)
{
char ch;

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×