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

  这位小朋友犯过的很多错误都非常典型,在初学者中非常普遍,于是整理了一下,应该对其他初学者有借鉴意义。

问题

开灯问题

  有n盏灯,编号为1~n,第1个人把所有灯打开,第2个人按下所有编号为2 的倍数的开关(这些灯将被关掉),第3 个人按下所有编号为3的倍数的开关(其中关掉的灯将被打开,开着的灯将被关闭),依此类推。一共有k个人,问最后有哪些灯开着?输入:n和k,输出开着的灯编号。k≤n≤1000

代码:

 #include <stdio.h>
#include <math.h> int main()
{
int a[],n,k,i,j; printf("请分别输入灯和人的数量\n");
scanf("%d%d",&n,&k); while() //检验是否超出
{
if(k>= && k<= && n>=k && n<=)
break;
else
{
printf("数值不符,请重新输入:\n");
scanf("%d%d",&n,&k);
}
} for(i=;i<=k;i++) //每操作一次第i*j个开关,a[i*j]加1
{
for(j=;i*j<=n;j++)
{
a[i*j]=a[i*j]+;
}
} for(i=;i<=n;i++) //若操作次数为偶数,表示该位置的灯亮着
{
if(a[i]%== && a[i]!=)
printf("%d\t",i);
} printf("\n");
return ;
}

测试:

“自己测了觉得没问题..在线系统结果是WrongAnswer ..未找出原因..”

评:

  最明显的错误就是第26行

a[i*j]=a[i*j]+;

由于前面定义a数组为局部auto类别,在不进行初始化的情况下,a中的数据是垃圾值。换句话说,a中的数据是无意义的。因此a[i*j]+1这个表达式没有意义。

  此外,第22行

  for(i=;i<=k;i++) //每操作一次第i*j个开关,a[i*j]加1

在逻辑上也是错误的,缺乏“第1个人把所有灯打开”的步骤。

  另外

   printf("请分别输入灯和人的数量\n");
scanf("%d%d",&n,&k); while() //检验是否超出
{
if(k>= && k<= && n>=k && n<=)
break;
else
{
printf("数值不符,请重新输入:\n");
scanf("%d%d",&n,&k);
}
}

  这段写得很丑,属于典型的谭浩强风格,C语言应该这样写:

printf("请分别输入灯和人的数量\n");
while(scanf("%d%d",&n,&k) ,( k < || n<k || n>) )
{
printf("数值不符,请重新输入:\n");
}

  代码中还有其他一些毛病,由于不是最主要的问题,这里就不再进一步指出了。

重构:

#include <stdio.h> 

#define MAXNUM 1000
#define ON 0
#define OFF 1 int main( void )
{
int light[MAXNUM] = { ON } ; //把所有灯打开
int n , k ;
int i ; printf( "请分别输入灯和人的数量\n" );
while ( scanf("%d%d", & n ,& k ) ,( k < || n < k || n > MAXNUM ) )
printf("数值不符,请重新输入:\n"); for ( i = - ; i < k ; i ++ ) //第2个人按下所有编号为2 的倍数的开关……
{
int j ;
for ( j = i ; j < n ; j += i + )
light[j] = ! light[j];
} for ( i = ; i < n ; i ++ )
if( light[i]==ON )
printf( "%d " , i + );
putchar('\n'); return ;
}

C语言初学者代码中的常见错误与瑕疵(1)的更多相关文章

  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语言初学者代码中的常见错误与瑕疵(12)

    前文链接:分数的加减法——C语言初学者代码中的常见错误与瑕疵(11) 重构 题目的修正 我抛弃了原题中“其中a, b, c, d是一个0-9的整数”这样的前提条件,因为这种限制毫无必要.只假设a, b ...

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

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

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

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

  9. 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,计算可以从中找到 ...

随机推荐

  1. [LeetCode]题解(python):063-Unique path II

    题目来源 https://leetcode.com/problems/unique-paths-ii/ Follow up for "Unique Paths": Now cons ...

  2. urlencode和rawurlencode的区别

    摘自http://blog.csdn.net/doggie1024/article/details/5698615 urlencode:返回字符串,此字符串中除了 -_. 之外的所有非字母数字字符都将 ...

  3. Windows 服务器使用FTP出现“当前的安全设置不允许从该位置下载文件" 警告

    为了安全,Windows服务器默认禁用了从网上下载文件的安全选项.此错误即是出现在这里,所以打开这个选项即可: 控制面板  —— Internet选项 ——安全 —— 找到“自定义级别” —— 找到“ ...

  4. NSDate如何获取一个月后的日期

    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; NSDateCo ...

  5. Ubuntu14.04安装和配置Tomcat8.0.12(转)

    Ubuntu14.04长的好看,所以一时间很感兴趣,研究各种软件的安装和开发环境的配置.今天先把安装的tomcat 8.0.12的教程分享给大家.如果你需要,请收藏!!!   工具/原料 系统环境:U ...

  6. 最近在研究电台类app,分享2个源码大家一起讨论

    好像去年有一阵,电台类的app特别火爆,喜马拉雅和蜻蜓FM互相还撕逼.听老罗,听好好说话,都得在电台app里,所以我想研究研究这些app.我没那么多资源,只好从app的开发架构方面去研究. 我看api ...

  7. 前端实战——前端效果accordition的实现

    一.bootstrap实现 1)水平折叠组件 使用panel和collaspe组件 <!doctype html> <html lang="zh-hans"> ...

  8. java中的、标识符、运算符以及数据类型之间的转换。

    ---恢复内容开始--- 数据类型之间的转换: 1:自动转换:就是不用说出要转换成什么类型,由java中的虚拟机自动将小数据类型转换成大数据类型,但大数据中的数据精度有可能被破坏. 2:强制转换:强制 ...

  9. c# 基本知识 ref 和 out

    一:首先两者都是引用传递,都是按地址传递的. 二: 区别 (1)ref 默认必须初始化,out 不需要显式初始化.例如: ; int num2; refMethod(ref num1); outMet ...

  10. JDK里的设计模式

    一.Creational patterns 创建模式 Abstract factory (recognizeable by creational methods returning the facto ...