where does open open the file?

G

Gunnar G

I'm having problem reading from the beginning of a file.
Here is the code (more or less)




ifstream codefin;
ofstream codefout;

while (not_annoyed)
{
codefout.open("bar");
// write to bar, works fine
codefout.bar();
system("command to change bar to foo");

codefin.open("foo");
if (!codefin.is_open())
cout<<"ERROR: couldn't open foo for reading"<<endl;

cout<<codefin.tellg();
codefin.seekg(0,ios::beg);
cout<<codefin.tellg();

if (codefin.eof())
cout<<"FRACK!\n";
while (!codefin.eof())
getline(codefin,text);
codefin.close();
}


The files foo and bar are there and they look alright, but when I run the
program, at the second run I get the FRACK output. The file foo is not
opened in the beginning. I add the seekg/tellg commands to see, but there
is nothing but -1 and -1 printed.

What have I done wrong?
 
V

Victor Bazarov

Gunnar said:
I'm having problem reading from the beginning of a file.
Here is the code (more or less)




ifstream codefin;
ofstream codefout;

while (not_annoyed)
{
codefout.open("bar");
// write to bar, works fine
codefout.bar();

You mean,

coutfout.close();
system("command to change bar to foo");

codefin.open("foo");
if (!codefin.is_open())
cout<<"ERROR: couldn't open foo for reading"<<endl;

cout<<codefin.tellg();
codefin.seekg(0,ios::beg);
cout<<codefin.tellg();

if (codefin.eof())
cout<<"FRACK!\n";
while (!codefin.eof())
getline(codefin,text);
codefin.close();
}


The files foo and bar are there and they look alright, but when I run
the program, at the second run I get the FRACK output. The file foo
is not opened in the beginning. I add the seekg/tellg commands to
see, but there is nothing but -1 and -1 printed.

What have I done wrong?

I am not sure. Post _real_ code, *complete* and *compilable*. Even
though 'system' is OS-specific, you could simply explain what you mean
by "change bar to foo". Rename? Why not use 'std::rename'? Anyway...

V
 
G

Gunnar G

I am not sure. Post _real_ code, *complete* and *compilable*.

Here it is then.

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <vector>
#include <string>
using namespace std;

int main(int argc, char* argv[])
{
if (argc!=2) {
cout<<"Usage: "<<argv[0]<<" latex_fil.tex"<<endl<<endl;
return 0;
}

bool codemode=false; // found code?
string line;
string texline;
string tmp="/tmp/.Big_secret_I_love_emacs_and_I_hate_vim.cpp";
string tmptex=tmp+".tex";
string command="highlight -A -L -t 4 -I -f -r -q -i "+tmp+" -o "+tmptex;

vector<string> source;
vector<string> latex_out; // the resulting latex file
string codefile;
ofstream codefout;
ifstream codefin;
ifstream fin(argv[1]);
if (!fin.is_open())
{
cout<<"Could not open the file "<<argv[1]<<endl<<endl;
return -1;
}
cout<<" Opening "<<argv[1]<<endl;
while (!fin.eof())
{
getline(fin,line);
if (line!="\\begin{KODcpp}" && line!= "\\end{KODcpp}")
{
if (!codemode)
latex_out.push_back(line);
else
{
// write to the file
if (line[line.size()-1]=='\\' && line[line.size()-2]=='\\')
line=line.substr(0,line.size()-2);
codefout<<line<<endl;
}
}
else
{
if (!codemode)
{ // open file and write
cout<<" Creating code in "<<tmp<<endl;
codefout.open(tmp.c_str());
if (!codefout.is_open())
{
cout<<"ERROR: couldn't open "<<tmp<<" for writing"<<endl;
}
latex_out.push_back("\\begin{KODcpp}");
codemode=true;
}
else
{ // close file and run highlight and then insert it
codefout.close();
codemode=false;
system(command.c_str());
system("cat /tmp/.Big_secret_I_love_emacs_and_I_hate_vim.cpp");
cout<<endl<<endl;
system("cat /tmp/.Big_secret_I_love_emacs_and_I_hate_vim.cpp.tex");
codefin.open(tmptex.c_str());
if (!codefin.is_open())
{
cout<<"ERROR: couldn't open "<<tmptex<<" for reading"<<endl;
}
cout<<codefin.tellg();
codefin.seekg(0,ios::beg);
cout<<codefin.tellg();
if (codefin.eof()) cout<<"SHIT! What is this crap Im doing?\n";
while (!codefin.eof())
{
getline(codefin,texline);
cout<<"Read :"<<texline<<endl;
latex_out.push_back(texline);
}
codefin.close();
latex_out.push_back("\\end{KODcpp}");
}
}

}
fin.close();

ofstream fout(argv[1]);
if (!fout.is_open())
{
cout<<"Could not open the file "<<argv[1]<<endl<<endl;
return -1;
}
cout<<" Writing "<<argv[1]<<endl;
for (unsigned int i=0;i<latex_out.size();i++)
fout<<latex_out<<endl;
fout.close();
return 0;
}

