1.实验内容
(1)掌握栈的特点及其存储方式。
(2)用链式存储结构实现一个栈。
(3)掌握栈的初始化、进栈、出栈和显示栈顶元素等基本操作。
(4)了解进制转换及表达式转换并求值的算法。
2.实验内容
(1)定义一个字符类型的单链栈。
(2)编写出实现进栈、出栈、显示栈顶元素
(3)编写一个求进制转换的算法。
(4)编写一个将中缀表达式转换成后缀表达式的函数,在设计一个用该后缀表达式求值的函数。
(5)设计如下选择式菜单,以选择菜单方式操作。将上述各种算法实现。
3.源代码
//栈子系统
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<stdlib.h>
typedef int DataType;
typedef struct Stacksubsystem{
DataType data;
struct Stacksubsystem *next;
}Stack;
typedef char Data;
typedef struct Baseconversion{
Data record;
struct Baseconversion *top;
}Base;
Base *BaseStack(){
Base *l;
l=NULL;
if(l==NULL){
printf("创建Baseconversion成功。");
}else{
printf("创建Baseconversion失败,请检查后重新创建!");
exit(1);
}
return l;
}
Stack *InitStack(){
Stack *s;
s=NULL;
if(s==NULL){
printf("创建 Stacksubsystem成功。");
}else{
printf("创建 Stacksubsystem失败,请检查后重新创建!");
exit(1);
}
return s;
}
int Judge(Stack *s){
if(s==NULL){
return 0;
}else{
return 1;
}
}
Stack *Push(Stack *s){
void Statistical(Stack *s);
int js(Stack *s);
Stack *p;
int k,j;
k=j=0;
k=js(s);
char q[50];
static char Start[]="Start";
static char End[]="End";
printf("输入Start开始进栈,输入End结束:");
gets(q);
while(strcmp(q,Start)!=0){
if(strcmp(q,End)==0){
printf("你没有进行进栈操作!");
break;
}
printf("\n输入错误!输入Start开始进栈:");
memset(q,0,sizeof q);
gets(q);
}
if(strcmp(q,Start)==0){
printf("\n输入进栈元素:");
memset(q,0,sizeof q);
gets(q);
}
while(strcmp(q,End)!=0){
p=(Stack *)malloc(sizeof(Stack));
p->data=atoi(q);
p->next=s;
s=p;
printf("\n输入进栈元素:");
memset(q,0,sizeof q);
gets(q);
j++;
}
if(k+j==j&&j==0){
printf("进栈失败!");
}
else if(j!=0){
printf("进栈成功!");
Statistical(s);
}
return s;
}
void Statistical(Stack *s){
Stack *l=s;
if(l==NULL){
printf("栈为空!!");
}else{
printf("\n栈中元素为:");
while(l!=NULL){
printf("%5d",l->data);
l=l->next;
}
}
}
int js(Stack *s){
Stack *p=s;
int i=0;
if(p==NULL){
while(p!=NULL){
i++;
p=p->next;
}
}
return i;
}
Stack *Pop(Stack *s){
int k,j;
k=j=0;
k=js(s);
int x;
Stack *p;
if(Judge(s)==0){
printf("栈为空无法删除!!");
return NULL;
}else{
printf("\n删除前栈中元素:");
Statistical(s);
}
char q[50];
static char Start[]="Start";
static char End[]="End";
printf("\n输入Start开始出栈,输入End结束:");
gets(q);
while(strcmp(q,Start)!=0){
if(strcmp(q,End)==0){
printf("你没有进行出栈操作!");
break;
}
printf("\n输入错误!输入Start开始出栈:");
memset(q,0,sizeof q);
gets(q);
}
if(strcmp(q,Start)==0){
memset(q,0,sizeof q);
}
while(strcmp(q,End)!=0){
printf("\n请输入出栈元素:");
gets(q);
x=atoi(q);
if(s->data==x){
j++;
x=s->data;
p=s;
s=s->next;
free(p);
}
else{
if(strcmp(q,End)!=0){
printf("\n不符合出栈规则!");
continue;
}
}
}
if(k+j==j&&j==0){
printf("出栈失败!");
}
else if(j!=0){
printf("\n出栈成功!");
Statistical(s);
}
return s;
}
void Topofstack(Stack *s){
int x;
if(Judge(s)==0){
printf("栈空!取值失败!");
exit(1);
}else{
printf("栈顶元素为:");
x=s->data ;
printf("%5d",x);
}
}
void DecimaltoN(Base *l){
Base *p;
Base *t;
char q[50];
static char Start[]="Start";
static char End[]="End";
printf("输入Start开始进制转换,输入End结束:");
gets(q);
while(strcmp(q,Start)!=0){
if(strcmp(q,End)==0){
printf("你取消了进制转换!");
break;
}
printf("\n输入错误!输入Start开始进制转换:");
memset(q,0,sizeof q);
gets(q);
}
while(strcmp(q,End)!=0){
int n,x,i,k;
k=0;
char z='A';
printf("\n输入要转换的数值与转换的进制:");
scanf("%d %d",&x,&n);
while(x!=0){
p=(Base *)malloc(sizeof(Base));
i=x%n;
p->record=i;
if(i>9){
p->record+=z-10;
}else{
p->record+='0';
}
p->top=l;
l=p;
x=x/n;
k++;
}
t=l;
if(t==NULL){
printf("错误!!");
}
else{
printf("\n进制转换后:");
for(i=0;i<k;i++){
printf("%c",t->record);
t=t->top;
}
}
printf("\n输入要转换的值与转换的进制或者输入End结束进制转换:");
l=NULL;
free(p);
memset(q,0,sizeof q);
gets(q);
gets(q);
}
}
//表达式部分为书上代码
void trans(char *exp,char *postexp)
{ /*将中缀表达式转换成后缀表达式函数*/
struct
{
char data[100];
int top;
} op; /*运算符栈*/
int i=0;
op.top=-1;
while(*exp!='#') /*当表达式没结束时*/
{
switch(*exp) /*判断表达式的每个字符*/
{
case '(': /*当字符为'('时*/
op.top++;op.data[op.top]=*exp; /*栈顶指针增1,运算符入栈*/
exp++; /*中缀表达式指针增1*/
break;
case ')': /*当字符为')'时*/
while(op.data[op.top]!='(') /*只要运算符栈顶元素不是'('时*/
{
postexp[i++]=op.data[op.top]; /*将栈顶运算符写入后缀表达式数组中*/
op.top--; /*栈顶指针减1*/
}
op.top--;exp++; /*栈顶指针减1,表达式指针加1*/
break;
case '+':
case '-':
while(op.top!=-1&&op.data[op.top]!='(') /*运算符栈不为空且栈顶元素不为'('时*/
{
postexp[i++]=op.data[op.top]; /*将栈顶运算符写入后缀表达式数组中*/
op.top--; /*运算符栈顶指针减1*/
}
op.top++; /*运算符栈顶指针加1*/
op.data[op.top]=*exp; /*将中缀表达式元素入符号栈*/
exp++; /*中缀表达式指针加1*/
break;
case '*':
case '/':
while(op.data[op.top]=='*'||op.data[op.top]=='/') /*当栈顶元素不是'*'和'/'时*/
{
postexp[i++]=op.data[op.top]; /*栈顶运算符写到后缀表达式数组中*/
op.top--; /*栈顶指针减1*/
}
op.top++;/*栈顶指针加1*/
op.data[op.top]=*exp; /*中缀表达式的元素入栈*/
exp++; /*表达式指针加1*/
break;
case ' ':break;
default:
while(*exp>='0'&&*exp<='9') /*当表达式对象是数字时*/
{
postexp[i++]=*exp; /*将数字写到后缀表达式数组中*/
exp++; /*中缀指针加1*/
}
postexp[i++]='#'; /*将每个操作数之间增加分隔符'#'*/
}
}
while(op.top!=-1) /*当运算符栈不为空时*/
{
postexp[i++]=op.data[op.top]; /*将栈顶运算符写入后缀表达式数组中*/
op.top--; /*栈顶指针减1*/
}
postexp[i]='\0'; /*为后缀表达式加一个结束标志*/
}
float compvalue(char *postexp)
{ /*根据后缀表达式求值函数*/
struct
{
float data[100];
int top;
} st; /*数栈结点类型*/
float a,b,c,d;
st.top=-1; /*栈顶指针赋初值-1*/
while(*postexp!='\0') /*当后缀表达式没结束时*/
{
switch(*postexp)
{
case '+':
a=st.data[st.top]; /*数栈顶元素赋给变量a*/
st.top--; /*栈顶指针减1*/
b=st.data[st.top]; /*数栈顶元素赋给变量b*/
st.top--; /*栈顶指针减1*/
c=b+a; /*将a加b的结果存入变量c*/
st.top++; /*栈顶指针加1*/
st.data[st.top]=c; /*将变量c入栈*/
break;
case '-':
a=st.data[st.top];
st.top--;
b=st.data[st.top];
st.top--;
c=b-a;
st.top++;
st.data[st.top]=c;
break;
case '*':
a=st.data[st.top];
st.top--;
b=st.data[st.top];
st.top--;
c=b*a;
st.top++;
st.data[st.top]=c;
break;
case '/':
a=st.data[st.top];
st.top--;
b=st.data[st.top];
st.top--;
if(a!=0)
{
c=b/a;
st.top++;
st.data[st.top]=c;
}
else
printf("\n\t除零错误!\n");
break;
default: /*后缀表达式的字符是数字字符时,将其转换为整数*/
d=0;
while(*postexp>='0'&&*postexp<='9')
{
d=10*d+*postexp-'0';
postexp++;
}
st.top++;
st.data[st.top]=d; /*将转换之后的整数入栈*/
break;
}
postexp++;
}
return st.data[st.top]; /*返回数栈的栈顶元素即为所求的结果*/
}
void Menu(){
printf("\n 栈子系统");
printf("\n-------------------------");
printf("\n 1-初始化栈 ");
printf("\n 2-入栈元素 ");
printf("\n 3-出栈操作 ");
printf("\n 4-显示栈顶元素 ");
printf("\n 5-显示栈中元素 ");
printf("\n 6-进制转换 ");
printf("\n 7-表达式转换求值 ");
printf("\n 0-退出 ");
printf("\n--------------------------");
printf("\n请输入菜单号(0-7):");
}
int main(){
Stack *s;
Base *l;
int js(Stack *s);
char ch1,ch2,a;
char exp[100],postexp[100];
ch1='y';
while(ch1=='y'||ch1=='Y'){
Menu();
scanf("%c",&ch2);
getchar();
switch(ch2){
case '1':
s=InitStack();
break;
case '2':
s=Push(s);
break;
case '3':
s=Pop(s);
break;
case '4':
Topofstack(s);
break;
case '5':
Statistical(s);
break;
case '6':
DecimaltoN(l);
break;
case '7':
printf("请输入算术表达式(只有+、-、*、/四种运算符),以'#'结束:");
scanf("%s",&exp);
trans(exp,postexp);
printf("则该表达式的中缀表达式为:%s\n",exp);
printf("转换之后的后缀表达式为(每个操作数用“#”分隔):%s\n",postexp);
printf("表达式的值为:%.2f\n",compvalue(postexp));
break;
case '0':
ch1='n';
break;
default:
printf("输入有误!!!!");
}
if(ch2!='0'){
printf("\n按回车键继续,按任意键返回主菜单!\n");
}
a=getchar();
if(a!='\xA'){
getchar();
ch1='n';
}
}
}