Lecture six - Input and Output
In every program, there is some data which is taken as input and generate the processed data as output following the
input > process > output
cycle.
Inputs are the signals or data received by the system and outputs are the signals or data sent from it.
If bytes flow from a device like a keyboard, a disk drive, or a network connection etc. to main memory, this is called input operation
If bytes flow from main memory to a device like a display screen, a printer, a disk drive, or a network connection, etc., this is called output operation.
In most operating systems there is an additional Error output chanel.
The idea is that the regular output of the application goes to the Output channel, and all the warnings and error messages go to the Error channel.
As a programmer you need to decide which output is considered being part of the regular flow of your program.
C++ defines additionally an extra logging output chanel.
The printf() function is declared in "stdio.h" header file and designed to "send" information to output chanel.
It uses placeholder formats code in the output "pattern string".
printf("%d + %d is %d",19, 31, 19+31); //print output integer to STDOUT
The scanf() function is declared in "stdio.h" header file and designed to "read" information from input chanel.
Uses the same placeholders as printf().
The scanf() function requires the memory address of the variable to which you want to save the input value.
If you are trying to input a string using scanf, you should not include the & operator.
scanf("%d",&n); //read an integer from STDIN
char name[80] = { 0 };
scanf("%s", name );
When data is typed at a keyboard, the information does not go straight to the program that is running.
It is first stored in what is known as a buffer - a small amount of memory reserved for the input source.
Sometimes there will be data left in the buffer when the program wants to read from the input source, and the scanf() function will read this data instead of waiting for the user to type something.
The int getchar(void) function reads the next available character from the buffer and returns it as an integer. This function reads only single character at a time.
The int putchar(int c) function puts the passed character on the screen and returns the same character.
#include <stdio.h>
int main( ) {
int c;
printf( "Enter a value :");
c = getchar( );
printf( "\nYou entered: ");
putchar( c );
return 0;
}
Output
Enter a value : this is test
You entered: t
The puts() function is a very simple way to send a string to the screen when you have no placeholders to be concerned about. Puts function writes the string and newline character to stdout.
The gets(char *s) function reads a line from stdin into the buffer pointed to by s until either a terminating newline or EOF (End of File).
#include <stdio.h>
int main( ) {
char str[100];
printf( "Enter a value :");
gets( str );
printf( "\nYou entered: ");
puts( str );
return 0;
}
Output
Enter a value : this is test
You entered: this is test
sscanf() reads data from string and stores them according to parameter format into the locations given by the additional arguments, as if scanf was used, but reading from s instead of the standard input (stdin).
/* sscanf example */
#include <stdio.h>
int main ()
{
char sentence []="Rudolph 12";
char str [20];
int i;
sscanf (sentence,"%s %d",str,&i);
printf ("%s -> %d\n",str,i);
return 0;
}
Output:
Rudolph -> 12
The input / output system creates an interface to the programmer that is independent of the actual device being accessed.
This interface is known as stream.
A stream is a sequence of bytes which acts either as a source from which input data can be obtained or as a destination to which output data can be sent.
The stream model of file I/O was popularized by Unix, which was developed concurrently with the C programming language itself.
You can be writing to console, file, network connection, serial port, etc, using the same functions.
All input and output is performed with stream.
Stream is a sequences of characters organized into lines.
Each line consists of zero or more characters, and end with the newline character.
When program execution begins, input, output and error streams are connected to the program automatically.
C/C++ I/O operations are based on streams of bytes and are device independent.
The same set of operations can be applied to different types of IO devices, despite of the C or C++ syntax / compiler.
Standard input in C and C++ is stream-oriented i.e. the Enter key doesn’t end stream input; it merely rides along in the stream, like any other character.
C / C++ has no direct support for random-access a stream.
You enter the stream at the beginning and can not move through it freely.
To read from a record in the middle of a file, the programmer must create a stream, seek to the middle of the file, and then read bytes in sequence from the stream in order to get there.
Stream variables define in the stdio.h
Name | Description |
stdin | A pointer to a FILE which refers to the standard input stream, usually a keyboard. |
stdout | A pointer to a FILE which refers to the standard output stream, usually a display terminal. |
stderr | A pointer to a FILE which refers to the standard error stream, often a display terminal. |
They are similar to Unix systems file descriptors numbered 0,1,2.
C++ provides its own implementations of stream connected to I/O operations.
stream | description |
cin | standard input stream |
cout | standard output stream |
cerr | standard error (output) stream |
clog | standard logging (output) stream |
The cin object is said to be attached to the standard input device, which usually is the keyboard.
cin is used together with the extraction operator, which is written as >>
This operator is then followed by the variable where the extracted data is stored. For example:
int age;
cin >> age;
Note that the characters introduced using the keyboard are only transmitted to the program when the ENTER (or RETURN) key is pressed.
Operation on cin uses the type of the variable after the >> operator to determine how it interprets the characters read from the input.
Cin is type-safe (you can't have divergence between the type of the object and the type specified in the format string),
#include <iostream>
using namespace std;
int main ()
{
int i;
cout << "Please enter an integer value: ";
cin >> i;
cout << "The value you entered is " << i;
cout << " and its double is " << i*2 << ".\n";
return 0;
}
If the extraction operation fails cin lets the program continue without setting a value for variable i, producing undetermined results if the value of i is used later.
cin read strings as any other variable
string mystring;
cin >> mystring;
cin extraction always considers spaces (whitespaces, tabs, new-line...) as terminating the value being extracted, and thus extracting a string means to always extract a single word.
To get an entire line from cin, there exists a special function, called getline.
string mystr;
cout << "What's your name? ";
getline (cin, mystr);
It assume that we read a line of characters from console which are finished with ENTER.
There are two or three parameters in getline() function. They are a pointer to an array of characters and maximum number of characters and an optional delimiter.
#include <iostream>
using namespace std;
int main( )
{
char line[100];
cin.getline( line, 100, 't' );
cout << line;
return 0;
}
Input
coding
is fun
t
Output:
coding
is fun
The cout object is said to be "connected to" the standard output device, which usually is the display screen.
cout is used together with the insertion operator, which is written as <<.
cout << "Output sentence"; // prints Output sentence on screen
cout << 120; // prints number 120 on screen
cout << x; // prints the value of x on screen
cout << x << " " << 120 << " Output sentence"; //prints chain of statements
The << operator inserts the data that follows it into the stream that precedes it.
For floating-point numbers, the default precison is 6 digits, except that the trailing zeros will not be shown.
This default precision (of 6 digits) include all digits before and after the decimal point, but exclude the leading zeros.
Scientific notation (E-notation) will be used if the exponent is 6 or more or -5 or less.
cout << "|" << 1.20000 << "|" << endl; // |1.2| (trailing zeros not displayed)
cout << "|" << 1.23456 << "|" << endl; // |1.23456| (default precision is 6 digits)
cout << "|" << -1.23456 << "|" << endl; // |-1.23456|
cout << "|" << 1.234567 << "|" << endl; // |1.23457|
cout << "|" << 123456.7 << "|" << endl; // |123457|
cout << "|" << 1234567.89 << "|" << endl; // |1.23457e+006| (scientific-notation for e>=6)
cout << "|" << 0.0001234567 << "|" << endl; // |0.000123457| (leading zeros not counted towards precision)
cout << "|" << 0.00001234567 << "|" << endl; // |1.23457e-005| (scientific-notation for e<=-5)
what will be written here?
cout << "|" << 0.0001234567836387387368376387 << "|" << endl;
There are special functions called manipulators, which allow to manipulate the values return by the stream
//setw set minimal number of characters to be displayed
cout << "|" << setw(5) << 123 << "|" << endl;
// setw() is non-sticky. "|" and 123 displayed with default width
cout << "|" << setw(5) << 1234567 << "|" << endl;
// no truncation of data
cout << fixed << setprecision(2);
cout << "|" << 123.456789 << "|" << endl;
cout << "|" << 123. << "|" << endl;
Output:
| 123|
|1234567|
|123.46|
|123.00|
#include <iostream>
using namespace std;
int main ()
{
int n;
n = 43;
cout << hex << n << endl;
return 0;
}
Output:
2b
The cerr object is said to be attached to the standard error device, which is also a display screen but the object cerr is un-buffered and each stream insertion to cerr causes its output to appear immediately.
#include <iostream>
using namespace std;
int main() {
char str[] = "Unable to read....";
cerr << "Error message : " << str << endl;
}
The clog object is said to be attached to the standard error device, which is also a display screen but the object clog is buffered.
This means that each insertion to clog could cause its output to be held in a buffer until the buffer is filled or until the buffer is flushed.
#include <iostream>
using namespace std;
int main() {
char str[] = "Unable to read....";
clog << "Error message : " << str << endl;
}
iostream makes use of stdio‘s buffering system. So, cin synchronize itself with the underlying C-library’s stdio buffer, so that calls to both scanf() and cin can be interleaved.
This makes cin a lot slower. If you put:
std::ios::sync_with_stdio(false);
then cin becomes faster than scanf() as it should have been.
Notice: With synchronization turned off, using cin and scanf() together will result in an undefined mess.
When you output to a stream from your program, it does not go immediately to the file or terminal.
It will be put into a buffer, where it will be held until there is enough data to be worth outputting - for example, a full block to file on disk. If you are outputting to a terminal, this can be disconcerting: part or all of the output may not appear, even if it was asking a question to which a reply is needed.
Flushing the output stream forces all output to be written out, so that it is in a disk file or appears on the screen.
Data may wait in a buffer until some unspecified event, e.g. buffer full enough, reading from input, or exit from program.
Buffering makes it faster to print a large amount of output, particularly if you are producing the output bit-by-bit (e.g. one character at a time).
Forcing all buffered output to actually be printed is known as "flushing" the stream. A flush can be forced by calling the flush() function associated with each output stream, inserting the magic variable flush into the stream, or inserting endl.
cout << flush;
cout.flush();
cout << endl;
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
int main()
{
for(int i = 1; i < 11; ++i)
{
this_thread::sleep_for(i*200ms);
cout << i <<" "; // This line
}
return 0;
}
vs
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
int main()
{
for(int i = 1; i < 11; ++i)
{
this_thread::sleep_for(i*200ms);
cout << i <<" ";
cout.flush(); // This line
}
return 0;
}
cout and cin are not keywords in the C++ language. They are variables, instances of classes, that have been declared in <iostream>.
cout is a variable of type ostream. cin is a variable of type istream.
Similarly to C, the standard header <sstream> defines a type called stringstream that allows a string to be treated as a stream.
string mystr ("1204");
int myint;
stringstream(mystr) >> myint;
C/C++ programming treats all the devices as files (similar to linux).
In particular standard input, output and error output are types of files.
Therefore we can use the same functions as above to work with files.
Basically every file is just a series of bytes one after the other.
In general every file is a binary file, but if the data in it contains only text (letter, numbers and other symbols one would use in writing), and if it consists of lines, then we consider it a text file.
If you looked at the ASCII table you saw that only very few languages could be written with those letters. Therefore text files have encodings.
A binary file is basically any file that is not "line-oriented".
A program written in the C programming language is a text file, but after you compiled it, the compiled version is binary.
For files you want to read or write, you need a file pointer, e.g.:
FILE *fp;
Where FILE is just a special type. In reality, FILE is a structure that holds information about the file.
In order to open a file, use the function fopen():
fp = fopen(filename, mode);
fopen() returns a FILE* that can then be used to access the file. When the file cannot be opened fopen() will return NULL.
FILE *ifp, *ofp;
char *mode = "r";
char outputFilename[] = "out.list";
ifp = fopen("in.list", mode);
if (ifp == NULL) {
fprintf(stderr, "Can't open input file in.list!\n");
exit(1);
}
ofp = fopen(outputFilename, "w");
if (ofp == NULL) {
fprintf(stderr, "Can't open output file %s!\n", outputFilename);
exit(1);
}
Note that the input file that we are opening for reading ("r") must already exist. In contrast, the output file we are opening for writing ("w") does not have to exist.
Once a file has been successfully opened, you can read from it using fscanf() or write to it using fprintf().
These functions work just like scanf() and printf(), except they require an extra first parameter, a FILE* for the file to be read/written.
ofp = fopen(outputFilename, "w");
fprintf(ofp, "%s %d\n", username, score+10);
When done with a file, it must be closed using the function fclose().
fclose(ifp);
fclose(ofp);
Closing a file is very important, especially with output files. The reason is that output is often buffered.
fprintf(ofp, "Whatever!\n");
it doesn't necessary get written to disk right away, but may end up in a buffer in memory. When the buffer fills up (or when the file is closed), the data is finally written to disk.
C++ handles file IO similar to standard IO.
Steps to handle files in C++:
* Construct an ostream object.
* Connect it to a file (i.e., file open) and set the mode of file operation (e.g, truncate, append).
* Perform output operation via insertion >> operator or write(), put() functions.
* Disconnect (close the file which flushes the output buffer) and free the ostream object.
// basic file operations
#include <iostream>
#include <fstream>
using namespace std;
int main () {
ofstream myfile;
myfile.open ("example.txt");
myfile << "Writing this to a file.\n";
myfile.close();
return 0;
}
Example reading from file:
// reading a text file
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main () {
string line;
ifstream myfile ("example.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
cout << line << '\n';
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
ofstream myfile;
myfile.open ("example.bin", ios::out | ios::app | ios::binary);
Each of the open member functions of classes ofstream, ifstream and fstream has a default mode that is used if the file is opened without a second argument:
class | default mode parameter |
ofstream | ios::out |
ifstream | ios::in |
fstream | ios::in | ios::out |
istream& read (char* s, streamsize n);
Read block of data. Extracts n characters from the stream and stores them in the array pointed to by s.
ostream& write (const char* s, streamsize n);
Write block of data. Inserts the first n characters of the array pointed by s into the stream.
// Copy a file
#include <fstream> // std::ifstream, std::ofstream
int main () {
std::ifstream infile ("test.txt",std::ifstream::binary);
std::ofstream outfile ("new.txt",std::ofstream::binary);
// get size of file
infile.seekg (0,infile.end);
long size = infile.tellg();
infile.seekg (0);
// allocate memory for file content
char* buffer = new char[size];
// read content of infile
infile.read (buffer,size);
// write to outfile
outfile.write (buffer,size);
// release dynamically-allocated memory
delete[] buffer;
outfile.close();
infile.close();
return 0;
}
http://www.cplusplus.com/doc/tutorial/basic_io/
http://www.geeksforgeeks.org/basic-input-output-c/
https://www.w3schools.in/cplusplus-tutorial/input-output/
https://www.ntu.edu.sg/home/ehchua/programming/cpp/cp10_IO.html
https://en.wikibooks.org/wiki/C_Programming/Simple_input_and_output
https://www.sitepoint.com/data-input-and-output-in-c-part-1/
https://www.cs.hmc.edu/~geoff/classes/hmc.cs070.200109/notes/io.html
https://sites.google.com/site/usfcomputerscience/basic-input-output
https://docs.python.org/3/library/io.html
https://www.cs.bu.edu/teaching/c/file-io/intro/
https://www.ntu.edu.sg/home/ehchua/programming/cpp/cp10_IO.html