C程序设计语言(K&R 第二版):练习4-4

题目:在栈操作中添加几个命令,分别用于在不弹出元素的情况下打印栈顶元素;复制栈顶元素;交换栈顶两个元素的值。另外增加一个命令用于清空栈。

自我解答:

void printTop(void)
{
    if(sp > 0)
        printf("the top element of the stack is %f\n", val[sp - 1]);
    else
        printf("error: stack empty");
}

double copyTop(void)
{
    if(sp > 0)
        return val[sp - 1];
    else
    {
        printf("error: stack empty");
        return 0.0;
    }
}

void swap(void)
{
    double temp;
    if(sp > 1)
    {
        temp = val[sp - 1];
        val[sp - 1] = val[sp - 2];
        val[sp - 2] = temp;
    }
    else
        printf("error: the size of stack is less than 2\n");
}

void emptyStack(void)
{
    sp = 0;
}

所有对栈的操作都可以通过两个外部变量 val和sp来实现

参考答案:

 

#include 
#include            /* for atof()                       */

#define MAXOP       100     /* max size of operand or operator  */
#define NUMBER      '0'     /* signal that a number was found   */

int getop(char []);
void push(double);
double pop(void);
void clear(void);

/* reverse Polish calculator                                    */
int main()
{
    int type;
    double op2;
    char s[MAXOP];
    
    while((type = getop(s)) != EOF)
    {
        switch (type)
        {
        case NUMBER:
            push(atof(s));
            printTop();
            printf("%f\n", copyTop());
            break;
        case '+':
            push(pop() + pop());
            break;
        case '*':
            push(pop() * pop());
            break;
        case '-':
            op2 = pop();
            push(pop() - op2);
            break;
        case '/':
            op2 = pop();
            if(op2 != 0.0)
                push(pop() / op2);
            else
                printf("error: zero divisor\n");
            break;
        case '?':   /* print top element of the stack       */
            op2 = pop();
            printf("\t%.8g\n", op2);
            push(op2);
            break;
        case 'c':   /* clear the stack                      */
            clear();
            break;
        case 'd':   /* duplicate top elem. of the stack     */
            op2 = pop();
            push(op2);
            push(op2);
            break;
        case 's':   /* swap the top two elements            */
            op1 = pop();
            op2 = pop();
            push(op1);
            push(op2);
            break;
        case '\n':
            printf("\t%.8g\n", pop());
            break;
        default:
            printf("error: unknown command %s\n", s);
            break;
        }
    }
    return 0;
}

 现有的换行操作符将弹出栈顶元素并打印。我们新增的操作符“?”将弹出栈顶元素并打印,再把它压入堆栈。“?”操作符不会像换行操作符那样把栈顶元素永久地弹出堆栈,并采用“出栈,打印,入栈”这一方案的原因是为了避免主程序直接对堆栈和堆栈指针变量(sp)进行操作。

复制栈顶元素的操作过程是:先弹出栈顶元素,再把它压入两次。

交换栈顶两个元素的操作过程是:先依次弹出两个栈顶元素,再按相反的顺序把它们压入堆栈。

清除堆栈内容的工作很容易完成:把sp设置为零即可。我们增加了一个完成这项工作的函数,并把它与push和pop放置在一起。这样做的目的是只允许这三个函数维护堆栈、访问堆栈及堆栈指针变量。

/* clear: clear the stack    */
void clear(void)
{
    sp = 0;
}

总结:

自我解答和参考答案中的实现完成的功能虽然类似,但是参考答案中完全是借用了push和pop函数进行,而自我解答中是增加了函数实现,操作了堆栈和堆栈指针sp。所以对题目中的“不弹出元素”的理解不是指不能用push和pop函数,而是弹出后再压回不影响原有的堆栈结构。自我解答中对不弹出元素的理解是“不能使用push和pop”函数,所以采用了直接操作堆栈和堆栈指针。

你可能感兴趣的:(C语言程序设计学习笔记,c语言,开发语言,后端)