-1

I've been trying to code this as sort of a beginner program for C++ to help me understand the language more but I don't really know how to tackle this.

Basically the program needs to only accept '+', '*', '/', '%' or numbers, otherwise it will say the input is invalid.

Here's what I've done so far

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string x;

    cout<<"Enter expression: ";
    getline(cin,x);



    if(x.find('*') != string::npos){

        cout<<"Multiplication";
    }else if(x.find('/') != string::npos){

        cout<<"Division";
    }else if(x.find('%') != string::npos){

        cout<<"Modulo";
    }else if(x.find('+') != string::npos){

        cout<<"Addition";
    }else{

        cout<<"Invalid!";
}
    return 0;
}
John Smith
  • 41
  • 4
  • What's your request, then? It's not clear. – Patrick Roncagliolo Jan 23 '19 at 16:06
  • Sorry if it's not clear, basically if the input is a string or character it will say the input is invalid, otherwise if its a logical operator symbol, or an integer the output will say that. – John Smith Jan 23 '19 at 16:11
  • You need to more formally specify the rules for your input. Right now, `"abcdef*"` is valid input. – PaulMcKenzie Jan 23 '19 at 17:01
  • May I ask how? I'm new to C++ sorry – John Smith Jan 23 '19 at 17:07
  • You need to parse each character of the input stream. Also you may wish to consider what to do in case of unclear input. For example, are you ok if there is more than one operator? If I wrote in input `12 + 34 * 4` would be a valid input for the program? – Valentino Jan 23 '19 at 17:09
  • The input would be invalid, I'm just aiming for only one operator so 1+1 would be valid, but adding in other symbols would become invalid, or just add in another conditional statement? – John Smith Jan 23 '19 at 17:12
  • @JohnSmith You could setup a [`std::regex`](https://en.cppreference.com/w/cpp/regex/basic_regex) to validate your input. – πάντα ῥεῖ Jan 23 '19 at 17:17
  • @JohnSmith Do you accept negative integers? Are both `+1` and `-1` valid inputs? – Hiroki Jan 23 '19 at 17:30
  • I'm so new to this I think probably not, I'd just like to see how to get C++ to detect if the input is a number or operator symbol, cause wouldn't that mean I have to convert the input? or am I handling this wrong – John Smith Jan 23 '19 at 17:39

1 Answers1

1

Definition of the Valid Input

Here I assume that the valid input is given by the following natural statements. First of all, as you mentioned,

  • Each input must be constructed from *, /, %, + and an integer.

  • Only zero or one operation. ( So 1+1 is valid. )

For an input of an integer, I also assume

  • Whitespace characters are allowed in the left and right side of the input string.

  • Whitespace characters between non-whitespace characters are not allowed.

  • The first non-whitespace character must be 0, 1, ..., 9 or - (for negative integers).

  • The second and the subsequent non-whitespace characters must be 0, 1, ..., 8 or 9.

Note that in my assumption the positive sign character +, decimal-point character . are not allowed for integer inputs. For instance, in this definition,

  • "123", " 123", "123 " and " -123 " are all valid integer inputs.
  • "abc", "123a", " 1 23", "+123" and "1.0" are all invalid ones.

Validity Check Function for An Integer

First, to check the validity of the input of an integer, we trim the input and remove left and right whitespaces using the following trimming function: ( If you can use C++17, std::string_view would be more preferable from the performance poin of view.)

#include <string>

std::string trimLR(const std::string& str)
{
    const auto strBegin = str.find_first_not_of(" \f\n\r\t\v");
    if (strBegin == std::string::npos){
        return "";
    }

    const auto strEnd = str.find_last_not_of(" \f\n\r\t\v");
    const auto strRange = strEnd - strBegin + 1;

    return str.substr(strBegin, strRange);
}

Next, we define the following simple validity check function isInteger which checks whether the passed string is an integer or not. Here std::isdigit is useful to check whether each character is digits or not. Please note that various interesting methods are proposed in the past posts.

#include <string>
#include <algorithm>

bool isInteger(const std::string& s)
{
    const auto ts = trimLR(s);

    if(ts.empty()){
        return false;
    }

    const std::size_t offset = (ts[0] == '-') ? 1 : 0;
    const auto begin = ts.cbegin() + offset;

    return (begin != ts.cend()) // false if s is just a negative sign "-"
              && std::all_of(begin, ts.cend(), [](unsigned char c){
                     return std::isdigit(c);
                 });
}

Main Function

Now it is easy and straightforward to implement the main function. The following code will check inputs and work fine. The next considerations are writing tests and performance tunings:

DEMO(Multiplication)

DEMO(Division)

DEMO(Modulo)

DEMO(Addition)

DEMO(Invalid 1)

DEMO(Invalid 2)

#include <iostream>

int main()
{
    std::string x;

    std::cout << "Enter expression: ";
    std::getline(std::cin, x);

    const auto optPos = x.find_first_of("*/%+");

    if (optPos == std::string::npos)
    {
        if(isInteger(x)){
            std::cout << "Valid input, " << x;
        }
        else{
            std::cout << "Invalid input, " << x;
        }

        return 0;
    }

    const auto left  = x.substr(0, optPos);
    const auto opt   = x.substr(optPos, 1);
    const auto right = x.substr(std::min(optPos+1, x.length()-1));

    if (!isInteger(left) || !isInteger(right))
    {
        std::cout
            << "Either `" << left << "`, `" << right 
            << "` or both are invalid inputs." << std::endl;

        return 0;
    }

    const auto leftVal  = std::stod(left);
    const auto rightVal = std::stod(right);

    if(opt == "*")
    {
        std::cout 
            << "Multiplication: " 
            << x << " = " << (leftVal * rightVal);
    }
    else if(opt == "/")
    {
        std::cout 
            << "Division: " 
            << x << " = " << (leftVal / rightVal);
    }
    else if(opt == "%")
    {
        std::cout 
            << "Modulo: " 
            << x << " = " << (std::stoi(left) % std::stoi(right));
    }
    else if(opt == "+")
    {
        std::cout 
            << "Addition: " 
            << x << " = " << (leftVal + rightVal);
    }

    return 0;
}
Hiroki
  • 2,780
  • 3
  • 12
  • 26