banner

[Rule] Rules  [Home] Main Forum  [Portal] Portal  
[Members] Member Listing  [Statistics] Statistics  [Search] Search  [Reading Room] Reading Room 
[Register] Register  
[Login] Loginhttp  | https  ]
 
Forum Index Thảo luận hệ điều hành Windows Vài điều về vào ra tệp trong C++ có thể bạn chưa biết  XML
  [Programming]   Vài điều về vào ra tệp trong C++ có thể bạn chưa biết 04/01/2008 17:29:47 (+0700) | #1 | 108290
[Avatar]
zThienLongz
Member

[Minus]    0    [Plus]
Joined: 29/08/2006 10:09:05
Messages: 104
Location: World
Offline
[Profile] [PM] [WWW]
Hôm nay mình xin được trình bày về vào ra tệp trong C++ , có vài điều lý thú có thể có những người chưa biêt.
Mình xin đặt ra vấn đề các bạn thử lý giải xem tại sao.
Code:
#include"iostream"
#include"fstream"
using namespace std;
void ghifile(){
  ofstream ptr("Doc.dat",ios::out|ios::binary);
  for(int i=1;i<5;++i)
  ptr.write((char*)&i,4);
  ptr.close();
}
void docfile(){
  int x=-1;
  fstream ptr("Doc.dat",ios::in|ios::binary);
  while(ptr){
    ptr.read((char *)&x,4);
    cout<<x<<endl;
  }
  ptr.seekg(0,ios::beg);
  if(ptr.eof()) cout<<"error"<<endl;
  ptr.close();
}
int main(){
ghifile();
docfile();
return 0;
}

khi chương trình sẽ in ra màn hình :
Code:
1
2
3
4
4
error

các bạn hãy lý giải tại sao in ra 2 lần số 4 và tại sao câu lệnh " ptr.seekg(0,ios::beg)" lại khộng thực hiện
[Up] [Print Copy]
  [Question]   Re: Vài điều về vào ra tệp trong C++ có thể bạn chưa biết 04/01/2008 18:29:14 (+0700) | #2 | 108291
[Avatar]
secmask
Elite Member

[Minus]    0    [Plus]
Joined: 29/10/2004 13:52:24
Messages: 553
Location: graveyard
Offline
[Profile] [PM] [WWW]
bài này có 1 vài điểm mình thấy cần làm rõ trước khi trả lời câu hỏi của bạn.
1. sizeof(int) của bản C bạn đang dùng bằng bao nhiêu (2 or 4 or ?)
2.
Code:
while(ptr){
     ptr.read((char *)&x,4);
     cout<<x<<endl;
   }

đoạn này mình chưa thấy chỗ nào cho thoát khỏi vòng lặp, chắc đọc nhiều quá nên tẩu hỏa nhập ma --> error.
3.Code:
ptr.seekg(0,ios::beg);
   if(ptr.eof()) cout<<"error"<<endl;
   ptr.close();

đoạn này được hiểu là bạn di chuyển con trỏ file đến offset 0 so với begin của file sau đó kiểm tra nếu đã là cuối file thì đóng file lại, chỗ này chắc bạn nhầm. Thông thường theo cách mà bạn đã dùng thì người ta thường lặp đọc file, kiểm tra nếu đã là cuối file thì dừng lặp và đóng file lại.
4.Code:
for(int i=1;i<5;++i)
   ptr.write((char*)&i,4);

chỗ này có lẽ nên là
Code:
for(int i=1;i<5;++i)
   ptr.write((char*)&i,sizeof(i));
.
trong help của turbo c mình đọc thấy phương thức write như sau.
ostream& write(const signed char* pt, int n) sẽ insert n char được trỏ bởi pt vào luồng ra.
theo đó, có thể dùng ptr.write((char*)&i,sizeof(i)); để ghi số nguyên i vào luồng ra.
[Up] [Print Copy]
  [Question]   Re: Vài điều về vào ra tệp trong C++ có thể bạn chưa biết 05/01/2008 02:34:04 (+0700) | #3 | 108326
