C++ Exercises. Part 2.

C++ Exercises. Processing data.

Introduction: Input redirection.

Reading user’s input from the keyboard can be very useful, but it’s not the only possible source of input for your program. When a lot of data must be processed, you can store this data in a file, which also can be read by your program.

The textbook describes file streams in the section 2.4. However, there is an even easier way to read a file, and we are going to use it in these exercises.

It is called standard input redirection.

stdin redirection

In Unix, if we run the program as follows:

./program < myfile.txt

Every time you read from cin, for example as in the statement

cin >> s;

the string is read not from the keyboard, but from the text file myfile.txt you specified. Isn’t it neat? It is called file redirection. The text from the file is redirected character by character as the standard input for your program.

To read the full contents of the file, you can write a program:

#include <iostream>
using namespace std;
int main() {
    string s;
    while(cin >> s) {       // While the reading operation is a success
        cout << s << endl;  // print the read word
    }
}

It relies on the fact that the expression cin >> s is not only reading a string into the variable s, but it itself evaluates to true if the reading operation was a success, and to false if it was a failure.

Practically, it means that when the program reaches the end of the file, the operation cin >> s fails to read anything from the file, evaluating to false, and indicating that the loop should stop.

Example: The longest word

Consider the following program, it reads a text from cin word by word, and prints the longest word that was input:

#include <iostream>
using namespace std;
int main() {
    string s;
    string longest = ""; // initialize with an empty string

    while(cin >> s) { // read a new word
        if (s.size() > longest.size()) { // if the new word is longer
            longest = s;                 // remember it
        }
    }
    
    cout << longest << endl;
}

Before you proceed doing the assignment, check that the above program works on some short input file. A particularly fun way to run it is to feed the program’s source code as the input. If this program is called prog.cpp, then if you use this file as the input, you will get:

./a.out < prog.cpp
longest.size())

Because "longest.size())" is the longest sequence of characters not interrupted by whitespaces.

Task 1. The most repeated word

repeat

Write a program repeated.cpp that reads a text from cin, and prints the word that was repeated in succession the largest number of times.

For example, if you have a file puddle.txt that contains this:

river canal bay lake lake spring ocean ocean ocean ocean 
lagoon lake lake river river estuary pond sea spring bay
swamp lake 

then if you redirect it into your program, it should print ocean:

./a.out < puddle.txt
ocean

Because ocean ocean ocean ocean is the longest stretch of a repeated word (which can span multiple lines, in principle).

Task 2. A + - Calculator

Calculator

We want to make a simple calculator that can add and subtract integers, and will accept arbitrarily long mathematical formulas composed of symbols +, -, and non-negative integer numbers.

Imagine you have a file formula.txt with the summation formula such as:

100 + 50 - 25 + 0 + 123 - 1

(And by the way, observe that all + and - symbols are separated by spaces.)
If you redirect the file into your program, it should compute and print the answer:

./a.out < formula.txt
247

Is that cool? It may sound tricky, but it is actually easy to write such a program, and you already know all the needed tools. Just think carefully how to put it all together.

Specifically, write a program calc.cpp that reads from the cin a sequence of one or more non-negative integers written to be added or subtracted. After the input ends (end-of-file is reached), the program should compute and print the result of the input summation.

Possible inputs may look like:

15
10 + 3 + 0 + 25 
5 + 6 - 7 - 8 + 9 + 10 - 11 
1 + 1 + 1 + 1 + 
1 + 1 + 1 + 1 + 
1 + 1 + 1 + 1 + 
1 + 1 + 1 + 1
1000 
+ 100 
+ 10 - 2

(Each of the inputs above is a separate file containing one single formula.)
The corresponding outputs should be: 15, 38, 4, 16, and 1108.

Notice that there are always spaces between +, -, and the numbers. So it is possible to read the operator and the following number using the familiar cin >> operations. Without such separating spaces the task of parsing the input would be substantially harder for us.

How to test the calculator program

In addition to writing your formulas into files, remember that your program still accepts the input from the keyboard (Hey, do you see the benefit of input redirection? The program can work great on both keyboard and file inputs!)

When typing the input from the keyboard, the key combination Ctrl+D emulates the End-of-file situation, telling the program that the input has ended.

So, you can test your program like this:

./a.out
15 - 4 + 13 - 2 + 1   
23

(finalizing your input by pressing Enter and Ctrl+D).