Please Give Constructive Feedback

I am learning C++ from the Stroustrup book "Programming Principles and Practice". I have been doing the exercises in each chapter. I have gotten stuck on chapter 6. I understand the concepts of classes, constructors, functions, and 'throw and catch' error handling, but seemingly not well enough to actually write a program with these elements that compiles and runs. I have written a program for exercise 10 in chapter 6 that runs almost correctly.

It is not a pretty program and the error exception for non-integer inputs causes the program to crash with a message relating to error exception #3 instead of my intended #4. I don't know how to put all the error exceptions into the same class. Thank you in advance for your help!

N.B. You will have to change the header line if you want to run this program. The header in the program is the one Stroustrup instructs us to download from his site

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
94
95
96
97
98
99
100
101
102
103
104

#include "../../std_lib_facilities.h"

class myexception1: public exception    // Classes for handling errors.
{
  virtual const char* what() const throw()
  {
    return "The set and subset sizes must be greater than 0.\n";
  }
} myex1;

class myexception2: public exception
{
  virtual const char* what() const throw()
  {
    return "The set size must be greater than the subset size.\n";
  }
} myex2;

class myexception3: public exception
{
  virtual const char* what() const throw()
  {
    return "Either a 'c' for combination or a 'p' for permutation must be indicated.\n";
  }
} myex3;

class myexception4: public exception
{
  virtual const char* what() const throw()
  {
    return "The set and subset sizes must be integers.\n";
  }
} myex4;

int factorial (int x)     //  Factorial function using the recursive method.
{
	int f;
	if (x == 0) {
		f = 1;
	} else {
		f = x * factorial(x-1);
	}
	return (f);
}

int permu (int n, int r)     // Ordered arrangement calculation (permuatation) for subset of size 'r' out of a set of size 'n'. 
{
	int pm;
	pm = factorial(n) / factorial(n-r);
	return pm;
}

int combi (int n, int r)    // Unordered arrangement calculation (combination) for subset of size 'r' out of a set of size 'n'.
{
	int cb;
	cb = permu(n,r) / factorial(r);
	return cb;
}

int main () 
try {
	int c = 0;
	int d = 0;
	char z = ' ';
	int result = 0;

	cout <<"Enter the set size which must be greater than zero, the subset size, \nand the type of computation.\n";
	cout <<"The set size must be greater the subset size.  \nEnter 'c' for combination or 'p' for permutation.\n";
	cout <<"Separate your entries by a space.\n";

	cin >> c >> d >> z;

	if (c <= 0 || d < 0) throw myex1;         // Negative size error.
	if (c < d) throw myex2;                   // Set size less than subet size error.
	if (z != 'c' && z != 'p') throw myex3;    // Choice other than combination or permutation error.
	if (c%1 != 0 || d%1 != 0) throw myex4;    // Non-integer error.

    if (z == 'p') {
		result = permu(c,d);
        cout << "The number of permutations is " << result <<".\n";
	}

	if (z == 'c') {
	    result = combi(c,d);
        cout << "The number of combinations is " << result <<".\n";
	}

    keep_window_open();
    return 0;

} catch(exception& e) {
	cerr << e.what() << endl;
    
	keep_window_open();
    return 1;

} catch(...) {
	cerr <<"Something else went wrong.\n";
    
	keep_window_open();
    return 2;
}
.
closed account (Lv0f92yv)
You want to have
1
2
3
4
5
if (c <= 0 || d < 0) throw myex1;         // Negative size error.
	if (c < d) throw myex2;                   // Set size less than subet size error.
	if (z != 'c' && z != 'p') throw myex3;    // Choice other than combination or permutation error.
	if (c%1 != 0 || d%1 != 0) throw myex4;    // Non-integer error.


these exceptions all in one class?

One way to do this might be to
A: Pass a 'string' argument (or char*) to the constructor of one exception class, and return an object containing that string for the 'what()' call.
B: Pass another parameter, which is checked in the single exception class to determine which message to use.

I'm no expert, but I think if the exception means something conceptually different, then it should be separate. This allows for more modular customization for your exception.
Thank you for your suggestions, Desh. I hadn't thought that having different exceptions in different classes was an appropriate formulation.

This morning I woke up realizing why my 4th exception was crashing the program. I am using the modulo operator with a double when it can only be used with ints. I need a different test for an int.
I only gave it a quick glance, but a few notes:

1. Use virtual inheritance from std::exception, so that some day down the road you can combine two exceptions (if it makes sense to do so).

2. You are creating the exception objects globally, regardless of whether or not they are ever used.
Topic archived. No new replies allowed.