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

浏览:
字体:
发布时间:2013-12-15 22:18:46
来源:
矩形的个数
 
  在一个3*2的矩形中,可以找到6个1*1的矩形,4个2*1的矩形3个1*2的矩形,2个2*2的矩形,2个3*1的矩形和1个3*2的矩形,总共18个矩形。给出A,B,计算可以从中找到多少个矩形
 
 
输入:
  本题有多组输入数据(<10000),你必须处理到EOF为止
 
  输入2个整数A,B(1<=A,B<=1000)
 
 
输出:
 
  输出找到的矩形数。
 
 
样例:
 
输入:
 
1 2 
3 2
 
 
输出: 
18
 
 原代码-1:
复制代码
#include <stdio.h>
int rectangle(int x,int y)
{
    int i,j,sum,temp;
 
    for(i=1,sum=0,temp=0;i<=x;i++)
    {
        for(j=1;j<=y;j++)
        {
            temp = (x-i+1)*(y-j+1);
            sum += temp;
        }
    }
 
    return sum;
}
 
int main()
{
    long int A[1000],B[1000],i;
    int rectangle(int x,int y);
    //printf("input A&B and end with 0/n");
 
    for(i=0;i<1000;i++)
    {
        scanf("%d",&A[i]);
        
        if (A[i]==0)
        {
            break;
        }
 
        scanf("%d",&B[i]);
    }
 
    for(i=0;A[i]!=0;i++)
    {
        printf("%d/n",rectangle(A[i],B[i]));
    }
 
    return 0;
}
复制代码
 评析:
   写完之后这位小朋友坦率地承认:
 
露珠不知道如何以EOF结尾..只好用0了...哪位指点下..
 
   我告诉他,
 
没必要用数组 
while( scanf("%d%d", &A,&B)!=EOF ) 
     //计算输出矩形个数 
}
  于是他很快给出了新代码:
 
 原代码-2:
复制代码
#include <stdio.h>
int rectangle(int x,int y)
{
    int i,j,sum,temp;
 
    for(i=1,sum=0,temp=0;i<=x;i++)
    {
        for(j=1;j<=y;j++)
        {
            temp = (x-i+1)*(y-j+1);
            sum += temp;
        }
    }
 
    return sum;
}
 
int main()
{
    long int A,B;
    int rectangle(int x,int y);
    printf("input A&B and end with EOF/n");
 
    while(scanf("%d%d",&A,&B)!= EOF)
    {
        printf("%d/n",rectangle(A,B));
    }
 
    return 0;
}
复制代码
评析:
  这次好多了。不过他又有了新的困惑:
 
我修改成这样之后,比如我先输入 2 3 跳出来 18,输入eof 就一直跳 18 停止不了了... 
总之就是一直跳最后一次出来的结果 ..
  看来他不清楚EOF是怎么回事,还以为是在键盘上键入eof三个字符呢。
 
  我告诉他:
 
EOF不是三个字符 
而是一个符号常量 
如果你用的是WIN系统 
在行首输入Control-Z试试
 
  实际上EOF是在stdio.h中定义的一个宏,通常是这样的 
 
#define    EOF    (-1)
  不过C语言并没说EOF一定为-1。
 
  在键盘上是没有这个EOF的,但在输入流中遇到特殊的字符,scanf()函数的返回值可以是EOF。那么,这句话究竟是什么意思呢?
 
  通常scanf()的返回值是一个非负整数。比如
 
int i;
scanf("%d", &i ) ;
  如果你在键盘上键入的是123(1、2、3与%d相匹配),scanf("%d", &i )的值就为1,因为为1个变量赋了值;如果你在键盘上键的是abc(a与%d不匹配),scanf("%d", &i )的值就为0,因为scanf无法把"a"视为十进制整数(%d),也无法对它进行转换,更无法为变量 i 赋值,也就是说scanf这种情况下没有为任何变量赋值,所以返回值为0。如果scanf()在输入流中遇到的是某个特殊的字符(具体是哪个字符与环境有关),则返回值为EOF。
 
  另外我告诉他:
 
把函数类型声明 
int rectangle(int x,int y); 
写在main()函数之内很傻
(应该把函数类型声明)写在函数外面
 
另外那个temp多余
 
temp赋值为零就更多余
 
(因为可以直接)
 
sum += (x-i+1)*(y-j+1);    
 
  就这样,他再次进行了修改:
 
