【问题标题】:PHP String-to-Integer ExceptionPHP 字符串到整数异常
【发布时间】:2016-07-28 18:49:48
【问题描述】:

我对 HackersRank 上的一个问题有疑问 - Day 16: Exceptions - String to Integer 。总之任务是

读取一个字符串,SS,并打印它的整数值;如果 SS 不能转换为整数,则打印 Bad StringBad String。

注意:您必须使用提交语言中内置的 String-to-Integer 和异常处理构造。 如果您尝试使用循环/条件语句,您将获得 00 分。

任务本身非常简单,我在 Python 上解决了它。我的问题是我没有看到用 PHP 做到这一点的方法 - 如果你试图将字符串转换为整数,PHP 中是否有函数抛出异常?

【问题讨论】:

  • 没有内置的,AFAIK。 Casting strings to integers 只会导致 int 值 0,如果字符串不能被解析为数值 - 它不会抛出异常。您可能必须自己实现,通过检查字符串内容是否为有效数字,如果不是,则自己抛出异常。
  • 哈哈哈。 HackerRank 希望开发人员完成的任务:使用 try-catch 块。 PHP 开发人员最终完成了什么:修复内部 PHP 函数。我确信 HackerRank 不是那个意思。

标签: php type-conversion


【解决方案1】:

这是另一个使用 try {..} catch 机制的 hacky 解决方案:

try {
    new ReflectionClass('ReflectionClass' . ((int)$SS . "" !== $SS));
    echo $SS;
} catch (Exception $e) {
    echo "Bad StringBad String";
}

它的工作原理是这样的:如果字符串 $SS 实际上没有解析为整数,代码将尝试查找 ReflectionClass1 类,该类最终会抛出一个 @ 987654324@.

解析工作只需将$SS 转换为int,然后返回字符串并将其与初始值进行比较。

【讨论】:

【解决方案2】:

仅适用于 php 7(HackersRank 使用它):

class Printer {
    public static function printInt(int $value) {
        echo $value;
    }
}

$handle = fopen ("php://stdin","r");
fscanf($handle,"%s",$S);
try {
    sscanf($S, "%d", $out);
    Printer::printInt($out);
} catch (TypeError $e) {
    echo "Bad String";
}

【讨论】:

  • 强制 PHP 使用内置类型检查。这很整洁。
  • 为我解决了。认为这是最好的解决方案
【解决方案3】:

一般来说,不会。 PHP 是weakly typed,因此您可以将整数更改为字符串,反之亦然,无需任何特殊工作。 (强调我的)

PHP 是一种动态的、松散类型的语言,它使用写时复制和引用计数。
澄清一下上述语句的确切含义:PHP 是一种高级语言,弱类型隐含了引擎偏好在执行类型时将变量转换或强制转换为所需类型

这里唯一的例外是在 PHP 7.0 中引入的strict type hints。因此,尝试将它们与严格的类型提示互换使用会引发错误

<?php
declare(strict_types=1);
$var = 1; //integer

function foo(string $data) :string {
    echo $data;
}
foo($var);

生产 (demo)

致命错误:未捕获的 TypeError:传递给 foo() 的参数 1 必须是字符串类型,给定整数,在第 8 行的 /in/Be68h 中调用并在 /in/Be68h:5 中定义

