Input Output
Contents
Console Input/Output
C Functions
C++ includes most of what the language C has to offer and that includes the input output functions that predate "cout" and "cin".File: i1.cpp
#include <stdio.h> int main() { char ch ; printf( "Enter a character:" ) ; ch = getchar() ; printf ( "%c\n" , ch ) ; printf( "A literal string.\n" ) ; printf( "Using format specifiers. %d %d\n" , 5, 10 ) ; int x1 ; printf ( "Enter a number:" ) ; scanf( "%d" , &x1) ; printf( "x1 is %d\n" , x1 ) ; //Input buffer has the end of line character in it //creating a problem. printf ( "Enter a number -number-:" ) ; scanf( "-%d-" , &x1) ; printf( "x1 is %d\n" , x1 ) ; return ( 1) ; }
Output: $ g++ i1.cpp ; ./a.exe Enter a character:e e A literal string. Using format specifiers. 5 10 Enter a number:4 x1 is 4 Enter a number -number-:x1 is 4
We notice that we are not given an opportunity to enter the last "scanf". The way the input works is when the user types in something and hits the "Enter" key the input is stored in a buffer and the "scanf" then reads from the buffer.
The
scanf( "%d" , &x1) ;reads the number from the buffer but left the new line character in there and the next scanf read that. We can correct this in the following program.
File: i1a.cpp
#include <stdio.h> #include <string.h> int main() { char ch ; printf( "Enter a character:" ) ; ch = getchar() ; printf ( "%c\n" , ch ) ; printf( "A literal string.\n" ) ; printf( "Using format specifiers. %d %d\n" , 5, 10 ) ; int x1 ; printf ( "Enter a number:" ) ; scanf( "%d" , &x1) ; printf( "x1 is %d\n" , x1 ) ; //Input buffer has the end of line character in it //creating a problem. getchar() ; //read the end of line character printf ( "Enter a number -number-:" ) ; scanf( "-%d-" , &x1) ; printf( "x1 is %d\n" , x1 ) ; getchar() ; char buffer[256] ; printf( "Enter your full name:" ) ; //Does not read the full name scanf( "%s" , buffer ) ; printf( "%s\n" , buffer ) ; //Clear the buffer scanf( "%s" , buffer ) ; printf( "%s\n" , buffer ) ; getchar() ; //printf( "Enter your full name:" ) ; // memset( buffer, 0 , 256 ) ; //Will read the whole line // gets ( buffer ) ; // printf( "%s\n" , buffer ) ; return ( 1) ; }The "gets" function call has been deprecated. If we do need to get it compiled we can use the "-std=" option to specify what version of C++ we want to use. The function has been replaced with "getline" that uses a string object.
g++ -std=c++03 i1a.cpp
The "printf" function has different format specifiers for the place holders. Some of the specifiers are:
%c Character %d Signed integer %f Float values %lf Double %p Pointer The "printf" function can also specify widths of the placeholders.
File: i2.cpp
#include <stdio.h> int main() { printf ( "%10s %10s\n" , "Number" , "Square" ) ; for( int i1=1 ; i1 <=5 ; i1++ ) { printf( "%10d %10d\n" , i1 , i1*i1 ) ; } //for //Left justified printf ( "%-10s %-10s\n" , "Number" , "Square of a number" ) ; for( int i1=1 ; i1 <=5 ; i1++ ) { printf( "%-10d %-10d\n" , i1 , i1*i1 ) ; } //for return ( 1) ; }Output: $ ./a.exe Number Square 1 1 2 4 3 9 4 16 5 25 Number Square of a number 1 1 2 4 3 9 4 16 5 25The below example shows how to use the format specifier for a floating point number.
File: i3.cpp
#include <stdio.h> int main() { float PI = 3.142 ; printf ( "%-10s %-10s\n" , "Radius" , "Area" ) ; for( float i1=1 ; i1 <=5 ; i1++ ) { printf( "%-10.0f %-10.2f\n" , i1 , i1*i1*PI ) ; } //for return ( 1) ; }Output: $ ./a.exe Radius Area 1 3.14 2 12.57 3 28.28 4 50.27 5 78.55
The "printf" and "scanf" have a different form called "sprintf" and "sscanf" used for writing and reading to strings instead of the console.
File: i4.cpp
#include <stdio.h> int main() { char buffer[256] ; int x1 = 0 ; sprintf( buffer , "%d-Test" , 25 ) ; printf( "Buffer %s\n" , buffer ) ; sscanf ( buffer, "%d-Test" , &x1 ) ; printf( "x1: %d\n" , x1 ) ; return ( 1) ; }Output:$ g++ i4.cpp ; ./a.exe Buffer 25-Test x1: 25We can use "sprintf" to convert a number to a string and also read a number from a string. The function "atoi" can also be used to convert a string to an integer and "itoa" to convert an integer to string. However the function "itoa" is not standard and not supported by most compilers.
File: i4a.cpp
#include <stdio.h> #include <stdlib.h> int main() { char buffer[256] ; int x1 = 10 ; int y1 = 0 ; itoa( x1, buffer, 10 ) ; printf( "Buffer %s\n" , buffer ) ; y1 = atoi( buffer ) ; printf( "y1: %d\n" , y1 ) ; return ( 1) ; }[amittal@hills io]$ itoa( x1, buffer, 10 ) ; -bash: syntax error near unexpected token `x1,'The functions can be used to parse a string into different inputs.
File: i5.cpp
#include <stdio.h> #include <stdlib.h> #include <string.h> int main () { int day, year; char weekday[20], month[20], dtm[100]; strcpy( dtm, "Saturday March 25 1989" ); sscanf( dtm, "%s %s %d %d", weekday, month, &day, &year ); printf("%s %d, %d %s\n", month, day, year, weekday ); return(0); }Exercise
1)
Ask the user for 2 integers representing a range ( of Celsius) and then print a table showing the conversion to Fahrenheit with the Celsius values getting incrdmented by 1. The table should be left justified with 2 decimal points for the Fahrenheit. Also print a heading. You can use "C" and "F" as the heading and use 10 as the width for each heading as well as 10 for the number values. Total width is 20.
File: ex1.cpp
#include <stdio.h> int main() { int lowRange ; int highRange ; printf( "Print the lower range:" ) ; scanf( "%d" , &lowRange ) ; printf( "Print the higher range:" ) ; scanf( "%d" , &highRange ) ; return 0; }Output should look like: $ g++ ex1s.cpp ; ./a.exe Print the lower range:50 Print the higher range:80 C F 50 122.00 51 123.80 52 125.60 53 127.40 54 129.20 55 131.00
File: ex1s.cpp
C++ Console Input/Output
File: c1.cpp
#include <iostream> #include <iomanip> using namespace std ; int main() { cout << "*" << setw(10) << 17 << "*" << endl ; cout << "*" << setw(10) << "Heading1" << "*" << endl ; //setw needs to be applied to each output cout << "*" << "Heading2" << "*" << endl; cout << left << "---------------" << endl ; cout << "*" << setw(10) << 17 << "*" << endl ; cout << "*" << setw(10) << "Heading1" << "*" << endl; cout << fixed << setprecision(2) << 3.14159 << endl ; cout << right ; cout << fixed << setprecision(2) << setw(10) << 3.14159 << endl ; return 0; }We also have the same problem with just a single word being read when we docin >> str1
File: c2.cpp
#include <iostream> #include <iomanip> using namespace std ; int main() { string str1 ; cout << "Enter your name." ; cin >> str1 ; cout << str1 << endl ; //Reads the second word cin >> str1 ; //cout << (int)cin.peek() << endl ; //cin.get() ; //Another way //read and discard up to 100 characters from //the input buffer, or until a newline is read cin.ignore(100, '\n') ; //resets any error flags in the cin stream cin.clear() ; cout << "Enter your name again." ; getline ( cin, str1 ) ; cout << str1 << endl ; cout << "Enter your name again." ; getline ( cin, str1 ) ; cout << str1 << endl ; return 0; }Output: $ g++ c2.cpp ; ./a.exe Enter your name.Marvin Hagler Marvin Enter your name again.Marvin Hagler Marvin Haglerstring str1 ; cout << "Enter your name." ; cin >> str1 ;The "cin >> str1" only reads a word and not the whole line. We need to use the function "getline" to read the whole line. The code shows some of the cin functions. The "peek" lets us see the next character in the buffer. The "ignore" function clears the buffer. We can specify the number of characters to clear or clear the buffer till a specific character is found. The below program how errors can be handled with "cin" .
File: c2a.cpp
#include <iostream> #include <iomanip> using namespace std ; int main() { int i1= 0 ; cout << "Enter an integer." ; cin >> i1 ; //cout << "i1:" << i1 << endl ; //Once cin goes into an error state. //All bets are off //cout << "Enter an integer." ; //cin >> i1 ; //cout << "i1:" << i1 << endl ; while( !std::cin ) { cin.clear() ; cin.ignore(10000, '\n'); cout << "Enter an integer." ; cin >> i1 ; } return 0; }
File: c3.cpp
#include <iomanip> #include<limits> #include<iostream> using namespace std ; int main() { int x1 = 0 ; /* cout << "Enter x1 value." ; cin >> x1 ; cout << x1 << endl ; while(1) { if(cin.fail()) { //clears the error flag cin.clear() ; //Ignore anything else in the buffer cin.ignore( numeric_limits<streamsize>::max() , '\n' ); cout<< "You have entered wrong input."<< endl; cin >> x1 ; } else break ; } cout << "x1:" << x1 << endl ; */ //Another way .. Does not work cout << numeric_limits<int>::max() << endl ; x1 = numeric_limits<int>::max() ; while ( x1 == numeric_limits<int>::max() ) { cout << "Enter x1 value." ; cin >> x1 ; //x1 is 0 at this point cout << x1 << endl ; } //while return 0; }Exercise
2) Repeat the exercise 1 to use cin and cout instead.
3) The below program skips "getline" call. Explain why the problem occurs and correct it by using the "cin.get()" function call. Correct the problem by using "getline" for the first "cin" call.
File: ex3.cpp
#include <iostream> #include <iomanip> #include <string> using namespace std ; int main() { string str1 ; cout << "Enter a word." ; cin >> str1 ; cout << "first input:"<< str1 << endl; cout << "Enter a line." ; getline(cin, str1 ) ; cout << "Line input:" << str1 << endl ; return 0; }
The "cout" is a class that someone wrote and is not part of the C++ basic, core syntax. The class is a part of the standard library that became part of the C++ standard. We can also write a similar class.
File: c4.cpp
#include <iostream> #include <iomanip> #include<limits> using namespace std ; class mycout { public: static string myendl ; mycout& operator<<( int& x1) { printf ( "%d" , x1 ) ; return ( *this ) ; } mycout& operator<<(const char* str1) { printf ( "%s" , str1 ) ; return ( *this ) ; } mycout& operator<<(string& str1) { printf ( "%s" , str1.c_str() ) ; return ( *this ) ; } }; string mycout::myendl = "\n" ; int main() { int x1 = 0 ; mycout obj1 ; string str1 = "Another String" ; obj1 << x1 << " Test some string\n" ; obj1 << str1 ; obj1 << mycout::myendl << mycout::myendl ; return 0; }Text and binary files
Both text and binary files store 0's and 1's .
A text file has characters with the range of 0 to 127 while a binary file will have characters within the range of 0 to 255 . A text file can be thought of something we can open with an editor. If we open a binary file with an editor then we will see gibberish on the screen. On the unix system we can see a file in it's binary form with the command:
hexdump -C nameOfFile
Sample Output: [amittal@hills InputOutput]$ hexdump -C demofile.txt 00000000 42 61 63 68 0a 42 65 65 74 68 6f 76 65 6e 0a 4d |Bach.Beethoven.M| 00000010 6f 7a 61 72 74 0a 53 63 68 75 62 65 72 74 0a 42 |ozart.Schubert.B| 00000020 61 63 68 0a 42 65 65 74 68 6f 76 65 6e 0a 4d 6f |ach.Beethoven.Mo| 00000030 7a 61 72 74 0a 53 63 68 75 62 65 72 74 0a |zart.Schubert.| Each character is shown in 2 hexadecimal characters. Let us run the same command on a binary file. [amittal@hills InputOutput]$ hexdump -C a.out | more 00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| 00000010 02 00 3e 00 01 00 00 00 d0 08 40 00 00 00 00 00 |..>.......@.....| 00000020 40 00 00 00 00 00 00 00 40 1d 00 00 00 00 00 00 |@.......@.......| 00000030 00 00 00 00 40 00 38 00 09 00 40 00 1f 00 1e 00 |....@.8...@.....| 00000040 06 00 00 00 05 00 00 00 40 00 00 00 00 00 00 00 |........@.......| 00000050 40 00 40 00 00 00 00 00 40 00 40 00 00 00 00 00 |@.@.....@.@.....|We can see that some of the character in the binary output such as "d0" ( Decimal 208 ) are greater than 127 . Text files will usually be terminated by end of line character and upon opening the file or printing the file we will see line by line output. Textpad is an editor that can open files in text or binary mode and can be used to see the underlying characters of a file. Binary files will usually hold the internal representation of data. Let's assume we have a C program with a variable"x1" int x1 = 2134562 ;The variable holds a large number 2 million and something. When this is written to a text file it is written as is with 7 characters. Remember an int in "C" is usually represented by 4 bytes which contains the corresponding binary number.Converting the above number gives us: In hex ?00 20 92 22?The above 4 bytes is what will get written to the binary file.Reading and Writing to Files
Writing an integer to a binary file.
File: f1.cpp
#include <stdio.h> #include <cstring> int main() { FILE* cfPtr ; char buffer[100] ; strcpy( buffer, "hello" ) ; if ( (cfPtr = fopen( "data1.txt" , "wb" ) ) == NULL ) { printf( "File could not be opened.\n" ); } else { for( int i1=100 ; i1 <= 110 ; i1++ ) { fwrite( &i1, sizeof( i1 ), 1, cfPtr ) ; } fwrite( buffer, strlen( buffer), 1, cfPtr ) ; fclose ( cfPtr ); } /* fclose closes the file */ return 0; }
Reading the values back from the data file.
File: f2.cpp
#include <stdio.h> int main() { FILE* cfPtr ; int x1 ; char buffer[100] ; if ( (cfPtr = fopen( "data1.txt" , "rb" ) ) == NULL ) { printf( "File could not be opened.\n" ); } else { for( int i1=1 ; i1 <= 10 ; i1++ ) { int x2 ; fread( &x2, sizeof( x2 ), 1, cfPtr ) ; printf( "Value read was: %d\n" , x2 ) ; } fread( &buffer, 5, 1, cfPtr ) ; buffer[5] = 0 ; printf( "Value read was: %s\n" , buffer ) ; fclose ( cfPtr ); /* fclose closes the file */ } return 0; }The above shows how we can read the binary values back. Let us write the numbers in text format.
File: f3.cpp
#include <stdio.h> //Text data int main() { FILE* cfPtr ; if ( (cfPtr = fopen( "data2.txt" , "w" ) ) == NULL ) { printf( "File could not be opened.\n" ); } else { fputs( "This is a line.\n" , cfPtr) ; fprintf( cfPtr, "This is the second line.\n" ) ; int x1=100 ; fprintf( cfPtr, "%d\n" , x1 ) ; fclose ( cfPtr ); } char buffer[100] ; if ( (cfPtr = fopen( "data2.txt" , "r" ) ) == NULL ) { printf( "File could not be opened.\n" ); } else { fgets( buffer ,100, cfPtr ) ; printf( "%s\n" , buffer ) ; //Problem because of spaces //Will read only one word fscanf( cfPtr, "%s" , buffer ) ; printf( "%s\n" , buffer ) ; //Read rest of the line fgets( buffer ,100, cfPtr ) ; printf( "%s\n" , buffer ) ; //Read the integer fgets( buffer ,100, cfPtr ) ; printf( "%s\n" , buffer ) ; fclose ( cfPtr ); } return 0; }Exercise
4) Rewrite exercise 1 to take the range as input but instead of writing to the console; write the values to a file named "conversion.txt" using the open call.
//-------------------------------------------------------------
C++ File Reading and Writing
There are 2 kinds of file access methods. One is sequential and the other random. In the sequential method data is first read from the beginning of the file in a sequential manner. If we need to read some data In the random access method we are allowed to read data from any position in the file .
Writing to a file
To write data to a file:
File: of1.cpp
#include <iostream> #include <fstream> using namespace std; int main() { int x1 ; ofstream outputFile; outputFile.open("demofile.txt"); cout << "Now writing data to the file.\n"; // Write four names to the file. outputFile << "Bach\n"; outputFile << "Beethoven\n"; outputFile << "Mozart\n"; outputFile << "Schubert\n"; x1 = 100 ; outputFile << x1 << endl ; // Close the file outputFile.close(); cout << "Done.\n"; return 0; }To write data to a file we create an "ofstream" object. The type "ofstream" is from the standard template library and that means it's a class and is not part of the C++ language feature. What that means is that someone wrote the class using C++ . The object "outputFile" is an instance of the "ofstream" object and can be used the way "cout" is used. The statement:outputFile << "Bach\n"; will write "Bach" to the file and will also write the end of line character "\n" to the file. After running the above program our "demofile.txt" will contain: Bach Beethoven Mozart Schubert 100 Instead of the following 2 statements: ofstream outputFile; outputFile.open("demofile.txt"); We can also write the above in one statement ofstream outputFile("demofile.txt") ; The above states that "outputFile" object is of type "ofstream" and will open the file "demofile.txt" . Below program shows how this is used:
File: of2.cpp
// This program writes data to a file. #include <iostream> #include <fstream> using namespace std; int main() { int x1 ; ofstream outputFile("demofile.txt", ofstream::app) ; //outputFile.("demofile.txt", ofstream::app) ; cout << "Now writing data to the file.\n"; // Write four names to the file. outputFile << "Bach\n"; outputFile << "Beethoven\n"; outputFile << "Mozart\n"; outputFile << "Schubert\n"; x1 = 100 ; outputFile << x1 << endl ; // Close the file outputFile.close(); cout << "Done.\n"; return 0; }Reading from a file
Data can be read from a file using the "ifstream" class. Suppose there is a file called "friends.txt". Contents of the file are://Friends.txt John Patrick Lee Williams
File: if1.cpp
#include <iostream> #include <fstream> using namespace std; int main() { ifstream inputFile; string name; inputFile.open("friends.txt"); cout << "Reading data from the file.\n"; inputFile >> name; // Read name 1 from the file cout << name << endl ; inputFile >> name ; // Read name 2 from the file cout << name << endl ; inputFile.close() ; return ( 1) ; }Reading a line from a file.
File: if2.cpp
#include <iostream> #include <fstream> using namespace std; int main() { ofstream outputFile ; ifstream inputFile ; int number ; string word ; outputFile.open("data6.txt"); cout << "Now writing data to the file.\n"; // Write four names to the file. outputFile << "We are in a C++ class." << endl ; outputFile << "What" << endl ; outputFile << "fun." << endl ; outputFile.close() ; // Open the file. inputFile.open("data6.txt"); // If the file successfully opened, process it. if (inputFile) { cout << "Inside if condition." << endl ; inputFile >> word ; cout << word << endl ; inputFile >> word ; cout << word << endl ; inputFile >> word ; cout << word << endl ; getline( inputFile, word ) ; cout << word << endl ; // Close the file. inputFile.close(); } else { // Display an error message. cout << "Error opening the file.\n"; } //if return 0; } //mainWriting binary data.
File: if3.cpp
#include <iostream> #include <fstream> using namespace std; int main() { ofstream outputFile ; ifstream inputFile ; int number ; string word ; int x1 = 100 ; outputFile.open("data7.txt"); cout << "Now writing data to the file.\n"; outputFile.write( (const char*)&x1, sizeof( x1 ) ) ; x1=200 ; outputFile.write( (const char*)&x1, sizeof( x1 ) ) ; outputFile.close() ; inputFile.open( "data7.txt", ::std::ios::binary); while ( inputFile ) { int x2=0 ; inputFile.read((char*) &x2, sizeof(x2 ) ) ; if (inputFile) { ::std::cout << "Read a " << x2 << "\n"; } } //while return 0; } //main
Using open call.
On Unix like systems we also have the "open", "read", "write", "close" calls to read/write to the files. However this call is not portable and may not work on other operating systems. The below program shows how the calls work in a program.
File: o1.cpp
// C program to illustrate close system Call #include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <string.h> int main() { int fd1 = open("data.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644) ; int sz ; if (fd1 < 0) { perror("c1"); return(1); } printf("opened the fd = % d\n", fd1); sz = write(fd1, "hello class\n", strlen("hello class\n")); // Using close system Call if (close(fd1) < 0) { perror("c1") ; return(1) ; } printf("closed the fd.\n"); return( 0 ) ; }Solutions
1)
File: ex1s.cpp
2)
File: ex2s.cpp
3) The "cin >> str1 ;" only reads a word.