[Avatar]
zThienLongz
Member

[Minus]    0    [Plus]
Joined: 29/08/2006 10:09:05
Messages: 104
Location: World
Offline
[Profile] [PM] [WWW]
1. sorry tại vì kiểu int trong máy mình là 4 byte nên mình viết luôn là như vậy
2. đúng là vẫn ở trong vòng lặp nhưng tại sao nó lại in ra 2 lần số cuối cái đó bạn vẫn chưa trả lời đc
3. mình cố ý làm như vậy để các bạn thấy đc rằng khi mà con trỏ ptr trỏ tới eof thì không thể nào dịch chuyển con trỏ được
4. thêm 1 lần nữa sorry vì sizeof(int ) của máy mình là 4byte
[Up] [Print Copy]
  [Question]   Re: Vài điều về vào ra tệp trong C++ có thể bạn chưa biết 05/01/2008 04:36:43 (+0700) | #4 | 108343
[Avatar]
secmask
Elite Member

[Minus]    0    [Plus]
Joined: 29/10/2004 13:52:24
Messages: 553
Location: graveyard
Offline
[Profile] [PM] [WWW]
nó in ra 2 lần số 4 với lý do như sau:
trong file có 4 phần tử, đọc 4 phần tử và in ra ok.
lần đọc tiếp theo, read sẽ bị chuyển đến eof và ko đọc ra gì cả, bitfail được set. tuy nhiên bạn không kiểm tra việc đọc ra có thành công hay không mà vẫn in ra x, x lúc này vẫn chứa giá trị của lần đọc trước (=4) , do đó in ra 4 2 lần
khi vòng lặp tiếp theo thực hiên, while(ptr) sẽ break do operator void *() method của iostream check bitfail và trả lại 0.
[Up] [Print Copy]
  [Question]   Re: Vài điều về vào ra tệp trong C++ có thể bạn chưa biết 05/01/2008 04:57:59 (+0700) | #5 | 108347
[Avatar]
zThienLongz
Member

[Minus]    0    [Plus]
Joined: 29/08/2006 10:09:05
Messages: 104
Location: World
Offline
[Profile] [PM] [WWW]
hè hè ai kêu ông là đọc xong 4 phần tử kìa là sẽ chuyển dến eof. Nếu nói như ông thì nếu ta mở tệp ở chế độ cuối tệp thì nó là eof hả? Điều này là không đúng.
[Up] [Print Copy]
  [Question]   Re: Vài điều về vào ra tệp trong C++ có thể bạn chưa biết 05/01/2008 05:23:26 (+0700) | #6 | 108349
[Avatar]
secmask
Elite Member

[Minus]    0    [Plus]
Joined: 29/10/2004 13:52:24
Messages: 553
Location: graveyard
Offline
[Profile] [PM] [WWW]
bạn đọc lại phần tôi viết, file ghi ra có 4 phần tử, đọc hết 4 phần tử, lần đọc thứ 5 sẽ fail do method read gặp end of file, nó sẽ set biến eof = true chứ tôi đâu nói rằng cứ đọc hết 4 phần tử là eof file. Việc eof hay không là do io module kiểm tra và set khi ta đọc dữ liệu.
[Up] [Print Copy]
  [Question]   Re: Vài điều về vào ra tệp trong C++ có thể bạn chưa biết 05/01/2008 06:00:10 (+0700) | #7 | 108353
[Avatar]
zThienLongz
Member