【讨论】:

    【解决方案4】:

    hackerrank 问题表明您不能使用循环或条件,如果它不是整数则必须抛出异常。 我尝试了以下代码并且它有效:

    <?php
    $handle = fopen ("php://stdin","r");
    fscanf($handle,"%s",$S);
    
    set_error_handler("BadString");
    function BadString($errno, $errstr, $errfile, $errline)
    {
        throw new BadStringException('Bad String');
    }
    
    
    class BadStringException extends Exception { }    
    
    class Numeric extends BadStringException
    {
        private $number;
        public function __construct($input)
        {
            $this->number = intval($input);
        }
    
        public function Display()
        {
            echo ($this->number / $this->number) + ($this->number - 1);
        }
    }
    
    try {
        (new Numeric($S))->Display();
    } catch (BadStringException $E) {
        echo $E->getMessage();
    }
    

    【讨论】:

      【解决方案5】:

      免责声明

      @Machavity 在下面的回答中提供了更多关于 PHP 类型的有用信息。我在这里以一种 hacky 的方式解决了一个奇怪的问题,为了记录,我永远不会把它放在我正在编写的软件中。

      解决方案

      function badString($errno, $errstr, $errfile, $errline) {
        print "Bad String\n";
      }
      
      set_error_handler('badString');
      
      function parseString($string) {
        $temp = 1 / ($string + ($string === "0"));
      }
      

      方法

      1. 如果字符串错误,则生成除以零警告
      2. 在警告中,打印错误字符串

      1。生成警告

      如果不能将其转换为整数,则$string 在用作整数时为0(参见@CBroe 的评论)。

      如果它以字符串“0”开头,那么强相等运算符 === 将为 $string === "0".... 返回 true,其值为 1。

      因此,如果输入不是数字,则$string 为零,$string === "0" 为零,则 1/0 生成警告。

       input | $string  | $string === "0"    |   ($string + ($string === "0"))
      +=======================================================================+
       foo   |     0    |         0          |               0
       0     |     0    |         1          |               1
       1     |     1    |         0          |               1
       45    |     45   |         0          |               45
      

      2。警告时,打印

      借自https://stackoverflow.com/a/3071119/3012550

      【讨论】:

        【解决方案6】:

        这是使用委托的答案,不使用三元条件。

        $funcArr = [true=>"intval", false=>function ($s) {return "Bad String";}];
        $func = $funcArr[ctype_digit($S)];
        echo $func($S);
        

        【讨论】:

          【解决方案7】:

          另一个使用 PHP TypeError 异常处理的 PHP 7 解决方案:

          function check(int $val) { echo $val; } 
          try {
              check($SS);
          } catch (TypeError $ex) {
              echo 'Bad String';
          }
          

          【讨论】:

            【解决方案8】:

            这可行,但感觉不对:

            <?php
            $handle = fopen("php://stdin", "r");
            fscanf($handle, "%s", $SS);
            
            $i = (int) is_numeric($SS);
            $N = 'a' . $i;
            
            $str = "goto $N;
                a0:
                return new Exception('Bad StringBad String');
            
                a1:
                return new Exception($SS);
               ";
            try {
                throw eval($str);
            } catch (Exception $e) {
                echo $e->getMessage();
            }
            

            【讨论】:

              【解决方案9】:

              我刚刚在 HackerRank 上遇到了这个问题,被那里的 cmets 引导到这里。我坚持了很长一段时间,因为他们的提交测试员非常挑剔和愚蠢。他们检查您的代码中是否没有字符串if,并且您没有使用三元运算符。但是,这些检查不跨越行,因此如果您拆分它,您可以使用三元。它们实际上也不会检查异常的使用,因此您可以完全跳过该部分。

              虽然此解决方案没有明确遵循规定的规则,但它确实通过了所有测试。而且因为我也是代码打高尔夫球的粉丝,所以它应该是最短的可行解决方案。 :)

              <?=is_numeric($i=fgets(STDIN))?$i
              :'Bad String';
              

              【讨论】:

                【解决方案10】:

                我的解决方法是使用intdiv 生成不带条件语句的异常:

                try {
                    // Convoluted way to throw an integer conversion exception.
                    $i1 = intdiv( 1, intval($S . "1") );
                    $converted = (int)$S;
                    echo "$converted\n";
                } catch( DivisionByZeroError $exception ) {
                    echo "Bad String\n";
                }
                

                【讨论】:

                  【解决方案11】:

                  更优雅,但仍然很棘手 %)

                  <?php
                  set_error_handler(function () {
                      throw new Exception('Ach!');
                  });
                  
                  $handle = fopen ("php://stdin","r");
                  fscanf($handle,"%s",$S);
                  
                  
                  try {
                      $S/(int)$S;
                      print $S;
                  }
                  catch(Exception $e) {
                      print "Bad String";
                  }
                  
                  ?>
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2020-11-04
                    • 2015-08-01
                    • 1970-01-01
                    • 2018-12-20
                    • 1970-01-01
                    相关资源
                    最近更新 更多