-------------------------------------------------------------------------
The input file is a latex file that contains

\begin{KODcpp}
.... INSERT c++ code HERE...
\end{KODcpp}

at different places, not nested.
 
R

red floyd

Gunnar said:
I am not sure. Post _real_ code, *complete* and *compilable*.

Here it is then.
int main(){
>
[redacted]
vector<string> source;
vector<string> latex_out; // the resulting latex file
string codefile;
ofstream codefout;
ifstream codefin;
ifstream fin(argv[1]);
if (!fin.is_open())
{
cout<<"Could not open the file "<<argv[1]<<endl<<endl;
return -1;
}
cout<<" Opening "<<argv[1]<<endl;
while (!fin.eof())
{
getline(fin,line);
[loop body redacted]
}
fin.close();

[remainder of function redacted]
}

Your loop is incorrect. Please see FAQ 15.5
(http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.5).

fin.eof() only returns true *AFTER* an attempt to read past EOF. So you
will attempt to read an extra line. Your while loop should read:

while (getline(fin,line))
{
// body of loop.
}

This will exit on EOF.
 
D

David Harmon

On Sat, 21 Jan 2006 21:13:05 GMT in comp.lang.c++, Gunnar G
But the problem seems to be that eof() is still true after closing the file
and opening it again.

After an operation fails, whether because of eof or some other
reason, the stream is in a failed state and will do nothing more for
you until you .clear() it.
 
R

red floyd

David said:
On Sat, 21 Jan 2006 21:13:05 GMT in comp.lang.c++, Gunnar G


After an operation fails, whether because of eof or some other
reason, the stream is in a failed state and will do nothing more for
you until you .clear() it.

Yes, but I believe that this is a deficiency in the standard. .close()
followed by .open() should clear any previous state.
 
M

Mike Wahler

red floyd said:
Yes, but I believe that this is a deficiency in the standard. .close()
followed by .open() should clear any previous state.

If a stream is in a 'fail' state, I don't believe
'close()' will succeed.

-Mike
 
R

red floyd

Mike said:
>

If a stream is in a 'fail' state, I don't believe
'close()' will succeed.

-Mike

EOF is a fail state. Why should it fail to close when you've reached EOF?
 
M

Mike Wahler

red floyd said:
EOF is a fail state.
Right.

Why should it fail to close when you've reached EOF?

Because, as I understand it, once 'good()' returns 'false',
any other operation on the stream will fail, including
'close()'.

