University of Leeds

Flags

Introduction

We have see how we can pass in data to programs using both command line arguments and the user entering data via the command line. But what happens if the user enters incorrect data? For example, they enter the string "Hello, World!" instead of an integer? What will happen? It is extremely likely that the program will not function as intended. This probably isn't a problem for a simple program that calculates the area of a circle. The user can just run it again with the correct type of input. But what about the launch system on a nuclear submarine? Do you really want to start World War III because the captain pressed the wrong key!?

It is therefore a good idea to validate the user input before using it in the program.

Guessing Game Example

The example below is for a simple guessing game. The program generates a random number in the range 1 to 10 (these can be changed in the code). The user is then asked to guess the number and a suitable message is displayed depending on whether the guess was correct. There are two levels of data validation. First the input is checked to ensure that it is an integer using a C++11 regular expression and also that the guess is within range. The validation code is in a loop so that the user will have to keep entering data until valid values are entered.

The random number is generated using the C++ random library. A Mersenne Twister random number generator is used with the current time (from the chrono library) used to seed the random number generator to ensure that a different set of random numbers are generated each time the program is run.

There are also some basic functions such as print_line and print_word have been used to print lines in the command line and print text centrally. This is just to make a very simple command line interface.

 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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include <chrono>
#include <iostream>
#include <random>
#include <regex>

int get_random_number(int low, int high);
void print_line(int n);
void print_word(std::string word);
void welcome();
bool is_integer(std::string num);
int get_input(int low, int high);

int main(int argc, char const *argv[]) {
  welcome();
  int low = 1;
  int high = 10;

  // beginning of game loop
  int n = get_random_number(low, high);
  // for de-bugging only! Comment the line below to play properly!
  std::cout << n << std::endl;
  std::cout << "You need to guess the number in the range " << low << " to "
            << high << std::endl;
  int guess = get_input(low, high);

  if (guess == n) {
    std::cout << "You've guessed correctly! Winner!\n\n";
  } else {
    std::cout << "Incorrect! Loser!\n\n";
  }
  // end of game loop

  print_line(80);
}

int get_random_number(int low, int high) {
  int seed =
      std::chrono::high_resolution_clock::now().time_since_epoch().count();
  std::mt19937 generator(seed);
  std::uniform_int_distribution<int> distribution(low, high);
  return distribution(generator);
}

void print_line(int n) {
  for (int i = 0; i < n; i++) {
    std::cout << "#";
  }
}

void print_word(std::string word) {
  int length = word.length();
  for (int i = 0; i < (80 - length) / 2 - 1; i++) {
    std::cout << " ";
  }
  std::cout << word << std::endl;
}

void welcome() {
  print_line(80);
  std::cout << "\n\n";
  print_word("Welcome to the Guessing Game!");
}

// https://codereview.stackexchange.com/questions/162569/checking-if-each-char-in-a-string-is-a-decimal-digit
bool is_integer(std::string num) {
  return std::regex_match(num, std::regex("[+-]?[0-9]+"));
}

int get_input(int low, int high) {
  std::string guess_string;
  bool valid_input = false;
  int guess = 0;

  do {
    std::cout << "\nHave a guess: ";
    std::cin >> guess_string;
    valid_input = is_integer(guess_string);
    // if input is not an integer, print an error message
    if (valid_input == false) {
      std::cout << "You didn't enter an integer!\n";
    } else {  // if it is an int, check whether in range
      guess = std::stoi(guess_string);  // convert to int
      if (guess >= low && guess <= high) {
        valid_input = true;
      } else {
        std::cout << "Input out of range!\n";
        valid_input = false;
      }
    }
  } while (valid_input == false);

  return guess;
}

Program Output

Various program outputs are shown below.

Incorrect guess.

################################################################################

                        Welcome to the Guessing Game!

You need to guess the number in the range 1 to 10

Have a guess: 6

Incorrect! Loser!

################################################################################

Correct guess.

################################################################################

                        Welcome to the Guessing Game!

You need to guess the number in the range 1 to 10

Have a guess: 6

You've guessed correctly! Winner!

################################################################################

Out of range guesses.

################################################################################

                        Welcome to the Guessing Game!

You need to guess the number in the range 1 to 10

Have a guess: 12
Input out of range!

Have a guess: 15
Input out of range!

Have a guess: -1
Input out of range!

Have a guess: 2

Incorrect! Loser!

################################################################################

Invalid inputs (float and string).

################################################################################

                        Welcome to the Guessing Game!

You need to guess the number in the range 1 to 10

Have a guess: 1.1
You didn't enter an integer!

Have a guess: Hello
You didn't enter an integer!

Have a guess: 2

Incorrect! Loser!

################################################################################