11: I/O and Midterm Exam 2

What We Will Cover


Continuations

Questions from last class?

Homework Questions?

11.1: Review of Vectors and Objects

  • Vectors are a convenient way to process lists of data
  • The vector data type is defined in the standard library vector:
    #include <vector>
    using namespace std;
    
  • As an example, the following is the declaration of a vector named scores that holds 10 values of type int:
    vector<int> scores(10);
    
  • Compare this to the declaration of a similar array of 10 elements of type int:
    int scores[10];
    
  • Both declarations create 10 contiguous slots in memory that each hold an int

    list

Accessing Vector Elements

  • We must specify which element (slot) to access with the [] operator:
    scores[4] = 98;
    
  • The number inside the brackets is called an index
  • Any element is a variable of the vector data type and can be used individually like a variable:
    scores[4]++;
    cout << scores[4] << endl;
    
  • The index of a vector can be any integer value, which means we can use variables or arithmetic expressions to specify the index
  • This lets us use the counter variable of a loop as the vector index, like:
    for (int i = 0; i < 10; i++) {
        cout << scores[i] << endl;
    }
    

Vector Size

  • We can discover the size of a vector by calling the size() function
    cout << scores.size() << endl;
    
  • We made use of the size() member function to create a print function in vectorfun.cpp like:
    void print(vector<int> v) {
        for (unsigned i = 0; i < v.size(); i++) {
            cout << v[i] << " ";
        }
        cout << endl;
    }
    
  • If we know the size of data we are working with, then we should declare the size when we define the vector
  • However, we do not always know the size of data we will work with
  • Oftentimes the user will decide how many data items to enter into the program
  • In this case, we start with an empty vector and grow the vector whenever we add another element
  • The push_back() function resizes the vector by adding one element to its end:
    scores.push_back(data);
  • Another member function, pop_back(), removes the last element of a vector, shrinking its size by one:
    scores.pop_back();
  • We can write functions with vector parameters and return types
  • We can pass vector parameters by value or by reference

Linear Search

  • One of the algorithms we discussed was linear search
  • We use linear search to find a specific element of a vector
  • Linear search is easy to implement using a simple loop:
    int find(const vector<int>& v, int item) {
        for (unsigned i = 0; i < v.size(); i++) {
            if (item == v[i]) {
                return i;
            }
        }
        return -1;
    }
    

Removing an Element

  • We discussed how to remove an element from a list as well
  • If order does not matter then we can:
    1. Overwrite the element to be removed with the last element of the vector
    2. Shrink the size of the vector by calling pop_back()
  • However, if order matters then we must:
    1. Write a loop to move all elements down by one slot
    2. Shrink the size of the vector by calling pop_back()
  • Again, we can implement this operation using a loop:
    void erase(vector<int>& v, int pos) {
        for (unsigned i = pos; i < v.size() - 1; i++) {
            v[i] = v[i+1];
        }
        v.pop_back();
    }
    

Inserting an Element

  • In addition to removing items from a list, we often need to insert elements
  • We can either add elements to the end of a list or in the middle
  • If we add items to the end, we can just call the push_back() function of the vector:
    v.push_back(item);
  • However, if we want to insert an item in the middle of a list we must:
    1. Add space for a new element at the end of the vector
    2. Copy elements up by one index from the end of the list to the insertion index
    3. Assign the new value at the insertion index
  • For example:
    void insert(vector<int>& v, int pos, int value) {
        int last = v.size() - 1;
        v.push_back(v[last]);
        for (int i = last; i > pos; i--) {
            v[i] = v[i - 1];
        }
        v[pos] = value;
    }
    

Vectors and Objects

  • Sometimes we need to keep track of multiple attributes about a list of items
  • The naive way to code this is to use parallel vectors
  • Parallel vectors become a headache in larger programs:
    • Each vector must be the same length
    • Each slice is filled with values that belong together
    • Any function that operates on a slice must get several vectors as parameters
  • To remove parallel vectors, look at the slice and find the concept it represents
  • Then make the concept into a class
  • Finally, eliminate the parallel vectors and replace them with a single vector of objects
  • We looked at an example of a vector of Product objects

Exercise 11.1: Vector of Objects (15m)

  1. Copy the following starter code into a text editor, save it as cat.cpp, and then compile and run the starter code to make sure you copied it correctly.
    #include <iostream>
    #include <vector>
    using namespace std;
    
    // Add class Cat here
    
    int main() {
        // Uncomment after developing class.
        //vector<Cat> cats(3);
        //cats[0] = Cat("Fluffy", 7);
        //cats[1] = Cat("Garfield", 5);
        //cats[2] = Cat("Kitty", 3);
    
        // Uncomment after defining printOldest()
        //printOldest(cats);
        return 0;
    }
    
  2. Declare a class for creating Cat objects following the rules and guidelines of object-oriented programming. Each cat has a name and an age and needs a function to access the age and print inormation.

    When finished developing your Cat class, click here Click to show answer to compare your solution to mine. After you have completed your own solution, reviewing another is often helpful in learning how to improve your programming skills.

  3. Write the implementation (definitions) of the member functions for your Cat class.
  4. In main(), create a vector of three cats, assigning a name and age to each cat.
  5. Write a non-member function named printOldest() with a vector of cat parameter and a void return type.
    void printOldest(const vector<Cat>& cats);
    
  6. In printOldest(), write a loop that accesses the age of each cat in the vector and prints the name and age of the oldest cat.
  7. Call the printOldest() function from main() with output like the following:
    Oldest cat is Fluffy at 7 years.
    
  8. Submit cat.cpp as part of the next assignment.

