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]
结果:与表格和文件版本中已获得的结果相同。
文件 [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。