我已经实现了一个字符串堆栈,我正在尝试使用它将 rpn 转换为中缀。这是中缀函数工作时堆栈的外观,例如,如果我输入2 3 + 5 - 8 *
:
2 //push 2
2,3 //push 3
(2+3) //reach operator, pop 2 and 3, format it, put result back on the stack
(2+3),5 //push 5
((2+3)-5) //reach operator, pop (2+3) and 5, format it, put result back
((2+3)-5),8 //push 8
(((2+3)-5)*8) //reach operator, pop ((2+3)-5) and 8, format, put result back
可悲的是,这不是该程序为我工作的方式,我认为它是技术性的,而不是我的算法。输入“2 5 A”时,它起作用,结果为“(2+5)”。尝试“40 50 A”,我得到“(40+50)”。但是,当尝试“50 100 A”时,我得到“(+)”。像“1 2 A 3 S”这样较长的表达式也只给了我“(-)”。我似乎无法弄清楚是什么原因造成的。请随时试一试。这是我的代码:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
/*options to later implement (-e for evaluate, -c for infix conversion, -g for mock assembly */
#define OP_EVAL "-e"
#define OP_INFX "-c"
#define OP_GENI "-g"
/* begin stack of strings implementation */
struct stack_entry {
char *data;
struct stack_entry *next;
};
struct stack_t
{
struct stack_entry *head;
size_t stackSize;
};
struct stack_t *newStack(void)
{
struct stack_t *stack = malloc(sizeof *stack);
if (stack)
{
stack->head = NULL;
stack->stackSize = 0;
}
return stack;
}
char *copyString(char *str)
{
char *tmp = malloc(strlen(str) + 1);
if (tmp)
strcpy(tmp, str);
return tmp;
}
void push(struct stack_t *theStack, char *value)
{
struct stack_entry *entry = malloc(sizeof *entry);
if (entry)
{
entry->data = copyString(value);
entry->next = theStack->head;
theStack->head = entry;
theStack->stackSize++;
}
else
{
printf("FAILURE\n");
}
}
char *top(struct stack_t *theStack)
{
if (theStack && theStack->head)
return theStack->head->data;
else
return NULL;
}
void pop(struct stack_t *theStack)
{
if (theStack->head != NULL)
{
struct stack_entry *tmp = theStack->head;
theStack->head = theStack->head->next;
free(tmp->data);
free(tmp);
theStack->stackSize--;
}
}
/*end stack of strings implementation */
/*begin argument handling for -c, -e and -g */
enum method
{
EVAL,
INFX,
GENI
};
int
is_option(const char *str)
{
return (strcmp(str, OP_EVAL) == 0) ||
(strcmp(str, OP_INFX) == 0) ||
(strcmp(str, OP_GENI) == 0);
}
enum method
manip_method(const char *arg)
{
if (strcmp(arg, OP_EVAL) == 0)
return EVAL;
else if (strcmp(arg, OP_INFX) == 0)
return INFX;
else if (strcmp(arg, OP_GENI) == 0)
return GENI;
else
return 0;
}
/* end of argument handling code (again, not even being used yet) */
/* gets operator, converts it, if not A, S, X, D, or M returns NULL */
char*
get_oper(char *op){
if(strcmp(op, "A") == 0)
return "+";
if(strcmp(op, "S") == 0)
return "-";
if(strcmp(op, "X") == 0)
return "*";
if(strcmp(op, "D") == 0)
return "\\";
if(strcmp(op, "M") == 0)
return "%";
else
return NULL;
}
/* formats an infix expression */
char*
formats(char *s1, char *s2, char* op){
int length = strlen(s1) + strlen(s2) + strlen(op) + 3;
char *buf = malloc(length);
strcpy(buf, "(");
strcat(buf, s2);
strcat(buf, op);
strcat(buf, s1);
strcat(buf, ")");
return buf;
}
/* 1) reads tokens and puts them on stack
2) when operator is reached, pops two elements off
the stack and formats it, then pushes the result onto the stack
3) after the loop ends, there should only be one element left on the
stack: the final infix expression */
char*
infix(int argc, char *argv[], int x){
int i;
char *format, *result, *s1, *s2, *op;
struct stack_t *stack = newStack();
for(i = x; i < argc; i++){
if(!get_oper(argv[i])){
push(stack, argv[i]);
} else {
s1 = top(stack);
pop(stack);
s2 = top(stack);
pop(stack);
op = get_oper(argv[i]);
format = formats(s1, s2, op);
push(stack, format);
}
}
result = top(stack);
pop(stack);
return result;
}
int
main(int argc, char *argv[])
{
char *result;
enum method method;
int x;
if (argc >= 4){
if (is_option(argv[1])){
if (argc < 5){
printf("not a valid calculatable expression, exiting now...\n");
exit (EXIT_FAILURE);
}
x = 2;
method = manip_method(argv[1]);
}
else {
x = 1;
method = EVAL;
}
} else {
printf("need option and or a valid reverse polish notation expression, exiting now...\n");
exit (EXIT_FAILURE);
}
result = infix(argc, argv, x);
printf("result: %s\n", result);
exit (EXIT_SUCCESS);
}
编辑:这是程序行为的更多示例
mesquite$ rpcalc 1 5 A
result: (1+5)
mesquite$ rpcalc 1 100 S
result: (1-100)
mesquite$ rpcalc 1 2 A 3 D
result: (\)
mesquite$ rpcalc 10 100 M
result: (%)