課題3解答例

平均値を計算して出力する場合の処理の流れ

データ数を記憶する変数=0

while(データの最後になるまで) {
  1行読み込み
  カンマで区切り,個々の数値(文字列)を<td>で囲んで出力
  各数値を対応する列ごとに合計を記憶する変数に足し込む
  データ数(行数)を記憶する変数値を1増やす
}

各列ごとに,合計値をデータ数で割って表示

合計を記憶する変数の定義,使い方はいろいろなやりかた(工夫)がありえます.一通りではありません.

解答例

<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.01 traditional//en">
<html>
<head>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
</head>
<body>
<?php

$str_array = array();
$handle = @fopen("../data/simple_sample.csv","r");
$avg_array = array();  //平均値用変数
$data_num = -1;                            // タイトル行が1行あることを想定
if($handle) {
  echo "<table border=2>";
  while(!feof($handle)) {
    $buffer = trim(fgets($handle));   // trimは前後の空白や改行コードをとる関数
    if($buffer =="") continue;        //空行なら下を実行せず次の行の処理へ
    $data_num++;                      // データ数(行数)のカウント
    $str_array = explode(",",$buffer);
    echo "<tr>";

    for($i=0; $i<count($str_array); $i++) {
      echo "<td>" . $str_array[$i] ."</td>";
      if(!isset($avg_array[$i])) {          // $i列の平均値用要素がなければ
        $avg_array[$i] = $str_array[$i];    // 新たに作り,値を代入
      } else {
        $avg_array[$i] += $str_array[$i];   // 平均値用配列要素があれば,値を追加
      }
    }
    echo "</tr>";

  }

  //平均値の行の出力
  $avg_array[0] = "平均"; $avg_array[1] ="";
  echo "<tr>";
  for($i=0; $i<count($avg_array); $i++) {
    echo "<td>";
    if(is_numeric($avg_array[$i])) {
      printf("%.2f",$avg_array[$i]/$data_num);
    } else {
      echo $avg_array[$i];
    }
    echo "</td>";
  }
  echo "</tr>";
  echo "</table>";
}


?>
</body>
</html>

より進んだ解答例

<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.01 traditional//en">
<html>
<head>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
</head>
<body>
<?php

$str_array = array();
$handle = @fopen("../data/utf8/sample1.csv","r"); // ファイル名は各自設定
$avg_array = array();  //平均値用変数
if($handle) {
  echo "<table border=2>";
  while(!feof($handle)) {
    $buffer = trim(fgets($handle));   // trimは前後の空白や改行コードをとる関数
    if($buffer =="") continue;        //空行なら下を実行せず次の行の処理へ
    $buffer = str_replace('"','',$buffer); // 見出しなどにあるダブルクォーテーションを削除
    $str_array = explode(",",$buffer);
    echo "<tr>";

    for($i=0; $i<count($str_array); $i++) {
      if(!isset($avg_array[$i])) {
        if(is_numeric($str_array[$i])) {
          $avg_array[$i] = $str_array[$i];
          $data_num[$i] = 1; // $data_num[$i]が数値なら$i列目のデータ数を1にセット
        }
      } else {
        if(is_numeric($str_array[$i])) {   // 値が数値でないならカウントしない
          $avg_array[$i] += $str_array[$i];
          $data_num[$i]++; // $data_num[$i]が数値なら$i列目のデータ数を1増やす
        }
      }
      echo "<td>" . $str_array[$i] ."</td>";
    }
    echo "</tr>";

  }

  //平均値の行の出力
  $avg_array[0] = "平均"; $avg_array[1] ="";
  echo "<tr>";
  for($i=0; $i<count($avg_array); $i++) {
    echo "<td>";
    if(is_numeric($avg_array[$i])) {
      printf("%.2f",$avg_array[$i]/$data_num[$i]);
    } else {
      echo $avg_array[$i];
    }
    echo "</td>";
  }
  echo "</tr>";
  echo "</table>";
}


?>
</body>
</html>

is_numeric($x)という関数は,引数$xが数値である場合にtrueを返します.したがって,数字以外の文字が入っていたり,空白だったりするとfalseになります. $num_data[$i]を増加させるかどうかの判断には,これを使うのが最適です.

print, printf, echo の使い方

printとechoは

print 変数名(あるいは定数);
のように使います.printのところはechoでも同じです.変数や定数はかっこで囲む必要はありませんが,囲んでも同様の出力が得られます.厳密言うと,printやechoは関数ではなく言語構造の一部です.(ややこしいですが.)

解答では,

 print("<td>$str_array[$i]</td>");
 

というのがありました. ダブルクォーテーションの中に変数を埋め込むのことは可能で,上記の命令は文法としては正しいですし,使い慣れた人はよくやる手でもあります.が,使い方をよく理解した上で使いましょう.

 print "<td>" . $str_array[$i] . "</td>";

くらいが平明ですね.

あるは,printfを使って,

 printf("<td>%f</td>",$str_array[$i]);
とするのが,Cで書いていたときの流儀からすると自然に思えるかもしれません.これでもよいです.