-2

so i have been tasked with creating a c++ calculator that takes user input as a string equation like "-2.5 + 40 - 3 * 8 / 2) which would read from left to right(order of operations not followed) and output 138 as the answer. there has to be spaces between each operator and operand.

ive made a calculator, but it only works on single digit positive integers. here is the code.

    #include <iostream>
    #include <string>

    float calculator(string input){
    float result = 0;
    for(int i = 0; i < input.length(); i++){
    if(input[i] == '+'){
    result += (input[i-2]-'0') + (input[i+2]-'0');
    }
    return result;
    }

int main(){
string input = "";
cout << "enter string" << endl;
getline(cin, input);
cout << calculator(input) << endl;

so inputting "1 + 3" gives 4 but "12 + 3" yields 5. i know why it is giving 5 i just don't know how to fix it. i don't want anyone to just plain give me the answer, but if someone could point me in the right direction? i thought maybe using the regular cin instead of getline because that would read up to a space and store it, but couldn't really think of how to continue this.

with your guys pointers, i made another calculator that uses cin>>. but it only works if i give exactly the right amount of operators and operands, which is not possible to know if I'm receiving random user equations. any ideas?

  int main(){
float num1 = 0, num2 = 0, num3 = 0, answer = 0;
char op1, op2;
cout << "enter string\n";
cin >> num1;
cin >> op1;
cin >> num2;
cin >> op2;
cin >> num3;

if(op1 == '/'){
answer = num1/num2;
}

if(op1 == '*'){
answer = num1*num2;
}

if(op1 == '-'){
answer = num1-num2;
}

if(op1 == '+'){
answer = num1+num2;
}

cout << "answer is " << answer << endl;

return 0;
}
billy bob
  • 11
  • 5
  • 1
    You need to "tokenize" the input so that `12` is a single unit rather than treating the `1` and `2` as separate pieces. – Code-Apprentice Feb 16 '18 at 01:32
  • 1
    Are you guaranteed spaces between each token? If so, a `std::istringstream` and using the `>>` to read into `std::string`s may help. – user4581301 Feb 16 '18 at 01:33
  • 1
    @user4581301 "*there has to be spaces between each operator and operand.*" -- sounds like a guarantee to me. – Robᵩ Feb 16 '18 at 01:36
  • yes i am guaranteed spaces between each operator and operand. so cin>> would read the first operand, with the rest of the string still in the input buffer, then my next cin>> would be my operator and so on and so forth....i tried doing a while(!cin.eof) loop but it would never exit the loop. – billy bob Feb 16 '18 at 01:37
  • @Robᵩ Time to get my eyes checked. billy bob, `getline` just like you are doing and take the line apart with a `stringstream` like in this answer: https://stackoverflow.com/a/7868998/4581301 . By the way, consider all of your options before looping on EOF. [It almost never works.](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) In this case `cin` does not have an easily defined end of file because it's the program console. You have to close the console to close the file, and then you can't talk to the program anymore. – user4581301 Feb 16 '18 at 01:57
  • For my general interest, what sort of programming course is this assignment for? an introductory first programming course, an intermediate course, or an algorithms and data structures course? – user4581301 Feb 16 '18 at 02:04
  • @user4581301 this is an intro class, would you look at my edit above and check out my second version of the calculator? – billy bob Feb 16 '18 at 02:13
  • Your new approach to input is headed in a good direction, but it would be easier if you grab the entire equation with a `getline`. Currently you don't know when the equation ends, and have no chance of respecting the order of operations. With `getline` each line is a string, and you can simply keep splitting up the line until you run out of string. – user4581301 Feb 16 '18 at 02:23
  • Initialize an accumulator `double lhs;` with the first read. Then make a loop and read `cin >> opp >> rhs` each time round the loop. Use `opp` to decide how to apply `lhs` to the `rhs` storing the result back in `lhs` for next time round the loop. – Galik Feb 16 '18 at 02:23
  • *"order of operations not followed"* Smurf! My reading is horrible this day! And Thank Crom. Order of operations makes this a much, much nastier question. – user4581301 Feb 16 '18 at 02:25
  • @billybob • if you find yourself working on (what is effectively a DSL) these kinds of parsers, you might find Boost Spirit to be both very useful, albeit very daunting until you are familiar with it. – Eljay Feb 16 '18 at 03:49
  • @user4581301 - To avoid the inevitable bugs that `while(cin.eof)` creates, follow @Galik's advice with loop structure: `while(std::cin >> op >> rhs) { ... }`. – Robᵩ Feb 16 '18 at 06:48

1 Answers1

1

try parsing the numbers with strtok instead of reading the string char by char

EDIT

may sscanf is a better approach here

Community
  • 1
  • 1
akiva
  • 2,677
  • 3
  • 31
  • 40
  • `strtok` may not be a good solution here, this being C++ and all. – user4581301 Feb 16 '18 at 01:31
  • ya reading about strtok, i seem to understand its meant for c style strings – billy bob Feb 16 '18 at 01:33
  • Since the input language always has whitespace between operands and operators, how about just `>>`? – Robᵩ Feb 16 '18 at 01:33
  • yes i am guaranteed spaces between each operator and operand. so cin>> would read the first operand, with the rest of the string still in the input buffer, then my next cin>> would be my operator and so on and so forth....i tried doing a while(!cin.eof) loop but it would never exit the loop. – billy bob Feb 16 '18 at 01:37
  • @Robᵩ would you look at my edit above and check out my second bit of code. it utilizes cin>> but I'm stuck. – billy bob Feb 16 '18 at 02:14
  • if i could figure out how many operators are inputted, i would then know that operands equals operators+1. so to figure out how many operators i could loop through the string and count the /,*,-,+....how can i use the .length() on num1 when num1 is a float and not a string? – billy bob Feb 16 '18 at 02:21