Log in

View Full Version : Resolved Debugging: Can't Find Cause of Fatal Error



marain
05-25-2020, 08:26 PM
Folks,

The code below produces this error message:

testing connection from line 132 of test function
string(5) "Debug" float(8)
Fatal error: Uncaught Error: Function name must be a string in /home/marainla/public_html/pageContent/test.txt:95 Stack trace: #0 /home/marainla/public_html/pageContent/test.txt(134): cardinalNumber(5432, 668) #1 /home/marainla/public_html/includes/page.class.php(11): require('/home/marainla/...') #2 /home/marainla/public_html/page.php(26): page->showPage() #3 {main} thrown in /home/marainla/public_html/pageContent/test.txt on line 95



<?php
$lastUpdate = date( 'j F Y', filemtime( 'pageContent/test.txt' ) );
?>
<?php
$result = 01234; // TESTING TESTING TESTING

function cardinalNumber($test_number, $result) { // TESTING TESTING TESTING

//function cardinalNumber($_SESSION["limit"], $result) {

/*****************************************************************************************************
*
* INPUT: ANY POSITIVE INTEGER
*
* RETURNS: RESULT
*
* REFERENCE: https://www.php.net/manual/en/langref.php
*
* REMARKS: Two ways to do this occur to me. The first way is to convert the input integer to a string and then extract
* each digit, one at a time. Each extracted digit is then individually converted back to numeric form.
* We call this the "brute force" method. The second way is to arithmetically compute each digit.
*
* Door Two is, oh, so much more elegant. This function uses door two.
*
******************************************************************************************************/

// Part Zero: Definitions

$numbers = array (
"",
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine",
"ten",
"eleven",
"twelve",
"thirteen",
"fourteen",
"fifteen",
"sixteen",
"seventeen",
"eighteen",
"nineteen"
);

$decades = array (
"", // aughts
"", // tens
"twenty",
"thirty",
"forty",
"fifty",
"sixty",
"seventy",
"eighty",
"ninety"
);


// [obtain/retrieve $argument]

// $argument = min($_SESSION["limit"], 9999); // commented for testing purposes only // are you kidding me?

$argument = $test_number; // TESTING TESTING TESTING
$argument = 8765; // TESTING TESTING TESTING
$argument = min($argument, 9999); // TESTING TESTING TESTING





// Part One: Determine place values: thousands, hundreds, tens, units

$working_number = $argument; // bring the bu, bu, bucket down
$thousands = ($working_number / 1000) - (($working_number % 1000) / 1000); // ditch remainder, for pure thousands
var_dump ("Debug", $thousands);
$working_number = $working_number - (1000 * $thousands); // ditch thousands
$hundreds = ($working_number / 100) - (($working_number % 100) / 100); // ditch remainder, for pure hundreds
$working_number = $working_number - (100 * $hundreds); // ditch hundreds
$tens = ($working_number - ($working_number % 10) / 10); // ditch remainder, for pure tens
$units = ($working_number - (10 * $tens)); // ditch tens, for units

//
// Part Two: Construct Result
//

// Determine Thousands

$result = $numbers ($thousands);
if ($thousands != 0) {
$result = $result . " thousand";
}

// Determine Hundreds

$result = $result . $numbers ($hundreds);
if ($hundreds != 0) {
$result = " " . $result . " hundred";
}

// Determine Tens and Units

$result = $result . $decades ($tens);
if ($tens > 1) {
$result = $result . " " . $decades ($tens);
if ($units) {
$result = $result . "-" . $units;
}
else {
$result = $result . " " . $numbers ((10 * $tens) + $units);
}
}

//
// Part Three: Return Result//
//

echo $result; // TESTING TESTING TESTING
return $result;
}


echo "<br />";
echo "<br />";
echo "<br />";
echo "<br />";
echo "testing connection from line 132 of test function <br />";
cardinalNumber(5432, $result);
?>
This is line 135 of test.txt.
<br />
<br />
<br />
<br />



Can y'all help me?

A.

keyboard
05-27-2020, 04:28 AM
Hey Marain!
There's a few issues with the code provided:

1. I loaded up your code on a local server and got the same error -
Fatal error: Uncaught Error: Function name must be a string in C:\xampp\htdocs\mo.php:95 Stack trace: #0 C:\xampp\htdocs\mo.php(134): cardinalNumber(5432, 668) #1 {main} thrown in C:\xampp\htdocs\mo.php on line 95

The line that's causing the error is line 95 -

$result = $numbers ($thousands);

It looks like you're trying to get a value from an array array[key] but instead you're making a function call (note the rounded brackets).
This error also happens in a few other places.

2. If you echo out all the values

echo $working_number . '<br />';
echo $thousands . '<br />';
echo $hundreds . '<br />';
echo $tens . '<br />';
echo $units . '<br />';

You'll get the result

65
8
7
64.5
-580
Which doesn't look right. You'll have to fix the math there.

3. You're passing a variable to the function cardinalNumber(5432, $result); ($result) and trying to change it, but this won't update the value of the variable.
See the below example
function test($varToChange) {
$varToChange = 5;
}

$testVar = 1;

echo $testVar; // 1
test($testVar);
echo $testVar; // still 1

To change a variable outside the scope of the function you have to pass it as a reference

function test(&$varToChange) {
$varToChange = 5;
}

$testVar = 1;

echo $testVar; // 1
test($testVar);
echo $testVar; // now prints 5


4.There is a function in the NumberFormatter class to achieve what you're doing -
NOTE: It may not be enabled by default on your webserver, see https://stackoverflow.com/questions/30554177/fatal-error-class-numberformatter-not-found

$f = new NumberFormatter("en", NumberFormatter::SPELLOUT);
echo $f->format(5432);

marain
05-27-2020, 12:39 PM
Keyboard,

Thanks!

The key to the fatality, as you pointed out, was what you called Issue 1. I fixed that there and, as you also pointed out, in other places. Logic errors existed but, once getting past the fatality, were straightforward to track down and fix. The function and the logic now work perfectly. (Well, it still needs to be cleaned up, before being inserted into the page, but that's no big deal.)

The final logic, it turns out, is very streamlined. Behold:



// Part One: Determine place values: thousands, hundreds, tens, units

$thousands = intval($argument / 1000); // whole number of thousands
$hundreds = intval(($argument - (1000 * $thousands)) / 100); // whole number of hundreds left over
$tens = intval(($argument - ((1000 * $thousands) + (100 * $hundreds))) / 10); // whole number of tens left over
$units = $argument - (($thousands * 1000) + ($hundreds * 100) + ($tens * 10)); // what's left over

//
// Part Two: Build Result
//

// Determine Thousands

$result = $numbers [$thousands];
if ($thousands) {
$result = $result . " thousand";
}

// Determine Hundreds

$result = $result . " " . $numbers [$hundreds];
if ($hundreds) {
$result = " " . $result . " hundred";
}

// Determine Tens and Units

if ($tens > 1) {
$result = $result . " " . $decades [$tens];
if ($units) {
$result = $result . "-" . $numbers [$units];
}
}
else {
$result = $result . " " . $numbers [($tens * 10) + $units];
}


Thanks again for your help. Dynamic Drive comes through again!

A.