0

Now, before this question gets marked for duplicate. I have already gone through most of the questions and their relative answers of C++. These are the links that I have tried and none of them work for me. It maybe because they are using an older version of C++, and I have the latest version of C++. Here are the links that I have tried:

Now, with the duplicates out of the way. I am making an expression calculator. So, for example if the user input is: 2+2*6*9/9, then the output should be 14.
The code where I suspect that the problem lies is in:

#include <iostream>
#include <vector>

using std::cout;
using std::cin;
using std::string;
using std::vector;

void clear();
void error(string message);

int main() {
    cout << "Enter an expression: ";
    double l_Value = 0, r_Value = 0, result = 0, count = 0, previous_number;
    char op;
        while (cin >> l_Value) { // 1+2*3+6-4/2+3
            if (!cin) {
                error("Invalid operand entered!");
            }
            else {
                bool is_Error = 0; // false
                vector<double> numbers;
                numbers.push_back(l_Value);
                previous_number = l_Value;
                while (cin >> op) {
                    if (op == '\0') {
                        break;
                    }
                    cin >> r_Value;
                    switch (op)
                    {
                    case '+':
                        numbers.push_back(r_Value);
                        previous_number = r_Value;
                        break;
                    case '-':
                        numbers.push_back((-1 * r_Value));
                        previous_number = (-1 * r_Value);
                        break;
                    case '*':
                        numbers.pop_back(); // take out the number
                        r_Value *= previous_number;
                        numbers.push_back(r_Value);
                        previous_number = r_Value;
                        break;
                    case '/':
                        if (r_Value == 0) {
                            error("Sorry, division by zero has occured. Please re-evaluate your expression!\n");
                            is_Error = 1; // true
                            break;
                        }
                        else {
                            numbers.pop_back(); // take out the number
                            previous_number /= r_Value;
                            numbers.push_back(previous_number);
                            break;
                        }
                    }
                }
                if (!is_Error) {
                    for (int i = 0; i < numbers.size(); i++) {
                        result += numbers[i];
                    }
                    cout << result << '\n';
                }
                numbers.clear();
                result = 0;
                l_Value = 0;
                r_Value = 0;
                
            }
        cout << "Enter an expression: ";
    }

    clear();
    return 0;
}

None of the links above seemed to work for me.
When I press the Enter key, it expects me to give another input, and that is not supposed to happen. So when I used
cin.get() == 'n' or cin.get() == (int)'\n', it expects for another input. But, when I have an 'x' at the end of the expression, it works perfectly fine. So, I need the "cin" operator to help me detect an Enter character at the end of the expression and then terminate the program.
Here, is a sample run of a program with 'x':

[![running as x-terminator][1]][1]
[1]: https://i.sstatic.net/ORPQa.png

When I try the above solution such as "cin.get() == '\n':

running as enter-terminator
Then, I thought that maybe it is reading the null character and so, I tried if (op == '\0'):

null character terminator

For the enter key and null character I had to press Ctrl+Z to terminate the program. Please help!

As, mentioned by user @idclev, I already have a string program that works, but I am trying to avoid using string to calculate any expressions! So, if I could detect an enter key pressed using a character datatype that would be great!

18
  • 1
    Please include a minimal reproducible example Commented Jul 1, 2020 at 13:52
  • 1
    That's a too low-level perspective. Read one line at a time with std::getline, then use std::istringstream for parsing the line. Commented Jul 1, 2020 at 13:54
  • 1
    you missed to include a minimal reproducible example, code that others can copy and paste, then compile and run to reproduce your problem. The code you did post is both incomplete (it doesnt complie as is) and has too much that isnt relevant for the acutal quesiton Commented Jul 1, 2020 at 13:54
  • 1
    I read your question, but most of it I didnt understand. To "detect enter" you just need std::string x; std::cin >> x; if (x == "") std::cout << "user pressed only enter"; Commented Jul 1, 2020 at 13:55
  • 2
    here you can see the edit history stackoverflow.com/posts/62678370/revisions afaik users are not notified when there is no comment of theirs in the thread Commented Jul 1, 2020 at 14:08

2 Answers 2

1

I avoided strings to avoid parsing through the text

That argument is moot. What you can read from cin you can also read from a std::string, no difference whatsoever. You just need to add one step:

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

