C++ try/catch/throw

Hi,
I have tried to understand try/catch/throw principle but right now i think i need someone to twist the iron wire with me.

Here is the code:
1
2
3
4
5
6
7
8
9
10
11
12
start:
	cout << "How many informations you want to enter: ";
	cin >> count;
	try {
		if (count > 1 || count < 10)
			throw(count);
	 }
	catch (int b){
		cout << "Number " << b << " is too small.";

	goto start;
	}


With this i would like to prevent user to put number outside of the 1-10. This works for the first time right but when user put right number (exmpl. 5) it still gaves me the error message "Number is too small".

Ideas what i do wrong?
(count > 1 || count < 10)
Throw if count is bigger than 1.
Throw if count is less than 10.

This works for the first time right but when user put right number (exmpl. 5) it still gaves me the error message "Number is too small".

5 is bigger than 1, so it will throw.

Argh, thats right. What a blackout.

So i tried again, but this doesnt work either.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
	// First try
	try {
		if (count < 1)
			throw(count);
	 }
	catch (int b) {
		cout << "Number " << b << " is too small.";
	}
	goto start;

	// Second try
	try {
		if (count > 20)
			throw(count);
	}
	catch (int b) {
		cout << "Number " << b << " is too big.";
	}
	goto start;


I also tried this but not working.
1
2
3
4
5
6
7
8
9
10
11
	try {
		if (count < 1)
			throw(count);
		if (count > 20)
			throw(count);
	 }

	catch (int b) {
		cout << "Number " << b << " is too small.";
	}
	goto start;
Last edited on
Hello Scorpia,

Look closely at what Repeater said then try this in your original code:
if (count < 1 || count > 10)

Andy
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
#include <iostream>

int main()
{
	int count {};

start:
	std::cout << "How many informations you want to enter (1 - 10): ";
	std::cin >> count;

	// First try
	try {
		if (count < 1)
			throw(count);
	}
	catch (int b) {
		std::cout << "Number " << b << " is too small.\n";
		goto start;
	}

	// Second try
	try {
		if (count > 10)
			throw(count);
	}
	catch (int b) {
		std::cout << "Number " << b << " is too big.\n";
		goto start;
	}

	std::cout << "Number OK\n";
}


Watch where you put the goto's.

1
2
3
4
5
6
7
8
9
// First try
	try {
		if (count < 1)
			throw(count);
	 }
	catch (int b) {
		cout << "Number " << b << " is too small.";
	}
	goto start;

This code ALWAYS goes back to start, because goto start: is ALWAYS reached. There is no way through this code without hitting goto start:





1
2
3
4
5
6
7
8
9
10
11
try {
		if (count < 1)
			throw(count);
		if (count > 20)
			throw(count);
	 }

	catch (int b) {
		cout << "Number " << b << " is too small.";
	}
	goto start;

This code ALWAYS goes back to start, because goto start: is ALWAYS reached. There is no way through this code without hitting goto start:

Stop using goto ; you've tried to use it in the most simple way possible and already confused yourself.
Last edited on
Right, many blackouts here! Thank you for patience.

I did this with while loop and its working now. I just think is "good coding" use while with this kind of situation? In my code i have many places where I need this kind of check up. Should I put this while loop for everywhere I need?

Serial question: I want to make check up where user cant put number to cin when user needs to put letter. And vice versa.
Last edited on
Hello Scorpia,

Having a chance to work on the code I came up with this:
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
#include <iostream>
#include <iomanip>
#include <string>
#include <limits>

int main()
{
    int count{};

    do
    {
        std::cout << "How many informations you want to enter: ";
        std::cin >> count;

        try
        {
            if (count < 1 || count > 10)
                throw(count);
        }
        catch (int b)
        {
            std::cout << "\n     Number " << b << " is too " << (b < 1 ? "small." : "large.") << "\n\n";
        }
    } while (count < 1 || count > 10);


    // <--- Keeps console window open when running in debug mode on Visual Studio. Or a good way to pause the program.
    // The next line may not be needed. If you have to press enter to see the prompt it is not needed.
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.
    std::cout << "\n\n Press Enter to continue: ";
    std::cin.get();

    return 0;  // <--- Not required, but makes a good break point.
}

