Ex W2

Questions about the Lecture

Important: For all exercises working with standard input (std::cin) you might want to terminate the input stream. You should be able to do this on Windows with ctrl-z and on Unix-like systems with ctrl-d. For more information see CevelopFAQ.

Simple calculator (future testat hand in!)

In this exercise you will...

a) Implement a calc function

Create a function with the signature int calc(int, int, char) that takes two numbers an a character denoting an operator symbol ('+', '-', '*', '/' and '%'). The function calc should interpret the operator character and compute its result by combining the two integers accordingly. To give you a headstart you can use the code below in a CUTE Project as Test.cpp. Add additional test cases for the corner cases of the function. Consider and test valid and invalid input, e.g. unknown operators and division by zero. What options for error handling are feasible? Discuss them with your supervisor and your peers.

To start, just use a single CUTE Test Project and develop your code there. In the last part of this exercise you will split the code into different projects.

#include "cute.h"
#include "ide_listener.h"
#include "xml_listener.h"
#include "cute_runner.h"

int calc(int lhs, int rhs, char op) {
	//TODO Implement functionality
	return 0;

void test_one_plus_one() {
	auto result = calc(1, 1, '+');
	ASSERT_EQUAL(2, result);

//TODO Add more tests here

bool runAllTests(int argc, char const *argv[]) {
	cute::suite s { };
	//TODO Register tests
	cute::xml_file_opener xmlfile(argc, argv);
	cute::xml_listener<cute::ide_listener<>> lis(xmlfile.out);
	auto runner { cute::makeRunner(lis, argc, argv) };
	bool success = runner(s, "AllTests");
	return success;

int main(int argc, char const *argv[]) {
    return runAllTests(argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE;

Tip for the implementation: Consider using a switch statement in the calc function.

b) Extension: Simple calculator with stream input (future hand in)

Extend your simple calculator from above and create an additional function int calc(std::istream& in) that will read a number, an operator character and another number from the istream in and compute the result of the operation. E.g. 1 + 1 results in 2. Also provide unit tests for this new calculator.

When tests for a function taking an std::istream & as argument, you have to create an std::istringstream that contains the given input.

void testCalcWithStream() {
  std::istringstream input{"95/5"};
  auto result = calc(input);

c) Modularization: Separate Projects

You have implemented the complete functionality of the calc function in the unit test project. In order to use them in an executable it would be desirable to have them in a separate library. This is best realized stepwise.

Now your test project should compile without errors and run as before. If not figure out why and fix remaining errors.

Now your test project should compile without errors and run as before. If not figure out why and fix remaining error.

Now create an executable project with a main.cpp source file that contains the following main function. You have to set up the dependencies from the executable project to the library project as well (See steps above). Then you can use your calculator from the console.

int main() {
  while (std::cin) {
    std::cout << '=' << calc(std::cin) << '\n';

The function calc with all of its test will be part of the first hand in later ("Testat"). Show your solution including your CUTE unit tests to your exercise supervisor, you will get feedback!

Counting Input Elements

In this exercise you will...


doesn’t help with solving the problem.


a) charc: Count non-whitespace char

Write a function charc to count non-whitespace char values by reading from an input stream (std::istream)). The result should be the number of characters found in the stream.

unsigned charc(std::istream & input) {
  //Your implementation of charc

Example: if you call the charc function with a stream containing the characters Hello, world!, the function should return 12.

Please note, that the input operator>> always skips white space characters such as blank, tab and newline.

b) allcharc: Count all characters

Create a function allcharc with the same signature as charc. The allcharc function must not skip white-space characters when counting.


Question: Can you find other means (than the member function of std::istream) to not skip the white space?

c) wc: Count words

Write a function wc, calling it to count words separated by white space character by reading from a given std::istream. The result should be the number of words found in the stream.

A word should be defined by what the input operator (>>) decides to be read as a std::string.

d) lc: Count lines

Write a function lc to count the lines by reading from standard input.

Hint: There are several means to achieve that, for example, count the characters matching the newline character ’\n’, or, use the getline() function and count how often you can call it until you reach the end of the input.

e) Modularization

After you have implemented all functions you can split up the structure as follows:

Note: Do not write any fancy "UI", so that you can use your programs also as filters within a shell-pipeline.

Compare the result of your function with the size of the file you use as input on the console (e.g., $ allcharc < file.txt). You executables should be located in the Debug directory of the executable project.

Experiments (see also lecture code)

In this exercise you will...

a) Experiment: unspecified sequence

Modify the program greeting.cpp from the self-study material of this week (SsW2). Add a second string parameter to sayGreeting() and output it together with name. Call it with calling inputName() twice. What happens? Is the sequence of words the same as you entered it? Is the program safe to use?

b) Experiment: output with conditional operator

What happens if the following piece of code gets compiled and executed as part of a main function?

#include <iostream>

int main() {
    bool cond{};
    std::cout << cond ? "Hello" : "Peter";
Can you explain your observation? Can you fix the code to get what one might expect.

Hint: CPPReference might help.

c) Questions/Experiments on input behavior

  1. What happens if a user provides an invalid number to std::cin >> anAnswer; ? Can the program continue to read further numbers?
  2. How can you read a std::string name with the code std::cin >> name; if the name provided consists of several words? How can you read the rest of the input into the string variable?
  3. Look at declaration of std::getline() function and explain its parameter passing. Why is the std::string parameter passed as reference?

Optional exercises (also for self-study)

Sum numbers

Write a program ’sumi’ to sum up a sequence of integer numbers given in standard input. Assume only numbers separated by whitespace are given. Print the resulting sum on standard output.

Example: Input 0 55 222 41 11 should result in 329

Once you are done, change your program to accept floating point numbers instead ('sumf'). How many places do you need to change?

Average numbers

Write a program ’averagei’ to calculate the average of a sequence of integer numbers given in standard input. Assume only numbers separated by whitespace are provided. Print the resulting average with the number of elements on standard output.


> averagei
0 55 222 41 11<EOF>
Average: 65.8
Count: 5

Once you are done, change your program to accept floating point numbers instead (’averagef’). How many places do you need to change?

Multiplication table (nested loops)

Write a program ’multab’ to print a multiplication table for the integers from 1 to 20. Make it more flexible, so that one can input the maximum factor up to 30 and create the table up to that factor. Make the table look nice and aligned if printed with a fixed-width font.


> multab
Enter limit (max 30):5
    1    2    3    4    5
    2    4    6    8   10
    3    6    9   12   15
    4    8   12   16   20
    5   10   15   20   25

Decimal Fractions

Can you vary your program 'multab' to print a table of decimal fractions (’fractab’) for a divided by b, where a and b take the range from 1 to 10? Example:

> fractab
enter limit (max 30):6
        0        1        2        3        4        5        6
        1        1      0.5  0.33333     0.25      0.2  0.16667
        2        2        1  0.66667      0.5      0.4  0.33333
        3        3      1.5        1     0.75      0.6      0.5
        4        4        2   1.3333        1      0.8  0.66667
        5        5      2.5   1.6667     1.25        1  0.83333
        6        6        3        2      1.5      1.2        1

Bartender cheat sheet (loops)

The VSHSR bartender who sells lots of drinks on the semester party might have a few drinks herself. Multiplication of drink prices can thus become a challenge.

Create a multiplication sheet for the multiples up to 10 times for the following drinks: ’small’ Beer 4.65, a ’Moaß’ Beer 9.15, Schnapps 3.85, Soda 2.95. This sheet will help the bartender with her task of asking for the money when one buys a round.

Last edited September 27, 2017