Input/Output Streams C++ Language

Input/Output Streams C++ Language

We have used iostream objects from the very beginning. std::cout is the output stream object that prints to the screen. std::cin is the input stream object that receives values from the keyboard. The precise type of std::cout is std::ostream, and std::cin’s type is std::istream.

Like other objects, std::cout and std::cin have methods. The << and >> operators actually are the methods operator<< and operator>>. (The operators << and >> normally are used on integers to perform left and right bitwise shift operations;

std::cin >> x;
std::cout << x;
cin.operator>>(x);
cout.operator<<(x);
#include <iostream>
int main() {
    int x;
    // I hope the user does the right thing!
    std::cout << "Please enter an integer: ";
    std::cin >> x;
    std::cout << "You entered " << x << '\n';
}

What if the user enters the word “five,” which arguably is an integer? The program produces incorrect results.

#include <iostream>
#include <limits>

int main() {
    int x;
    // I hope the user does the right thing!
    std::cout << "Please enter an integer: ";
    // Enter and remain in the loop as long as the user provides
    // bad input
    while (!(std::cin >> x)) {
        // Report error and re-prompt
        std::cout << "Bad entry, please try again: ";
        // Clean up the input stream
        std::cin.clear(); // Clear the error state of the stream
        // Empty the keyboard buffer
        std::cin.ignore(std::numeric_limits < std::streamsize > ::max(), '\n');
    }
    std::cout << "You entered " << x << '\n';
}
#include <iostream>

#include <string>

int main() {
    std::string line;
    std::cout << "Please enter a line of text: ";
    std::cin >> line;
    std::cout << "You entered: \"" << line << "\"" << '\n';
}
Please enter a line of text: Mary had a little lamb.
You entered: "Mary"
#include <iostream>
#include <string>
int main() {
    std::string line;
    std::cout << "Please enter a line of text: ";
    getline(std::cin, line);
    std::cout << "You entered: \"" << line << "\"" << '\n';
}
Please enter a line of text: Mary has a little lamb.
You entered: "Mary has a little lamb."

File Streams

Many applications allow users to create and manipulate data. Truly useful applications allow users to store their data to files; for example, word processors can save and load documents.

Vectors would be more useful it they were persistent. Data is persistent when it exists between program executions. During one execution of a particular program the user may create and populate a vector. The user then saves the contents of the vector to disk and quits the program. Later, the user can run the program again and reload the vector from the disk and resume work.

#include <iostream>

#include <fstream>

#include <string>

#include <vector>

/*
 * print_vector(v)
 * Prints the contents of vector v.
 * v is a vector holding integers.
 */
void print_vector(const std::vector < int > & vec) {
    std::cout << "{";
    int len = vec.size();
    if (len > 0) {
        for (int i = 0; i < len - 1; i++)
            std::cout << vec[i] << ","; // Comma after elements
        std::cout << vec[len - 1]; // No comma after last element
    }
    std::cout << "}\n";
}

void load_vector(const std::string & filename, std::vector < int > & vec) {
    // Open a text file for reading
    std::ifstream in (filename);
    if ( in .good()) { // Make sure the file was opened properly
        vec.clear(); // Start with empty vector
        int value;
        while ( in >> value) // Read until end of file
            vec.push_back(value);
    } else
        std::cout << "Unable to load in the file\n";
}
int main() {
    std::vector < int > list;
    bool done = false;
    char command;
    while (!done) {
        std::cout << "I)nsert <item> P)rint " <<
            "S)ave <filename> L)oad <filename> " <<
            "E)rase Q)uit: ";
        std::cin >> command;
        int value;
        std::string filename;
        switch (command) {
        case 'I':
        case 'i':
            std::cin >> value;
            list.push_back(value);
            break;
        case 'P':
        case 'p':
            print_vector(list);
            break;
        case 'S':
        case 's':
            std::cin >> filename;
            save_vector(filename, list);
            break;
        case 'L':
        case 'l':
            std::cin >> filename;
            load_vector(filename, list);
            break;
        case 'E':
        case 'e':
            list.clear();
            break;
        case 'Q':
        case 'q':
            done = true;
            break;
        }
    }
}
I)nsert <item> P)rint S)ave <filename> L)oad <filename> E)rase Q)uit: E
I)nsert <item> P)rint S)ave <filename> L)oad <filename> E)rase Q)uit:
L data1.text

Notice that in the save_vector and load_vector functions we pass the std::string parameter as a const reference. We do this for the same reason we do so for std::vector objects this technique avoids unnecessarily making a copy the string to pass the functions. These functions can see the actual string via the reference, rather than a copy of the string object. The const specifier prevents the functions from modifying the string passed.

also exploits the special relationship between std:cout and any std::ofstream object. The print_with_endl and print_with_n functions both accept a std::ostream object as their second parameter. Note that the caller, main, passes both the std::cout object and the fout object to these printing functions at various times, and the compiler does not complain. We defer an explanation of how this works until Chapter 17.