Welcome to Lesson 19!


Learning Objectives
By the end of today's class, you should know...
  • How do you read input from a file?
  • How do you write output to a file?
  • How do you use a loop to read in data from a file?

Announcements

  • Quiz 7 after the break
  • Lab 8 due Friday

Review Activity

1. What will be the current value after executing this program

void increment(double num){
    num+=1;
}

void decrement(double& num) {
     num-=1;
}

int main() {
    double value = 4.5;
    increment(value);
    decrement(value);
    cout << "The current value: " << value;
}

(a) The current value: 4.5
(b) The current value: 5.5
(c) The current value: 3.5


2. Write the following function that takes in a value parameter

char capitalizeLetter(char letter);
//Given a char that is a valid letter (a-z or A-Z)
//Returns a capitalized letter
//capitalizeLetter('a') - > 'A'
//capitalizeLetter('A') -> 'A'


3. Write the following function which takes in a reference parameter:

void capitalizeLetter(char& letter);
//Given a char that is a valid letter (a-z or A-Z)
//Returns a capitalized letter
//capitalizeLetter('a') - > 'A'
//capitalizeLetter('A') -> 'A'

4. Call the two functions given the starter code below:


int main() {

    char letter;

    cout << "Enter a letter: ";

    cin >> letter;

    //Call the two versions of the function here

    cout << "The capitalized letter is: " << letter;

}

Streams and File I/O


About Program I/O
  • Program I/O = Program Input/Output
    • Input to and output from programs
  • Input can be from a keyboard, mouse or file
  • Output can be to a display screen, printer or file
  • Note that files can be both input and output devices for programs
  • Advantages of file I/O:
    • Data still exists after the program ends
    • Input can be automated (rather than entered manually)
    • Output from one program can be input to another
  • To store and retrieve data in a file, we need two constructs:
    • A file
    • A file stream object
  • We will look at files first

Files

File: a collection of data stored under a common name on a storage medium.

  • Files provide long-term storage of large amounts of data
  • Usually, you store files on durable storage mediums
    • Magnetic disks
    • Optical disks
    • Flash storage, like USB storage devices
  • Files are a single sequence of bytes

    Byte 0 Byte 1 Byte 2 ... Byte n−1 End-of-file marker

  • Since the data arranged as bytes, any type of data can be stored in a file
  • The operating system keeps track of the number of bytes in a file
  • Files must have a name
    • Naming requirements depend on the underlying operating system (OS)
  • The operating system organizes files into directories

Types of Files

  • All data in a file is ultimately just zeros and ones
  • Each binary digit can have one of two values: 0 or 1
  • A bit is one binary digit
  • A byte is a group of eight bits
  • These binary digits may represent integer values or text characters
  • It is up to the program using the file to understand the meaning and internal format of the data
  • In general, programs interpret data using two broad categories: text and binary

Text Files

  • In text files, the bits represent printable characters
  • Files are usually stored as one byte per character (ASCII)
  • Each line is delimited by end-of-line characters:
    • Macintosh (before OS-X): "\r"
    • Unix: "\n"
    • Windows: "\r\n"
  • An example of a text file is source code
  • We can read text files because each byte is interpreted by a program as textual characters
  • Some of these programs, like TextPad, then display the textual data to your computer's screen
  • Since there are many programs that read and display text, text files are called human readable

Binary Files

  • Data other than text is usually referred to as binary data
  • Each bit represents some type of encoded information
    • Such as program instructions or integer data
  • Binary files are easily read by the computer but not by humans
  • The following table compares binary and text values saved in a file
  • First we consider the value "1234" as ASCII codes and compare these bits to a binary value of 1234
  • As we can see, the bit patterns are different for the same data when stored as text or binary

Comparing Binary and Textual Data

Description Byte 0 Byte 1 Byte 2 Byte 3
"1234" as char's '1' '2' '3' '4'
"1234" as ASCII codes (bytes) 49 50 51 52
"1234" as ASCII codes (bits) 00110001 00110010 00110011 00110100
(int) 1234 as binary bits 00000000 00000000 00000100 11010010

Streams

Stream: a one-way transmission path that either delivers data to a destination (screen, file, etc.) or that takes data from a source (keyboard, file, etc.)

  • A stream connects a program to an I/O object
  • Input stream: an object that provides a sequence of bytes to a program
image depicting an input stream

  • Output stream: an object that accepts a sequence of bytes from a program
image depicting an output stream

  • cin and cout are input and output streams

File Streams

File stream: a one-way transmission path used to connect a program to a file.

  • File streams can be either input or output streams
  • File input streams receive data from a file
  • File output streams send data to a file
  • File I/O uses streams of type ifstream and ofstream
  • To declare a file input stream, we write code like:
    ifstream fin; //declares a file input stream
  • Similarly, to declare a file input stream we write code like:
    ofstream fout; //declares a file output stream
  • Each file your program uses will need a separate file stream object
