-2

I am trying to solve a problem that evaluates simple expressions in a string like 10+20 should return 30

The problem is the string can contain white spaces so i uses stringstring with skipws flag it works for white spaces within the string like 10 + 20 etc but when white space is in the end its not passing towards the correctly.

This is how I am parsing the string

void build_stack(const string& str) {
    istringstream ss(str);

    char op;
    int op1, op2;
    ss>>skipws>>op1;
    operands.push(op1);
    while(!ss.eof()) {
        ss>>op;
        operators.push(op);
        ss>>op2;
        operands.push(op2);
    }
}

full code with various string inputs here in rextester.

when the string is 3+5 / 2 my stacks gets built as operands => 2 2 5 3 operators => / / +

when the string is 3+5 / 2 (i.e with trailing whitespace) my stacks gets built as operands => 2 5 3 operators => / +

i tried

while(ss.peek() == ' ') {
    char c; ss>>c;
}

but this is removing all characters after seeing a whitespace.

user3279954
  • 384
  • 3
  • 19
  • Always test all input operations, such as use of operator >>, and report failures. And https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-i-e-while-stream-eof-cons –  Sep 17 '19 at 17:22
  • Please provide a [mcve]. Don't do `while(!ss.eof())` https://stackoverflow.com/questions/5837639/eof-bad-practice – Thomas Sablik Sep 17 '19 at 17:42

1 Answers1

0

Example "3+5 / 2 ":

  1. ss>>skipws>>op1;

    3 is written into op1

  2. operands.push(op1);

    op1 is pushed into operands

  3. while(!ss.eof()) {

    is true

  4. ss>>op;

    + is written into op

  5. operators.push(op);

    op is pushed into operators

  6. ss>>op2;

    5 is written into op2

  7. operands.push(op2);

    op2 is pushed into operands

  8. while(!ss.eof()) {

    is true

  9. ss>>op;

    / is written into op

  10. operators.push(op);

    op is pushed into operators

  11. ss>>op2;

    2 is written into op2

  12. operands.push(op2);

    op2 is pushed into operands, ss contains a whitespace, not empty

  13. while(!ss.eof()) {

    is true

  14. ss>>op;

    can't be read, / stays in op, eof is set

  15. operators.push(op);

    op is pushed into operators

  16. ss>>op2;

    can't be read, 2 stays in op2

  17. operands.push(op2);

    op2 is pushed into operands

  18. while(!ss.eof()) {

    is false

in contrast to example "3+5 / 2":

  1. ss>>skipws>>op1;

    3 is written into op1

  2. operands.push(op1);

    op1 is pushed into operands

  3. while(!ss.eof()) {

    is true

  4. ss>>op;

    + is written into op

  5. operators.push(op);

    op is pushed into operators

  6. ss>>op2;

    5 is written into op2

  7. operands.push(op2);

    op2 is pushed into operands

  8. while(!ss.eof()) {

    is true

  9. ss>>op;

    / is written into op

  10. operators.push(op);

    op is pushed into operators

  11. ss>>op2;

    2 is written into op2

  12. operands.push(op2);

    op2 is pushed into operands, ss is empty, eof is set

  13. while(!ss.eof()) {

    is false

You can fix it with

void build_stack(const string& str) {
    istringstream ss(str);

    char op;
    int op1, op2;
    ss>>skipws>>op1;
    operands.push(op1);
    while(true) {
        if (!(ss>>op)) break;
        operators.push(op);
        if (!(ss>>op2)) break;
        operands.push(op2);
    }
}
Thomas Sablik
  • 15,040
  • 7
  • 26
  • 51
  • Thanks @ThomasSablik for the step by step explanation. So the value is being reused from the stack confirmed by modifying the values in the stack and see the dummy values gets inserted new source [location](https://rextester.com/MQQJ44129). My question still is since the ignore whitespace flag is set shouldnt `ss.eof()` check right away if remaining stream is valid or the last read adjust whitespace characters ? Rightnow i switched to `while(ss>>op)` instead. to avoid two breaks. – user3279954 Sep 17 '19 at 19:50
  • First, `ss>>skipws` does nothing in your example. skipws is the default behavior: https://en.cppreference.com/w/cpp/io/manip/skipws. Whitespaces are skipped until input, not after input. "_Enables or disables skipping of __leading__ whitespace"_ Without both breaks input like `5+5+` will yield `5 5 5` and `+ +`. – Thomas Sablik Sep 17 '19 at 20:01