分数的加减法——C语言初学者代码中的常见错误与瑕疵(12)

浏览:
字体:
发布时间:2013-12-23 12:22:24
来源:
题目的修正 
  我抛弃了原题中“其中a, b, c, d是一个0-9的整数”这样的前提条件,因为这种限制毫无必要。只假设a, b, c, d是十进制整数形式的字符序列。
 
  我也不清楚这种题目应该如何结束输入。下面的代码假设在没有正确输入完整的运算式时结束。
 
数据结构 
 
typedef
   struct 
   {
      int numer ; //分子
      int denom ; //分母
   }
frac_t ;//分数类型
 
 数据 
  一共需要三个变量,两个记录分数,一个记录运算符。
 
 
#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 )
      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 );
}
 
//计算,输出部分
  首先排除无意义的输入  
 
     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' );
完整的代码:
 
/*
分数的加减法 
编写一个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
 
 
*/
 
 
#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 )
      return FAIL ;
   
   switch ( * p_o )
   {
      default : return FAIL ;//不是加、减法 
      case '+':
      case '-': 
                ;
   }
 
   if ( input_frac( p_f2 ) != 2 )
      return FAIL ;
 
   return !FAIL ;
}
 
>更多相关文章
24小时热门资讯
24小时回复排行
资讯 | QQ | 安全 | 编程 | 数据库 | 系统 | 网络 | 考试 | 站长 | 关于东联 | 安全雇佣 | 搞笑视频大全 | 微信学院 | 视频课程 |
关于我们 | 联系我们 | 广告服务 | 免责申明 | 作品发布 | 网站地图 | 官方微博 | 技术培训
Copyright © 2007 - 2024 Vm888.Com. All Rights Reserved
粤公网安备 44060402001498号 粤ICP备19097316号 请遵循相关法律法规
');})();