Your algorithm needs more thinking. But first, here is some commentary on your code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <cctype> // Use C++ includes
using namespace std;
const int maxstack = 20;
//const char initstack = 'z'; // You do not need this
void createStack(char stack[], int &top)
{
int i;
top = -1;
// for (i = 0; i < maxstack; i++) // Or this. Unused data has no meaning.
// stack[i] = initstack;
}
bool fullStack(int top)
{
return top >= maxstack - 1;
}
bool emptyStack(int top)
{
return top < 0;
}
void push(char stack[], int &top, char ch)
{
if (!fullStack(top))
{
top++;
stack[top] = ch;
}
else
cout << "The stack is full, can't push" << endl;
}
char pop(char stack[], int &top)
{
char ch = '\0'; // A good choice for an invalid char is zero. (A bad choice is 'z', since that is a valid input!)
if (!emptyStack(top))
{
ch = stack[top];
// stack[top] = initstack;
top--;
}
return ch;
}
int priority(char ch)
{
switch (ch)
{
case '+':
return 1;
// break; // unreachable code -- you have already 'return'ed
case '-':
return 1;
// break;
case '*':
return 5;
// break;
case '/':
return 5;
// break;
}
return 0; // What happens if you get a character OTHER than the above four?
}
void readEm(char stack[], int &top) // declare local variables...
{
char ch; // ... in the local context
string inString, outString;
int i; //, len;
ifstream inf("Program3RPN.dat");
ofstream outf("Program3RPN.out");
while (inf >> inString) // Forget EOF. 'While input obtained' is correct.
{
// inf >> inString;
// ch = inString[i];
// outString += ch;
// len = inString.length();
for (i = 0; i < inString.length() /*len*/; i++)
{
ch = inString[i];
if(isalpha(ch)) // ch is the character value you are testing for 'alphaness' here
outString += ch;
else if(emptyStack(top))
push(stack, top, ch);
// else if (priority(ch)== priority(stack[top])) // you check for this below
// push(stack, top, ch);
// else if(emptyStack(top)) // you, er, already tested for this...
// pop(stack, top); // ... but want something DIFFERENT to happen?
else if(priority(ch) >= /*<=*/ priority(stack[top])) // see below
push(stack, top, ch);
}
// } er, what?
while (!emptyStack(top))// && priority(ch) <= priority(stack[top])) // see below
{
outString += pop(stack, top); // see below
}
cout << inString << " " << outString << endl;
outf << inString << " " << outString << endl;
//cout << inString << " " << outString << endl;
outString = ""; // <-- this, and...
} // <-- here
}
int main()
{
// char ch;
char stack[maxstack];
int top;
createStack(stack, top);
readEm(stack, top);//, ch);
// system("pause");
return 0;
}
|
Point by point:
An unused value has no meaning. You do not need to set unused pieces of the stack to any specific value.
Why is addition priority 1 and multiplication priority 5? That looks really arbitrary. (It doesn’t really matter here, but I don’t know of any operations that will fall between addition and multiplication.)
If you
return
from a function, there is nothing else to
break
from. Also, you need to return something for all possible control paths, even if that path will never be taken (you think!).
Don’t use arguments to provide a local value.
Declare variables in as tight a scope as possible:
i
is only used in the loop, by the loop, hence, it belongs with the loop. That
ch
could also be declared in the loop as
91 92
|
char ch = inString[i];
|
What remains, really, is the logic of the algorithm. You have been presented, somewhere, a good design (needs a little refinement, but it works well) to convert infix to RPN. But you have missed something. You
MUST spend some time to understand it.
Here are some example infix expressions to work through to think about it:
input output stack
A+B*C input
^ A add variable to output
^ A + add operator to empty stack
^ AB + add variable to output
^ AB +* add higher priority operator to stack
^ ABC +* add variable to output
^ ABC* + no more input: pop from stack to output
^ ABC*+ no more input: pop from stack to output
input output stack
A*B+C input
^ A add variable to output
^ A * add operator to empty stack
^ AB * add variable to output
^ AB* pop higher priority operator from stack to output
^ AB* + add operator to empty stack
^ AB*C + add variable to output
^ AB*C+ no more input: pop from stack to output
|
What you have right now is a whole lot of ‘try something and see if it works’.
Unfortunately, that
never works.
Currently half of the conditions you check in your loop are checked
twice, and they aren’t always the consequence! You must FIRST think of the flow, THEN program it in. The only way to get it is to work through some examples.
(And examples must be chosen carefully to test edge cases.)
Notice how the last step(s) in the examples above are to pop the stack until empty. But you do that outside the loop. Hence the weird expressions. Be careful to reset ALL variables for each input.
With some minor modifications I got your program running for everything that does not include parentheses. Once you do that too, then it is time to think about how to get parentheses working.
input output stack
(A+B)*C input
^ ( add parenthesis operator to empty stack
^ A ( add variable to output
^ A (+ add operator to stack
^ AB (+ add variable to output
^ AB+ ( pop operator(s) until...
^ AB+ ...matching parenthesis operator popped
^ AB+ * add operator to empty stack
^ AB+C * add variable to output
^ AB+C* no more input: pop from stack to output
input output stack
A*(B+C) input
^ A add variable to output
^ A * add operator to empty stack
^ A *( add parenthesis operator to stack
^ AB *( add variable to output
^ AB *(+ add operator to stack
^ ABC *(+ add variable to output
^ ABC+ *( pop operator(s) until...
^ ABC+ * ...matching parentesis operator popped
^ ABC+* no more input: pop from stack to output
|
Hope this helps.