694 - The Collatz Sequence---关于goto语句的一些反思(还有uva的Runtime Error问题的解决)

来源:互联网 发布:软件安装手册模板 编辑:程序博客网 时间:2024/06/05 20:39

听很多老师苦口婆心的说过goto语句存在的重大安全隐患以及它的使用可能带来的代码诡异难懂的问题,但是这道题目是个goto语句的典型,我才真正开始思考到底用什么来代替简单的goto语句确又不产生过多的代码冗余问题?一是C++本身与生俱来的没面向对象封装的方法,把每一个要goto的代码段封装成函数,面向对象来调用,既简便又易懂。二是像本题这种,跳转后依然顺序执行的,这就要改变代码的组织方式了。

题目意思很简单:

任意正整数A,作为第一位输入,顺序执行:

                                                  biaoqian1: if(A是1)  stop   

                                                  biaoqian2:  if(A为偶数)   A=A/2   goto  biaoqian1

                                                  biaoqian3:  if(A为奇数)   A=A*3+1 goto biaoqian1

#include<stdio.h>
#include<iostream>
using namespace std;

bool isEven(int value) //判定偶数
{
  if(value%2==0)
     return true;
  else return false;
}

int main()
{
  long A,value,limit;
  int count,num=0;
  while(scanf("%d%d",&value,&limit)==2&&(value!=-1)&&(limit!=-1))
  {
    num++;
    count=1;
    A=value;
    isOne: if(value==1) goto end;
    if(isEven(value))
    {
      value=value/2;
      count++;
      goto isOne;
    }
    if(!isEven(value))
    {
      value=3*value+1;
      if(value<=limit)
      {
    count++;
    goto isOne;
      }
      else goto end;
    }
    end: printf("Case %d: A = %d, limit = %d, number of terms = %d\n",num,A,limit,count);
  }
  return 1;
}


程序没错误,但是判定Time limit exceeded, 显然是goto拖长了程序的运行时间。


改进后的代码,这下变成了Runtime Error:

#include<stdio.h>


bool isEven(long long value) //判定偶数
{
  if(value%2==0)
     return true;
  else return false;
}

int main()
{
  int limit,A;
  long long value;
  int count,num=0;
  while(scanf("%lld%d",&value,&limit)==2&&(value>0)&&(limit>0))
  {
    num++;
    count=1;
    A=value;
    while(value!=1)
    {
      if(isEven(value)) 
      {
value=value/2;
count++;
      }
      else if(!isEven(value)) 
      {
if(3*value>=limit) break;
else{
     value=3*value+1;
     count++;
   }
      }
    }
    printf("Case %d: A = %d, limit = %d, number of terms = %d\n",num,A,limit,count);
  }
  return 1;
}

神啊,你知道我这个Runtime Error的错误是怎么解决的吗???????????大哭竟然啊是最后的return的值必须是0!!!!妈呀,我就没见过这么变态的。我的return 1改成return 0,立马就AC了……我那个汗那……我那个去啊……

不过,关于int main() 的返回值是有说法的,以前一直以为return 0/1都无所谓,只是自己规定啥时侯是正常退出罢了,但是并不是这样的。main函数的返回值用于向编译器说明该程序的退出状态,如果返回0,则说明程序正常退出,返回其他值,代表程序异常退出,不同的值代表不同的异常状态。

gcc的标准中int main()的各种情况还是要注意一下,可不能用c中的void main了呢

详细解释见博文:http://blog.sina.com.cn/s/blog_6642cd0201016lqo.html

实际上网上说的改成long long类型或是long类型经过代码书写方式的改进之后完全没有必要。反而会浪费运行时间。。。

现自己的AC代码如下:

#include<stdio.h>

int main()
{
  int limit,A;
  int value;
  int count,num=0;
  while(scanf("%d%d",&value,&limit)==2&&(value>0)&&(limit>0))
  {
    num++;
    count=1;
    A=value;
    while(value!=1)
    {
      if(value%2==0) 
      {
value=value/2;
count++;
      }
      else if(value%2==1) 
      {
if(value>=limit/3) break;
else{
     value=3*value+1;
     count++;
   }
      }
    }
    printf("Case %d: A = %d, limit = %d, number of terms = %d\n",num,A,limit,count);
  }
  return 0;
}