php - Split file on every second line and format the results as a table

I have a .txt file where each line contains a number value.

The first line is a student's score on a test. The second line is the highest possible score for that test.

I'm tasked with converting this content to an html table with these requirements:

  • each row in the table must contain the columns of row index, score, possible score, percentage in that order
  • the last row of the table should total the values like Student score= 761 Possible= 850 Percentage= 90%

The .txt file is called scores.txt and below are the grades.

89
100
67
75
89
90
57
65
34
40
62
70
49
55
80
95
45
60
189
200 

Below is what it should look like this

<!DOCTYPE html>
<html>

  <body>

    <table border="1">
      <tr>
        <th>Index</th>
        <th>Student Score</th>
        <th>Possible Score</th>
        <th>Percentage</th>
      <tr>

      <tr>
        <td>1</td>
        <td>89</td>
        <td>100</td>
        <td>89%</td>
      </tr>
      <tr>
        <td>2</td>
        <td>67</td>
        <td>75</td>
        <td>89%</td>
      </tr>
      <tr>
        <td>3</td>
        <td>89</td>
        <td>90</td>
        <td>99%</td>
      </tr>
      <tr>
        <td>4</td>
        <td>57</td>
        <td>65</td>
        <td>88%</td>
      </tr>
      <tr>
        <td>5</td>
        <td>34</td>
        <td>40</td>
        <td>85%</td>
      </tr>
      <tr>
        <td>6</td>
        <td>62</td>
        <td>70</td>
        <td>89%</td>
      </tr>
      <tr>
        <td>7</td>
        <td>49</td>
        <td>55</td>
        <td>89%</td>
      </tr>
      <tr>
        <td>8</td>
        <td>80 </td>
        <td>95</td>
        <td>84%</td>
      </tr>
      <tr>
        <td>9</td>
        <td>45</td>
        <td>60</td>
        <td>75%</td>
      </tr>
      <tr>
        <td>10</td>
        <td>189</td>
        <td>200</td>
        <td>95%</td>
      </tr>
      <tr>
        <td>Total</td>
        <td>761</td>
        <td>850</td>
        <td>90%</td>
      </tr>
    </table>

  </body>

</html> 

My code

<!DOCTYPE html>
<html lang="en">
<html>
<head><title>Grades Results</title></head>

<body>

<html>
<body>
<?
    if(!file_exists("scores.txt"))
    {
        echo "The file from above cannot be found!";
        exit;
    }
    
    $fp = fopen("scores.txt", "r");
    
    if(!$fp)
    {
        echo "Somehow the file cannot be opened! :)";
        exit;
    }
    echo "<table border = 4>";
    $counter = 1;
    while(!feof($fp))
    {
        $zeile = fgets($fp);
        echo "<tr><td>$counter</td>";
        echo "<td>$zeile</td>";
        $counter++;
    }
        echo "</table>";
    fclose($fp)
    
?>
</body>
</html>
</body>
</html>

UPDATE: I rewrote my code and it is still not working, I even added list areas to add and it is confusing me even more.

<!DOCTYPE html>
<html lang="en">
<html>
<head><title>Grades Results</title></head>

<body>

<html>
<table>
<tr>
</tr>
<table>   
    <?php
        $file = fopen("scores.txt", "r") or die("Unable to open file!");
        while (!feof($file)){   
            $data = fgets($file); 
            list($studentscore, $possiblescore, $percentage) = explode("|", $data);
    ?> 
    <tr>
        <td><?=$studentscore ?></td>
        <td><?=$possiblescore ?></td>
        <td><?=$percentage ?></td>
        ...
    </tr>
    <?php
        }
        fclose($failas);
   ?>
</table>
</form>
</body>
</html>
</body>
</html>

Answer

Solution:

This code will do what you need as seen in this example.

NOTE: Now that we've done your homework for you, your new assignment is to read all of the comments in the code below and then read the documentation for all the functions and language constructs used so that you will understand how this does what you need and become a better programmer.:

Reading list:

PHP Code:

<?php