Once you are finished, check your source code by clicking here. Click to show answer

11.2: Streams and File I/O

Learner Outcomes

At the end of the lesson the student will be able to:

  • List the types of files
  • Describe the purpose of a stream
  • Read and write text files

11.2.1: Computer Files

  • Sometimes we want to use data even after the program creating the data finishes executing
  • We need a way to save (store) data rather than having to re-enter it
  • For durable storage of data we use computer files
  • Files offer many advantages to computer programs:
    • 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 files in C++, we need two items:
    • files
    • file streams
  • We will look at files first

Introduction to Computer Files

Computer File: a collection of data stored under a common name, usually saved so it is available after a program finishes executing.

  • Files provide long-term storage of potentially large amounts of data
  • Usually, files are stored on non-volatile storage using:
    • Magnetic memory, like hard drives
    • Flash memory, like USB memory sticks
    • Optical memory, like DVDs
    • Holographic memory, like HVD
    • Molecular memory (being researched)
  • Computer files are stored in binary
  • 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

    8 bits to a byte

  • Video: Binary Numbers in 60 Seconds
  • Files are a single sequence of bytes

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

  • Since the data is arranged as bytes, any type of digital data can be stored in a file
  • Files must have a name and naming requirements depend on the underlying operating system (OS)
  • Most operating systems organize files into directories, also known as folders

Check Yourself

  1. A collection of data stored under a common name is known as a computer ________.
  2. Of the following, the advantage of using files for program I/O is ________ .
    1. data still exists after the program ends
    2. input can be automated (rather than entered manually)
    3. output from one program can be input to another
    4. all of these
  3. True or false: the operating system keeps track of the file based on a file name.
  4. A file resembles a(n) ________ of bytes.
  5. Files are typically organized into directories, also known as ________.

11.2.2: Types of Files

  • All data in a file is ultimately just zeros and ones (bits)
  • However, we can classify the files based on their data into 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)
  • However, non-ASCII character sets, like Unicode, are usually stored in wider character sets
  • Each line in a text file is delimited by end-of-line characters:
    • Unix/OS-X: "\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 text-reading 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
  • If you are using Windows, be sure to save all text files in the UNIX file format with TextPad

    TextPad selecting UNIX file format

  • If you are using a Mac or Linux, then you automatically save in UNIX file format

Binary Files

  • Data other than text is usually referred to as binary data
  • Each bit represents some type of encoded information
  • Examples of binary data includes C++ compiled code
  • 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

Understanding Binary -- or Not?

Only 10 types of people

Try It: What's My File Type? (4m)

  1. Right-click and save the file to an easy to access location like the Desktop: starter.cpp
  2. Open the file in a text editor like TextPad or NotePad++ (NOT NotePad): can you read the file?
  3. Now compile and open the compiled binary file:
    1. If you are using Windows, open the file in NotePad (NOT NotePad++): what is different about the file?
    2. If you are using a Mac, it depends on your computer. See google: view binary files mac. For instance drag the binary into TextWrangler or in a Terminal type: od -h filename.
    3. If you are using Linux type in a Terminal: xxd -b file where file is the filename.
  4. Can you read the compiled file? Why or why not?
  5. Be prepared to answer the following Check Yourself questions when called upon.

Check Yourself

  1. True or false: data in a file is restricted to characters only.
  2. Since text files can be displayed in any text editor, text files are known as ________ readable files.
  3. Files that store non-text data are known as ________ files.
  4. True or false: line endings in a file are stored as one or two bytes of data.
  5. Of the following, ________ is not one of the commonly used line endings for files.
    1. '\n'
    2. '\r'
    3. '\n\r'
    4. '\r\n'

11.2.3: Streams

Stream: an ordered list of data delivered over time

  • A stream connects a program to an I/O object
  • Input stream: an object that provides a sequence of bytes to a program from a source

    input stream

  • Output stream: an object that accepts a sequence of bytes from a program to a source

    output stream

  • cin and cout are input and output streams respectively

File Streams

