-1
\$\begingroup\$

[Please don't comment on using Turbo C++. I know that it's obsolete but we are taught this way only.]

#include<fstream.h>
#include<conio.h>
void main()
{
 clrscr();
 char ch;
 ifstream read;
 read.open("Employee.txt");
 ofstream write;
 write.open("Another.txt");

 while(!read.eof())
    {
    read.get(ch);  //Also when I use, write<<read.get(ch) is it writes some kind of
    write<<ch;     //address in the file. Please tell me about that too why it happens.
    }
 read.close();
 write.close();
 getch();
}

The problem I'm facing is that it appends ÿ character at the end of 'another' file.

enter image description here

\$\endgroup\$
4
\$\begingroup\$

This is a deprecated head (C++ headers don't have .h on the end)

#include<fstream.h>
// Should be
#include<fstream>

OK your Turbo stuff:

#include<conio.h>

This is not a valid main() declaration:

void main()

There are two valid main() declarations accepted by the standard:

int main()
int main(int argc, char* argv[])

Declare varaibles as close to the point of use as you can:

char ch;  // You don't use this till the other end of the function.
          // How am I supposed to remember its type. O yes you
          // seem to have just shortened the name of the type.
          // more meaningful names is also useful (this is not a
          // tersity competition).

May as well use the constructor the at opens them.

ifstream read;
read.open("Employee.txt");

// Much easier to read and write as
ifstream read("Employee.txt");

Same again

ofstream write;
write.open("Another.txt");

Note. If you had included the correct header file. These are both in the standard namespace.

This is nearly always wrong way to write a loop

while(!read.eof())

The problem is that the eof flag is not set until you read past the end of file. But the last successful read will read upto the end of file (not past). So even though there is absolutely no data left on the stream the eof flag is still false. It is not until you try and read a character that is not there that the flag is set.

To get around this you can write the loop like this.

while(!read.eof())
{
    read.get(ch);
    if (read.eof()) { break;}

    // PS. This is why you are seeing the funny character on your output
    //     You read past the end of file and even though the stream told
    //     you it had failed (by setting the eof flag). You failed to
    //     check the value after the read and thus printed some random
    //     garbage to your output (as ch was set to random stuff).

    // STUFF
}

BUT wait. There are more problems with the above. What happens if eof is never set. But you say that can never happen. Actually it can (and is very common in normal use). If you set any of the other bad bits on the stream you now get stuck in an infinite loop. Because once the bad bit is set no more data is read from the stream so it never advances to reach the end (luckily for you get() is not going to do that but other standard read commands are). But what happens if the file does not exist? It is not eof() but a bad bit is set. So if the file does not exist your loop enters an infinite blocking loop.

while(!read.eof())
{
    int x;
    read >> x;
    if (read.eof()) { break;}

    // STUFF
}

Here if the input does not contain an int you have an infinite loop. You can fix it by testing for read.bad() but now things are getting more complex.

But an easier way to write this is (The correct way):

while(read.get(ch))
{
    // STUFF
}

Your loop is only entered if the read worked.
This works because the result of the get() is a reference to the stream (i.e. a reference to read). When a stream is used in a boolean context (like a while loop test) it is auto converted into a boolean like type. The value of this boolean type is based on the state of the stream, if you can still read from it (ie the last read worked) then it is true otherwise false.

As noted above you should declare variables as close to the point of use as possible. Because you declared ch at the top but only use it inside the loop you are polluting the rest of the code with an unneeded value. This can lead to errors where you accidentally use the value.

Also when I use, write<<read.get(ch) is it writes some kind of address in the file. Please tell me about that too why it happens.

This happens because the result of get() returns a reference to the stream. When used on the right hand side of operator<< there is a conversion into a type that can be written to an output stream. As it happens it is the same as the conversion that happens above (as explained for while). The boolean like type in C++03 is a pointer (NULL pointer is false all other pointers are true). In C++11 this was fixed and the boolean like type is actually a bool. I would not read too much into the value of the pointer only that it is (or is not) NULL.

Don't manually close the streams. This is what RAII is for: see My C++ code involving an fstream failed review

read.close();
write.close();

You can use standard functions to achieve the same affect as pausing for the human.

getch();

// standard compliant way.
std::cin.clear();
std::string line;
std::getline(std::cin, line);
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.