关于fscanf用法的求助

作者在 2008-07-27 11:23:48 发布以下内容
形式是“input.txt",输出结果存放到"output.txt"文件中。在输人文件中等式的格式必须是中缀格式,例如1+2*3,而且每一行只可以有一个表达式。
本程序将读入的中缀表达式转换为后缀表达式,并存放在temp.txt文件中;随后从temp.txt中读取后缀表达式,并将计算结果输出到output.txt中。
一个char类型的栈"Whereat"用来记录后缀表达式中操作数和运算符号的顺序,以决定需要多少次计算。
下面就是这个程序
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int PrintError = 0;
/*全局变量,0代表正常,1代表表达式出错*/
/*char类型链表式堆栈,用来存放运算符号,以及用在中缀表达式转换等时候*/
typedef struct Node *PtrToNode;
typedef PtrToNode Stack;
int IsEmpty(Stack S);
void MakeEmpty(Stack S);
void Push(char X,Stack S);
char Top(Stack S);
void Pop(Stack S);
typedef struct Node{
 char Element;
 PtrToNode Next;
};
/*float类型链表式堆栈,用来存放操作数*/
typedef struct FNode *Ptr_Fn;
typedef Ptr_Fn FStack;
int FisEmpty(FStack S);
void FPush(float X,FStack S);
float FTop(FStack S);
void FPop(FStack S);
 
typedef struct FNode{
 float Element;
 Ptr_Fn Next;
};
void ConvertToPost(FILE *In, Stack Whereat,FILE *Temp);
void Reverse(Stack Rev);
void Calculate(FILE *Change, Stack Whereat,FILE *Temp);
/******主函数******/
int main()
{
 FILE *InputFile, *OutputFile,*Temp;    /*初始化变量*/
 Stack Whereat; 
 char sample;
 InputFile = fopen("Input.txt","r");     /*打开文件*/
 OutputFile = fopen("Output.txt","w");
 Whereat = malloc(sizeof(struct Node));    /*给 Whereat分配空间*/
 Whereat->Next = NULL;
 if (!InputFile || !OutputFile) {                   /*错误处理*/
  printf("intput or output file(s) do not exist.\n");
  return(1);
 }
 sample = getc(InputFile);          
 while ( sample != EOF){
  Temp = fopen("Temp.txt","w+");     /*生成Temp文件*/
  ungetc(sample,InputFile);      /* put back sample字符*/
  ConvertToPost(InputFile,Whereat,Temp);   /*中缀变后缀*/
  if (PrintError){                             /*错误处理*/
   fprintf(OutputFile,"Error in infix notation."); 
   fscanf(InputFile,"\n",&sample);
   PrintError = 0;
  }
  else if (IsEmpty(Whereat) == 1){              /*跳过在input文件中的空格*/
  }
  else if (IsEmpty(Whereat) != 1){
   Reverse(Whereat);
   if (Top(Whereat) == 'B'){       /*错误处理,*/
                                           /*A表示操作数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);     
 }                                           /* While循环结束*/
 free(Whereat);                                 
 fclose(InputFile);
 fclose(OutputFile);
 remove("Temp.txt");                           /* 删除Temp.txt*/
 return 1;
}
/******检查堆栈是否为空******/
int IsEmpty(Stack S)

 return(S->Next==NULL);   
}
/******检查float堆栈是否为空******/
int FIsEmpty(FStack S)

 return(S->Next==NULL);   
}
/******弹出栈顶元素******/
void Pop(Stack S)
{     
 PtrToNode FirstCell;
 if (IsEmpty(S))
   perror("Empty Stack"); 
 else{
  FirstCell = S->Next;
  S->Next = S->Next->Next;
  free(FirstCell);
 }
}
/******弹出float栈顶元素******/
void FPop(FStack S)
{   
 Ptr_Fn FirstCell;
 if (FIsEmpty(S))
   perror("Empty Stack"); 
 else{
  FirstCell = S->Next;
  S->Next = S->Next->Next;
  free(FirstCell);
 }
}
/******将堆栈置空******/
void MakeEmpty(Stack S)
{   
 if (S == NULL)
   perror("Must use Createstack first");
 else
  while (!IsEmpty(S))
   Pop(S);
}
/******将float堆栈置空******/
void FMakeEmpty(FStack S)
{   
 if (S == NULL)
   perror("Must use Createstack first");
 else
  while (!IsEmpty(S))
   Pop(S);
}
/******元素进栈******/
void Push(char X, Stack S)
{  
 PtrToNode TmpCell;
 TmpCell = (PtrToNode)malloc(sizeof(struct Node));
 if (TmpCell == NULL)
  perror("Out of Space!");
 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)
  perror("Out of Space!");
 else{
  TmpCell->Element = X;
  TmpCell->Next = S->Next;
  S->Next = TmpCell;
 }
}
/******返回栈顶元素******/
char Top(Stack S)
{
 if (!IsEmpty(S))
  return S->Next->Element; 
 perror("Empty Stack");
 exit(1);
 return 0;
}
/******返回float栈顶元素******/
float FTop(FStack S)
{
 if (!FIsEmpty(S))
  return S->Next->Element;
 perror("Empty Stack");
 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;    /*指向新的堆栈*/
}

