0

I'm trying to build a program that asks to user to input a positive integer and then the prime factors of this number are outputted. I'm giving the user three attempts to enter a valid input or the program ends. So any negative integers and non integers as well as other characters such as letters will give an error message. I'm nearly there but my output won't behave as I want. It treats decimal numbers as integers and negative numbers aren't returning the error.

#include <iostream>
#include <iomanip>
#include <cmath>
#include <stdio.h>

using namespace std;

int main()
{
    int num,i,flag,n;



    //executes loop if the input fails (e.g., no characters were read)
    while (cout << "Enter a number: " && !(cin >> num)) 
    {
        cin.clear(); //clear bad input flag
        cin.ignore(numeric_limits<streamsize>::max(), '\n'); //discard input
        cout << "Invalid input, please re-enter: \n";
    }

    i=2;
    n=num;
    cout<< "\nThe Prime factors of "<< num << " are:"<< endl;
    while(i<=num)
    {
        flag=0;
        while(n%i==0)
        { 
            n=n/i;
            flag++;
        }
        if(flag>0)
        {
            cout <<i<< endl;
        }
        ++i;
     }


     system("PAUSE");
     return 0;
}
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
teme92
  • 13
  • 2

2 Answers2

2

You are not getting an error for entering a negative number as you are not checking for that in you input validation. You could add into your while condition to check for a negative output as:

while (cout << "Enter a number: " && (!(cin >> num) || num <= 0)) 

The reason you do not catch input of a decimal number is cin successfully converts and stores the input up to the decimal point and then stops, leaving the remainder of the input in the buffer. We can see that with:

#include <iostream>

int main() 
{
    int foo;
    double bar;
    std::cin >> foo;
    std::cin >> bar;
    std::cout << foo << std::endl;
    std::cout << bar;
}

Input:

5.82

Output:

5
0.82

Live Example

You could include a check in your while loop condition to see if there is more input waiting in the stream with

while (cout << "Enter a number: " && (!(cin >> num) || num <= 0 || cin.get() != '\n'))

As for looping only three times you can add a counter to the program and increment the counter each time the body of the loop executes. Once the counter gets to 3 then you would exit the program

int counter = 0;
while (cout << "Enter a number: " && (!(cin >> num) || num <= 0 || cin.get() != '\n'))
{
    if (counter == 3)
        return 0;  // exit
    cin.clear(); //clear bad input flag
    cin.ignore(numeric_limits<streamsize>::max(), '\n'); //discard input
    cout << "Invalid input, please re-enter: \n";
    counter++;
}
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • Grammar of the second paragraph is garbled, otherwise excellent answer. I suggest "The reason you do not catch input of a decimal number is cin successfully converts and stores the input up to the decimal point and then stops, leaving the remainder of the input in the buffer." – user4581301 Sep 28 '15 at 17:02
  • Also, the last code snipped is faulty, there should be logical ORs. Or, describe what a valid input should look like, and negate that: `while(cout << "enter a number: " && !(cin >> i && i >= 0 && cin.get() == '\n'))` – LogicStuff Sep 28 '15 at 17:07
  • @user4581301 Thanks for the suggestion. I did not proof read that well engough. I have used your suggestion. – NathanOliver Sep 28 '15 at 17:08
  • The version with ORs would be: `while(cout << "enter a number: " && (!(iss >> i) || i < 0 || iss.get() != '\n'))` - De Morgan's laws – LogicStuff Sep 28 '15 at 17:15
  • @LogicStuff I already edited that into my answer. we posted at about the same time. – NathanOliver Sep 28 '15 at 17:16
  • Still, I think the first one is better :) – LogicStuff Sep 28 '15 at 17:17
  • Thanks guys for the help, seems to have done the trick. What about only allowing three attempts though? – teme92 Sep 28 '15 at 18:10
  • @teme92 I added that into the answer. – NathanOliver Sep 28 '15 at 18:17
  • Thanks @NathanOliver for that, much appreciated. – teme92 Sep 28 '15 at 18:21
0

!(cin >> num) is only true when cin fails to insert the input character data into num, which is an int. Both negative integers (like -12) and decimal quantities (like 3.14) can be stuffed into a signed int. The decimal quantity works because floats can be coerced into ints by truncation.

To do what you want, you need to first capture your console input as a string, then attempt to parse out a positive integer. Take a look at How do I check if a C++ string is an int? and also boost::lexical_cast (if boost is an option).

Community
  • 1
  • 1
wesholler
  • 122
  • 4
  • Not quite right on float being truncated. the value is never a float. A `>>` into int stops dead as soon as a non-digit is found and provides what was read as an int. The remainder sit in the stream, waiting for the next read if it is not manually detected and extracted. NathanOliver covers this in his answer. – user4581301 Sep 28 '15 at 17:47
  • @user4581301 Good call. – wesholler Sep 29 '15 at 19:44