2

I'm a C++ beginner and I'm currently working on a simple calculator project. I want the input to be only numbers so I made a if else statement to check if the input is only number, if yes then do the calculation and return to "Enter operator" bla bla. Please ignore case 2 3 4 as I want to make the input checker work. What am I doing wrong and how do I fix this ? Thank you in advance ! But for some reason it just wouldn't work.

# include <iostream>

using namespace std;

int main() {
    bool whileRunning = true;
    while(whileRunning){
        char op;
        float num1, num2;
        cout << "\n Enter operator either 1 (+) or 2 (-) or 3 (*) or 4 (/) or 5 to exit: ";
        cin >> op;
       
        switch (op)
        {
        case '1':     
            cout << "Enter two operands: ";
            cin >> num1 >> num2;
            if (isdigit(num1) == 0 && isdigit(num2) == 0) {
                cout << num1 + num2;
            }
            else
                cout << " Please only input numbers";
                break;
            break;
        case '2':
            cout << "Enter two operands: ";
            cin >> num1 >> num2;
            if (isdigit(num1) && isdigit(num2)) {
                cout << num1 - num2;
            }
            else
                break;

            break;

        case '3':
            cout << "Enter two operands: ";
            cin >> num1 >> num2;
            if (isdigit(num1) && isdigit(num2)) {
                cout << num1 * num2;
            }
            else
                break;
            break;

        case '4':
            cout << "Enter two operands: ";
            cin >> num1 >> num2;
            if (isdigit(num1) && isdigit(num2)) {
                if (num2 == 0) {
                    cout << "You tried to divide by 0, Try again!";
                    break;
                }
                else
                    cout << num1 / num2;
            }
            else
                break;
            

            break;
        case '5':
            whileRunning = false;
            break;

        default:
            // If the operator is other than +, -, * or /, error message is shown
            cout << "Error! Your input must be >= 1 and  <= 5. Please try again";
            break;

        }
    }
 

    return 0;
};


  • Can you post the complete code? – Shubham Srivastava Nov 25 '20 at 07:35
  • 3
    I think, you expect `isdigit` to do something else than it actually does. It doesn't make much sense to use it on a `float`. See the [reference](https://en.cppreference.com/w/cpp/string/byte/isdigit). – churill Nov 25 '20 at 07:36
  • Updated with the full code with other cases! – KaizIsCoding Nov 25 '20 at 07:36
  • 3
    Please see this [How to determine if a string is a number with C++?](https://stackoverflow.com/questions/4654636/how-to-determine-if-a-string-is-a-number-with-c) – Suthiro Nov 25 '20 at 07:38
  • 2
    Regardless of your indentation... both of your "case" statements resolve to `break;break` ALSO: "isdigit()" is used incorrectly, and you probably DON'T want "cin" of a float. Rather, you want 1) input as a string, 2) parse the string after input, 3) process accordingly. – paulsm4 Nov 25 '20 at 07:41
  • This doesn't address the question, but when asking the user to specify an operation such as `+`, `-`, `*`, or `/`, I'd be inclined to ask for those characters rather than asking for numbers and explaining how those numbers map to operations. – Pete Becker Nov 25 '20 at 14:27

4 Answers4

3

You do the wrong check in isDigit and isDigit cannot be used in with float number.

As said by C++ Refernce the return value is:

A value different from zero (i.e., true) if indeed c is a decimal digit. Zero (i.e., false) otherwise.

So you need to check if the isDigit function return a value different from 0. The right code is this:

# include <iostream>

using namespace std;

int main() {
    bool whileRunning = true;
    while(whileRunning){
        char op;
        int num1, num2;
        cout << "\n Enter operator either 1 (+) or 2 (-) or 3 (*) or 4 (/) or 5 to exit: ";
        cin >> op;
       
        switch (op)
        {
        case '1':     
            cout << "Enter two operands: ";
            cin >> num1 >> num2;
            if (isdigit(num1) != 0 && isdigit(num2) != 0) {
                cout << num1 + num2;
            }
            else
                cout << " Please only input numbers";
                break;
        
        ....
         
        default:
            // If the operator is other than 1, 2, 3, 4, 5 error message is shown
            cout << "Error! Your input must be >= 1 and  <= 5. Please try again";
            break;

        }
    }
 

    return 0;
};

In your code you test the opposite one.

You can find further reading on isDigit function on this site.

For the float number you can use this other approach:

if(scanf("%f", &userNum) == 1) {
    // Handle item float here
}

So your code seems like :

# include <iostream>

using namespace std;

int main() {
    bool whileRunning = true;
    while(whileRunning){
        char op;
        float num1, num2;
        cout << "\n Enter operator either 1 (+) or 2 (-) or 3 (*) or 4 (/) or 5 to exit: ";
        cin >> op;
       
        switch (op)
        {
        case '1':     
            cout << "Enter two operands: ";
            if(scanf("%f %f", &num1, &num2) == 2){ {
                cout << num1 + num2;
            }
            else
                cout << " Please only input numbers";
                break;
        
        ....
         
        default:
            // If the operator is other than 1, 2, 3, 4, 5 error message is shown
            cout << "Error! Your input must be >= 1 and  <= 5. Please try again";
            break;

        }
    }
 

    return 0;
};

You can find scanf reference here.

Zig Razor
  • 2,907
  • 2
  • 8
  • 27
  • 4
    I guess you also need to take a look at the [reference](https://en.cppreference.com/w/cpp/string/byte/isdigit). Yes, Op used it the wrong way around, but no, it still doesn't make any sense to use `isdigit` on a `float`. So technically correct, but not what OP wants. Explanation: `isdigit(num1)` will return true when `num >= '0' && num <= '9'`, i.e. `num >= 48 && num <= 57`. – churill Nov 25 '20 at 07:43
  • 1
    The logical expression could be simplified as `(isdigit(num1) && isdigit(num2))`. – CKE Nov 25 '20 at 07:43
  • This is also what I tried to do but when I type a or literally anything but numbers It will spit out the first line and it doesn't break. – KaizIsCoding Nov 25 '20 at 07:47
  • 1
    i correct my answer, i don't focus on the type of the number before – Zig Razor Nov 25 '20 at 07:52
  • I have not learnt how to use scanf yet and the reference is useful but is there another way to do this ? – KaizIsCoding Nov 25 '20 at 07:54
1

First of: std::isdigit only checks if the argument you passed is a digit from '0'...'9'. Yes, it's confusing that it's parameter is of type int, not char and it's even more confusing, because you can feed it a float.

cin >> num1 >> num2;
if (isdigit(num1) == 0 && isdigit(num2) == 0) {
    cout << num1 + num2;
}

will basically check if num1 >= '0' && num1 <= '9'. If we replace that char ltierals with ascii codes you get num1 >= 48 && num1 <= 57 (Same for num2). So far to why it doesn't work this way.


How to fix it:

cin >> num1 >> num2;

will always, no matter what, try to read a float. If you enter a string it will not magically store a string in the variables, but instead will set a fail bit.

A common way of doing input validation is this:

if (cin >> num1 >> num2) {
    cout << num1 + num2;
}
else {
    cout << " Please only input numbers";
    // ignore faulty input until the next line or eof
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
    // reset flags to allow further input
    cin.clear(); 
}

*std:: ommited for brevity

This works because std::istream::operator>> returns a reference to itself which can then be converted to bool, thus yielding true when and only when the user entered two floats.

churill
  • 9,299
  • 3
  • 13
  • 23
1

I've decided to re-write the code. Thank you for all the help!

#include<iostream>
#include<string.h>

using namespace std;

bool ifstring(string number) {
    for (int i = 0; i < number.length(); i++)
        if (isdigit(number[i]) == true)
            return false;
    return true;
}


int main() {
    bool whileRunning = true;
    while(whileRunning){
        char op;
        string num1, num2;
        float dnum1, dnum2;

        cout << "\n Enter operator either 1 (+) or 2 (-) or 3 (*) or 4 (/) or 5 to exit: ";
        cin >> op;
       
        switch (op)
        {
        case '1':     
            cout << "Enter two operands: ";
            cin >> num1 >> num2;

            if (ifstring(num1) == 0 && ifstring(num2) == 0) {
                dnum1 = stof(num1);
                dnum2 = stof(num2);
                
                cout << dnum1 + dnum2;
            }
            else
                cout << " INPUT PLS";
                break;
            break;
        case '2':
            cout << "Enter two operands: ";
            cin >> num1 >> num2;
            if (ifstring(num1) == 0 && ifstring(num2) == 0) {
                dnum1 = stof(num1);
                dnum2 = stof(num2);

                cout << dnum1 - dnum2;
            }
            else
                break;

            break;

        case '3':
            cout << "Enter two operands: ";
            cin >> num1 >> num2;
            if (ifstring(num1) == 0 && ifstring(num2) == 0) {
                dnum1 = stof(num1);
                dnum2 = stof(num2);

                cout << dnum1 * dnum2;
            }
            else
                break;
            break;

        case '4':
            cout << "Enter two operands: ";
            cin >> num1 >> num2;

            if (ifstring(num1) == 0 && ifstring(num2) == 0) {
                dnum1 = stof(num1);
                dnum2 = stof(num2);

                if (dnum2 == 0) {
                    cout << "You tried to divide by 0, Try again!";
                    break;
                }
                else
                    cout << dnum1 / dnum2;
            }
            else
                break;
            

            break;
        case '5':
            whileRunning = false;
            break;

        default:
            // If the operator is other than +, -, * or /, error message is shown
            cout << "Error! Your input must be >= 1 and  <= 5. Please try again";
            break;

        }
    }
 

    return 0;
};
0

As already noted C++ has no intrinsic function to check an input for being a number. Therefore you can use the following function to check if a string is a number:

bool isNumber(const std::string& s)
{
    std::istringstream iss(s);
    float f;
    char c;
    return iss >> f && !(iss >> c);
}

Applied this to your simple calculator program, it could be written as:

#include <iostream>
#include <sstream>
#include <string>

using namespace std;

bool isNumber(const std::string& s)
{
    std::istringstream iss(s);
    float f;
    char c;
    return iss >> f && !(iss >> c);
}

int main() {
    bool whileRunning = true;
    while (whileRunning) {
        char op;
        float num1, num2;
        string str1, str2;
        cout << "\n Enter operator either 1 (+) or 2 (-) or 3 (*) or 4 (/) or 5 to exit: ";
        cin >> op;
        if (op != '5')
        {
            cout << "Enter two operands: ";
            cin >> str1 >> str2;
            if (isNumber(str1) && isNumber(str2))
            {
                num1 = static_cast<float>(atof(str1.c_str()));
                num2 = static_cast<float>(atof(str2.c_str()));
            }
            else
                continue;
        }
        switch (op)
        {
        case '1':
            cout << num1 + num2;
            break;
        case '2':
            cout << num1 - num2;
            break;
        case '3':
            cout << num1 * num2;
            break;
        case '4':
            if (num2 == 0)
                cout << "You tried to divide by 0, Try again!";
            else
                cout << num1 / num2;
            break;
        case '5':
            whileRunning = false;
            break;
        default:
            // If the operator is other than +, -, * or /, error message is shown
            cout << "Error! Your input must be >= 1 and  <= 5. Please try again";
            break;
        }
    }
    return 0;
};

Just one hint: Please use double instead of float if you want to avoid casting and/or you want to have a good precision for numerical calculations.

Hope it helps?

CKE
  • 1,344
  • 9
  • 14
  • 25