1. Behaviors
The same code by a student has two different behavior in Visual Studio 2008 and g++ in codepad.org:
(1) in VC++, if a read operation finished and the file pointer is now in file end, eof() still tells false, only after you call read operation again, eof() bit then will be set.
(2) in g++, if a a read operation finished and the file pointer is reach file end, eof() will return true.
2. Root cause
3. Source code of istream::read() and istream::_Read_s(...):
=======================================================================================
Appendix A: Source code of VC ++, related to istream::eof()
=======================================================================================
_Myt& __CLR_OR_THIS_CALL _Read_s(_Elem *_Str, size_t _Str_size, streamsize _Count)
{ // read up to _Count characters into buffer
_DEBUG_POINTER(_Str);
ios_base::iostate _State = ios_base::goodbit;
_Chcount = 0;
const sentry _Ok(*this, true);
if (_Ok)
{ // state okay, use facet to extract
_TRY_IO_BEGIN
const streamsize _Num = _Myios::rdbuf()->_Sgetn_s(_Str, _Str_size, _Count);
_Chcount += _Num;
if (_Num != _Count)
_State |= ios_base::eofbit | ios_base::failbit; // short read
_CATCH_IO_END
}
_Myios::setstate(_State);
return (*this);
}
_Myt& __CLR_OR_THIS_CALL read(_Elem *_Str, streamsize _Count)
{
return _Read_s(_Str, (size_t)-1, _Count);
}
=======================================================================================
Appendix B: Key test code
=======================================================================================
while(!ifile.eof())
{
ifile.read((char*)&Y,sizeof(T));
if(ifile.fail())
{
}
else
{
this->EnQueue(Y);
//将数压入队列中
cout<<"
"<<Y;
//测试是否能将对象的数据保留下来
}
}
}
=======================================================================================
Appendix C: full source code
=======================================================================================
// Stupid sina blog always remove something in source code, for example "<>"
// so the following code could not pass building.
#include
#include
#include
#include
#include
using namespace std;
template
class CIntQueue;
template
class Node
{
public:
Node(T data=0,Node* next=NULL)
{
info=data;
link=next;
}
public:
friend class CIntQueue;
private:
T info;
Node * link;
};
template
class CIntQueue
{
public:
{
MakeEmpty();
}
bool IsEmpty()
//判断队空
{
return head==NULL;
}
bool EnQueue(const T data); // 将数据压入队列,成功TRUE,失败FALSE
void MakeEmpty();
//置空队列
private:
Node *head,*tail;
};
template
CIntQueue::CIntQueue()
{
head=tail=NULL;
ifstream ifile("queue.ini",ios::binary);
T X,Y;
if(!ifile)
{
ofstream ofile("queue.ini",ios::binary);
srand(time(0));
for(int i=0;i<6;i++)
{
X=rand() % 1000;
cout<<"
"<<X;
//将对象的数据输出
this->EnQueue(X);
ofile.write((char*)&X,sizeof(T));
}
ofile.close();
ofile.clear();
}
else
{
while(!ifile.eof())
{
ifile.read((char*)&Y,sizeof(T));
if(ifile.fail())
{
ifile.clear();
// 清楚错误标志;
ifile.ignore(); // NND, 把无效字符干掉!
cout<<"-------------- sss ---------------"<<endl;
}
else
{
this->EnQueue(Y);
//将数压入队列中
cout<<"
"<<Y;
//测试是否能将对象的数据保留下来
}
}
}
ifile.close();
ifile.clear();
}
template
bool CIntQueue::EnQueue(const T data)
{
Node *tempP=new Node();
if(!tempP)
{
return false;
}
else
{
tempP->info=data;
if(tail==NULL)
head=tail=tempP;
else
tail->link=tempP;
return true;
}
}
template
bool CIntQueue::DeQueue(T& data)
{
if(!IsEmpty())
{
return false;
}
else
{
Node *tempP=head;
if(tempP->info!=data)
{
return false;
}
else
{
head=head->link;
delete tempP;
return true;
}
}
}
template
void CIntQueue::MakeEmpty()
{
Node * tempP;
while(head!=NULL)
{
tempP=head;
head=head->link;
delete tempP;
}
}
int main()
{
CIntQueue Queue;
cout<<endl;
CIntQueue Queue1;
cout<<endl;
CIntQueue Queue2;
return 0;
}
=======================================================================================
Appendix D: "web C++": codepad
=======================================================================================
URL:
http://codepad.org