分數的加減法——C語言初學者代碼中的常見錯誤與瑕疵(12)

 前文連接:分數的加減法——C語言初學者代碼中的常見錯誤與瑕疵(11)

重構

題目的修正 


  我拋棄了原題中「其中a, b, c, d是一個0-9的整數」這樣的前提條件,由於這種限制毫無必要。只假設a, b, c, d是十進制整數形式的字符序列。html

  我也不清楚這種題目應該如何結束輸入。下面的代碼假設在沒有正確輸入完整的運算式時結束。數據結構

數據結構 


typedef
   struct 
   {
      int numer ; //分子
      int denom ; //分母
   }
frac_t ;//分數類型

 數據 


  一共須要三個變量,兩個記錄分數,一個記錄運算符。spa

#include <stdio.h>

int main( void )
{
  frac_t frc1 , frc2 ;//兩個操做數
  char op ;           //運算符
  
  return 0;
}

整體結構


#define FAIL 0

int main( void )
{
  frac_t frc1 , frc2 ;//兩個分數
  char op ;           //運算符
  
  while ( input_exp( &frc1 , &op , &frc2 ) != FAIL )//輸入算式 
  {
     //計算,輸出 
  }

  return 0;
}

input_exp()的實現


int input_exp( frac_t * , char * , frac_t * ); 
int input_frac( frac_t * );

int input_exp( frac_t * p_f1 , char * p_o , frac_t * p_f2 )
{
   if ( input_frac( p_f1 ) != 2 )
      return FAIL ;
    
   if ( scanf(" %c" , p_o ) != 1 )//if ( scanf(" %c " , p_o ) != 1 )
      return FAIL ;
   
   switch ( * p_o )
   {
      default : return FAIL ;//不是加、減法
      case '+':
      case '-':
                ;
   }

   if ( input_frac( p_f2 ) != 2 )
      return FAIL ;

   return !FAIL ;
}

int input_frac( frac_t * p_f )
{
   return scanf("%d / %d" , &p_f->numer , &p_f->denom );
}

//計算,輸出部分


  首先排除無心義的輸入  code

     if ( frc1.denom == 0 || frc2.denom == 0 ) //無心義的輸入 
     {
        puts( "分數無心義" );
        continue ;
     }

  把減法變爲加法htm

     switch ( op )
     {
        case '-':frc2.numer = - frc2.numer ;//把減法化爲加法 
        case '+':add_to( &frc1 , &frc2 );   //計算結果放在frc1中 
                 break ;
     }

  最後輸出結果blog

     output( frc1 );
     putchar( '\n' );

完整的代碼:


/*
分數的加減法 
編寫一個C程序,實現兩個分數的加減法 
輸入:輸入包含多行數據 
每行數據的格式是 a/boc/d 。 
其中a, b, c, d爲十進制整數,o是運算符"+"或者"-"。 
輸出:對於輸入數據的每一行輸出兩個分數的運算結果。 
注意結果應符合書寫習慣,沒有多餘的符號、分子、分母,而且化簡至最簡分數 

樣例輸入: 
1/8+3/8 
1/4-1/2 
1/3-1/3 
輸出: 
1/2 
-1/4 
0

做者:薛非
出處:http://www.cnblogs.com/pmer/   「C語言初學者代碼中的常見錯誤與瑕疵」系列博文

*/


#include <stdio.h>
#include <stdlib.h>

typedef
   struct 
   {
      int numer ; //分子
      int denom ; //分母
   }
frac_t ;//分數類型

#define FAIL 0

int input_exp( frac_t * , char * , frac_t * ); 
int input_frac( frac_t * );
void add_to( frac_t * , frac_t const * );
int find_lcm( int , int );
int find_gcd( int , int );
void reduce( frac_t * );
void output( frac_t );

int main( void )
{
  frac_t frc1 , frc2 ;//兩個分數
  char op ;           //運算符
  
  while ( input_exp( &frc1 , &op , &frc2 ) != FAIL )//輸入算式 
  {
     //計算,輸出 
     if ( frc1.denom == 0 || frc2.denom == 0 ) //無心義的輸入 
     {
        puts( "分數無心義" );
        continue ;
     }
     
     switch ( op )
     {
        case '-':frc2.numer = - frc2.numer ;//把減法化爲加法 
        case '+':add_to( &frc1 , &frc2 );   //計算結果放在frc1中 
                 break ;
     }
     
     output( frc1 );
     putchar( '\n' );
  }

  return 0;
}

void output( frac_t fr )
{
   if ( fr.numer < 0 )
   {
      putchar( '-' );
      fr.numer = - fr.numer ; 
   }
   
   if ( fr.denom == 1 )
   {
      printf( "%d" , fr.numer );
      return ;
   }
   
   printf( "%d/%d" , fr.numer , fr.denom );
}

void reduce( frac_t * p_f )
{
   int gcd = find_gcd( abs( p_f->numer ) , abs( p_f->denom ) ) ; 
             
   p_f->denom /= gcd ;
   p_f->numer /= gcd ;
}

int find_gcd( int m , int n )
{
   int t ;
   
   return (t = m % n) == 0 ? n : find_gcd( n , t );
}

int find_lcm( int m , int n )
{
   return m / find_gcd( m , n ) * n ; 
}

void add_to( frac_t * p_f1 , frac_t const * p_f2 )
{
   int lcm = find_lcm( abs( p_f1->denom ) , abs( p_f2->denom ) );
   
   p_f1->numer = lcm / p_f1->denom * p_f1->numer 
               + lcm / p_f2->denom * p_f2->numer ;
   p_f1->denom = lcm ;   //分母老是正的 
   
   reduce( p_f1 );       //約分           
}

int input_frac( frac_t * p_f )
{
   return scanf( "%d / %d" , &p_f->numer , &p_f->denom );
}

int input_exp( frac_t * p_f1 , char * p_o , frac_t * p_f2 )
{
   if ( input_frac( p_f1 ) != 2 )
      return FAIL ;
    
   if ( scanf(" %c" , p_o ) != 1 )//if ( scanf( " %c " , p_o ) != 1 )
      return FAIL ;
   
   switch ( * p_o )
   {
      default : return FAIL ;//不是加、減法 
      case '+':
      case '-': 
                ;
   }

   if ( input_frac( p_f2 ) != 2 )
      return FAIL ;

   return !FAIL ;
}
相關文章
相關標籤/搜索