练习 4-4
在栈操作中添加几个命令,分别用于在不弹出元素的情况下打印栈顶元素;
复制栈顶元素;交换栈顶两个元素的值。另外增加一个命令用于清空栈。
/*打印栈顶元素*/
void printtop(void)
{
if (op > 0)
printf("%g\n", val[op - 1]);
else
printf("error: stack empty\n");
}
/*复制栈顶元素 如果成功返回被复制元素的值*/
double copy(void)
{
double n;
if (op > 0)
{
push(n = val[op - 1]);
return n;
}
else
{
printf("error: stack empty\n");
return 0.0;
}
}
/*交换栈顶的两个元素的值 成功返回 1 ,否则返回 0 */
int swop()
{
double t;
if (op > 1)
{
t = val[op - 1];
val[op - 1] = val[op - 2];
val[op - 2] = t;
return 1;
}
else
{
printf("The number of elements in the stack is insufficient\n");
return 0;
}
}
/*清空栈 返回被清空的元素数*/
int clear()
{
int n;
if (op > 0)
{
n = op;
op = 0;
return n;
}
else
{
printf("error: stack empty\n");
return 0;
}
}
我在 main 里面加了一些对应的字符指令
p : 打印栈顶元素
c : 复制栈顶的元素并压入栈
s : 交换栈顶的两个元素的值
e : 清空栈 打印被清空的元素数
b : 删除栈顶元素,实际上调用的是 pop 函数
case 'c':
case 'C':
op2 = copy();
if (op2 != 0)
printf("%g to be copied\n", op2);
break;
case 'e':
case 'E':
op2 = clear();
if (op2 != 0)
printf("The %d elements were deleted\n", (int)op2);
break;
case 'p':
case 'P':
printtop();
break;
case 's':
case 'S':
swop();
break;
case 'b':
case 'B':
op2 = pop();
printf("%g deleted\n", op2);
break;
完整代码 :
/*练习 4-4 在栈操作中添加几个命令,分别用于在不弹出元素的情况下打印栈顶元素;
复制栈顶元素;交换栈顶两个元素的值。另外增加一个命令用于清空栈。*/
#include
//--------------main------------------------------------------------
#define MAXOP 100 //操作数与操作符的最大值
#define NUMBER '0' //getop得到数字或小数点时返回的值
/*获取输入的字符*/
int getop(char[]);
/*将 d 压入栈顶*/
void push(double d);
/*弹出栈顶元素*/
double pop(void);
/*打印栈顶元素*/
void printtop(void);
/*复制栈顶元素 如果成功返回被复制元素的值*/
double copy(void);
/*获得栈顶元素的值*/
double peek(void);
/*交换栈顶的两个元素的值 成功返回 1 ,否则返回 0 */
int swop();
/*清空栈 返回被清空的元素数*/
int clear();
double atof(char s[]);
int isspace(int);
int isdigit(int);
main()
{
int type;
double op2, op3;
char s[MAXOP];
while ((type = getop(s)) != EOF)
switch (type)
{
case NUMBER:
push(atof(s));
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 '%':
op2 = pop();
op3 = pop();
if (op2 != (int)op2 || op3 != (int)op3) //要保证取模的两个数都是整数
printf("error: Only integers can get the modulus\n");
else if (op2 == 0)
printf("error: zero divisor\n");
else if (op2 < 0)
push(0);
else
push((int)op3 % (int)op2);
break;
case '=': //等于号用来取出栈中最上面的值
printf("\t%.8g\n", pop());
break;
case '.':
printf("error: There's no number in front of the decimal point");
break;
case 'c':
case 'C':
op2 = copy();
if (op2 != 0)
printf("%g to be copied\n", op2);
break;
case 'e':
case 'E':
op2 = clear();
if (op2 != 0)
printf("The %d elements were deleted\n", (int)op2);
break;
case 'p':
case 'P':
printtop();
break;
case 's':
case 'S':
swop();
break;
case 'b':
case 'B':
op2 = pop();
printf("%g deleted\n", op2);
break;
case ' ': //空白字符不处理
case '\n':
case '\t':
break;
default:
printf("error: unknown command %s\n", s);
break;
}
}
//--------------------------------------------------------------
//-------------获取字符-------------------------------------------------
int getch(void);
void ungetch(int);
int getop(char s[])
{
int i, c, c2;
while ((c = getch()) == ' ' || c == '\n' || c == '\t') //去除多余的空白字符
;
if (c == '-' || c == '+') // '-' 和 '+' 有可能作为符号位
if (isdigit(c2 = getch()))//所以读取下一位,若是数字,则当做符号位
{
s[i++] = c;
c = c2;
}
else
{
ungetch(c2);
return c;
}
if (isdigit(c))
{
s[0] = c;
i = 1;
//数字的格式为 "xxx.xxx"
// x 是数字
while (isdigit(c = getch()))
s[i++] = c;
if (c == '.')
{
s[i++] = c;
while (isdigit(c = getch()))
s[i++] = c;
}
//数字结束
s[i] = '\0';
if (c != '\n' && c != ' ' && c != '\t')
ungetch(c);
return NUMBER;
}
else
return c;
}
#define BUFSIZE 100
char buf[BUFSIZE]; //缓存的字符数组
int bufp = 0; //缓存数组指针
int getch(void)
{
if (bufp > 0)
return buf[--bufp];
else
return getchar();
}
void ungetch(int c)
{
if (bufp >= BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++] = c;
}
//--------------------------------------------------------------
//----------------栈操作----------------------------------------------
#define MAXVAL 100 //栈的最大长度
int op = 0;
double val[MAXVAL];
/*将 d 压入栈顶*/
void push(double d)
{
if (op < MAXVAL)
val[op++] = d;
else
printf("error: stack full, can't push %g\n", d);
}
/*弹出栈顶元素*/
double pop(void)
{
if (op > 0)
return val[--op];
else
printf("error: stack empty\n");
return 0.0;
}
/*打印栈顶元素*/
void printtop(void)
{
if (op > 0)
printf("%g\n", val[op - 1]);
else
printf("error: stack empty\n");
}
/*复制栈顶元素 如果成功返回被复制元素的值*/
double copy(void)
{
double n;
if (op > 0)
{
push(n = val[op - 1]);
return n;
}
else
{
printf("error: stack empty\n");
return 0.0;
}
}
/*获得栈顶元素的值*/
double peek(void)
{
if (op > 0)
return val[op - 1];
else
printf("error: stack empty\n");
return 0.0;
}
/*交换栈顶的两个元素的值 成功返回 1 ,否则返回 0 */
int swop()
{
double t;
if (op > 1)
{
t = val[op - 1];
val[op - 1] = val[op - 2];
val[op - 2] = t;
return 1;
}
else
{
printf("The number of elements in the stack is insufficient\n");
return 0;
}
}
/*清空栈 返回被清空的元素数*/
int clear()
{
int n;
if (op > 0)
{
n = op;
op = 0;
return n;
}
else
{
printf("error: stack empty\n");
return 0;
}
}
//--------------------------------------------------------------
//---------------转换成数字-----------------------------------------------
double atof(char s[])
{
double power, val;
int sign, i, sign2, j, n;
for (i = 0; isspace(s[i]); i++)
;
sign = (s[i] == '-') ? -1 : 1;
if (s[i] == '-' || s[i] == '+')
i++;
for (val = 0.0; isdigit(s[i]); i++)
val = val * 10 + (s[i] - '0');
if (s[i] == '.')
i++;
for (power = 1.0; isdigit(s[i]); i++)
{
val = val * 10 + (s[i] - '0');
power *= 10;
}
if (s[i] == 'e' || s[i] == 'E')
{
i++;
sign2 = (s[i] == '-') ? 1 : 0;
if (s[i] == '-' || s[i] == '+')
i++;
for (n = 0; isdigit(s[i]); i++)
n = n * 10 + (s[i] - '0');
for (j = 0; j < n; j++)
power = (sign2) ? (power * 10) : (power / 10);
}
return val * sign / power;
}
int isspace(int x)
{
return (x == ' ' || x == '\t' || x == '\n') ? 1 : 0;
}
int isdigit(int x)
{
return (x >= '0' && x <= '9') ? 1 : 0;
}
//--------------------------------------------------------------
发现 getop函数在处理 ‘+’ 和 ‘-’ 时写的代码有问题,
已修改
by 2018-1-4