前文链接:分数的加减法——C语言初学者代码中的常见错误与瑕疵(11)

重构

题目的修正


  我抛弃了原题中“其中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 ;           //运算符

  ;
}

总体结构


#define FAIL 0

int main( void )
{
  frac_t frc1 , frc2 ;//两个分数
  char op ;           //运算符

  while ( input_exp( &frc1 , &op , &frc2 ) != FAIL )//输入算式
  {
     //计算,输出
  }

  ;
}

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 )
{
    )
      return FAIL ;

    )
      return FAIL ;

   switch ( * p_o )
   {
      default : return FAIL ;//不是加、减法
      case '+':
      case '-':
                ;
   }

    )
      return FAIL ;

   return !FAIL ;
}

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

//计算,输出部分


  首先排除无意义的输入

      || frc2.denom ==  ) //无意义的输入
     {
        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

作者:薛非
出处: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 )//输入算式
  {
     //计算,输出
      || frc2.denom ==  ) //无意义的输入
     {
        puts( "分数无意义" );
        continue ;
     }

     switch ( op )
     {
        case '-':frc2.numer = - frc2.numer ;//把减法化为加法
        case '+':add_to( &frc1 , &frc2 );   //计算结果放在frc1中
                 break ;
     }

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

  ;
}

void output( frac_t fr )
{
    )
   {
      putchar( '-' );
      fr.numer = - fr.numer ;
   }

    )
   {
      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 ;

    ? 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 )
{
    )
      return FAIL ;

    )
      return FAIL ;

   switch ( * p_o )
   {
      default : return FAIL ;//不是加、减法
      case '+':
      case '-':
                ;
   }

    )
      return FAIL ;

   return !FAIL ;
}

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

  1. C语言初学者代码中的常见错误与瑕疵(23)

    见:C语言初学者代码中的常见错误与瑕疵(23)

  2. 一个超复杂的间接递归——C语言初学者代码中的常见错误与瑕疵(6)

    问题: 问题出处见 C语言初学者代码中的常见错误与瑕疵(5) . 在该文的最后,曾提到完成的代码还有进一步改进的余地.本文完成了这个改进.所以本文讨论的并不是初学者代码中的常见错误与瑕疵,而是对我自己 ...

  3. C语言初学者代码中的常见错误与瑕疵(5)

    问题: 素数 在世博园某信息通信馆中,游客可利用手机等终端参与互动小游戏,与虚拟人物Kr. Kong 进行猜数比赛. 当屏幕出现一个整数X时,若你能比Kr. Kong更快的发出最接近它的素数答案,你将 ...

  4. C语言初学者代码中的常见错误与瑕疵(19)

    见:C语言初学者代码中的常见错误与瑕疵(19)

  5. C语言初学者代码中的常见错误与瑕疵(14)

    见:C语言初学者代码中的常见错误与瑕疵(14) 相关链接:http://www.anycodex.com/blog/?p=87

  6. C语言初学者代码中的常见错误与瑕疵(9)

    题目 字母的个数 现在给你一个由小写字母组成字符串,要你找出字符串中出现次数最多的字母,如果出现次数最多字母有多个那么输出最小的那个. 输入:第一行输入一个正整数T(0<T<25) 随后T ...

  7. 要心中有“数”——C语言初学者代码中的常见错误与瑕疵(8)

    在 C语言初学者代码中的常见错误与瑕疵(7) 中,我给出的重构代码中存在BUG.这个BUG是在飞鸟_Asuka网友指出“是不是时间复杂度比较大”,并说他“第一眼看到我就想把它当成一个数学问题来做”之后 ...

  8. C语言初学者代码中的常见错误与瑕疵(7)

    问题: 矩形的个数 在一个3*2的矩形中,可以找到6个1*1的矩形,4个2*1的矩形3个1*2的矩形,2个2*2的矩形,2个3*1的矩形和1个3*2的矩形,总共18个矩形.给出A,B,计算可以从中找到 ...

  9. C语言初学者代码中的常见错误与瑕疵(1)

    曾在豆瓣上看到过一个小朋友贴出他自己的代码(http://www.douban.com/group/topic/40293109/),当时随口指点了几句.难得这位小朋友虚心修正.从善如流,不断地改,又 ...

随机推荐

  1. Oracle学习总结_day06_视图&amp;序列&amp;索引

    本文为博主辛苦总结,希望自己以后返回来看的时候理解更深刻,也希望可以起到帮助初学者的作用. 转载请注明 出自 : luogg的博客园 谢谢配合! day 06 视图,索引,序列 视图 什么是视图: 视 ...

  2. Droidbox恶意软件动态分析环境搭建

    @author : Dlive 0x01 DroidBox简介 DroidBox是一款,可以获得以下信息 1.APK包hash值 2.网络通信数据 3.文件读写操作 4.网络通信,文件读写,SMS中的 ...

  3. 高清DVI编码器|上海视涛科技

    DVI编码器(E600)简介 高清DVI编码器是上海视涛科技出品的高性能DVI编码产品.该DVI编码器是上海视涛科技完全自主研发,并适用于VGA.DVI.HDMI等信号的编码采集及网络传输的专用硬件设 ...

  4. 重写 Ext.toolbar.Paging 扩展功能

    直接代码,放项目overrides文件夹中即可 //重写类 分页插件 //汉化 //默认下方布局 //默认显示额外信息 //当删除数据时,处理页面变化 Ext.define("overrid ...

  5. php多层数组与对象的转换实例代码

    通过json_decode(json_encode($object)可以将对象一次性转换为数组,但是object中遇到非utf-8编码的非ascii字符则会出现问题,比如gbk的中文,何况json_e ...

  6. 迅为IMX6Q PLUS开发板烧写Android6.0系统方法

    平台:迅为IMX6Q PLUS开发板工具:MfgTool2 工具 镜像文件在光盘目录“03 镜像_android 6.0.1 文件系统”下.其中商业级核心板为 2G内存镜像,工业级核心板为 1G 内存 ...

  7. nodejs -- 主模块 ,初始化.

    一:知识点: 1-1: 模块初始化: 1-2 主模块: 二: 测试 2-1: 代码: 1) 主模块 1:   main.js var counter1 = require("./counte ...

  8. Struts2 &lt;s:select &gt;标签的使用

    select 取值session中的内容 <s:select name="meal.mealseries.seriesid" list="#session.meal ...

  9. centos7下rsync+crontab定期同步备份

    最近需求想定期备份内部重要的服务器数据到存储里面,顺便做个笔记 以前整过一个win下的cwrsync(客户端)+rsync(服务端:存储)的bat脚本 这次整一个Linux下的脚本sh,执行定期自动备 ...

  10. centos6.5虚拟机快照技术

    一.查看现有磁盘镜像格式与转换 查看磁盘格式 [root@localhost ~]# qemu-img info /var/lib/libvirt/images/centos7.img image: ...