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) ;
read 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 ) ; getchar() ; printf( "Enter your full name:" ) ; memset( buffer, 0 , 256 ) ; //Will read the whole line gets ( buffer ) ; printf( "%s\n" , buffer ) ; return ( 1) ;}
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:
$ g++ i2.cpp ; ./a.exe Number Square 1 1 2 4 3 9 4 16 5 25 Number Square of a number 1 12 43 94 165 25
The 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:
$ g++ i3.cpp ; ./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" , 25 ) ; printf( "Buffer %s\n" , buffer ) ; sscanf ( buffer, "%d" , &x1 ) ; printf( "x1: %d\n" , x1 ) ; return ( 1) ;}
Output:
$ ./a.exe Buffer 25 x1: 25
We 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. The functions can be used to parse a string into different inputs. 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);}
Output:
$ g++ i5.cpp ; ./a.exe March 25, 1989 Saturday
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.
Output should look like:
$ g++ ex1.cpp ; ./a.exe Enter the start range:10 Enter the high range:20 C F 10 50.0011 51.8012 53.6013 55.4014 57.2015 59.0016 60.8017 62.6018 64.4019 66.2020 68.00
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;}
Output:
$ g++ c1.cpp ; ./a.exe
* 17*
* Heading1*
*Heading2*
---------------
*17 *
*Heading1 *
3.14
3.14
Exercise
2) Repeat the exercise 1 to use cin and cout instead.
We know that everything in the computer in terms of data is 1 and 0's. We have different kinds of data that we can classify as text or binary data. This classification can easily be seen in files. The text files usually contain something that is readable when we print the file out on console.
File: "date.txt"
Sat, May 23, 2020 8:02:42 PM
$ cat date.txt
Sat, May 23, 2020 8:02:42 PM
Binary files on the other hand usually contain gibberish characters when we print the file out.
File: "a.exe"
$cat a.exe
.text.data`.bss▒R``o▒
Text files will have bytes that are in the range 0 to 127 corresponding to the characters in the ASCII chart where as binary files can have any range from 0 to 255 leading to unprintable characters when we print the file out.
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. In fact any integer will always be written as 4 bytes.
Fopen
Writing binary data to a file.
File: "f1.c"
#include <stdio.h>
int main()
{
FILE* cfPtr ;
if ( (cfPtr = fopen( "data3.txt" , "wb" ) ) == NULL )
{
printf( "File could not be opened.\n" );
} /* end if */
else
{
for( int i1=1 ; i1 <= 10 ; i1++ )
{
fwrite( &i1, sizeof( i1 ), 1, cfPtr ) ;
}
fclose ( cfPtr ); /* fclose closes the file */
} /* end else */
return 0; /* indicates successful termination */
} /* end main */
File: "f2.c"
#include <stdio.h>
int main()
{
FILE* cfPtr ;
if ( (cfPtr = fopen( "data4.txt" , "w" ) ) == NULL )
{
printf( "File could not be opened.\n" );
} /* end if */
else
{
for( int i1=1 ; i1 <= 10 ; i1++ )
{
fprintf(cfPtr, "%d\n" , i1 ) ;
}
fclose ( cfPtr ); /* fclose closes the file */
} /* end else */
return 0; /* indicates successful termination */
} /* end main */
Writing and reading records.
File: "f3.c"
#include <stdio.h>
struct student
{
int id ;
int grade ;
};
int main()
{
FILE* cfPtr ;
if ( (cfPtr = fopen( "data5.txt" , "wb" ) ) == NULL )
{
printf( "File could not be opened.\n" );
} /* end if */
else
{
struct student studentObject ;
for( int i1=1 ; i1 <= 10 ; i1++ )
{
studentObject.id = i1 ;
studentObject.grade = 10 + i1 ;
fwrite( &studentObject, sizeof( studentObject ), 1, cfPtr ) ;
}
fclose ( cfPtr ); /* fclose closes the file */
} /* end else */
return 0; /* indicates successful termination */
} /* end main */
File: "f4.c"
#include <stdio.h>
struct student
{
int id ;
int grade ;
};
int main()
{
FILE* cfPtr ;
if ( (cfPtr = fopen( "data5.txt" , "rb" ) ) == NULL )
{
printf( "File could not be opened.\n" );
} /* end if */
else
{
struct student studentObject ;
int no ;
printf( "Enter the record#:" ) ;
scanf( "%d" , &no ) ;
fseek( cfPtr, sizeof( studentObject) * (no-1), SEEK_SET ) ;
fread( &studentObject, sizeof( studentObject) ,1, cfPtr ) ;
printf( "Student Id: %d Grade: %d\n" , studentObject.id ,
studentObject.grade ) ;
fclose ( cfPtr ); /* fclose closes the file */
} /* end else */
return 0; /* indicates successful termination */
} /* end main */
Open
We can write and read data using the "open" function which is defined as a standard C library functions for the Unix system.
File: "openb1.c"
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int fd;
int n;
fd = open("data.txt", O_WRONLY|O_CREAT|O_TRUNC, 0644);
n = 1; write(fd, &n, 4);
n = 2; write(fd, &n, 4);
n = 3; write(fd, &n, 4);
n = 4; write(fd, &n, 4);
n = 5; write(fd, &n, 4);
n = 6; write(fd, &n, 4);
n = 7; write(fd, &n, 4);
n = 8; write(fd, &n, 4);
n = 9; write(fd, &n, 4);
close(fd);
}
The above writes some integers to a file named "data.txt" . The "open" call takes the name of the file as the first parameter and flags as the second parameter. Here we are specifying "O_WRONLY" to indicate write only , "O_CREAT" to specify create and "O_TRUNC" indicates that if the file exists it will be truncated to size 0 . The third parameter ( sometimes optional ) indicates the file permissions for this file. The write call is of the form:
write(fd, &n, 4);
The first argument is the file descriptor returned from the "open" call and the second argument is the address of the variable. The third argument is the number of bytes we want written.
We can also write the data in a text format as shown by the below program.
File: "opent1.c"
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
char buffer[256] ;
int fd ;
sprintf(buffer, "%s %d\n" , "Writing text to file." , 100 ) ;
fd = open("data1.txt", O_WRONLY|O_CREAT|O_TRUNC, 0644);
write( fd , buffer , strlen( buffer ) ) ;
close(fd);
}
Output:
$ cat data1.txt
Writing text to file. 100