How would you create a function to either take input from a file, or from keyboard entry. All being in the same function
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
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 );
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.