-1

So basically I am trying to get it to stop repeating. If I enter numbers correctly it works fine. If I enter negative numbers which are not allowed and needs a try-catch exception it keeps repeating and won't stop asking for numbers. All I have is this source file for the code and I am trying to make a function for main.

#include <iostream>
#include <iomanip>
#include <string>

using namespace std;

void gcd(int x, int y);

int main()
{
    int x;
    int y;
    cout << "Please enter two integer values" << endl;
    cin >> x;
    cin >> y;
    gcd(x, y);

    return 0;
}

void gcd(int x, int y)
{
    int gcd;
    int s = 0;
    while (s == 0)
    {
        try
        {
            if (x < 0 || y < 0)
                throw 1;
            else
            {
                s == 1;
                break;
            }
        }
        catch (int x)
        {
            cout << "Wrong negative input please type in two Positive integers" << endl;
            cin >> x >> y;
            continue;
        }
    }
    for (int i = 1; i <= x && i <= y; i++)
    {
        if (x % i == 0 && y % i == 0)
            gcd = i;
    }
    cout << "The gcd of x: " << x << " and y: " << y << " is: " << gcd << endl;
}
Derek Langer
  • 29
  • 1
  • 7

2 Answers2

1

If you don't want your function gcd() to be called with negative values, throw a std::invalid_argument exception. It is not the business of gcd() to request user input. Validate the input in main() before you call gcd().

#include <limits>
#include <stdexcept>
#include <iostream>

int gcd(int, int);

int main()
{
    int x, y;
    while (std::cout << "Please enter two positive integers: ",
           !(std::cin >> x >> y) || x < 0 || y < 0)
    {
        std::cerr << "Input error :(\n\n";
        if (std::cin.fail()) {
            std::cin.clear();
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        }
    }

    std::cout << "The gcd of x: " << x << " and y: " << y << " is: " << gcd(x, y) << "\n\n";
}

int gcd(int x, int y)
{
    if (x < 0 || y < 0)
        throw std::invalid_argument("No negative arguments to gcd(), please :(");
    return y == 0 ? x : gcd(y, x % y);
}
Swordfish
  • 12,971
  • 3
  • 21
  • 43
  • Or `gcd` can take unsigned type :-) – Jarod42 Feb 21 '19 at 09:44
  • Have you ever tried to error-check the extraction of an `unsigned` from a stream? – Swordfish Feb 21 '19 at 09:46
  • As you said, not the job of `gcd` to request/validate user input. so `main`can stay unchanged. (but indeed behavior of `std::cin >> u` is sad [Demo](https://ideone.com/Ka076n)). – Jarod42 Feb 21 '19 at 09:50
  • Thank you that works and I see where the code was going, but does anyone know where one could find a list of all exceptions we could use? – Derek Langer Feb 21 '19 at 16:36
  • @DerekLanger you can throw every type you like. but here you are: [](http://www.cplusplus.com/reference/stdexcept/) – Swordfish Feb 21 '19 at 17:57
0

You can (and perhaps should) remove the logic from gcd function and instead place it where you get your input from user, that is, in main. Also, state the requirements up front. For example:

int main()
{
    int x;
    int y;
    cout << "Please enter two positive integer values" << endl;
    cin >> x;
    cin >> y;
    if (x < 0 || y < 0)
    {
        cout << "Wrong negative input please type in two Positive integers" << endl;
        return 0;
    }

    gcd(x, y);

    return 0;
}

Now, you can place assertions in gcd to enforce no negative values get in:

void gcd(int x, int y)
{
    assert(x >= 0);
    assert(y >= 0);
    // ...
}
Krzysiek Karbowiak
  • 1,655
  • 1
  • 9
  • 17
  • `assert`ions will only work in debug builds. when `cin >> x` or `cin >> y` fail you're in a world of shiiiiet. – Swordfish Feb 21 '19 at 07:47