重构

题目的修正

我抛弃了原题中“其中a, b, c, d是一个0-9的整数”这样的前提条件,因为这种限制毫无必要。只假设a, b, c, d是十进制整数形式的字符序列。

我也不清楚这种题目应该如何结束输入。下面的代码假设在没有正确输入完整的运算式时结束。

数据结构

typedef

struct

{

int numer ; //分子

int denom ; //分母

}

frac_t ;//分数类型

数据

一共需要三个变量,两个记录分数,一个记录运算符。

#include

int main( void )

{

frac_t frc1 , frc2 ;//两个操作数

char op ; //运算符

return ;

}

总体结构

#define FAIL 0

int main( void )

{

frac_t frc1 , frc2 ;//两个分数

char op ; //运算符

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

{

//计算,输出

}

return ;

}

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 ) != )

return FAIL ;

if ( scanf(" %c" , p_o ) != )//if ( scanf(" %c " , p_o ) != )

return FAIL ;

switch ( * p_o )

{

default : return FAIL ;//不是加、减法

case '+':

case '-':

;

}

if ( input_frac( p_f2 ) != )

return FAIL ;

return !FAIL ;

}

int input_frac( frac_t * p_f )

{

return scanf("%d / %d" , &p_f->numer , &p_f->denom );

}

//计算,输出部分

首先排除无意义的输入

if ( frc1.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

#include

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

{

puts( "分数无意义" );

continue ;

}

switch ( op )

{

case '-':frc2.numer = - frc2.numer ;//把减法化为加法

case '+':add_to( &frc1 , &frc2 ); //计算结果放在frc1中

break ;

}

output( frc1 );

putchar( '\n' );

}

return ;

}

void output( frac_t fr )

{

if ( fr.numer < )

{

putchar( '-' );

fr.numer = - fr.numer ;

}

if ( fr.denom == )

{

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) == ? 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 ) != )

return FAIL ;

if ( scanf(" %c" , p_o ) != )//if ( scanf( " %c " , p_o ) != )

return FAIL ;

switch ( * p_o )

{

default : return FAIL ;//不是加、减法

case '+':

case '-':

;

}

if ( input_frac( p_f2 ) != )

return FAIL ;

return !FAIL ;

}

一个超复杂的间接递归——C语言初学者代码中的常见错误与瑕疵&lpar;6&rpar;

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

C语言初学者代码中的常见错误与瑕疵&lpar;5&rpar;

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

C语言初学者代码中的常见错误与瑕疵&lpar;14&rpar;

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

C语言初学者代码中的常见错误与瑕疵&lpar;9&rpar;

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

要心中有&OpenCurlyDoubleQuote;数”——C语言初学者代码中的常见错误与瑕疵&lpar;8&rpar;

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

C语言初学者代码中的常见错误与瑕疵&lpar;7&rpar;

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

C语言初学者代码中的常见错误与瑕疵&lpar;1&rpar;

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

随机推荐

使用XmlDataDocument将数据存储到XML文档

string str = "Data Source=192.168.1.20;Initial Catalog=WebTest;User ID=sa;Password="; SqlC ...

SQL Server中解决死锁

SQL Server中解决死锁的新方法介绍 数据库操作的死锁是不可避免的,本文并不打算讨论死锁如何产生,重点在于解决死锁,通过SQL Server 2005, 现在似乎有了一种新的解决办法. 将下面的 ...

status 状态栏

http://www.pchou.info/ios/2015/08/22/oc-statusbar.html IOS的项目多数会遇到控制状态栏和导航栏的问题,比如隐藏状态栏.控制状态栏的文字颜色等,导 ...

Asp&period;net默认配置下,Session莫名丢失的原因及解决

Asp.net默认配置下,Session莫名丢失的原因及解决 我们平时写的asp.net程序,里面要用到Session来保存一些跨页面的数据.但是Session会经常无故丢失,上网查查,也没找到原因. ...

fscanf(格式化字符串输入)

fscanf(格式化字符串输入) 相关函数 scanf,sscanf 表头文件 #include 定义函数 int fscanf(FILE * stream ,const ...

简易ORM&lpar;基于注解&rpar;