There might be exceptions of which I'm unaware, but my
experience has been that when 'eof()' returns 'true',
so will 'fail()' (this makes sense to me because triggering
'eof()' results from an attempt to read past eof, which
would mean the read operation failed, setting 'failbit'.

-Mike
 
B

BobR

Mike Wahler wrote in message ...
Because, as I understand it, once 'good()' returns 'false',
any other operation on the stream will fail, including
'close()'.

There might be exceptions of which I'm unaware, but my
experience has been that when 'eof()' returns 'true',
so will 'fail()' (this makes sense to me because triggering
'eof()' results from an attempt to read past eof, which
would mean the read operation failed, setting 'failbit'.

-Mike

Got me curious, so I added to a test-section I had going:

// #includes
int main(){
using std::cout;
std::ifstream Ping("Bob4.png", std::ios_base::binary );
if( !Ping ){
cout<<"\n ifstream Ping(\"Bob4.png\", binary) FAILED"
<<std::endl;
}
cout<<" ofstream Ping.tellg() = "
<<Ping.tellg()<<std::endl;
Ping.seekg(0, std::ios::end);
cout<<" Ping.seekg(0, ios::end) Ping.tellg() = "
<<Ping.tellg()<<std::endl;
Ping.seekg(0, std::ios::beg);
cout<<" Ping.seekg(0, ios::beg) Ping.tellg() = "
<<Ping.tellg()<<std::endl;
std::vector<unsigned char> Image;
char In(0);
while( Ping.get(In) ){
Image.push_back(static_cast<unsigned char>(In));
}
cout<<"\n Image.size() = "<<Image.size()
<<" bytes."<<std::endl;
for(size_t i(0); i < 100; ++i){
int out( static_cast<int>( Image.at(i) ) );
cout<<std::setw(3)<<out<<" ";
if((i>0)&&(i%10) == 0){ cout<<std::endl;}
}
cout<<std::endl;
cout<<" ifstream Ping.tellg() = "<<Ping.tellg()<<std::endl;

Ping.close();
Ping.open("Bob4.xpm", std::ios_base::binary );
if( !Ping ){
cout<<"\n ifstream Ping(\"Bob4.xpm\", binary) FAILED"
<<std::endl;
}
cout<<" Ping.good() = "<<Ping.good()<<std::endl;
Ping.seekg(0, std::ios::end);
cout<<" Ping.seekg(0, ios::end) Ping.tellg() = "
<<Ping.tellg()<<std::endl;
Ping.clear();
Ping.seekg(0, std::ios::end);
cout<<" Ping.clear(); Ping.seekg(0, ios::end) Ping.tellg() = "
<<Ping.tellg()<<std::endl;
cout<<" Ping.good() = "<<Ping.good()<<std::endl;
Ping.seekg(0, std::ios::beg);
cout<<" Ping.seekg(0, ios::beg) Ping.tellg() = "
<<Ping.tellg()<<std::endl;
Ping.get(In);
unsigned char Unum(static_cast<unsigned char>(In));
int out( static_cast<int>( Unum ) );
cout<<std::setw(3)<<out<<" ";
cout<<std::endl;
return 0;
} // main() end

// -- output --
// ofstream Ping.tellg() = 0
// Ping.seekg(0, ios::end) Ping.tellg() = 4499
// Ping.seekg(0, ios::beg) Ping.tellg() = 0
// Image.size() = 4499 bytes.
// 137 // [snip]
// ifstream Ping.tellg() = -1
// ifstream Ping("Bob4.xpm", binary) FAILED
// Ping.good() = 0
// Ping.seekg(0, ios::end) Ping.tellg() = -1
// Ping.clear(); Ping.seekg(0, ios::end) Ping.tellg() = 25597
// Ping.good() = 1
// Ping.seekg(0, ios::beg) Ping.tellg() = 0
// 47

Note how the stream was in a fail-state after EOF, but, I was able to
..close() {which also puts the stream in a fail-state (according to my old
docs)} and then open the next file (still in a fail-state), then .clear() the
stream and use it to access the 2nd file(something you normally would not
do.<G>).

Comments? Is it UB that just seems to work?

[ This test was on a P4, win98, GCC 3.3.1(MinGW) machine. ]
[ fail-state == std::ios::fail set on stream object. ]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top