Skip to content

6. 应用练习 - 带对象的 IMPOTS(impots_03)

我们重新回顾之前已学习的练习(第 4.2 4.3 节),并使用类编写代码 PHP 来解决该问题。


<?php

// 定义一个名为“Impôts”的类
class Impôts {

  // 属性:3个数据数组
  private $limites;
  private $coeffR;
  private $coeffN;
  
  // 构造函数

  public function __construct($IMPOTS) {
    // $IMPOTS: 包含表 $limites、$coeffR、$coeffN 数据的文件名
    // 文件 $IMPOTS 是否存在?
    if (!file_exists($IMPOTS)) {
      throw new Exception("Le fichier $IMPOTS n'existe pas");
    }//if
    // 批量读取文件
    $tables = file($IMPOTS);
    if (!$tables) {
      throw new Exception("Erreur lors de l'exploitation du fichier $IMPOTS");
    }//if
    // 创建 3 个表——假设行在语法上正确
    $u = new Utilitaires(); // 以提供实用函数
    $this->limites = explode(":", $u->cutNewLineChar($tables[0]));
    $this->coeffR = explode(":", $u->cutNewLineChar($tables[1]));
    $this->coeffN = explode(":", $u->cutNewLineChar($tables[2]));
    }

  // --------------------------------------------------------------------------
  public function calculer($marié, $enfants, $salaire) {
    // $marié:是,否
    // $enfants:子女数量
    // $salaire:年薪
    
    // 份额数
    $marié = strtolower($marié);
    if ($marié == "oui")
      $nbParts = $enfants / 2 + 2;
    else
      $nbParts=$enfants / 2 + 1;
    // 若子女至少3名,则额外增加1/2份额
    if ($enfants >= 3)
      $nbParts+=0.5;
    // 应税收入
    $revenuImposable = 0.72 * $salaire;
    // 家庭系数
    $quotient = $revenuImposable / $nbParts;
    // 置于限额表末尾以终止后续循环
    $this->limites[count($this->limites) - 1] = $quotient;
    // 计算税额
    $i = 0;
    while ($quotient > $this->limites[$i])
      $i++;
    // 由于将 $quotient 放置在 $limites 表的末尾,因此前面的循环
    // 不能超出数组 $limites 的范围
    // 现在可以计算税款
    return floor($revenuImposable * $this->coeffR[$i] - $nbParts * $this->coeffN[$i]);
  }

}

// 一个实用函数类
class Utilitaires {

  public function cutNewLinechar($ligne) {
    // 如果存在,则删除 $ligne 中的行尾标记
    $L = strlen($ligne);  // 行长度
    while (substr($ligne, $L - 1, 1) == "\n" or substr($ligne, $L - 1, 1) == "\r") {
      $ligne = substr($ligne, 0, $L - 1);
      $L--;
    }//while
    // 结束
    return($ligne);
  }

}

// 测试 -----------------------------------------------------
// 常量定义
$DATA = "data.txt";
$RESULTATS = "resultats.txt";
$IMPOTS = "impots.txt";
// 计算税款所需的数据已放入文件 IMPOTS
// 每张表格占一行,格式为
// "val1":"val2":"val3",...
// 创建一个 Impôts 对象
try {
  $I = new Impôts($IMPOTS);
} catch (Exception $e) {
  print $e->getMessage();
  exit;
}
// 创建一个工具对象
$u = new Utilitaires();

// 读取用户数据
$data = fopen($DATA, "r");
if (!$data) {
  print "Impossible d'ouvrir en lecture le fichier des données [$DATA]\n";
  exit;
}

// 打开结果文件
$résultats = fopen($RESULTATS, "w");
if (!$résultats) {
  print "Impossible de créer le fichier des résultats [$RESULTATS]\n";
  exit;
}

// 处理数据文件的当前行
while ($ligne = fgets($data, 100)) {
  // 移除可能存在的换行符
  $ligne = $u->cutNewLineChar($ligne);
  // 提取构成 $ligne 的 3 个字段:已婚、子女、工资
  list($marié, $enfants, $salaire) = explode(",", $ligne);
  // 计算税额
  $impôt = $I->calculer($marié, $enfants, $salaire);
  // 写入计算结果
  fputs($résultats, "$marié:$enfants:$salaire:$impôt\n");
  // 下一条数据
}// while
// 关闭文件
fclose($data);
fclose($résultats);

// 结束
print "Terminé\n";
exit;
?>

文件 [impots.txt]:

12620:13190:15640:24740:31810:39970:48360:55790:92970:127860:151250:172040:195000:0
0:0.05:0.1:0.15:0.2:0.25:0.3:0.35:0.4:0.45:0.5:0.55:0.6:0.65
0:631:1290.5:2072.5:3309.5:4900:6898.5:9316.5:12106:16754.5:23147.5:30710:39312:49062

文件 [data.txt]

oui,2,200000
non,2,200000
oui,3,200000
non,3,200000
oui,5,50000
non,0,3000000

结果:与表格和文件版本中已获得的结果相同。

文件 [resultats.txt]

oui:2:200000:22504
non:2:200000:33388
oui:3:200000:16400
non:3:200000:22504
oui:5:50000:0
non:0:3000000:1354938

注释

  • 第4行:Impôts类。它封装了用于计算税款的数据和方法:
  • 数据:第7-9行——这是用于计算税款的三个数据数组。这三个数组由第13行的构造函数根据文本文件进行初始化。
  • 方法:第32行——方法calculer用于计算税款。
  • 第17、22行:当构造函数无法构建对象Impôts时,会抛出异常。
  • 第 25 行:定义了 Utilitaires 类,用于封装 cutNewLineChar 函数。
  • 第 26-28 行:初始化类 Impôts 的三个私有字段
  • 第 32 行:类 Impôts 的方法 calculer 用于计算纳税人的税款。
  • 第 65-78 行:Utilitaires
  • 第 89-94 行:创建 Impôts 对象并处理可能出现的异常。此创建过程将利用文本文件 $IMPOTS,将其内容填入 Impôts 对象的三个私有字段中。
  • 第96行:创建对象Utilitaires,以便使用函数cutNewLineChar