// get an array of all of the lines contained in the src file
if (!$lines = file('scores.txt', FILE_IGNORE_NEW_LINES)) {
    die('Unable to open file!'); // I'd do something better with this personally...
}
// count of all lines should be an even number, if not, something is wrong with the file...
if(count($lines) % 2 !== 0){
    die('File contains an odd number of lines!'); // I'd do something better with this personally...
}

// split that array into an array of arrays where each inner array contains 2 values/lines
// the first value in each array will be a student's score, the second will be the highest possible score for that test
$tests = array_chunk ($lines,2);

// loop over the tests array and process each assigning the results to a new array
$rows = [];
$totalScored = 0;
$totalPossible = 0;
foreach ($tests as $index => $test) {

    $score          = (int)$test[0];
    $possibleScore  = (int)$test[1];
    $percentage     = $score <= 0 ? '0' : ($score / $possibleScore) * 100; // NOTE that we check for 0 here to avoid "divide by 0" errors!
    $percentage     = round($percentage).'%';
    $totalScored   += $score;
    $totalPossible += $possibleScore;

    $rows[]= [$index+1, $score, $possibleScore, $percentage];
}
// now add our totals row
$totalPercentage     = $totalScored <= 0 ? '0' : ($totalScored / $totalPossible) * 100;
$totalPercentage     = round($totalPercentage).'%';
$rows[]= ['Total', $totalScored, $totalPossible, $totalPercentage];

// lets keep the html as clean as possible by converting all the elements of the array 
// we could have done this in the above foreach loop, but I'd prefer to keep that array with just the values
// in case we need them for anything else later.
$tableRows = array_map(
    static function($row) {
        return '<tr><td>'.implode('</td><td>', $row).'</td></tr>';
    },
    $rows
);

// finally, turn that array of strings into one long string of html. 
$tableRowString = implode(PHP_EOL, $tableRows);
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Grades Results</title>
</head>
<body>
<table>
    <tr>
        <th>Index</th>
        <th>Student Score</th>
        <th>Possible Score</th>
        <th>Percentage</th>
    <tr>
    <?= $tableRowString ?>
</table>
</body>
</html>

Modified version to work with dinosaur PHP versions...

Proof it works on php 5.1.5

<?php

// get an array of all of the lines contained in the src file
if (!$lines = file('scores.txt', FILE_IGNORE_NEW_LINES)) {
    die('Unable to open file!'); // I'd do something better with this personally...
}

// count of all lines should be an even number, if not, something is wrong with the file...
if(count($lines) % 2 !== 0){
    die('File contains an odd number of lines!'); // I'd do something better with this personally...
}

// split that array into an array of arrays where each inner array contains 2 values/lines
// the first value in each array will be a student's score, the second will be the highest possible score for that test
$tests = array_chunk ($lines,2);

// loop over the tests array and process each assigning the results to a new array
$rows = array();
$totalScored = 0;
$totalPossible = 0;
foreach ($tests as $index => $test) {
    
    $score          = (int)$test[0];
    $possibleScore  = (int)$test[1];
    $percentage     = $score <= 0 ? '0' : ($score / $possibleScore) * 100; // NOTE that we check for 0 here to avoid "divide by 0" errors!
    $percentage     = round($percentage).'%';
    $totalScored   += $score;
    $totalPossible += $possibleScore;

    $rows[]= array($index+1, $score, $possibleScore, $percentage);
}
// now add our totals row
$totalPercentage     = $totalScored <= 0 ? '0' : ($totalScored / $totalPossible) * 100;
$totalPercentage     = round($totalPercentage).'%';
$rows[]= array('Total', $totalScored, $totalPossible, $totalPercentage);

// lets keep the html as clean as possible by converting all the elements of the array 
// we could have done this in the above foreach loop, but I'd prefer to keep that array with just the values
// in case we need them for anything else later.

function callback($row) {
        return '<tr><td>'.implode('</td><td>', $row).'</td></tr>';
};
$tableRows = array_map('callback', $rows);

// finally, turn that array of strings into one long string of html. 
$tableRowString = implode("\n", $tableRows);


echo $tableRowString;

Source