【问题标题】:C - K&R expr: evaluate a reverse Polish expression from the command lineC - K&R expr:从命令行计算逆波兰表达式
【发布时间】:2017-07-23 22:39:46
【问题描述】:

我一直在尝试使用动态分配的堆栈完成 K&R 的练习 5-10。我的代码基于第 4 章中的代码(他们使用全局变量来实现堆栈)。问题是我的程序根本不起作用,我不知道出了什么问题。代码如下:

/* expr: evaluates a reverse Polish expression from the command line */

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define MAXOP 100 /* maximal operator length */
#define NUMBER '0' /* signal that a number was found */

int getop(char *argv);
void push(double **top, double val);
double pop(double **top);

int main(int argc, char *argv[])
{
     if (argc == 1) {
        printf("usage: evaluate a reverse Polish expression from the command line\n");
    return 1;
}

double *stack = malloc((argc-1)*sizeof(double));

if (stack == NULL) {
    printf("error: couldn't allocate enough space for the stack\n");
    return 2;
}

int i, type;
double op1, op2, *top = stack; /* top points to the next free stack position */
char s[MAXOP];

for (i = 1; argv[i] != NULL; i++) {
    type = getop(argv[i]);
    switch (type) {
        case NUMBER :
            push(&top, atof(argv[i]));
            break;
        case '+' :
            op2 = pop(&top);
            op1 = pop(&top);
            push(&top, op1+op2);
            break;
        case '-' :
            break;
        case '*' :
            break;
        case '/' :
            break;
        case '%' :
            break;
        default :
            printf("error: unknown command %s\n", argv[i]);
            return 3;
            break;
    }
}
printf(" = %.8g\n", pop(&top));
free(stack);
return 0;
}

 int getop(char *argv)
{
int i, c;

if (!isdigit(argv[0]))
    return argv[0];
else
    return NUMBER;
}

void push(double **top, double val)
 {
    **top = val;
    (*top)++;
/* is error checking needed? */
}

double pop(double **top)
{
   (*top)--;
    return *(*top+1);
/* is error checking needed? */
}

似乎没有考虑运算符 - 例如输入 ./expr 1 12 13 ++ 产生输出 13。

编辑: 感谢所有帮助人员,事实证明 push 和 pop 无法正常工作。我已经设法修复了该代码,尽管现在事后看来我可以在编写代码之前做好更好的准备。

修改后的代码如下:

/* expr: evaluates a reverse Polish expression from the command line */

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define MAXOP 100 /* maximal operator length */
#define NUMBER '0' /* signal that a number was found */

int getop(char *argv);
void push(double **top, double val);
double pop(double **top);

int main(int argc, char *argv[])
{
     if (argc == 1) {
        printf("usage: evaluate a reverse Polish expression from the command line\n");
    return 1;
}

double *stack = (double*) malloc((argc-1)*sizeof(double));

if (stack == NULL) {
    printf("error: couldn't allocate enough space for the stack\n");
    return 2;
}

int i, type;
double op1, op2, *top = stack; /* top points to the next free stack position */
char s[MAXOP];

for (i = 1; argv[i] != NULL; i++) {
    type = getop(argv[i]);
    switch (type) {
        case NUMBER :
            push(&top, atof(argv[i]));
            break;
        case '+' :
            op2 = pop(&top);
            op1 = pop(&top);
            push(&top, op1+op2);
            break;
        case '-' :
            op2 = pop(&top);
            op1 = pop(&top);
            push(&top, op1-op2);
            break;
        case 'x' :
            op2 = pop(&top);
            op1 = pop(&top);
            push(&top, op1*op2);
            break;
        case '/' :
        op2 = pop(&top);
            op1 = pop(&top);
        if (op2 != 0)
                push(&top, op1/op2);
        else {
        printf("error: division by zero\n");
                return 3;
        }
            break;
        default :
            printf("error: unknown command %s\n", argv[i]);
            return 4;
            break;
    }
}
printf(" = %.8g\n", pop(&top));
free(stack);
return 0;
}

 int getop(char *argv)
{
int i, c;

if (!isdigit(argv[0]))
    return argv[0];
else
    return NUMBER;
}