/*******
Whereat 说明:
Whereat 记录了操作数和运算符号的位置,用A和B区分。A = operand, B = operator.
(例如 1+2转换成12+,在whereat中的形式应该是 AAB)
OpHolder说明:
Char类型的堆栈Opholder用来保存运算符号。
******/
/******将中缀表带式转换为后缀表达式******/
void ConvertToPost(FILE *In, Stack Whereat, FILE *Temp)
{
 Stack OpHolder;
 char holder;
 char lastseen;
 int digitcounter = 0;                       /*操作数的计数器*/
 OpHolder = malloc(sizeof(struct Node));      /*初始化*/
 OpHolder->Next = NULL;
 holder=getc(In);
 lastseen = '@';                           /*用来防止输入格式错误,例如两个小数点*/
 putc(' ',Temp);
 
 while ((holder !='\n') && (holder != EOF)){
  if (holder == ' '){
   digitcounter = 0;
  }
  else if ( IsOperator(holder) == -1){       /*如果holder不是操作数或运算符号*/
   PrintError = 1;
  }
  else if (IsOperator(holder)==0){
   if ((lastseen == holder) && (lastseen == '.')){   /*错误处理*/
    PrintError = 1;
   }
   else
    lastseen = holder;
   if (digitcounter == 0){    
    Push('A',Whereat);             /*进栈*/
    digitcounter++;    /*计数器加一*/
    putc(' ',Temp);
   }
   putc(holder,Temp);
  }
  else{
   digitcounter = 0;
   if ((lastseen == holder) && (lastseen != '(') && (lastseen != ')'))  /*"("情况特殊对待*/
    PrintError = 1;    
   else
    lastseen = holder;
   if(IsEmpty(OpHolder)==1){      /*当OpHolder为空*/
    Push(holder,OpHolder);
   }
   else if(OperatorValue(Top(OpHolder)) == 6){  /*OpHolder是"("的情况*/
    if(OperatorValue(holder)==5)
     Pop(OpHolder);
    else
    Push(holder,OpHolder);
   }
   else if(OperatorValue(holder) == 6){ 
    Push(holder,OpHolder);
   }
   else if(OperatorValue(holder) == 5){         /* OpHolder是" )"的情况*/
   while ((IsEmpty(OpHolder) != 1) && (OperatorValue(Top(OpHolder)) != 6))
   { 
     putc(' ',Temp);
     Push('B',Whereat);
     putc(Top(OpHolder),Temp);
     Pop(OpHolder);
    }
    if (IsEmpty(OpHolder) == 1){          /*错误处理,括号不匹配*/
     PrintError = 1; 
    }
    else
     Pop(OpHolder);
   }
   else if((OperatorValue(holder) == OperatorValue(Top(OpHolder)))
     && (OperatorValue(holder) == 3)){      /*幂运算情况*/
    Push(holder,OpHolder);
   }
   else if((OperatorValue(holder) < OperatorValue(Top(OpHolder)))
     && OperatorValue(Top(OpHolder)) == 3){  /*幂运算情况*/
    putc(' ',Temp);
    Push('B',Whereat);  
    putc(Top(OpHolder),Temp);
    Pop(OpHolder);
    while((IsEmpty(OpHolder) != 1) && (OperatorValue(Top(OpHolder)) == 3))
    {
     Push('B',Whereat);
     putc(' ',Temp);    
     putc(Top(OpHolder),Temp);
     Pop(OpHolder);
    }
    Push(holder,OpHolder);
   }
/******
如果当前运算符号的优先级小于或者等于堆栈中的运算符号的优先级,则将其放入temp中,并且将堆栈中的运算符号出栈,放入temp中,直到堆栈为空或者优先级小于堆栈顶元素的优先级
******/
   else if(OperatorValue(Top(OpHolder)) >= OperatorValue(holder)){   
    while((IsEmpty(OpHolder) != 1)
      && (OperatorValue(Top(OpHolder)) >= OperatorValue(holder))
      && (OperatorValue(Top(OpHolder))!=6))
    {
     putc(' ',Temp); 
     putc(Top(OpHolder),Temp);
     Push('B',Whereat);
     Pop(OpHolder);
    }
    Push(holder,OpHolder);
   }
   else if(OperatorValue(Top(OpHolder)) < OperatorValue(holder)){  
/******
如果当前运算符号的优先级大于堆栈中的运算符号的优先级,则将其压入堆栈中
******/
    Push(holder,OpHolder);
   }
  }
  holder=getc(In); 
 }                                  /* While循环结束*/
 while(IsEmpty(OpHolder)!=1){
/******
最后如果堆栈中还有运算符号,则一并放到temp中
******/
  Push('B',Whereat);
  putc(' ',Temp);  
  putc(Top(OpHolder),Temp);
  Pop(OpHolder);
 }
 MakeEmpty(OpHolder);
 free(OpHolder);
}
/******判断类型,1为运算符号,0为操作数,-1为错误******/
int IsOperator(char ToCompare)
{
 if (ToCompare == '(' || ToCompare == ')'|| ToCompare == '+' || ToCompare == '-'
  || ToCompare == '*'|| ToCompare == '/' || ToCompare == '^'|| ToCompare == '%')
 {
  return 1;
 }
 else if (ToCompare == '1' || ToCompare == '2'|| ToCompare == '3'
   || ToCompare == '4' || ToCompare == '5'|| ToCompare == '6'
   || ToCompare == '7'|| ToCompare == '8' || ToCompare == '9'
   || ToCompare == '0'|| ToCompare == '.')
  {
     return 0;
      }
 else{
  return -1;
 }
}
/******返回运算符号的优先级******/
int OperatorValue(char ValueToGive)
{
 if (ValueToGive == '(')
  return 6;
 if (ValueToGive == ')')
  return 5;
 if (ValueToGive == '^') 
  return 3;
    if (ValueToGive == '%') 
  return 2;
 if (ValueToGive == '*')
  return 2;
 if (ValueToGive == '/')
  return 2;
 if (ValueToGive == '+')
  return 1;
 if (ValueToGive == '-')
  return 1;
 return 0;
}
/******计算后缀表达式******/
void Calculate(FILE *Change, Stack Whereat, FILE *Temp)
{
 FStack Operands;
 float looker;
 char Op;
 char spacefinder;
 float answer = 0;
 float NumA;
 float NumB;
 Operands = (Ptr_Fn)malloc(sizeof(struct FNode));
 Operands->Next= NULL;
 
 while ((IsEmpty(Whereat) != 1) && PrintError != 1)
 {                                     /*循环直到Whereat空,或者遇到错误*/
  if (Top(Whereat) == 'A'){
   fscanf(Temp," ",&spacefinder);
   fscanf(Temp,"%f",&looker);      /*如果是A,则是操作数*/
   FPush(looker,Operands); 
   Pop(Whereat);
  }
  else if (Top(Whereat) == 'B'){
   fscanf(Temp," ",&spacefinder);     /*如果是B,则是运算符*/
   Op = getc(Temp);      
   switch(Op){       /* 判断是什么运算符*/
   case('^'):                       /*幂运算*/
    NumB = FTop(Operands);
    FPop(Operands);
    if (FIsEmpty(Operands)){   /*错误处理*/
     PrintError = 1;
    }
    else{
     NumA = FTop(Operands);
     FPop(Operands);
     if ((NumA == 0 && NumB < 0)||((NumA<0)
      && (NumB - (int)NumB != 0)))
     {
      PrintError = 1;
     }
     else{
      answer = pow(NumA,NumB);
      FPush(answer,Operands);
     }
    }
    break;
   case '%':                         /*取模运算*/
    NumB = FTop(Operands);
    FPop(Operands);
    if (FIsEmpty(Operands)){  /*错误处理*/
     PrintError = 1;
    }
    else{
     NumA = FTop(Operands);
     FPop(Operands);
     if ((NumA - (int)NumA != 0) || (NumB - (int)NumB != 0)
      || (NumB == 0))
     {
      PrintError = 1;
     }
     else{
      answer = (int)NumA % (int)NumB;   /* x mod b*/
      FPush(answer,Operands);
     }
    }
    break;
   case '*':                                       /*乘法运算*/
    NumB = FTop(Operands);
    FPop(Operands);
    if (FIsEmpty(Operands)){ 
     PrintError = 1;
    }
    else{
     NumA = FTop(Operands);
     FPop(Operands);
     answer = NumA * NumB;      /* x * y*/
     FPush(answer,Operands);
    }
    break;
   case '/':                                        /*除法运算*/
    NumB = FTop(Operands);
    FPop(Operands);
    if (FIsEmpty(Operands)){ 
     PrintError = 1;
    }
    else{
     NumA = FTop(Operands);
     FPop(Operands);
     if (NumB == 0){
      PrintError = 1;                   /*分母不为0*/
     }
     else{
      answer = (float)(NumA / NumB);   /* x / y*/
      FPush(answer,Operands);
     }
    }
    break;
   case '+':                                      /*加法运算*/
    NumB = FTop(Operands);
    FPop(Operands);
    if (FIsEmpty(Operands)){ 
     PrintError = 1;
    }
    else{
     NumA = FTop(Operands);
     FPop(Operands);
     answer = NumA + NumB;    /* x + y*/
     FPush(answer,Operands);
    }
    break;
   case '-':                                      /*减法运算*/
    NumB = FTop(Operands);
    FPop(Operands);
    if (FIsEmpty(Operands)){ 
     PrintError = 1;
    }
    else{
     NumA = FTop(Operands);
     FPop(Operands);
     answer = NumA - NumB;    /* x - y*/
     FPush(answer,Operands);
    }
    break;
   default:
    PrintError = 1;
    break;
   }                                          /*判断结束*/
   Pop(Whereat);
  }
 }                                                  /*循环结束*/
 if (!PrintError){  
  answer =  FTop(Operands);
  FPop(Operands);
  if (FIsEmpty(Operands) != 1){
   fprintf(Change,"Error in infix notation.");         /*如果还有操作数*/
   PrintError = 0;
  }
  else
   fprintf(Change,"%.2f",answer);   
 }
 else{
  fprintf(Change,"Error in infix notation.");   
  PrintError = 0;
 }
 FMakeEmpty(Operands);
 free(Operands);
}
请问计算后缀表达式函数Calculate中的fscanf(Temp," ",&spacefinder);在次程序中有什么作用
c语言 | 阅读 23721 次
文章评论,共0条
游客请输入验证码
最新评论