루프에서 0을 반환하는 PHP 함수 [중복]

Aug 18 2020

정수에서 특정 숫자의 수를 계산하는 간단한 PHP 함수가 있습니다.

function countOccurrence($number, $digit){
    $result = 0; while ($number > 0){
        $lastDigit = $number % 10;
        if($lastDigit === $digit){
            $result++; } $number = ($number - $lastDigit)/10;
    }
    return $result;
}

완전히 잘 작동합니다. [countOccurrence (1111, 1)로 테스트하고 4를 반환했습니다.]

그러나 숫자 범위에 대한 루프에서 사용하면 항상 0을 반환합니다.

if (isset($_POST['submit'])){
    $startNum = $_POST['startNum'];
    $endNum = $_POST['endNum'];
    $findNum = $_POST['findNum'];
    $occur = 0; echo 'from ' . $startNum . ' to ' . $endNum . ' find how many times ' . $findNum . ' occurs';
    echo '<br>';

    $numRange = makeArray($startNum, $endNum); foreach ($numRange as $number){ $test = countOccurrence($number, $findNum);
        echo 'number: ' . $number . ' find: ' . $findNum . ' countOccurrence('.$number.', '.$findNum.'): ' . $test . '<br>'; } echo '<br>'; echo '<p>The digit ' . $findNum . ' occurred ' . $occur . ' times within the range</p>'; echo '<br>'; echo 'countOccurrence(1111, 1) = '; $test = countOccurrence(1111, 1);
    echo $test;
}

내가 얻은 결과는 "number : 1 find : 1 countOccurrence (1, 1) : 0"등입니다.

내가 수동으로 기능을 테스트 할 때 괜찮아 보이므로 여기서 어디에서 잘못되는지 잘 모르겠습니다.

편집 : 여기에 내 완전한 코드가 있습니다.

<html lang="en">
    <head>
        <title>Number Counter</title>
        <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
    </head>
    <body>
        <div class="container">
            <form id="form" class="form-group" action="" method="post">
                <div class="form-group">
                    <label for="startId">Start Num</label>
                    <input type="number" name="startNum" id="startId" class="form-control">
                </div>

                <div class="form-group">
                    <label for="endId">End Num</label>
                    <input type="number" name="endNum" id="endId" class="form-control">
                </div>

                <div class="form-group">
                    <label for="findId">Find Num</label>
                    <input type="number" name="findNum" id="findId" class="form-control">
                </div>

                <input type="submit" name="submit">
            </form>
        </div>
    <script src="bootstrap/js/jquery-3.5.1.min.js"></script>
    <script src="bootstrap/js/jquery.validate.min.js"></script>
    <script src="bootstrap/js/bootstrap.min.js"></script>
    <script src="validate.js"></script>
    </body>
</html>

<?php

function countOccurrence($number, $digit){ $result = 0;
    while ($number > 0){ $lastDigit = $number % 10; if($lastDigit === $digit){ $result++;
        }
        $number = ($number - $lastDigit)/10; } return $result;
}

function makeArray($startNum, $endNum){
    $numRange = array(); for($ctr = $startNum; $startNum <= $endNum; $startNum++){
        array_push($numRange, $startNum);
    }
    return $numRange; } if (isset($_POST['submit'])){
    $startNum = $_POST['startNum'];
    $endNum = $_POST['endNum'];
    $findNum = $_POST['findNum'];
    $occur = 0; echo 'from ' . $startNum . ' to ' . $endNum . ' find how many times ' . $findNum . ' occurs';
    echo '<br>';

    $numRange = makeArray($startNum, $endNum); foreach ($numRange as $number){ $test = countOccurrence($number, $findNum);
        echo 'number: ' . $number . ' find: ' . $findNum . ' countOccurrence('.$number.', '.$findNum.'): ' . $test . '<br>'; } echo '<br>'; echo '<p>The digit ' . $findNum . ' occurred ' . $occur . ' times within the range</p>'; echo '<br>'; echo 'countOccurrence(1111, 1) = '; $test = countOccurrence(1111, 1);
    echo $test;
}


편집 : 답변 주셔서 감사합니다! 예상 값을 얻기 위해 대신 $ _POST 값을 int로 구문 분석했습니다.

    $startNum = (int) $_POST['startNum'];
    $endNum = (int) $_POST['endNum'];
    $findNum = (int) $_POST['findNum'];

답변

SirPilan Aug 18 2020 at 10:04
function countOccurrence($number, $digit){
    $result = 0; while ($number > 0){
        $lastDigit = $number % 10;
        if($lastDigit === $digit){ // <-- bug is here
            $result++; } $number = ($number - $lastDigit)/10;
    }
    return $result;
}

엄격한 비교를 수행하기 때문에 이러한 값은 결코 같지 않습니다. 그 이유는 다음과 같습니다.

$ _POST에서 데이터를 가져 오면 항상 문자열입니다. 그래서 당신은 countOccurrence(1111, '1')0을 반환 할 전화 를하고 있습니다 :)

주석에서 언급했듯이 함수를 다음으로 바꿀 수 있습니다.

  • substr_count 대신에 countOccurrence
  • range 대신에 makeArray

당신이 당신의 기능을 고수하고 싶다면. intval 을 사용하여 함수에 전달하기 전에 입력을 int로 변환하십시오 .

추가 정보

미래에 이런 일이 발생하지 않도록합니다. 이 게시물을보십시오 . 이 유형의 시나리오 에 도입 된 비교적 새로운 PHP 기능입니다 .

TimBrownlaw Aug 18 2020 at 10:10

이것은 당신의 작은 벌레 곰이있는 곳입니다 ...

if($lastDigit === $digit){

여기서 기대하는 것은 값과 유형 (===) 별 비교 입니다.

gettype ();을 사용하여이를 확인할 수 있습니다.

while ($number > 0) { $lastDigit = $number % 10; echo '$lastDigit is a '.gettype($lastDigit); echo ' $digit is a '.gettype($digit); echo '<br>'; if ($lastDigit === $digit) { $result++;
    }
    $number = ($number - $lastDigit) / 10;
}

POST의 값은 항상 문자열 유형입니다. 따라서 $ digit는 문자열이고 $ lastDigit은 숫자 (정수)입니다. === 사용은 동일한 유형이 아니므로 실패합니다.

따라서 PHP는 자체적으로 typecast하는 기능이 있으므로 ===를 ==로 변경하면 작동합니다. IE

if ($lastDigit == $digit) {

PHP는 RHS 값을 LHS 유형으로 변환 한 다음 비교를 수행합니다.

이제 비교를 수행하고 PHP는 $ digit를 정수로 변환합니다.

더 안전한 방법은 캐스팅을 강제하는 것입니다. 따라서 $ digit를 문자열에서 정수로 캐스트하고 기존 코드를 사용할 수 있습니다.

function countOccurrence($number, $digit) { $result = 0;

    $digit = intval($digit); // Force $digit to be an integer while ($number > 0) {
        $lastDigit = $number % 10;
        echo '$lastDigit is a '.gettype($lastDigit);
        echo ' $digit is a '.gettype($digit);
        echo '<br>';
        if ($lastDigit === $digit) {
            $result++; } $number = ($number - $lastDigit) / 10;

        echo ' $number is a '.gettype($number);
    }

    return $result;
}

따라서 여기서 얻은 교훈은 ===를 사용할 때 유형도 동일한 지 확인하십시오.