原代码-3
复制代码
#include <stdio.h>
int rectangle(int x,int y)
{
    int i,j,sum,temp;
 
    for(i=1,sum=0;i<=x;i++)
    {
        for(j=1;j<=y;j++)
        {
            sum += (x-i+1)*(y-j+1);;
        }
    }
 
    return sum;
}
 
int rectangle(int x,int y);
int main()
{
    long int A,B;
    printf("input A&B and end with EOF/n");
 
    while(scanf("%d%d",&A,&B)!= EOF)
    {
        printf("%d/n",rectangle(A,B));
    }
 
    return 0;
}
复制代码
 评析:
   现在毛病少多了,不过还是有一些。
 
  首先, rectangle()函数定义的位置不妥,写在main()定义的后面为好。
 
  其次,数据类型有问题,这个问题比较严重。 
 
    long int A,B;
  这里绝对没有必要把A、B定义为long类型,int类型足矣。由于不当地把A、B定义成了long类型,所以代码中的
 
scanf("%d%d",&A,&B)
 
rectangle(A,B)
这两次调用都是错的。虽然没有产生错误的结果(估计在那个系统中long和int类型大小一样),但其实是瞎猫碰到死耗子,侥幸而已。
 
  此外的两处小瑕疵就是rectangle()函数定义中的temp变量忘记删除了,循环体内删除语句时不干净,有一“;”也忘记删除了。
 
  再有就是 
 
sum += (x-i+1)*(y-j+1);
   这个算法我没看懂,不知道是否正确。
 
重构:
  其实原来代码已经改得差不多了,只剩下少许小错和瑕疵。我在这里只说一下我的算法:
 
  我的算法是,穷举出两个点(P1,P2)的所有组合情况,只要P1可以是某个矩形的左上角,P2可以是某个矩形的右下角(P1_X<P2_X,P1_Y<P2_Y),则构成了一个矩形。
 
复制代码
 1 /*
 2 矩形的个数 
 3 在一个3*2的矩形中,可以找到6个1*1的矩形,4个2*1的矩形3个1*2的矩形,
 4 2个2*2的矩形,2个3*1的矩形和1个3*2的矩形,总共18个矩形。 
 5 给出A,B,计算可以从中找到多少个矩形。 
 6 
 7 输入: 
 8 本题有多组输入数据(<10000),你必须处理到EOF为止 
 9 输入2个整数A,B(1<=A,B<=1000) 
10 
11 输出: 
12 输出找到的矩形数。 
13 
14 样例:
15 
16 输入: 
17 1 2 
18 3 2 
19 
20 输出: 
21 3 
22 18
23 
24 作者:薛非
25 出处:http://www.cnblogs.com/pmer/   “C语言初学者代码中的常见错误与瑕疵”系列博文 
26 
27 */
28 
29 #include <stdio.h>
30 
31 int count( int , int ); 
32 
33 int main( void )
34 {
35   int A , B ;
36   
37   while ( printf( "输入2个整数A,B(1<=A,B<=1000)" ),
38           scanf( "%d%d" , &A , &B )!= EOF    
39         )
40   {
41      printf( "%d/n" , count( A , B ) );
42   }
43   
44   return 0;
45 }
46 
47 int count( int A , int B )
48 {
49    int x1 , y1 ;//第一个点的坐标 
50    int x2 , y2 ;//第二个点的坐标
51    int num = 0 ;
52    
53    for ( x1 = 0 ; x1 <= B ; x1 ++ )
54       for ( y1 = 0 ; y1 <= A ; y1 ++ )//穷举第一个点的各种可能 
55          for ( x2 = 0 ; x2 <= B ; x2 ++ )
56             for ( y2 = 0 ; y2 <= A ; y2 ++ )//穷举第二个点的各种可能 
57             {
58                if ( x1 < x2 && y1 < y2 )
59                   num ++ ;
60             }
61 
62    return num ;
63 }
>更多相关文章
24小时热门资讯
24小时回复排行
资讯 | QQ | 安全 | 编程 | 数据库 | 系统 | 网络 | 考试 | 站长 | 关于东联 | 安全雇佣 | 搞笑视频大全 | 微信学院 | 视频课程 |
关于我们 | 联系我们 | 广告服务 | 免责申明 | 作品发布 | 网站地图 | 官方微博 | 技术培训
Copyright © 2007 - 2024 Vm888.Com. All Rights Reserved
粤公网安备 44060402001498号 粤ICP备19097316号 请遵循相关法律法规
');})();