So I'm trying to make a working calculator using RPN (reverse polish notation), however, it works perfectly fine using positive numbers and doing a simple substract like (3*4-2+5)/3*2
which postfix expression is 34*2-5+3/2*
and 10
as result. The thing is I'm not sure how to implement negative numbers, such as (-4+2*2)
, in this case the postfix expression should be ??? (4-22*) ???
(I'm not sure about this one) but the result should be 0
I've already made a tokenizer which prints the type of each token and its value. I.e:
Input: (2*3+4-5)
Output:
(Infix expression) | (Postfix Expression)
Parenthesis [(] Number[2]
Number [2] Number[3]
Operator [*] Operator[*]
Number [3] Number[4]
Operator [+] Operator[+]
Number[4] Number[5]
Operator [-] Operator[-]
Number [5]
Parenthesis [)]
Result: 5.0
However, when I try to use a negative number expression like the one above (-4+2*2)
I get an error "Stack Underflow" because when I try to convert it I get:
(Infix Expression) | (Postfix Expression)
Parenthesis [(] Number[4]
Operator [-] Operator[-]
Number [4] Number[2]
Operator [+] Number[2]
Number [2] Operator[*]
Operator [*] Operator[+]
Number [2]
Parenthesis [)] ^^^^ Therefore, when I use my InfixToPostfix function,
It cannot find a number before the first [4] to do the [-]
operation, hence, in the "pop" function it prints the "Stack Underflow" error.
How can I fix this? I'm trying to fix it in the Tokenizer function which is the follow one:
Token.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "token.h"
/* Works using enum within the "token.h" and the TToken struct, defined as follows:
extern char strToken[][11];
typedef enum {variable, parentesis,operador, numero} tipoToken;
typedef struct{
tipoToken tipo; //Type of the token
char token[20]; //Content of that token
} TToken;
/*
char strToken[][11] = {"Variable", "Parentesis","Operador", "Numero"}; //Variable, Parenthesis, Operator, Number
int esOperador(char c) //isOperator function, which evaluates the valid nonalpha&&nondigit characters
{
int k;
static char operadores[] = "+-*/^";
int l = strlen(operadores);
for (k=0; k<l; k++)
if (c == operadores[k])
return 1;
return 0;
}
int esParentesis(char c) // IsParenthesis function
{
if (c=='(' || c==')')
return 1;
return 0;
}
TToken *token(char *s)
{
static char cadena[1000]; // The aux variable that will store 's' (original string)
static char *actual; // Keeps a track where the string is
int k;
char res[1000];
TToken *unToken=NULL;
if (s != NULL) {
strcpy(cadena,s);
actual = cadena;
}
while ((*actual == ' ') || (*actual =='\n') || (*actual=='\t')) //Only reads the valid characters of the string
actual++;
if (*actual == '\0')
return NULL;
if ( (esOperador(*actual) == 1) ) { // If is an operator, then...
res[0] = *actual;
res[1] = '\0';
unToken=malloc(sizeof(TToken));
unToken->tipo=operador;
strcpy(unToken->token,res);
actual = actual + 1;
return unToken;
} else if ( (esParentesis(*actual) == 1) ) { //If is a parenthesis, then...
res[0] = *actual;
res[1] = '\0';
unToken=malloc(sizeof(TToken));
unToken->tipo=parentesis;
strcpy(unToken->token,res);
actual = actual + 1;
return unToken;
} else if (isdigit(*actual) || (*actual=='.')) { // Read float numbers
k = 0;
while ( (*actual != '\0') && (isdigit(*actual) || *actual == '.' ) ) {
res[k] = *actual;
actual = actual + 1;
k = k+1;
}
res[k] = '\0';
unToken=malloc(sizeof(TToken));
unToken->tipo=numero;
strcpy(unToken->token,res);
return unToken;
} else if (isalpha(*actual)) { //**I might use this one also to evaluate also variables (Idk how, yet)**
k = 0;
while ( (*actual != '\0') && isalpha(*actual)) {
res[k] = *actual;
actual = actual + 1;
k = k+1;
}
res[k] = '\0';
unToken=malloc(sizeof(TToken));
unToken->tipo=variable;
strcpy(unToken->token,res);
return unToken;
}
printf("Error: Incorrect expression\n");
exit(0);
}
After that call to the token function, I call the InfixToPostfix expression, but in my opinion, the "correct" tokenized expression should be sent to InfixToPostfix and therefore, I should change the "token" function to allow negative numbers (unary minus).
If you do have any question do not hesitate asking (Such as another used functions in my code)