Wednesday, March 4, 2020

Functions & BASIC FILE I/O

A.   Files:
For storage of data for later use, files are used. Files are stored on the Hard Disk Drive (HDD). There are two types of files:
1.    Text files - in which all data is stored as ASCII characters, and
2.    Binary files - in which data is stored as is in main memory.

Every file type has its own merits and demerits. However, we will only use 'text' files in this lab/course.

1. Writing data to 'text' files:

There are five (5) steps associated with writing to a file:
1.    Include fstream library.
2.    Declare a variable (actually an object) of output file stream, i.e., of type ofstream.
3.    Attach the ofstream object to an existing or new file in text (default) mode.
4.    Write to the output file stream using insertion operator (<<).
5.    Close the file stream.

Look at the code below to understand these five steps, highlighted in statements in bold.

#include <iostream>
#include <fstream> /*step 1: include lib*/
using namespace std;

int main()
{
      ofstream fout; //step 2: create ofstream obj
      fout.open("lab14data.txt"); //step 3: attach to file
      fout << "Student Record\n"; //step 4: write to file

      char rollno[6];
      cout << "Enter your roll no: ";
      cin >> rollno;
      cout << "Roll Number: " << rollno << endl;

      fout << "Roll Number: " << rollno << endl; //step 4

      fout.close(); //step 5: close stream
      return 0;
}

The choice of '.txt' extension is to facilitate viewing of the file in Notepad. Otherwise extension can be left or other extensions can be used.

Run the code, enter your roll no. It will display your roll number and also create a file named lab14data.txt in the same folder as your .cpp file.

Go to the folder, open the lab14data.txt file and see its contents. They should be the same as displayed one the console window.

Important Note:
Also check the file size. Right click on the filename (in Windows explorer) and click properties.
Note the file size and match it with the number of characters displayed in the file. There would be a difference of 2 in the file size and the number of characters (including newline). The reason is, the newline character is entered as two characters, a 'carriage return' (CR) character (ASCII code of 13) and a line feed (LF) character (ASCII code of 10).

This is how you would write to a new file that did not exist before.

In case you wish to open an already existing file for writing (output) but you want to overwrite its contents, you will still use the same code.

To check this, run the code again. Enter a different roll number.

Check the file now. It should contain the newly entered roll number.


2. Reading data from 'text' files:

There are five (5) steps associated with reading from a file:
1.    Include fstream library.
2.    Declare a variable (actually an object) of input file stream, i.e., of type ifstream.
3.    Attach the ifstream object to an existing file (only) in text (default) mode.
4.    Read from the input file stream using extraction operator (>>).
5.    Close the file stream.

Look at the code below to understand these five steps, highlighted in statements in bold. The code reads in data from the previously created filel lab14data.txt and displays the first roll number.

#include <iostream>
#include <fstream> /*step 1: include lib*/
#include <string>
using namespace std;

int main()
{
      ifstream fin; //step 2: create ifstream obj
      fin.open("lab14data.txt"); //step 3: attach to file

      char line1[100];
      fin.getline(line1, 100); //step 4: read from file
      cout << line1 << endl;
      char roll[10], no[10], rollnumber[10];
      fin >> roll >> no>>rollnumber; //step 4

      cout << roll << " " << no << " " << rollnumber << endl;

      fin.close(); //step 5: close stream
      system("pause");
      return 0;
}

Experiment with the code and the file contents to read different types of data from input file.

Task # 1:
Write a code that takes the names and ages of five students and write them in a text file.

CODE:
#include <iostream>
#include <fstream>

using namespace std;

int main()
{
     ofstream fout;
     int n=1;
     fout.open("Task1_lab14.txt");
     fout << "Student's Name and Age record !"<<endl;


     char name[50];
     int age;
do
{    cout << "Enter Name of student no "<<n<<" : ";
    cin>>name;
     cout<<"input age : ";
     cin>>age;
     fout << "Name of student : " << name <<'\t'<<" Age of student : "<<age<< endl;
     n++;
     }while (n<=5);
     fout.close();
     cout<<endl<<"Thank you for Entering data..... kindly check Task1_lab14.txt....";
     return 0;
}


Task # 2:
Write a code to read the already written names and ages of the students in the file (done in task 1).

