Having some issues here. I am required to translate an entire program into SIMPLE C, (goto's for all loops) and then from there for our next project we will be translating it into assembler. I have the majority of the project translated and i have it running with only one "for" loop and one "if" not yet translated. The problem is, the for loop spans almost all the code, and I'm not sure how to include goto's correctly to do what I want. What this program does is translate any statement from infix to postfix. EX) (A+B)/(C-D) would be AB+CD-/
Could you please take a look at it, and possibly shed some light on how to write this for loop? I've been at it for days to no avail. If you search "PROBLEM" i used this word to mark where I need help. Throughout the entire project, I have commented out the loop it originally was, and my translation is under each one. It should be fairly easy to read. Thanks to anyone who can help
//C PROGRAM TO CONVERT GIVEN VALID INFIX EXPRESSION INTO POSTFIX EXPRESSION USING STACKS.
#include<stdio.h>
#include<conio.h>
#include<string.h>
//The bottom of the stack is stack[MAX-1]
//The stack grows towards stack[0]
#define MAX 20
char stack[MAX];
int top=MAX; //top will become top-1 as soon as the first push is executed
char infix[20],postfix[20];
char symbol;
//Push an operator onto the stack
void push(char item)
{
top--;
stack[top]=item;
}
//Pop an operator off the stack
char pop()
{
char a;
a=stack[top];
stack[top]='\0'; //Lorenzen unneccessarily deletes the popped operators from the stack as a debugging aid
top++;
return a;
}
//Determine the precedence of the current input operator
//This can't be translated into assembler because assembler has no switch, case, or break
/*
int prcd(char symbol)
{
switch(symbol)
{
case '+':
case '-':return 2;
break;
RETURN4:
ax = 4;
goto END_CASE; //"useless" but good if someone else adds more values to case
RETURN6:
ax = 6;
goto END_CASE;
RETURN1:
ax = 1;
goto END_CASE;
END_CASE: return(ax); //only 1 return per function in asm
}
//Return TRUE if the current input symbol is an operator
//Return FALSE if the current input symbol is an operand
int isoperator(char symbol)
{
//This code performs a linear search of the array from right to left.
//Since we insert symbol in the leftmost array position, we will always find the searched for symbol in the array.
//If we find it in the leftmost position, it wasn't part of the original initialization of the array.
#define NUMBER_OPERATORS 7
char operators[NUMBER_OPERATORS+2]=" +-*/^()"; //null char is automatically inserted at end of string initialization
operators[0]=symbol; //insert symbol in leftmost element of the array
int i=NUMBER_OPERATORS;
//If i!=0, symbol was found in the original initialization of the array and return 1 (equivalent to true)
//Else symbol wasn't part of the original initialization of the array and i==0 (equivalent to false).
/*
if (i!=0)
i=1;
*/
if (i != 0)
goto TRUE_PART;
goto END_IF;
TRUE_PART:
i = 1;
END_IF:;
isoperatorExit: return(i);
}
//Convert the input infix expression to postfix
void convertip(char infix[],char postfix[])
{
int i,j=0;
push('#');
for(i=0;i<strlen(infix);i++) //PROBLEM - THIS FOR LOOP SPANS ALMOST WHOLE PROGRAM, HOW DO I USE goto's?
{
symbol=infix[i];
//If the symbol is not an operator (ie it is an operand), append the operand to the postfix string
if(isoperator(symbol)==0) //if isoperator has returned FALSE
{
postfix[j]=symbol; //PROBLEM - ALSO CAN'T FIGURE OUT THIS IF
j++;
goto exitNestedIf;
}
//!!!!!!!!!!!!!!!!!!!!!!!!Now we know the symbol must be an operator!!!!!!!!!!!!!!!!!!!!!!!!
//If the operator is an open parenthesis, push it
/*
if (symbol == '(' ){
push(symbol);
goto exitNestedIf;}
*/
//If the operator is a close parenthesis,
// pop the stack and append operators to the postfix string until the matching open parenthesis is found
// pop the matching open parenthesis
/*
if( symbol==')' )
{
while( stack[top]!='(' )
{
postfix[j]=pop();
j++;
}
pop();//pop out (.
goto exitNestedIf;
}
*/
goto IF_WHILE_START;
IF_WHILE_START:
if (symbol == ')' ) goto IF_WHILE;
if (symbol != ')' ) goto IF_WHILE_END_WITHOUT_POP;
IF_WHILE:
if (stack[top]!= '(' )
goto IF_WHILE_TRUE;
if (stack[top] == '(' )
goto IF_WHILE_END_WITH_POP;
IF_WHILE_TRUE:
{postfix[j]=pop();
j++;
goto IF_WHILE_START;}
//While the precedence of the input operator is <= the precedence of the operator on the top of the stack
// pop the operator and append the operator to the postfix string
//Push the input operator.
/*
while(prcd(symbol)<=prcd(stack[top]))
{
postfix[j]=pop();
j++;
}
push(symbol);
goto exitNestedIf; //Though unnecessary, makes code symetrical and additional if clauses could be added.
*/
goto WHILE_COND2;
WHILE_COND2:
if (prcd(symbol)<=prcd(stack[top])) goto WHILE_BODY2;
if (prcd(symbol)>prcd(stack[top])) goto WHILE_END3;
WHILE_BODY2:
{postfix[j]=pop();
j++;}
//MIGHT BE MISSING push(symbol) here. see above
WHILE_END3:;
exitNestedIf:;
}//end of for. //PROBLEM - END OF FOR LOOP
//While the stack is not empty, pop operators and append them to the postfix string
First - could you please use code tags - the <> button on the right.
Now for a devilish comment :-D
If you were going to use goto's exclusively - then you wouldn't have any functions per say. You would goto the start of the function, then goto back again instead of return. You could try numbering your labels in steps of 10, in order through the code - like GWBASIC line numbers. That way you can add extra ones in without driving yourself nuts!!!
Edit: Or have both numbers & names if that is easier (like for function names)
I know this is annoying, but that is what asm is like. When I was learning asm, the most common statement was "My head hurts"
Edit2:
//This can't be translated into assembler because assembler has no switch, case, or break
Would it be even further annoying if I said that all C++ code can converted to assembler?
You guessed it - they are achieved with goto's !!!!!! So with you C program, any kind of flow control can be achieved with if's & goto's.
In asm, the only way to alter the flow control is via a jmp instruction. There are various way's of deciding whether to jmp or not.