File stream: a data delivery path used to connect a program to a file.

  • File streams can be input streams, output streams, or both
  • File input streams receive data from a file
  • File output streams send data to a file
  • Files streams that provide both input and output only flow one way at a time
  • File I/O uses streams of type ifstream, ofstream, or fstream
  • To declare a file input stream, we write code like:
    ifstream fin; //declares a file input stream
    fin.open("infile.txt");
    
  • Similarly, to declare a file input stream we write code like:
    ofstream fout; //declares a file output stream
    fout.open("outfile.txt");
    
  • Input and output to a single file uses fstream as the data type like:
    fstream data;
    data.open("data.txt", ios::in | ios::out); // i/o
    
  • Each file your program uses will need a separate file stream object
  • As we can see, with fstream we must specify whether we want input or output or both
  • Using fstream is slightly more complicated, so we use ifstream or ofstream unless the added features are needed

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 with cin is shown below
cin.fail();

Check Yourself

  1. A data transmission path is known as a ________.
  2. True or false: cin is an input stream and cout is an output stream.
  3. True or false: file streams are objects.
  4. To send data to a file, we use a stream of type ________.
  5. To receive data from a file, we use a stream of type ________.
  6. To both send and receive data using a single stream, we use a stream of type ________.

11.2.4: 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
    
  • If you are using Windows, be sure to save the file in the UNIX file format with TextPad

    TextPad selecting UNIX file format

  • Other options include:
  • The following program reads each number from infile.txt and then writes the sum to a file named outfile.txt
  • Examine 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/**
    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 failed to open.\n";
        exit(-1);
    }

    ofstream fout;
    fout.open("outfile.txt");
    if (fout.fail()) {
        cout << "Output file failed to open.\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

Check Yourself

  1. The library for file streams is named ________.
  2. Enter the code to declare a file input stream named "inStream".

    answer

  3. After opening a file stream, reading data is like using ________ and writing data is like using ________.
  4. True or false: you should close file streams when finished reading and writing, but closing output streams is more important because data may be lost otherwise.

11.2.5: 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. Read or write the data:
    • Read from a file with fin like using cin:
      double first, second, third;
      fin >> first;
      fin >> second;
      fin >> third;
      
    • Write to a file with fout like using cout:
      fout << "first = " << first << endl;
      
  5. Close the streams when finished reading and writing:
    fin.close();
    fout.close();
    

Check Yourself

  1. True or false: the only name you can use for a file input stream is fin.
  2. Enter the code to declare a file output stream named "outStream".

    answer

  3. To associate a file stream with a file, call the member function ________.
  4. To exit a program immediately, call the function ________.

More Information

Exercise 11.2: Reading and Writing Two Numbers (7m)

In this exercise we write a program that copies two numbers from an input stream to an output stream.

Specifications

  1. Copy the following program into a text editor, 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;
    }
    
  2. Save the file infile.txt to the same directory as your program source code.

    We will read from this file after writing our program.

  3. 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;
    
  4. Inside main(), declare names for the input and output streams:
    ifstream fin;
    ofstream fout;
    
  5. 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);
    }
    
  6. 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;
    
  7. 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;
    
  8. Close the streams when finished reading and writing:
    fin.close();
    fout.close();
    
  9. At the end of main() before return 0, add a cout statement like:
    cout << "All done!\n";
    
  10. 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.

  11. Using TextPad or WordPad, open the output file you created and verify that two numbers were copied. Your output file should look like:
    first = 10
    second = 20
    
  12. Using Notepad, open the output file you created and compare the output with what you saw in TextPad or WordPad.

    Notice how Notepad cannot display the end of line characters for Unix. However, TextPad and WordPad can display Unix end-of-line characters correctly.

  13. Save your program source code file to submit to Canvas as part of assignment 11.

Listing of copytwo.cpp

Listing of copytwo.cpp

Check Yourself

As time permits, be prepared to answer these questions. You can find more information by following the links after the question.

  1. What two items are needed to connect a file to a program? (11.2.1)
  2. What is a file? (11.2.2)
  3. What are the two types of files? (11.2.3)
  4. What is used to connect a program to a file? (11.2.4)
  5. What library is required for file I/O? (11.2.6)
  6. How are input and output streams declared? (11.2.6)
  7. What stream function is used to open a file? (11.2.6)
  8. What stream function is used to check that a file opened correctly? (11.2.6)
  9. How do you read and write data using a stream? (11.2.6)
  10. Why should you close a stream after you are done using it in your program? (11.2.5)

11.2.6: Summary

  • Programs use streams for input and output
  • cin and cout are types of streams
  • File I/O also uses streams of type ifstream and ofstream
  • Streams are objects and have functions associated with them
  • Some of the functions we call for file I/O include:
    • open("fileName"): establishes a connection from the stream to the file
    • fail(): tests the stream for errors
    • close(): closes the connection of the stream to the file
  • You use input streams like you use cin:
    fin >> first >> second >> third;
    
  • You use output streams like you use cout:
    fout << "first = " << first << endl;
    
  • To halt execution of your program on error, use the exit function:
    exit(-1);

Wrap Up

Due Next:
A10: Midterm 2 Review Problems (11/9/17)
A11-Keeping Lists (11/16/17)
  • When class is over, please shut down your computer
  • You may complete unfinished exercises at the end of the class or at any time before the next class.
Last Updated: November 11 2017 @16:00:23