CODE:
#include <iostream>
#include <fstream>
using namespace std;
int main ()
{
     ifstream file;
     file.open("lab14t2.txt");
     int count,age;
     char name[20];
     for (count=0;count<=4;count++)
     {
              file >> name;
              file >> age;
              cout << "NAME of student   :   " << name << endl <<"AGE   of student  :   " <<  age << endl;
              cout << endl;
     }
     return 0;
}
B.   Reading File using eof():

The amount of data stored in the file is often unknown.  So instead of manually counting data in a text file, we use C++ built in function eof() (stands for end of file).

eof(), returns nonzero (meaning TRUE) when there are no more data to be read from an input file stream and zero (meaning FALSE) otherwise.

Rules for using eof() are as follow:
a)    Always test for the end-of-file condition before processing data read from an input file stream. This ensures we only process data when available.
b)    Use a priming input statement before starting the loop.
c)    Repeat the input statement at the bottom of the loop body.
d)    Use a while loop for getting data from an input file stream.  A for loop is desirable only when you know the exact number of data items in the file, which is not the case here.

Following example 1, will read all integer numbers stored in file and sum them, until end of file is not reached.

Example 1:

#include <iostream>
#include<fstream>
using namespace std;

int main()
{
 int data, sum = 0; // declare a variable that will read each integer from file and initialize the sum

ifstream fin; // declare stream variable name

fin.open("myfile.txt"); // open file
fin >> data; //attempt to read data

// get first number from the file (priming the input statement).You //must attempt to read data prior to an eof() test.

while (!fin.eof())  //if not at end of file, continue reading numbers
 {
 sum += data;       //create a running sum of the incoming data
 fin>>data;         //get next number from file
 }
 fin.close( ); //close file

 sum += data;       //add the last incoming item
 cout << "sum of all numbers: " << data;     //display the sum

 return 0;
}


C.   Functions
A function is a group of statements that together perform a task. Every C++ program has at least one function, which is main(), and programs can define additional functions. You can divide up your code into separate functions.

Passing an array to a function:
When you need to pass an array to a function, C++ does not allow passing it by value, only passing by reference (address) is allowed. Remember that the name of the array is a reference to its starting (base) address. Thus, only the array name is passed to a function as a reference argument. Using a reference alone, there is no way to tell the size of the array, so the size needs to be passed separately.

Look at the following example to understand how an array is passed to a function. Since it is passed by reference, if the function changes the values in the array, the corresponding values in the array in the main() would also change.

Example 2:

#include <iostream>
using namespace std;
int maxval(int arr[], int size); // function declaration

int main () {
   const int SIZE = 5;
   int values[SIZE] = {50, 100, -100, 400, 333}, ret;

   ret = maxval(values, SIZE); // calling a function to get max value.
   cout << "Max value is: " << ret << endl;
   return 0;
}

int maxval(int arr[], int size) { //returns max in the array
   int result = arr[0];
   for(int i = 1; i < size; i++)
      if (arr[i] > result)
         result = arr[i];
   return result;
}

There may be other ways of making the size available in both main() and the function maxval(), for example, by the use of global variables. It is customary to use ALL CAPS to name the global variables to avoid confusion with local variables.

Example 3:

#include <iostream>
using namespace std;

const int SIZE = 5; //global variable, visible in all funcs below
int maxval(int arr[]); // function declaration

int main () {
   int values[SIZE] = {100, -100, 0, 400, 333}, ret;
   ret = maxval(values); // calling a function to get max value.
   cout << "Max value is: " << ret << endl;
   return 0;
}

// function returning the max between two numbers
int maxval(int arr[])
{
   int result = arr[0];
   for(int i = 1; i < SIZE; i++)
      if (arr[i] > result)
         result = arr[i];
   return result;
}

 Look at the following code and see how multiple functions with the same name can also be used in the same code. The compiler has no ambiguity about which function to call since the parameter list of each is different. This is known as function-overloading.




Try to identify which function call invokes which specific function in the below example:

Example 4:

#include <iostream>
using namespace std;

int maxval(int num1, int num2);
void maxval(int, int, int &);      //names not needed in declaration
int maxval(int arr[]);
int maxval(int [], int);

const int SIZE = 2;

int main () {
   int a = 100, b = 200, ret, array[SIZE] = {100, 200};

   cout << "Max value is : " << maxval(a,b) << endl;
   maxval(a, b, ret); //note this cannot be used within cout statement!
   cout << "Max value is : " << ret << endl;
   cout << "Max value is : " << maxval(array, SIZE) << endl;
   cout << "Max value is : " << maxval(array) << endl;

   return 0;
}

