ฟังก์ชัน PHP คืนค่า 0 หากอยู่ในลูป [ซ้ำ]
ฉันมีฟังก์ชัน 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'];
คำตอบ
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
ในกรณีที่คุณต้องการยึดติดกับฟังก์ชันของคุณ แปลงข้อมูลของคุณเพื่อเป็น int ก่อนที่จะผ่านไปยังฟังก์ชั่นของคุณด้วยintval
ข้อมูลเพิ่มเติม
เพื่อป้องกันไม่ให้สิ่งนี้เกิดขึ้นในอนาคต. ลองดูที่โพสต์นี้ คุณลักษณะที่ค่อนข้างใหม่ของ PHP, ซึ่งเป็นที่รู้จักสำหรับการนี้ประเภทของสถานการณ์
นี่คือจุดที่บักแบร์ตัวน้อยของคุณอยู่ ...
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 เป็นประเภท String เสมอ ดังนั้นเนื่องจาก $ digit เป็นสตริงและ $ lastDigit คือตัวเลข (จำนวนเต็ม) การใช้ === จะล้มเหลวเนื่องจากไม่ใช่ประเภทเดียวกัน
ดังนั้นเนื่องจาก PHP มีความสามารถในการพิมพ์คาสต์ได้ด้วยตัวเอง ... การเปลี่ยน === เป็น == ก็ใช้ได้ IE
if ($lastDigit == $digit) {
PHP จะพยายามแปลงค่า RHS เป็น LHS Type จากนั้นทำการเปรียบเทียบ
ตอนนี้คุณกำลังทำการเปรียบเทียบและ PHP กำลังแปลง $ หลักเป็นจำนวนเต็ม
วิธีที่ปลอดภัยกว่าคือการบังคับหล่อ คุณจึงสามารถโยน $ หลักจากสตริงเป็นจำนวนเต็มและใช้รหัสที่คุณมีอยู่
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;
}
ดังนั้นบทเรียนจากสิ่งนี้เมื่อใช้ === ตรวจสอบให้แน่ใจว่าประเภทของคุณเหมือนกัน