Streams and Objects

  • Streams are objects and thus cin and cout are objects
  • Objects are special variables that can have a function associated with them
  • To call a function of an object, we use the dot operator
  • An example of using the dot operator is with cin is shown below
cin.fail();

Example of File I/O

  • Let us consider an example that reads from a file and writes to a file
  • The program reads from a file named infile.txt, which contains the following values:
    10
    20
    30
    
  • After summing the values, the program writes them to a file named outfile.txt
  • Consider the following code and try to identify:
    1. What is the name of the input stream?
    2. Which line opens a file for reading
    3. What is the name of the output stream?
    4. Which line opens a file for writing
    5. Which line reads data from the input stream?
    6. Which lines write data to the output stream?

Example Program to Read and Write Files


/**
    Reads three numbers from the file infile.txt,
    sums the numbers, and writes the sum to the
    file outfile.txt.
*/
#include <fstream>   // for file I/O
#include <iostream>
#include <cstdlib>
using namespace std;

int main() {
    ifstream fin;
    fin.open("infile.txt");
    if (fin.fail()) {
        cout << "Input file opening failed.\n";
        exit(-1);
    }

    ofstream fout;
    fout.open("outfile.txt");
    if (fout.fail()) {
        cout << "Output file opening failed.\n";
        exit(-1);
    }

    int first, second, third;
    fin >> first >> second >> third;
    fout << "The sum of the first 3\n"
         << "numbers in infile.txt\n"
         << "is " << (first + second + third)
         << endl;

    fin.close();
    fout.close();

    cout << "Processing completed\n";

    return 0;
}
Closing a Stream

  • After finishing reading and writing you should close the file streams
  • If you do not close an output stream, you may lose data stored in the output buffer
  • In addition, streams consume system resources and you should not keep open any more streams than needed

Procedure For File I/O

  1. Place the following include directives in your program file:
    #include <fstream>   // for file I/O
    #include <iostream>  // for cout
    #include <cstdlib>   // for exit()
    using namespace std;
    
  2. Declare names for input and output streams like:
    ifstream fin;
    ofstream fout;
    
  3. Connect each stream to a file using open() and check for failure:
    fin.open("infile.txt");
    if (fin.fail()) {
        cout << "Input file failed to open.\n"; exit(-1);
    }
    
    fout.open("outfile.txt");
    if (fout.fail()) {
        cout << "Output file failed to open.\n";
        exit(-1);
    }
    
  4. If there is a failure, we need to check that the input file is stored in the same directory that the .cpp file is executing.
  5. Read or write the data:
    • Read from a file with fin like using cin:
      fin >> first >> second >> third;
      
    • Write to a file with fout like using cout:
      fout << "first = " << first << endl;
      
  6. Close the streams when finished reading and writing:
    fin.close();
    fout.close();
    

More Information


How to Save Your Files on the Mac

  • For the Mac, CodeBlocks will require you to save your txt files in your user directory rather than in the same folder as your program
  • Your user directory is the one that typically has your name. On my Mac, it is named parrishj.
  • You can find this directory by selecting Go -> Home

How to Save Your Files Using Eclipse

  • If you are using Eclipse for your assignments in this class, you can simply save the file in the same project folder as your program (not under src)
  • Right click on the project folder in the project explorer (right side bar)
  • Then, go to New->File from the drop down menu that appears
  • Name your file using the extension .txt
  • Note: if your project explorer is hidden, go to the following: Window->Show View->Other...->General->Project Explorer
     

Activity 19.1: Two Numbers

  • In this exercise we write a program that copies two numbers from an input stream to an output stream.
  • Copy the following program into a C++ file, save it as copytwo.cpp, and then compile and run the starter program to make sure you copied it correctly.
    #include <iostream>
    using namespace std;
    
    int main() {
        // Enter your code here
    
        return 0;
    }
    
  • Then, let's create a text file to test our program. Open up Notepad or another text editor (Word is not a good choice). Name the file infile.txt.
  • In the file, add a list of numbers each on their own line, like this:
10
20

  • Important: You need to save this file in the same directory that you are executing your C++ files.
  • We will read from this file after writing our program.

  • Place the following include directives in your source code file:
    #include <iostream>  // for cout
    #include <fstream>   // for file I/O
    #include <cstdlib>   // for exit()
    using namespace std;
    
  • Inside main(), declare names for the input and output streams:
    ifstream fin;
    ofstream fout;
    
  • Add code to connect each stream to a file using open() and check for failure:
    fin.open("infile.txt");
    if (fin.fail()) {
        cout << "Input file failed to open.\n";
        exit(-1);
    }
    
    fout.open("outfile.txt");
    if (fout.fail()) {
        cout << "Output file failed to open.\n";
        exit(-1);
    }
    
  • Add statements to read two numbers from the input stream. For example, here is possible code for reading the first number:
    int first;
    fin >> first;
    
  • Add statements to write the two numbers to the output stream. For example, here is possible code for writing the first number:
    fout << "first = " << first << endl;
    
  • Close the streams when finished reading and writing:
    fin.close();
    fout.close();
    
  • Compile and run your modified program to make sure you made the changes correctly.

    Notice that you do not see any output on the screen for file reading or writing. The output stream wrote the program output to the output file.

  • Save your program source code file to submit to Canvas

