博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C语言初学者代码中的常见错误与瑕疵(4)
阅读量:6757 次
发布时间:2019-06-26

本文共 3597 字,大约阅读时间需要 11 分钟。

问题


小学生数学

很多小学生在学习加法时,发现“进位”特别容易出错。你的任务是计算两个数在相加时需要多少次进位。你编制的程序应当可以连续处理多组数据,直到读到两个0(这是输入结束标记)。

样例:

输入

123 456
555 555
123 594
0 0

输出:

0
3
1

原代码:


1 #include 
2 #include
3 int Take_number(int x,int y) //定义函数取整数X的第Y位 4 { 5 int temp; 6 if(x==0) 7 { 8 printf("wrong number\n"); 9 return 0;10 }11 12 temp=(int)pow(10,y-1);13 temp=x/temp;14 return temp%10;15 }16 17 int count(int x) //定义函数取位数18 {19 int i,carry,count;20 for(i=0,count=1;;i++)21 {22 carry=(int)pow(10,i);23 if(x/carry==0)24 break;25 else count++;26 }27 return count;28 }29 30 int main()31 {32 int a[100],temp,i,j,carry[10];33 int Take_number(int x,int y);34 int count(int x);35 printf("plese input the number and end with 0 0\n");36 37 for(i=1;;i+=2) //输入相应数值38 { 39 scanf("%d%d",&a[i-1],&a[i]);40 if(a[i-1]==0 && a[i]==0)41 break;42 }43 44 for(i=1;a[i-1]!=0;i+=2)45 {46 for(j=1,temp=0;j<=(a[i-1]>a[i]?count(a[i-1]):count(a[i]));j++)47 { 48 carry[j]=0;49 if(carry[j-1]) //若前一位有进位,该位相加为9也有进位50 if(Take_number(a[i-1],j)+Take_number(a[i],j)>=9)51 carry[j]=1;52 else53 carry[j]=0;54 else 55 if(Take_number(a[i-1],j)+Take_number(a[i],j)>=10) //若前一位无进位,相加为10才有进位56 carry[j]=1;57 else ;58 if(carry[j])59 temp=temp+1;60 else ;61 }62 printf("%d\n",temp);63 }64 65 return 0;66 }

评析:


  题目比较有趣,但代码乏善可陈。

int a[100],temp,i,j,carry[10];

   还是变量定义太多,并不必要地使用了数组这种复杂的数据结构,表明作者缺乏大局观,对代码的整体设计错误。其实这里只需要两个变量就足够了,就是存储要做加法的那两个数。题目在这里也有欠严密,没提这两个数应该是正整数。如果是允许输入负整数或者输入小数,那就完全是另一道题了。

  用int [100]这种类型存储输入数据显然是错误的,因为这最多可以存储50对数据,再多就出错了。所以

printf("plese input the number and end with 0 0\n"); for(i=1;;i+=2)   //输入相应数值 {   scanf("%d%d",&a[i-1],&a[i]);  if(a[i-1]==0 && a[i]==0)   break; }

显然是错误的。只能采用输入一组数据就处理一组数据的方案。例如象下面这样写:

int addend1,addend2;while (scanf("%d%d",&addend1,&addend2),addend1!=0 || addend2!=0 ){   //处理addend1,addend2}

 

int Take_number(int x,int y); int count(int x);

   这个有些莫名其妙。把函数定义写在了前面,却又在main()中又写了函数类型声明,画蛇添足。应该把函数类型声明写在main()之外、之前,把函数定义放在main()后面。

for(i=1;a[i-1]!=0;i+=2) {  for(j=1,temp=0;j<=(a[i-1]>a[i]?count(a[i-1]):count(a[i]));j++)  {    carry[j]=0;   if(carry[j-1])  //若前一位有进位,该位相加为9也有进位    if(Take_number(a[i-1],j)+Take_number(a[i],j)>=9)     carry[j]=1;    else     carry[j]=0;   else     if(Take_number(a[i-1],j)+Take_number(a[i],j)>=10)  //若前一位无进位,相加为10才有进位     carry[j]=1;    else ;   if(carry[j])    temp=temp+1;   else ;  }  printf("%d\n",temp); }

  这个从结构上来说就不合理,main()中的代码写得太多太细了。从代码逻辑上看有几个明显的错误,就是在内层循环中的

if(carry[j-1])

  注意循环变量j的初值为1,而carry是一个没有初始化的局部auto数组,因此当j为1时carry[j-1]即carry[0]是垃圾值,所以这个if选择没有意义。显而易见,后面所有代码都是错误的。所以就不进一步分析了。

重构:


1 /* 2 题目:小学生数学  3 很多小学生在学习加法时,发现“进位”特别容易出错。 4 你的任务是计算两个非负整数在相加时需要多少次进位。 5 你编制的程序应当可以连续处理多组数据,直到读到两个0(这是输入结束标记)。  6 样例:输入  7 123 456  8 555 555  9 123 594 10 0 0 11 输出: 12 0 13 3 14 1 15 16 作者:薛非17 出处: 18 */ 19 20 #include 
21 22 unsigned get_carry_times ( unsigned , unsigned );23 24 int main( void )25 {26 unsigned addend1,addend2 ;27 28 while ( puts("输入两个非负整数,0 0表示结束"),29 scanf("%u%u",&addend1,&addend2),30 addend1!=0u || addend2!=0u )31 {32 printf("%u\n", get_carry_times ( addend1 , addend2 ) );33 } 34 35 return 0;36 }37 38 unsigned get_carry_times ( unsigned a1 , unsigned a2 )39 {40 unsigned c_t = 0u ;//进位次数 41 unsigned c = 0u ;//进位 42 43 do44 {45 c += a1 % 10u + a2 % 10u ;46 47 if ( (c /= 10u) != 0u )48 c_t ++ ;49 50 a1 /= 10u ;51 a2 /= 10u ; 52 }53 while ( a1 + a2 != 0u );54 55 return c_t ;56 }

 

转载地址:http://nvweo.baihongyu.com/

你可能感兴趣的文章
Kafka笔记整理(三):消费形式验证与性能测试
查看>>
WINPE集成SCSI/RAID驱动
查看>>
我们为什么需要大数据?
查看>>
单例模式-singleton
查看>>
自动布局下的iPhone 6 plus等比例放大,且UITextfield失败关于placeholder的原因
查看>>
利用div实现邮件收件人的输入框
查看>>
我的友情链接
查看>>
单页布局
查看>>
我的友情链接
查看>>
综合布线详细方案设计
查看>>
rhel6.3下安装GCC4.8.1
查看>>
大图片生成缩略图 导致imagecreatefromjpeg 内存崩溃问题
查看>>
我的友情链接
查看>>
手工恢复
查看>>
二 IOC再探
查看>>
一些常用软件的网络端口协议分类介绍
查看>>
机器学习服务器 PredictionIO 脱颖而出
查看>>
mysql不能连接远程mysql服务器
查看>>
Windows 8.1 重复数据删除——概念(一)
查看>>
iptables防火墙高级应用
查看>>