这是从我们现有项目做的一定的改进准备做成IDE插件 类似getter和setter的生成 1.定义实体类 通过注解说明其表名和字段名(SOURCE类型的注解 不需要运行时使用)@TableName(& ...

轻松理解JavaScript闭包

摘要 闭包机制是JavaScript的重点和难点,本文希望能帮助大家轻松的学习闭包 一.什么是闭包? 闭包就是可以访问另一个函数作用域中变量的函数. 下面列举出常见的闭包实现方式,以例子讲解闭包概念 ...

多线程面试题系列(5):经典线程同步 关键段CS

上一篇提出了一个经典的多线程同步互斥问题,本篇将用关键段CRITICAL_SECTION来尝试解决这个问题.本文首先介绍下如何使用关键段,然后再深层次的分析下关键段的实现机制与原理.关键段CRITIC ...

innerHTML、outerHTML、innerText、outerText的区别及兼容性问题

今天看了很多文章关于innerHTML.outerHTML.innerText.outerText的区别,都是很模糊的一个介绍,所以自己总结下这些区别以及一些重点内容.很多文章在描述这些区别的时候,都 ...

PyQt 5事件和信号

信号槽Signals & slots sld.valueChanged.connect(lcd.display) # 将滚动条的valueChanged信号连接到lcd的display插槽 # ...

为什么c语言加法错误,分数的加减法——C语言初学者代码中的常见错误与瑕疵(12)...相关推荐

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

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

  2. c语言一个数中是否含有8,要心中有“数”——C语言初学者代码中的常见错误与瑕疵(8)...

    在 飞鸟_Asuka网友指出"是不是时间复杂度比较大",并说他"第一眼看到我就想把它当成一个数学问题来做"之后,我又重新对问题进行了数学式的思考后发现的. 这个 ...

  3. c语言间接级别不同_一个超复杂的间接递归——C语言初学者代码中的常见错误与瑕疵(6)...

    问题: 在该文的最后,曾提到完成的代码还有进一步改进的余地.本文完成了这个改进.所以本文讨论的并不是初学者代码中的常见错误与瑕疵,而是对我自己代码的改进和优化.标题只是为了保持系列的连续性. 改进 程 ...

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

    问题: 另一种阶乘 大家都知道阶乘这个概念,举个简单的例子:5!=1*2*3*4*5. 现在我们引入一种新的阶乘概念,将原来的每个数相乘变为i不大于n的所有奇数相乘 例如:5!!=1*3*5.现在明白 ...

  5. 中虚数怎么表示_英文论文写作中的常见错误

    之前写过一篇如何写中文论文,这次就写个英文论文写作中的常见错误吧.都是平时自己整理总结的,也是一路摸爬滚打的见证吧.如有错误,欢迎批评指正.未完待续...... 1.逗号粘连: 两个独立的句子间要用句 ...

  6. SQL Server连接中的常见错误

    SQL Server连接中的常见错误: 一."SQL Server 不存在或访问被拒绝" 这个是最复杂的,错误发生的原因比较多,需要检查的方面也比较多. 一般说来,有以下几种可能性 ...

  7. WCF项目中出现常见错误的解决方法:基础连接已经关闭: 连接被意外关闭

    原文:WCF项目中出现常见错误的解决方法:基础连接已经关闭: 连接被意外关闭 在我们开发WCF项目的时候,常常会碰到一些莫名其妙的错误,有时候如果根据它的错误提示信息,一般很难定位到具体的问题所在,而 ...

  8. qt html 库段错误,连接Qwt库时Qt代码中的分段错误

    我试图用一些Qwt小部件创建一个Qt  应用程序,但是当我尝试链接Qwt库时,我发现Qt代码中存在分段错误.我使用的是非常简单的Qt程序,只弹出一个空白窗口:连接Qwt库时Qt代码中的分段错误 #in ...

  9. Android稳定性系列-01-使用 Address Sanitizer检测原生代码中的内存错误

    前言 想必大家曾经被各种Native Crash折磨过,本地测试没啥问题,一到线上或者自动化测试就出现各种SIGSEGV.SIGABRT.SIGILL.SIGBUS.SIGFPE异常,而且堆栈还是崩溃 ...

最新文章

  1. Luence简单实现1
  2. 以太坊区块链_以太坊区块链搭建与使用(一)-私有链
  3. LightOJ - 1098 A New Function
  4. hihoCoder #1954 : 压缩树(虚树)
  5. 【机器学习基础】理解关联规则算法
  6. MySQL5.7多源复制的实验
  7. python项目描述怎么写_个人项目(python)
  8. 计算机安装软件没有管理员权限设置,实用技巧:如何在win10中安装没有管理员权限的软件...
  9. QCC3024/QCC3020/QCC3034 对讲机(Intercom) 蓝牙耳机 替代CSR8670
  10. 前端开发常见的英语单词汇总
  11. unity shader 流光(1)
  12. python 日程管理程序_729. 我的日程安排表(Python)
  13. 如何挑选合适的卫星影像
  14. [数据集][VOC]老鼠数据集voc格式3001张
  15. 利用Vue制作一个商品管理页面(第二部分,小完结)
  16. 开奶茶店,哪里学奶茶的制作配方?
  17. java实现三角螺旋阵
  18. Java课堂笔记第九次428
  19. Android开源项目 个性化控件(View)
  20. 大家说说房价还会不会涨?

热门文章

  1. 淘宝中的UV,PV,IPV
  2. 克罗内克积 (Kronecker product) 在线性矩阵不等式 (LMI) 中怎么描述
  3. 小盒子可以在大盒子里面移动
  4. 传统企业如何做数字化转型?弄懂这3大底层逻辑你就懂了
  5. 我的一点企业上云经验
  6. 你的生存模式正确吗?
  7. 小程序onShareTimeline()分享朋友圈 --仅限Android
  8. 夏普Sharp AR-M207 一体机驱动
  9. css寸照的自适应比例设置
  10. FFmpeg[15] - 从官网下载FFmpeg时的坑,你有遇到吗?