栈的应用——进制转换、括号匹配检验、行编辑程序、表达式求值
顺序栈的基本操作
进制转换:对于输入的任意一个非负十进制整数,打印输出与其等值的八进制数。
int main()
{
SqStack S;
int x, e;
printf("输入一个非负的十进制整数:\n");
if(InitStack(S) != 1) printf("Creatd Error!\n");
scanf("%d", &x);
while(x)
{
Push(S, x%8);
x = x/8;
}
while(S.base != S.top)
{
Pop(S,e);
printf("%d", e);
}
}
括号匹配检验:假设表达式中允许包含两种括号:圆括号和方括号,其嵌套的顺序随意,即()或[([][])]等为正确的格式,[(]或([())或(()])均为不正确的格式。输入一个包含上述括号的表达式,检验括号是否配对。
void check()
{ // 对于输入的任意一个字符串,检验括号是否配对
SqStack s;
SElemType ch[80],*p,e;
if(InitStack(s)) // 初始化栈成功
{
printf("请输入表达式\n");
gets(ch);
p=ch;
while(*p) // 没到串尾
switch(*p)
{
case '(':
case '[': Push(s, *p); p++;
break; // 左括号入栈,且p++
case ')':
case ']': if(!StackEmpty(s)) // 栈不空
{
Pop(s, e); // 弹出栈顶元素
if(*p==')'&&e!='('|| *p==']'&&e!='[')
// 弹出的栈顶元素与*p不配对
{
printf("isn't matched pairs\n");
exit(ERROR);
}
else
{
p++;
break; // 跳出switch语句
}
}
else // 栈空
{
printf("lack of left parenthesis\n");
exit(ERROR);
}
default: p++; // 其它字符不处理,指针向后移
}
if(StackEmpty(s)) // 字符串结束时栈空
printf("matching\n");
else
printf("lack of right parenthesis\n");
}
}
行编辑程序:接受用户从终端输入的程序或数据,在输入过程中,允许用户输入出差错,并在发现有误时可以及时更正。例如:当用户发现刚刚键入的一个字符是错的时,可以补进一个退格符“#”,以表示前一个字符无效;如果发现当前键入的行内差错较多或难以补救,则可以键入一个退行符“@”,以表示当前行中的字符均无效。
void LineEdit()
{
SqStack s;
char ch,c;
int n,i;
InitStack(s);
scanf("%d",&n);
ch=getchar(); //把回车get了
for(i=1;i<=n;i++)
{
ch=getchar();
while(ch!='\n')
{
switch(ch)
{
case '#': Pop(s,c);
break; // 仅当栈非空时退栈
case '@': ClearStack(s);
break; // 重置s为空栈
default : Push(s,ch); // 有效字符进栈
}
ch = getchar(); // 从终端接收下一个字符
}
StackTraverse(s,visit); // 将从栈底到栈顶的栈内字符输出
ClearStack(s); // 重置s为空栈
}
DestroyStack(s);
}
表达式求值:输入含有“+”、“-”、“*”、“/”四则运算的表达式,其中负数要用(0-正数)表示,并以=结束。要求输出表达式的值。
unsigned char op[7] = {'+', '-', '*', '/', '(', ')', '='};
unsigned char opcmp[7][7] = {'>', '>', '<', '<', '<', '>', '>',
'>', '>', '<', '<', '<', '>', '>',
'>', '>', '>', '>', '<', '>', '>',
'>', '>', '>', '>', '<', '>', '>',
'<', '<', '<', '<', '<', '=', ' ',
'>', '>', '>', '>', ' ', '>', '>',
'<', '<', '<', '<', '<', ' ', '='};
SqStack OPTR, OPND; //OPTR寄存运算符,OPND寄存操作数或运算结果
Status In(char c, unsigned char op[]) //检验是否为运算符
{
int i;
for(i=0; i<7; i++)
{
if(c==op[i]) return OK;
}
return ERROR;
}
char Precede(char c1, char c2) //比较两个相邻运算符的优先关系
{
int i,j;
for(i=0; i<7; i++)
if(c1 == op[i]) break;
for(j=0; j<7; j++)
if(c2 == op[j]) break;
return opcmp[i][j];
}
void Operate(char a1, char theta1, char b1) //计算
{
int i;
char outcome;
for(i=0; i<4; i++)
if(theta1 == op[i]) break;
switch(i)
{
case 0: outcome = a1 + b1 - '0'; break;
case 1: outcome = a1 - b1 + '0'; break;
case 2: outcome = (a1-'0') * (b1-'0') + '0'; break;
case 3: outcome = (a1-'0') / (b1-'0') + '0'; break;
}
Push(OPND, outcome);
}
int main()
{
char c, e, x, theta;
char a, b;
if(!InitStack(OPTR) || !InitStack(OPND)) printf("Created Error!\n");
Push(OPTR, '=');
c = getchar();
while(c!='=' || GetTop(OPTR, e)!='=')
{
if(!In(c, op))
{
Push(OPND, c);
c = getchar();
}
else
{
switch(Precede(GetTop(OPTR, e) , c))
{
case'<': Push(OPTR, c); c = getchar(); break;
case'=': Pop(OPTR, x); c = getchar(); break;
case'>': Pop(OPTR, theta);
Pop(OPND, b); Pop(OPND, a);
Operate(a, theta, b); break;
}
}
}
printf("%c", GetTop(OPND, e));
}