void push(double **top, double val)
 {
    **top = val;
    (*top)++;
}

double pop(double **top)
{
    double temp = *(*(top)-1);
    (*top)--;
    return temp;
}   

【问题讨论】:

  • 你的pushpop 是一团糟,这可能就是原因。 26 在堆栈中。
  • 这也是学习使用调试器的好时机。
  • C 标签指的是标准 C,即 2011 年的 C11。如果您使用非标准 C,请添加更具体的标签。请注意,K&R-C 已过时 28 年,不应该用于学习或新代码(旧代码应尽可能重写)。如果您的意思是 C89/90(自 18 年以来已过时),请使用相应的标签。善意的建议:获取一本关于现代 C 的最新书籍,即至少 C99,更好的 C11。
  • 你推到栈顶,然后增加指针。然而,你也弹出堆栈的顶部。但是,最后推送的值实际上是 top 之前的值。

标签: c kernighan-and-ritchie


【解决方案1】:

您的代码似乎不明白您使用malloc 分配了一个数组,并且您正在尝试使用与基于指针的堆栈一起使用的“添加到前面”方法。您应该在将最近的项目推入堆栈后推送新值,并将最近推入堆栈的项目弹出(即在堆栈的“末端”)。

以下内容应该适合您。请注意,pcount 是指向堆栈上项目数的指针,否则您将不知道堆栈是否为空(例如,2 + 将是无效输入,因为 + 需要 2 个值但只有 1 个stack) 甚至在哪里添加另一个值,因为您将无法确定堆栈的“结束”在哪里。

#include <math.h>    // for HUGE_VAL; may need to link the math library?

// Push a value onto the stack and update the number of items on the stack.
void push(double *stk, double value, int *pcount)
{
    // Add new values at the end of the stack (technically after the last item pushed).
    stk[*pcount] = value;
    ++*pcount;
}

// Pop a value off the stack and update the number of items remaining on the
// stack. If there are no values, HUGE_VAL is returned. Since it is possibly
// a valid value on some implementations, checking for an error should be done
// using the value pcount points to:
//
//     n = pop(stk, &stkCount);
//     if (stkCount < 0) {
//         // error: stack had no elements before pop
//     }
//
double pop(double *stk, int *pcount)
{
    if (*pcount >= 0) {
        // Remove items from the end of the stack.
        --*pcount;
        return stk[*pcount];
    }
    return HUGE_VAL;
}

【讨论】:

    【解决方案2】:

    正如@AnttiHaapala 指出的那样,您的推送和弹出是一团糟。此外,您的数据的组织方式使错误检查变得困难,如果不是不可能的话。

    这里是正确的推送和弹出。

    typedef struct
    {
       double* base;    // base address of stack, allocated with malloc.
       double* end;     // top address of stack + 1 double, init to base + number of elements
       double* ptr;     // stack pointer, initialize to equal base
    } stack;
    
    int init_Stack(struct stack* p, int items)
    {
        p->base = malloc(items * sizeof(double));
        if (!p->base)
            return -1;
        p->end = p->base + items;
        p->ptr = p->base;
        return 0;
    }
    
    void push(struct stack* p, double val)
    {
        if (p->ptr >= p->end)
        {
            //stack overflow!
            exit(3);
        }
        *(p->ptr++) = val;
    }
    
    double pop(struct stack* p)
    {
        if (p->ptr <= p->base)
        {
            // stack underflow!
            exit(4);
        }
        return *(--(p->ptr));
    }
    

    【讨论】:

      猜你喜欢
      • 2020-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-13
      • 2021-11-29
      • 1970-01-01
      相关资源
      最近更新 更多