int maxval(int num1, int num2) {
   return (num1 > num2) ? num1 : num2;
}

void maxval(int num1, int num2, int &m) {
   m = (num1 > num2) ? num1 : num2;
}

int maxval(int arr[]) {
   int result = arr[0];
   for(int i = 1; i < SIZE; i++)
      if (arr[i] > result)
         result = arr[i];
   return result;
}

int maxval(int arr[], int size) {
   int result = arr[0];
   for(int i = 1; i < size; i++)
      if (arr[i] > result)
         result = arr[i];
   return result; }
Task # 3:
Add a function average() in the following code and shift the code segment that computes average to it. The function should return the computed value of average.
   Code:
#include <iostream>
using namespace std;
float average(float a[],float s);
int main ()
{
      float data[100], n;
      float avg;
  
      cout << "How many values will you enter :  ";
      cin >> n;
     
      for(int i = 0; i < n; i++)
      {       cout<<"Enter value no "<<i+1<<" : ";
                              cin >> data[i];
                  }
      avg=average(data,n);
     
      cout << "Average value is: " << avg<< endl; 
      return 0;
}
float average(float a[],float s)
{
  float sum=0;
  float avg;
  for(int i = 0; i < s; i++)
{
                  sum =sum + a[i];
}
avg = sum/s;
return avg;
}

#include <iostream>
using namespace std;

int main ()
{
   int data[100], n;
   double sum = 0, average;
  
   cout << "How many values will you enter (<100): ";
   cin >> n;
  
   for(int i = 0; i < n; i++)
         cin >> data[i];
  
   for(int i = 0; i < n; i++)
         sum += data[i];
  
   average = sum/n;
   cout << "Average value is: " << average << endl;     
   return 0;
}

Task # 4:
Now add a function getdata() in the code you wrote for task 3, which should get data from file already stored in that folder (manually create a file and fill with 20 numbers). The main() should first call getdata() to receive all input from a file and then invoke average() to find average of the values.

Code:
#include <iostream>
#include <fstream>
using namespace std;
float average(float a[],float s);
float getdata(float a[],float s);
int main ()
{
     float data[100],n;
     float avg;
  
     cout << "How many values do you want to read : ";
     cin >> n;
 getdata(data,n);

     avg=average(data,n);
    
     cout << "Average value is: " << avg<< endl;    
     return 0;
}
float getdata(float a[] ,float s)
{
     int data;
     ifstream fin; // declare stream variable name

fin.open("Task4_lab14.txt"); 

for (int i=0;i<s;i++)
{
//   cout<<data<<endl;
fin >> data;               // reading 1st value i.e first line
  a[i]=data;               //putting in array
  }
fin.close( );

}
float average(float a[],float s)
{
  float sum=0;
  float avg;
  for(int i = 0; i < s; i++)
{
              sum += a[i];
}
avg = sum/s;
return avg;
}


Task # 5:
In example 2 code, what happens if the size passed to the function maxval() is zero (i.e. the actual parameter SIZE is 0)? Would the return value be a valid max value? Resolve this ambiguity by introducing a mechanism to somehow warn the caller code that the returned value is a bogus value.
Hint: you may consider passing an additional parameter by reference and using it as a flag to indicate if the return value is valid or bogus.

Code:
#include <iostream>
using namespace std;
int maxval(int arr[], int size, int &flag); // function declaration

int main () {
    int SIZE = 5;
   
   int values[ ] = {50, 100, -100, 400, 333}, ret;
 int flag=0;
 cout<<"input size : ";
 cin>>SIZE;
   ret = maxval(values, SIZE,flag); // calling a function to get max value.
   if(flag==1)
   {
     cout <<"The Size value is out of bound so bogus value returned !!!!"<<endl;
  
   cout << "Max value is: " << ret << endl;
}
else
{
     cout << "Max value is: " << ret << endl;
}
   return 0;
}

int maxval(int arr[], int size, int&flag) { //returns max in the array
   int result = arr[0];
   for(int i = 1; i < size; i++)
      {
      if (arr[i] > result)
         result = arr[i];
     }
     if (size!=5)
     {
              flag=1;
     }
     else if (size==5)
     {
              flag=0;
     }
   return result;
}

Functions & BASIC FILE I/O

A.    Files : For storage of data for later use, files are used. Files are stored on the Hard Disk Drive (HDD). There are two types of f...