C语言初学者代码中的常见错误与瑕疵(4)
问题
小学生数学
很多小学生在学习加法时,发现“进位”特别容易出错。你的任务是计算两个数在相加时需要多少次进位。你编制的程序应当可以连续处理多组数据,直到读到两个0(这是输入结束标记)。样例:
输入
123 456
555 555
123 594
0 0输出:
0
3
1
原代码:
#include <stdio.h>
#include <math.h>
int Take_number(int x,int y) //定义函数取整数X的第Y位
{
int temp;
if(x==)
{
printf("wrong number\n");
return ;
} temp=(int)pow(,y-);
temp=x/temp;
return temp%;
} int count(int x) //定义函数取位数
{
int i,carry,count;
for(i=,count=;;i++)
{
carry=(int)pow(,i);
if(x/carry==)
break;
else count++;
}
return count;
} int main()
{
int a[],temp,i,j,carry[];
int Take_number(int x,int y);
int count(int x);
printf("plese input the number and end with 0 0\n"); for(i=;;i+=) //输入相应数值
{
scanf("%d%d",&a[i-],&a[i]);
if(a[i-]== && a[i]==)
break;
} for(i=;a[i-]!=;i+=)
{
for(j=,temp=;j<=(a[i-]>a[i]?count(a[i-]):count(a[i]));j++)
{
carry[j]=;
if(carry[j-]) //若前一位有进位,该位相加为9也有进位
if(Take_number(a[i-],j)+Take_number(a[i],j)>=)
carry[j]=;
else
carry[j]=;
else
if(Take_number(a[i-],j)+Take_number(a[i],j)>=) //若前一位无进位,相加为10才有进位
carry[j]=;
else ;
if(carry[j])
temp=temp+;
else ;
}
printf("%d\n",temp);
} return ;
}
评析:
题目比较有趣,但代码乏善可陈。
int a[],temp,i,j,carry[];
还是变量定义太多,并不必要地使用了数组这种复杂的数据结构,表明作者缺乏大局观,对代码的整体设计错误。其实这里只需要两个变量就足够了,就是存储要做加法的那两个数。题目在这里也有欠严密,没提这两个数应该是正整数。如果是允许输入负整数或者输入小数,那就完全是另一道题了。
用int [100]这种类型存储输入数据显然是错误的,因为这最多可以存储50对数据,再多就出错了。所以
printf("plese input the number and end with 0 0\n");
for(i=;;i+=) //输入相应数值
{
scanf("%d%d",&a[i-],&a[i]);
if(a[i-]== && a[i]==)
break;
}
显然是错误的。只能采用输入一组数据就处理一组数据的方案。例如象下面这样写:
int addend1,addend2;
while (scanf("%d%d",&addend1,&addend2),addend1!= || addend2!= )
{
//处理addend1,addend2
}
int Take_number(int x,int y);
int count(int x);
这个有些莫名其妙。把函数定义写在了前面,却又在main()中又写了函数类型声明,画蛇添足。应该把函数类型声明写在main()之外、之前,把函数定义放在main()后面。
for(i=;a[i-]!=;i+=)
{
for(j=,temp=;j<=(a[i-]>a[i]?count(a[i-]):count(a[i]));j++)
{
carry[j]=;
if(carry[j-]) //若前一位有进位,该位相加为9也有进位
if(Take_number(a[i-],j)+Take_number(a[i],j)>=)
carry[j]=;
else
carry[j]=;
else
if(Take_number(a[i-],j)+Take_number(a[i],j)>=) //若前一位无进位,相加为10才有进位
carry[j]=;
else ;
if(carry[j])
temp=temp+;
else ;
}
printf("%d\n",temp);
}
这个从结构上来说就不合理,main()中的代码写得太多太细了。从代码逻辑上看有几个明显的错误,就是在内层循环中的
if(carry[j-])
注意循环变量j的初值为1,而carry是一个没有初始化的局部auto数组,因此当j为1时carry[j-1]即carry[0]是垃圾值,所以这个if选择没有意义。显而易见,后面所有代码都是错误的。所以就不进一步分析了。
重构:
/*
题目:小学生数学
很多小学生在学习加法时,发现“进位”特别容易出错。
你的任务是计算两个非负整数在相加时需要多少次进位。
你编制的程序应当可以连续处理多组数据,直到读到两个0(这是输入结束标记)。
样例:输入
123 456
555 555
123 594
0 0
输出:
0
3
1 作者:薛非
出处:http://www.cnblogs.com/pmer/p/3428526.html
*/ #include <stdio.h> unsigned get_carry_times ( unsigned , unsigned ); int main( void )
{
unsigned addend1,addend2 ; while ( puts("输入两个非负整数,0 0表示结束"),
scanf("%u%u",&addend1,&addend2),
addend1!=0u || addend2!=0u )
{
printf("%u\n", get_carry_times ( addend1 , addend2 ) );
} return ;
} unsigned get_carry_times ( unsigned a1 , unsigned a2 )
{
unsigned c_t = 0u ;//进位次数
unsigned c = 0u ;//进位 do
{
c += a1 % 10u + a2 % 10u ; if ( (c /= 10u) != 0u )
c_t ++ ; a1 /= 10u ;
a2 /= 10u ;
}
while ( a1 + a2 != 0u ); return c_t ;
}
C语言初学者代码中的常见错误与瑕疵(4)的更多相关文章
- C语言初学者代码中的常见错误与瑕疵(23)
见:C语言初学者代码中的常见错误与瑕疵(23)
- 一个超复杂的间接递归——C语言初学者代码中的常见错误与瑕疵(6)
问题: 问题出处见 C语言初学者代码中的常见错误与瑕疵(5) . 在该文的最后,曾提到完成的代码还有进一步改进的余地.本文完成了这个改进.所以本文讨论的并不是初学者代码中的常见错误与瑕疵,而是对我自己 ...
- C语言初学者代码中的常见错误与瑕疵(5)
问题: 素数 在世博园某信息通信馆中,游客可利用手机等终端参与互动小游戏,与虚拟人物Kr. Kong 进行猜数比赛. 当屏幕出现一个整数X时,若你能比Kr. Kong更快的发出最接近它的素数答案,你将 ...
- C语言初学者代码中的常见错误与瑕疵(19)
见:C语言初学者代码中的常见错误与瑕疵(19)
- C语言初学者代码中的常见错误与瑕疵(14)
见:C语言初学者代码中的常见错误与瑕疵(14) 相关链接:http://www.anycodex.com/blog/?p=87
- 分数的加减法——C语言初学者代码中的常见错误与瑕疵(12)
前文链接:分数的加减法——C语言初学者代码中的常见错误与瑕疵(11) 重构 题目的修正 我抛弃了原题中“其中a, b, c, d是一个0-9的整数”这样的前提条件,因为这种限制毫无必要.只假设a, b ...
- C语言初学者代码中的常见错误与瑕疵(9)
题目 字母的个数 现在给你一个由小写字母组成字符串,要你找出字符串中出现次数最多的字母,如果出现次数最多字母有多个那么输出最小的那个. 输入:第一行输入一个正整数T(0<T<25) 随后T ...
- 要心中有“数”——C语言初学者代码中的常见错误与瑕疵(8)
在 C语言初学者代码中的常见错误与瑕疵(7) 中,我给出的重构代码中存在BUG.这个BUG是在飞鸟_Asuka网友指出“是不是时间复杂度比较大”,并说他“第一眼看到我就想把它当成一个数学问题来做”之后 ...
- 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,计算可以从中找到 ...
- C语言初学者代码中的常见错误与瑕疵(1)
曾在豆瓣上看到过一个小朋友贴出他自己的代码(http://www.douban.com/group/topic/40293109/),当时随口指点了几句.难得这位小朋友虚心修正.从善如流,不断地改,又 ...
随机推荐
- 浏览器获取ip地址
/** * 获取浏览器的ip地址 * @param request * @return */ public static String getIP(HttpServletRequest request ...
- LightOj 1090 - Trailing Zeroes (II)---求末尾0的个数
题目链接:http://lightoj.com/volume_showproblem.php?problem=1090 题意:给你四个数 n, r, p, q 求C(n, r) * p^q的结果中末尾 ...
- JS全局函数parseInt和parseFloat
1.parsetInt parseInt(string ,radix)解析一个字符串,并返回一个十进制的整数:该方法是将字符串转成十进制整数 console.log(parseInt("01 ...
- Selenium2学习-011-WebUI自动化实战实例-009-JavaScript 在 Selenium 自动化中的应用实例之一(赋值)
通常在编写 Selenium 的 WebUI 自动化脚本时,有些元素不易定位元素,或有些元素为隐藏的(此时用 WebElement.getText() 获取其值的时候,返回的结果为空),对日常的 UI ...
- Selenium2学习-003-WebUI自动化实战实例-001-百度搜索
此文主要通过百度搜索功能,进行 Selenium2 的实战实例讲解,文中所附源代码于 2015-01-16 02:01 亲测通过,敬请亲们阅览.希望能对初学 Selenium2 UI 自动化测试编程的 ...
- Ioc-Autofac实现自动的注入
在开发过程中,最郁闷的莫过于当你新增一个Service时,你需要对该Service进行注册,有的是使用代码注入,有的是XML配置注入,不管是哪种类型的注入,经常会出现开发人员忘记注入的情况. 于是我试 ...
- 使用Aspose.Cell控件实现多个Excel文件的合并
之前有写过多篇关于使用Apose.Cell控件制作自定义模板报表和通用的导出Excel表格数据的操作,对这个控件的功能还是比较满意,而且也比较便利.忽然有一天,一个朋友说:你已经有生成基于自定义模板报 ...
- 通往成功的钥匙--Web前端开发技术
互联网是一个服务性行业,用户对网站良好的体验度,直接影响到网站的效果.无论你做了多少广告推广,没有用户体验度等于零.Web前端技术是为了解决用户体验度而诞生的.无论是百度.新浪.阿里巴巴等大型网站,还 ...
- each的详解
首先我还是先观察w3c讲解: 先写一段代码,如图: 定义:each() 方法规定为每个匹配元素规定运行的函数. 提示:返回 false 可用于及早停止循环.(我在代码中加了return false,发 ...
- 微信JS SDK Demo
微信JS-SDK 分享到朋友圈 分享给朋友 分享到QQ 拍照或从手机相册中选图 识别音频并返回识别结果 使用微信内置地图查看位置原文:http://www.cnblogs.com/txw1958/p/ ...