[Minus]    0    [Plus]
Joined: 29/08/2006 10:09:05
Messages: 104
Location: World
Offline
[Profile] [PM] [WWW]
ừ bạn nói đúng lần đọc thứ 5 sẽ fail do đó x không thay đổi vì thế in số 4 lần thứ 2.
Mình xin nói rõ về cấu trúc của file tệp. Một tệp có cấu trúc gồm nhiều cửa sổ tệp trong đó có của sổ tệp cuối cùng là eof (viết tăt của End Of File) . Các bạn chú ý khi mở tệp với chế độ ios::app hoặc ios::ate thì vị trí của con trỏ tệp lúc này không phải là trỏ tới EOF , vị trí của ios::app (ios::ate) là nằm liền trước vị trí eof. Tại vị trí ios::app (ios::ate) ta không thể nào thực hiện việc đọc file được do đó , tuy vậy nếu ta vẫn cố tình đọc file như trong bài toán trên thì biến x sẽ không được gán đè lên 1 giá trị nào đó ( giá trị của x ko thay đổi) , mặc dù việc đọc file có lỗi nhưng con trỏ tệp vẫn chuyển sang cửa sổ tệp tiếp theo là EOF.
Vấn đề 1 được giải quyết . Vậy còn vấn đề 2 mọi người giải thích coi
[Up] [Print Copy]
  [Question]   Re: Vài điều về vào ra tệp trong C++ có thể bạn chưa biết 05/01/2008 06:21:02 (+0700) | #8 | 108358
[Avatar]
secmask
Elite Member

[Minus]    0    [Plus]
Joined: 29/10/2004 13:52:24
Messages: 553
Location: graveyard
Offline
[Profile] [PM] [WWW]
lý dó không seek được cũng từ vấn đề 1, khi đã reach eof thì không thể đọc hoặc seek được nữa, do đó khi đọc file mà bạn cần seek thì cần kiểm tra kích thước file để tránh gặp phải eof.
[Up] [Print Copy]
  [Question]   Re: Vài điều về vào ra tệp trong C++ có thể bạn chưa biết 05/01/2008 06:51:27 (+0700) | #9 | 108362
[Avatar]
zThienLongz
Member

[Minus]    0    [Plus]
Joined: 29/08/2006 10:09:05
Messages: 104
Location: World
Offline
[Profile] [PM] [WWW]
Uh do trỏ tới eof rùi nên không seek đc. Chủ đề chấm dứt rất cám ơn sự tham gia nhiệt tình của các bạn đặc biết là secmask (Hix có mỗi 1 người tham gia thao luận ) smilie
[Up] [Print Copy]
  [Question]   Re: Vài điều về vào ra tệp trong C++ có thể bạn chưa biết 05/01/2008 12:17:59 (+0700) | #10 | 108437
TQN
Elite Member

[Minus]    0    [Plus]
Joined: 29/06/2006 22:28:01
Messages: 888
Location: Biết làm chi ?
Offline
[Profile] [PM] [WWW] [Yahoo!]
Cậu build và test trên môi trường nào, tui test trên VC 2005 và VC 2008 Express thì OK, không print ra error. Nếu cậu dùng VC++ 6 thì sẽ print ra error. Đây là bug của STL trong VC++6
[Up] [Print Copy]
  [Question]   Re: Vài điều về vào ra tệp trong C++ có thể bạn chưa biết 05/01/2008 13:23:16 (+0700) | #11 | 108451
[Avatar]
zThienLongz
Member

[Minus]    0    [Plus]
Joined: 29/08/2006 10:09:05
Messages: 104
Location: World
Offline
[Profile] [PM] [WWW]
Hì thế thì lạ nhỉ em build trên Kdevelop với complier 4.1.2 phiên bản gần mới nhất rùi còn gì.
[Up] [Print Copy]
[digg] [delicious] [google] [yahoo] [technorati] [reddit] [stumbleupon]
Go to: 
 Users currently in here 
1 Anonymous

Powered by JForum - Extended by HVAOnline
 hvaonline.net  |  hvaforum.net  |  hvazone.net  |  hvanews.net  |  vnhacker.org
1999 - 2013 © v2012|0504|218|