You are here:

C++/File Handling in C++

Advertisement


Question
It's a file handling program in C++.
while executing the program below I got the last number printed twice.My required output is supposed to be twice as if I take input as 10 and 20 then output is supposed to be 10 and 20 only but I got 102020 as the output.
Plz specify the reason :

#include<fstream.h>
#include<conio.h>
void main()
{
ofstream fout("marks.dat");
int m;
cin>>m;
fout<<m<<"\n";
cin>>m;
fout<<m;
fout.close();

ifstream fin("marks.dat");
while(fin)
{
fin>>m;
cout<<m;
}
fin.close();
}

Answer
First, why are you using pre-standard and non-standard headers?

The standard C++ header is <fstream> _not_ <fstream.h> and <conio.h> is Microsoft specific if I remember correctly. Also I see no need for including conio.h anyway, as far as I can tell you are not using anything it defines or declares. Note that the C++ standard was published in 1998 and most, if not all compilers with standard C++ libraries released since then support the new header names (i.e. without a .h extension) - including quite old compilers such as MS VC++ 6.0. Oh and you need to include <iostream> to use cin and cout (in fact they are properly named std::cin and std::cout in standard C++ as most standard library names are in the std namespace - same for std::ofstream and std::ifstream).

Secondly the:

   void main()
   {
   }

Form of main is a non-standard Microsoft perversion. The standard forms are:

   int main()
   {
   }

And:

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

For these forms MS VC6.0 and before requires that an explicit return statement is used, however the standard permits for main only that it can be omitted, in which case it is as if there were a return 0. MS VC6.0 and earlier requires void to be used if there is no return value, which as noted is non-standard.

Anyhow your problem is not so much that you have an i/o problem than that you have a logic problem.

In the loop:

   while ( fin )
   {
       fin >> m;
       cout << m;
   }

Let us run through what happens:

Initially if fin opened OK the file read position is at the beginning of the file. So the first time through the first number you entered, 10, is read and output. All well and good.

The stream is in a good state so the loop continues. This time the second number, 20, is read and output. Again the stream is in a good state so the loop continues.

Oh dear! This time there is no more data in the file and the read operation from fin into m fails, thus m is not updated and retains its previous value. You do not check that the read operation succeeded before using the value supposedly read in so the value of m, 20, is output again. The fin stream is no longer in a good state; it is in the end of file (eof) state; so the loop terminates.

The fix is to add an additional check for fin being good inside the loop:

   while ( fin )
   {
       fin >> m;

       if ( fin )
       {
         cout << m;
       }
   }

Whilst we are on the topic of checking stream states although the presence of the above loop checks that fin is not read from if it is not open the same cannot be said of trying to write to fout if it fails to open: you just assume it does open OK - this may not be true. You may not have access to write to the location or file or you may not have specified a valid path (should be OK in this case as no path is given!), or the file system may have no room for further data etc. You can check the file stream is open using the is_open operation:

   if ( ! fout.is_open() )
   {
       std::cerr << "Unable to open file for writing." << std::endl;
       return 1;  // non-zero returns from main often indicate an error
   }

In fact if opening the file fails then the stream failbit should be set if the stream class is C++ standards conforming so we could also write:

   if ( !fout )
   ...

Lastly, you usually do not need to call close explicitly on a file. In this case you do if fout is open so that the file may be re-opened for reading as a file usually may only have one writer and no other readers or writers, but may have many readers and no writers. However you do not need to explicitly call close for fin - when a stream object is destroyed it will be closed if a file is open on it. In fact this is better for fin, as you should not call close if fin failed to open the file - how can you close a non-open stream?

Note that local objects such as fout and fin are destroyed when they go out of scope. In this case that is at the closing brace of main. Hence without the explicit call to close the "marks.dat" file would still be open for writing on fout when you open it for reading on fin - which should fail. However fout is closed at the end of the program as it is, so removing the line:

  fin.close();

would mean that fin is closed at the same point in the procedure, as the following line is the closing brace to main, where fout and fin are destroyed and files they hold open are closed.

Hope this helps.  

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Ralph McArdell

Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials

©2016 About.com. All rights reserved.