#include int PrintError = 0; /*全局变量,0代表正常,1代表表达式出错*/
typedef struct Node *PtrToNode; /*栈的定义*/
typedef PtrToNode Stack;
typedef struct FNode *Ptr_Fn;
typedef Ptr_Fn FStack;
typedef struct FNode{
float Element;
Ptr_Fn Next;
};
typedef struct Node{
char Element;
PtrToNode Next;
};
/*************************************
函数声明
**************************************/
int FisEmpty(FStack S);
void FPush(float X,FStack S);
float FTop(FStack S);
void FPop(FStack S);
int IsEmpty(Stack S);
void MakeEmpty(Stack S);
void Push(char X,Stack S);
char Top(Stack S);
void Pop(Stack S);
void ConvertToPost(FILE *In, Stack Whereat,FILE *Temp);
void Reverse(Stack Rev);
void Calculate(FILE *Change, Stack Whereat,FILE *Temp);
void cover();
void mainmenu();
void printoutput();
void author();
/*************************************
主函数
**************************************/
void main()
{
cover();
mainmenu();
}
/*************************************
封面函数
**************************************/
void cover()
{
system("color f0");
printf("\n\n\n");
printf("\t\t\t《数据结构》课程设计 之\n");
printf("\t\t\t ————表达式求值\n");
printf("\n\n\n\n\n\n");
printf("\t\t\t made by 薛国庆\n\n");
printf("\t\t\t 软件工程1102\n\n");
printf("\t\t\t 2013年6月\n\n\n\n");
printf("\t\t\t\t\t\t\t 按Enter继续");
getch();
}
/*************************************
关于作者
**************************************/
void author()
{int c;
system("cls");
printf("\n\n");
printf("\t————————————关于作者————————————\n\n");
printf("\t\t\t 程序员: \n\n");
printf("\t\t\t 测试员: \n\n");
printf("\t\t\t 文档员: \n\n");
printf("\n\n\n\n");
printf("\t\t _____________________________________________ \n");
printf("\t\t | [0] 返回主菜单 |\n");
printf("\t\t | [1] 退出 |\n");
printf("\t\t |_____________________________________________|\n");
printf("\t\t\t 请选择操作(0--1):");
scanf("%d",&c);
switch(c)
{
case 0: mainmenu();break;
case 1: exit(0);
default:mainmenu();
}
}
/*********************************************************************
操作目的:将用户输入的Input.txt文件中的中缀表达式计算结果存如Output.txt文件中。
初始条件:用户将中缀表达式,逐行输入到Input.txt文件中。
操作结果:自动生成一个Output.txt文档将结果逐行输出。
*********************************************************************/
int save()
{ int c;
FILE *InputFile, *OutputFile,*Temp; /*Temp用来存放后缀表达式*/
Stack Whereat; /*记录后缀表达式中操作数与运算符的顺序*/
char sample; /*用来存放*/
InputFile = fopen("Input.txt","r");
OutputFile = fopen("Output.txt","w");
Whereat = malloc(sizeof(struct Node));
Whereat->Next = NULL;
if (!InputFile || !OutputFile) {
printf("intput or output file(s) do not exist.\n");
return(1);
}
sample = getc(InputFile);
while ( sample != EOF){ /*EOF为文件结束的标志*/
Temp = fopen("Temp.txt","w+");
ungetc(sample,InputFile); /* 将sample字符退回至输入流中*/
ConvertToPost(InputFile,Whereat,Temp);/*中缀—————》》后缀*/
if (PrintError){
fprintf(OutputFile,"Error");
fscanf(InputFile,"\n",&sample);
PrintError = 0;
}
else if (IsEmpty(Whereat) == 1){ /*跳过在input文件中的空格*/
}
else if (IsEmpty(Whereat) != 1){
Reverse(Whereat); /*将Whereat栈倒置*/
if (Top(Whereat) == B){
/*B表示运算符*/
PrintError = 1; /*后缀表达式第一个元素是运算符号则表达式错误*/
}
fclose(Temp);
Temp = fopen("Temp.txt","r+");
Calculate(OutputFile, Whereat,Temp);/*计算后缀表达式的结果*/
}
fclose(Temp);
MakeEmpty(Whereat); /* 将Whereat栈置空*/
putc(\n,OutputFile);/* 在输出文件中换行*/
sample = getc(InputFile);
}
free(Whereat);
fclose(InputFile);
fclose(OutputFile);
remove("Temp.txt"); /*释放空间*/
system("cls");
printf("\n\n\n\n\t\t\t恭喜!Output.txt文件已经生成!\n");
printf("\n\n\n\n");
printf("\t\t ___________________表达式求值________________ \n\n");
printf("\t\t | [0] 返回主菜单 |\n\n");
printf("\t\t | [1] 退出 |\n\n");
printf("\t\t |_____________________________________________|\n");
printf("\t\t\t 请选择操作(0--1):");
scanf("%d",&c);
switch(c)
{
case 0: mainmenu();break;
case 1: exit(0);
default:mainmenu();
}
return 1;
}
/******************************************************************
操作目的:将自动生成的Output.txt中每一行的结果读取输出。
初始条件: 生成一个Output.txt文档将结果逐行输出。
操作结果:在窗口逐行输出结果
*******************************************************************/
/*************************************
Output输出函数
**************************************/
void printOutput()
{ int c;
int i=0;
char str[100][100]; /*二维数组用来存放字符串*/
char a[100]; /*中间变量*/
FILE *fp;
system("cls");
fp=fopen("Output.txt","rb");
if(fp==NULL)
{
printf("Open File error!");
}
while(!feof(fp))
{
fscanf(fp,"%s",a);
strcpy(str[i++],a); /*将a赋给str[i++]*/
}
printf(" ———————————欢迎使用——————————\n\n");
printf("\t\tInput.txt文件中每一行的中缀表达式的计算结果如下:\n\n");
for (i=0;i<38;i++) /*可以根据Output.txt中结果的个数改变循环次数*/
{
printf("\t\t%s\n",str[i]);
}
fclose(fp);
printf("\n\n\n\n");
printf("\t\t _____________________________________________ \n");
printf("\t\t | [0] 返回主菜单 |\n");
printf("\t\t | [1] 退出 |\n");
printf("\t\t |_____________________________________________|\n");
printf("\t\t\t 请选择操作(0--1):");
scanf("%d",&c);
switch(c)
{
case 0: mainmenu();break;
case 1: exit(0);
default:mainmenu();
}
}
/*******************************************************************
操作目的:将Input.txt每一行的结果读取输出。
初始条件: Input.txt文档存在。
操作结果:在窗口逐行输出Input.txt文件中的中缀表达式。
********************************************************************/
/*************************************
Input输出函数
**************************************/
void printInput()
{ int c;
int i=0;
char str[100][100];
char a[100];
FILE *fp;
system("cls");
fp=fopen("Input.txt","r");
if(fp==NULL)
{
printf("Open File error!");
}
while(!feof(fp))
{
fscanf(fp,"%s",a);
strcpy(str[i++],a);
}
printf(" ——————————欢迎使用——————————\n\n");
printf("\t\tInput.txt文件中每一行的中缀表达式如下:\n\n");
for (i=0;i<38;i++)
{
printf("\t\t%s\n",str[i]);
}
fclose(fp);
printf("\n\n\n\n");
printf("\t\t _____________________________________________ \n");
printf("\t\t | [0] 返回主菜单 |\n");
printf("\t\t | [1] 退出 |\n");
printf("\t\t |_____________________________________________|\n");
printf("\t\t\t 请选择操作(0--1):");
scanf("%d",&c);
switch(c)
{
case 0: mainmenu();break;
case 1: exit(0);
default:mainmenu();
}
}
/*************************************
主菜单函数
**************************************/
void mainmenu()
{
int c;
system("cls");
printf("\n\n\n\n");
printf("\t\t ___________________表达式求值________________ \n\n");
printf("\t\t | [1] 自动生成Output.txt文件 |\n\n");
printf("\t\t | [2] 显示Output.txt文件结果 |\n\n");
printf("\t\t | [3] 显示Input.txt中的表达式 |\n\n");
printf("\t\t | [4] 关于作者 |\n\n");
printf("\t\t | [5] 返回课程设计总菜单 |\n\n");
printf("\t\t | [0] 退出 |\n\n");
printf("\t\t |_____________________________________________|\n");
printf("\t\t\t 请选择操作(0--5):");
scanf("%d",&c);
switch(c)
{
case 1: save();break;
case 2: printOutput();break;
case 3: printInput();break;
case 4: author();break;
case 5: system("数据结构课程设计.exe");break;
case 0: exit(0);
default:mainmenu();
}
}
/*******************************************
检查两种类型的栈是否为空
*******************************************/
int IsEmpty(Stack S)
{
return(S->Next==NULL);
}
int FIsEmpty(FStack S)
{
return(S->Next==NULL);
}
/******************************************************
两种类型的弹出栈顶元素
******************************************************/
/**************弹出堆栈栈顶元素***************************/
void Pop(Stack S)
{
PtrToNode FirstCell;
if (IsEmpty(S))
printf("栈为空");
else{
FirstCell = S->Next;
S->Next = S->Next->Next;
free(FirstCell);
}
}
/********************弹出float栈顶元素****************/
void FPop(FStack S)
{
Ptr_Fn FirstCell;
if (FIsEmpty(S))
printf("栈为空");
else{
FirstCell = S->Next;
S->Next = S->Next->Next;
free(FirstCell);
}
}
/************************************************
两种类型的置空栈
*************************************************/
/********************将堆栈置空******************/
void MakeEmpty(Stack S)
{
if (S == NULL)
printf("你必须先建立一个栈!");
else
while (!IsEmpty(S))
Pop(S);
}
/******************将float堆栈置空****************/
void FMakeEmpty(FStack S)
{
if (S == NULL)
printf("你必须先建立一个栈!");
else
while (!IsEmpty(S))
Pop(S);
}
/****************************************
两种类型的元素进栈
******************************************/
/**********************元素进栈*******************/
void Push(char X, Stack S)
{
PtrToNode TmpCell;
TmpCell = (PtrToNode)malloc(sizeof(struct Node));
if (TmpCell == NULL)
printf("空间不够!");
else{
TmpCell->Element = X;
TmpCell->Next = S->Next;
S->Next = TmpCell;
}
}
/*********************float元素进栈*****************/
void FPush(float X, FStack S)
{
Ptr_Fn TmpCell;
TmpCell = (Ptr_Fn)malloc(sizeof(struct FNode));
if (TmpCell == NULL)
printf("空间不够!");
else{
TmpCell->Element = X;
TmpCell->Next = S->Next;
S->Next = TmpCell;
}
}
/******************************************
两种类型的返回栈顶元素
******************************************/
/***************返回栈顶元素**************/
char Top(Stack S)
{
if (!IsEmpty(S))
return S->Next->Element;
printf("栈为空");
exit(1);
return 0;
}
/**************返回float栈顶元素**********/
float FTop(FStack S)
{
if (!FIsEmpty(S))
return S->Next->Element;
printf("栈为空");
exit(1);
return 0;
}
/********************************************
将堆栈元素倒置
*********************************************/
void Reverse(Stack Rev)
{
Stack Tempstack;
Tempstack = malloc(sizeof(struct Node));
Tempstack->Next = NULL;
while (!IsEmpty(Rev)){
Push(Top(Rev),Tempstack); /*将元素压栈到一个临时堆栈*/
Pop(Rev);
}
Rev->Next = Tempstack->Next; /*指向新的堆栈*/
}
/**************************************************
中缀表达式转换为后缀表达式
***************************************************/
void ConvertToPost(FILE *In, Stack Whereat, FILE *Temp)
{
Stack OpHolder;
char holder; /*中间变量,用来存放操作数和运算符*/
char lastseen;
int digitcounter = 0; /*digitcounter用来计数*/
OpHolder = malloc(sizeof(struct Node)); /*初始化*/
OpHolder->Next = NULL;
holder=getc(In); /*从In中取字符赋给holder*/
lastseen = @; /*用来防止输入格式错误*/
putc( ,Temp); /*输入空格字符到存放后缀表达式的文件中*/
while ((holder !=\n) && (holder != EOF)){
if (holder == ){ /*当holder为空格时,开始计数*/
digitcounter = 0;
}
else if ( IsOperator(holder) == -1){ /*如果holder不是操作数或运算符号,则表达式有误*/
PrintErr