Something to consider.

Andy
In my code i have many places where I need this kind of check up.


IMO I wouldn't be using try/catch for this type of checking other than as an example. Try/throw is for catching run-time errors, not input validation. For this type of checking, I would use a simple loop.

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
#include <iostream>
#include <limits>

int main()
{
	int count {};

	do {
		while ((std::cout << "How many informations you want to enter (1 - 10): ") && !(std::cin >> count)) {
			std::cout << "Invalid number\n";
			std::cin.clear();
			std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
		}

		if (count < 1)
			std::cout << "Number " << count << " is too small.\n";
		else
			if (count > 10)
				std::cout << "Number " << count << " is too big.\n";
			else
				break;
	} while (true);

	std::cout << "Number OK\n";
}

You can do this with exceptions, but if you're catching and handling the exception at the same level as the try-catch, there's really no point to it at all.

So you've learned how to try, throw and catch. It was a nice learned exercise. You don''t need it for simple checking of input.

The useful property of exceptions is that when you throw them they KEEP going up through scopes until someone catches it, with objects destructing properly as the scopes are destroyed. If you instantly catch the exception at the same scope it is thrown, and deal with it, and the exception never continues upwards towards some higher-level catch in some function that was called five functions back in the call stack (for example) then you really don't need an exception.

Hello Scorpia,


In my code i have many places where I need this kind of check up. Should I put this while loop for everywhere I need?


This will work until you have to write it 3 or 4 times or more then you should start thinking how can I do this better.

I am not saying this is perfect, but it is a good start for now.
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
#include <iostream>
#include <iomanip>
#include <string>
#include <limits>

void FailedCin(std::string msg);
void OutOfRange(int min, int max, std::string msg);

int main()
{
    constexpr int MIN{ 1 }, MAX{ 10 };

    int count{};

    do
    {
        std::cout << "How many informations you want to enter: ";
        std::cin >> count;

        if (!std::cin || count < MIN || count > MAX)
        {
            if (!std::cin)
            {
                FailedCin("\n     Invalid Input!  Must be a number\n\n");
            }
            else if (count < MIN || count > MAX)
            {
                OutOfRange(MIN, MAX, "\n     Value out of range! Range is ");
            }
        }

    } while (count < MIN || count > MAX);


    // <--- Keeps console window open when running in debug mode on Visual Studio. Or a good way to pause the program.
    // The next line may not be needed. If you have to press enter to see the prompt it is not needed.
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.
    std::cout << "\n\n Press Enter to continue: ";
    std::cin.get();

    return 0;  // <--- Not required, but makes a good break point.
}

void FailedCin(std::string msg)
{
    std::cout << msg;

    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.
}

void OutOfRange(int min, int max, std::string msg)
{
    std::cout << msg << min << " to " << max << "\n\n";
}


Andy
If you want to use try/catch, note that the try/catch argument can be any type. There are several pre-defined types (http://www.cplusplus.com/reference/exception/exception/) but you can create your own type (class etc) which does what you want and use this. Consider:

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
#include <iostream>

class badNum {
	int no {};
	bool less {};

public:
	badNum(int n, bool l) : no(n), less(l) {}
	int getNo() const { return no; }
	bool isless() const { return less; }
};

int main()
{
	int count {};

start:
	std::cout << "How many informations you want to enter (1 - 10): ";
	std::cin >> count;

	try {
		if (count < 1)
			throw(badNum(count, true));
		else
			if (count > 10)
				throw(badNum(count, false));
	}
	catch (const badNum& bn)
	{
		if (bn.isless())
			std::cout << "Number " << bn.getNo() << " is too small.\n";
		else
			std::cout << "Number " << bn.getNo() << " is too big.\n";

		goto start;
	}

	std::cout << "Number OK\n";
}

Last edited on
Topic archived. No new replies allowed.