You are here:

C++/C++ Question

Advertisement


Question
How would you create a function to either take input from a file, or from keyboard entry. All being in the same function

Answer
As this is a C++ question I shall assume a standard C++ environment - which if you are using the likes of MS Windows will mean a console application (i.e. it runs in a console or DOS box window).

The idea is to use an I/O stream of some kind. I shall assume the decision of where exactly the input comes from is external to the function.

In fact we need to use an input file stream. In this case the execution and program start up environment will commonly use several standard file I/O streams - the one we are interested in for keyboard input is the standard input stream. Unless this is redirected the console will map this to the keyboard.

It may seem strange that a file stream can be used for input or output to things other than files but this is the case and quite common. In fact other things you can transfer data to and from include devices like serial ports.

Now due to C++ being largely compatible with C it has several different sets of standard library functionality to operate on streams of various kinds. At the base there are of course the facilities provided by the operating system - which of course vary according to your operating system.

The ones used for files by C are functions commonly prefixed with an f - fopen, fclose, fread and fwrite etc. and work with FILE structures - that is you open a file using its path name and this initialises a FILE object which is returned to you by pointer and which you then use to pass to fread and the like to read the contents of the files. By the start of execution of main there are already the standard file streams that are open for us - in particular the standard input FILE stream which is called stdin - so if we wish to read from the keyboard we can pass our function stdin instead of a FILE object for some other open file. To use these C function include <stdio.h> or, in modern C++, <cstdio>.

Now C++ has its own set of stream classes - sometimes called the IOStream library - which is part of the standard C++ library. Here we create an input file stream object - std::ifstream, open it, get input from it, close it etc.. We pass this object around to manipulate the file rather than the C FILE object. The C++ IOStream equivalent of stdin is std::cin. Note that in the names given previously std followed by :: indicates the name is in standard C++ library namespace, called std. To use std::cin include <iostream>, to use std::ifstream include <fstream>.

So all you need to do is pass in an input file stream object. In fact to make your function even more useful you do not even have to make it a file stream - you just pass in an input stream object. Of course this should be passed by reference, and as we will undoubtedly modify its state by reading data through it, it should not be const:

       bool InputData( std::istream & in )
       {
       // read data from the stream
         return stream_ok;
       }

Here we have a function that takes a std::istream by reference which can then be read from using what ever means you wish that is supported by  std::istream - such as the extraction operator ( in >> myvalue; ) or one of the get or read member functions. I made an arbitrary decision to make the function return a value indicating whether the reading was successful. Of course you could always check the stream after the function has been called to find out its state:

       std::ifstream inStream( "my_data_file" );
       if ( inStream.is_open() )
       {
         InputData( inStream );
         if ( instream.fail() )
         {
         // report error
         }
       }

In such a case maybe InputData should return nothing (i.e. void) instead - its your design so you will know what sort of usage you intend for the function you are asking about. Of course if you wish keyboard input you just pass std::cin to InputData:

       InputData( std::cin );

The point about passing a std::istream rather than a std::ifstream is that std::istream is a generalisation of stream input - that is it is a base class of std::ifstream so std::ifstream is a std::istream. Unless your function needs to do file-specific stream operations - which seems unlikely in this case - it is better to pass the more general type. For example your function could be used to extract its data from a string formatted in the same way as an input file by using a std::istringstream (include <sstream>, and <string> for std::string):

       std::string stringData("the data in a format like the file");
       std::istringstream stringStream( stringData );
       InputData(stringStream);
       if ( stringStream.fail() ) ...

One interesting thing about stdin or std::cin is that the 'file' they are attached to is the keyboard by default but may be redirected to take input from a file on the command line:

       my_program < my_input_file

This works for output as well:

       my_program > my_output_file

The output equivalent of stdin is stdout; the std::cin output equivalent is std::cout.

Note that you may find that you will require quite different error checking, reporting, and handling if the input is from the keyboard.  If input is from the keyboard the user can be told immediately a problem occurs and asked to retry the entry. However when reading from a file or string then the user cannot change the data so you probably have to get out as soon as an error occurs, report the error as a general "this file is bad at position nnn" type error and maybe terminate the program. One way to do this would be to pass in a Boolean (bool) value to indicate whether the input is interactive or not - interactive implying the user is present and entering the data as you go. This would also allow you to provide prompts to the user to remind them what to enter, but to suppress them when reading from file or string etc.

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.