int main( ){
    std::string x;
    std::cin >> x;
    if (x == "") {
            std::cout << "user pressed enter (and nothing else)";
    } else {
        double y;
        std::stringstream ss{x};
        ss >> y;
        std::cout << y;
    }
}

This will read one std::string. If user only hit enter then the string will be empty. If the user entered something the else branch will be taken and you can extract the number from the string in the same way you did extract the number from cin (via using a std::stringstream).

If you have more than one number in the input you need to use getline to read the string, because cin will (by default) only read till the next whitespace.

Again...

If I used a string, I would have a tough time in extracting single-digit and two-digit or n-number of digits in a string. The double data type does that for me

You can read single-digit or any number of digits from a stringstream in exactly the same way as you read them from cin.

I already made a program with string in it. I was trying to avoid string to see how much faster would it be without string.

It won't be any faster. Constructing the string and the stringstream is maybe in the order of microseconds. A user entering input is in the order of seconds, maybe milliseconds when they are typing very fast.

Your approach cannot work because hitting enter is not considered as a character. Trying to read a character when there is none in the stream will fail. It will not set the character to \n or \r.

Sign up to request clarification or add additional context in comments.

14 Comments

I already made a program with string in it. I was trying to avoid string to see how much faster would it be without string. If I could detect the enter key as a character input that would be a better solution!
But this code, only reads the first number, and truncates the rest of the expression!
@ProgrammingRage let me be clear (no offense intended, but somehow I have to get the message across): When I read your question I see a wall of code with vectors with a switch for operators and all such stuff, but I didnt even find the place in code that the question is about. If you have code that uses strings and you want to see if it can be made faster without then maybe you should write that in the question.
@ProgrammingRage this is just a simplified example, I wrote in the question that to read more numbers you need to use getline and then you can again read the numbers from the string exactly like you would from cin
Oh sorry, I thought that was irrelevant, but I will add it now. Plus i do not really know where the problem to my question is in my code.
|
1

On the outer loop, you are trying to read a double, but you keep pressing enter. There is no input to evaluate, so it keeps trying to read a double. You can get out of it by ending the input stream with ^Z, or you can give it any actual content to read, and it will try to make it into a double (which is what your code explicitly told it to wait for).

Basically, when you press enter, it's ignoring it because
http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/

Extracts as many characters as possible from the stream and inserts them into the output sequence controlled by the stream buffer object pointed by sb (if any), until either the input sequence is exhausted or the function fails to insert into the object pointed by sb.

Try experimenting with this to see what is happening.

#include <iostream>
#include <vector>
#include <string>

int main() {
    double x;
    std::cin >> x;
    std::cout << "read this value: " << x << std::endl;

    // this is what while or if will look at
    bool success = !std::cin.fail();
    if (success)
        std::cout << "success" << std::endl;
    else
        std::cout << "failure, loop will exit" << std::endl;
    return 0;
}

What you should want (in my opinion) is a function that takes the expression as a string, and returns the result, so you can write unit tests, and make sure the function works. You can use this function with any expression that you can put in a string. It doesn't HAVE to be typed in by a user.

If you want the user to type in the experession, it's a lot easier to just use getline() then pass the string to your function. The big problem with using cin on each variable and character is that the user has no idea which datetype is expected right then. Granted, it's not hard to guess with an expression, but you wrote it and debugged it and still didn't know which cin you were failing to get the right datatype to. (this is normal, btw -- been there, which is why I getline and parse separately)

4 Comments

I already have done that with my string program that I created. I just wanted to evaluate an expression without using text parsers of any sort. Now yes, my outer while loop is using double as an input. But imagine I have this expression: 2+2*6*9/9. 2, will be read by the first outerloop, and then it would never go back there until is has displayed the result. The rest of the expression is handled by the inner loop. So, 2 -> outerloop (l_Value), + -> inner loop (op), 2 -> inner loop (r_Value) and so on until it reaches the last character 9 which is read by r_Value. Then op reads.
Then op variable reads the next input, which is expecting a character input.
I told you where you actually got hung up on the wrong datatype, with the input you gave. There might be other ways to get hung up with different data types. The answer is the same. cplusplus.com/reference/istream/istream/operator%3E%3E continues to read whitespace until the end of the stream, or it gets actual text that it can succeed or fail to put into the requested variable. The demo should make that clear, if you play with it.
Yea, so I dropped the idea and now I will just stick to strings or use an 'x' to terminate the expression.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.