Listing of copytwo.cpp

copy two program

Using Loops to Read Files

  • Sometimes we do not know how many data items are in a file
  • To solve this problem, the typical approach is to use a loop to process the file
  • When reading input from the console, we can read the input as part of the test condition like:
    while (fin >> nextNum) { //returns true or false AND reads in the number!
        // process the input
    }
    
  • We saw this technique when we were checking cin for failure
  • While the read is successful, the input stream returns a value interpreted as true
  • If the stream fails or closes, then the test condition fails
  • This failing condition returns a value interpreted as false by the loop
  • Thus the loop ends and the program continues after the loop statement
  • We can use this behavior to read from a file as shown below

Example Program Reading a File Using a Loop


#include <fstream>   // for file I/O
#include <iostream>
#include <cstdlib>
using namespace std;

int main() {
    ifstream fin;
    fin.open("infile.txt");
    if (fin.fail()) {
        cout << "Input file failed to open.\n";
        exit(-1);
    }

    double nextNum, sum = 0;
    int count = 0;
    while (fin >> nextNum) {
        cout << "Read: " << nextNum << endl;
        sum = sum + nextNum;
        count++;
    }
    cout << "average = " << (sum / count) << endl;
    fin.close();

    return 0;
}



Activity 19.2: Averages (10pts)

  • We are going to write a program that takes in a list of numbers of unknown size from a file, and then outputs the average of these numbers.
  • This activity will help you practice using a loop to help you read data from a file.
  • Open up a new C++ file in CodeBlocks and name it averages.cpp
  • Copy and paste the starter code below into your file.
#include <iostream>
using namespace std;

int main() {
    
    return 0;
}
  • Now add the two additional libraries that are required for file I/O to the top of your program:
#include <fstream>
#include <cstdlib>
  • Next, lets create a new input stream variable at the top of main
ifstream fin;
  • Then, let's use this stream to open a file called nums.txt
fin.open("nums.txt");
  • Next, we will need to make sure that the file opened successfully by checking for failure:
if (fin.fail()) {
        cout << "Input file failed to open.\n";
        exit(-1);
}

  • Next, lets read in the numbers from the file. Since we are computing the average of the numbers, we need two pieces of information
1. The sum of the numbers
2. How many numbers there are
  • Remember: Average = sum / count
  • Therefore, as we read in the numbers from the file, we need to computer their sum and count how many there are.
  • We will therefore need two variables to keep track of this information. Add the following two variable declarations to the top of main:
double sum = 0.0;
int count = 0;
  • We will also need a variable to temporarily store each number as we read it in from the file. Add an additional variable declaration to the top of main like so:
double num;
  • Now, let's read in the numbers from the file and process them inside a loop. Add the following loop to your program:
while (fin >> num) {
    cout << "Processing the number: " << num << endl;
    sum += num; //adding the number to our running total for the sum
    count++; //counting how many numbers are in the file
}
  • Now, let's print the average to the console and output it to a file.
  • To print the average to the console, add the following line of code:
cout << "The average is: " << sum/count << endl;
  • To output the average to a file, we need to open a new output stream. Below the cout statement, add the following line of code:
ofstream fout;
  • Then, we need to open a file to write out to it. Let's open a file named average.txt.
fout.open("average.txt");

  • Before we can proceed, we need to make sure the file opened properly:
if (fout.fail()) {
    cout << "Output file failed to open." << endl;
    exit(-1);
}

  • Finally, lets write the average to the file.
fout  << "The average is: " << sum/count << endl;
  • As a last step we need to close our input and output streams. Add the following lines of code to the bottom of main:
fin.close();
fout.close();
  • Let's create a file to test our program. Open up Notepad or another text editor (Word is not a good choice) or create a text file inside of CodeBlocks. Name the file nums.txt. In the file, add a list of numbers each on their own line, like this:
10
20
30
40
50
  • Save the file in the same directory in which you are executing your source code files and close it.
  • Now, run the code and open up your file to make sure everything is working properly. Open up the file averages.txt and verify that you got the correct output.
  • When you are finished, upload averages.cpp to Canvas.
}


Wrap Up
  • With your partner, answer the questions from today's learning objectives

Upcoming Assignments