记一个个人觉得极其难以发现的错误代码(菜鸟级,大佬勿喷)
先上源代码:
<!DOCTYPE html>
<head>
<title>实验</title>
<meta charset="utf-8">
<style>
th{
width:100px;
}
</style>
</head>
<body>
<h4 style="margin-left:230px">请输入学生信息</h4>
<table border="0">
<form method="post" action="">
<tr>
<td ></td>
<td>学号</td>
<td>姓名</td>
<td>成绩</td>
</tr>
<tr>
<td>学生1:</td>
<td><input type="text" name="stu0_num"></td>
<td><input type="text" name="stu0_name"></td>
<td><input type="text" name="stu0_score"></td>
</tr>
<tr>
<td>学生2:</td>
<td><input type="text" name="stu1_num"></td>
<td><input type="text" name="stu1_name"></td>
<td><input type="text" name="stu1_score"></td>
</tr>
<tr>
<td>学生3:</td>
<td><input type="text" name="stu2_num"></td>
<td><input type="text" name="stu2_name"></td>
<td><input type="text" name="stu2_score"></td>
</tr>
<tr>
<td>学生4:</td>
<td><input type="text" name="stu3_num"></td>
<td><input type="text" name="stu3_name"></td>
<td><input type="text" name="stu3_score"></td>
</tr>
<tr>
<td>学生5:</td>
<td><input type="text" name="stu4_num"></td>
<td><input type="text" name="stu4_name"></td>
<td><input type="text" name="stu4_score"></td>
</tr>
<tr>
<td></td>
<td><input type="submit" name="submit" value="提交"></td>
<td></td>
<td><input type="reset" name="reset" value="重置"></td>
</tr>
</form>
</table>
<?php
#储存学生信息的临时数组
$arr= array(
range(1,3),
range(1,3),
range(1,3),
range(1,3),
range(1,3)
);
if (isset($_POST['submit'])) {
#如果提交了内容,将内容通过foreach函数,存放在数组当中
foreach ($arr as $key => &$table) {
//$table[$key] = $_POST["stu${key}_num"];
$table[0] = $_POST["stu${key}_num"];
$table[1] = $_POST["stu${key}_name"];
$table[2] = $_POST["stu${key}_score"];
}
#根据成绩对学生信息进行排序
/*foreach ($arr as $key => $table) {
$sort[$key] = $table[2];
}
array_multisort($sort,SORT_DESC,$arr);*/
var_dump($arr);
#打印出最终的结果
echo " <table border='1'>";
echo "<tr><th>学号</th><th>姓名</th><th>成绩</th></tr>";
foreach ($arr as $table) {
echo "<tr>";
foreach ($table as $value) {
echo "<td>$value</td>";
}
echo "</tr>";
}
echo "</table>";
var_dump($arr);
}
?>
</body>
</html>
要实现的功能,只是简单的学生信息收集,并按照收集的学生成绩排序,并打印成单个列表,功能如下图:
虽然功能简单,但是不免可以发现其中的问题。如
我输入的信息原本并不一致的,但是发现,这里竟然发生了意外。两条数据竟然数据一致了。
为了证明不是我的问题,我们接下来进行研究这个问题所出现的原因。
var_dump($arr);#var_dump一下同一个数据
#打印出最终的结果
echo " <table border='1'>";
echo "<tr><th>学号</th><th>姓名</th><th>成绩</th></tr>";
foreach ($arr as $table) {
echo "<tr>";
foreach ($table as $value) {
echo "<td>$value</td>";
}
echo "</tr>";
}
echo "</table>";
var_dump($arr);#var_dump一下同一个数据
然后再次重新刷新我们的页面,也就是重新提交表单
上边是我提交的正常的数据,下边是“变化”后。也就是这个“变化”,足以证明我输入的数据是不一样的,但是在打印成为表单的过程中,自动对值进行了改变。
既然与我所设想的结果不一样,那么肯定就是我的代码哪个地方出现了问题。是哪里呢?
我原来认为是两个var_dump函数之间打印的代码出了问题。
但经过询问和自己的一番研究发现,问题的所在是在这:
foreach ($arr as $key => &$table) {#这里的&符号是错误关键
//$table[$key] = $_POST["stu${key}_num"];
$table[0] = $_POST["stu${key}_num"];
$table[1] = $_POST["stu${key}_name"];
$table[2] = $_POST["stu${key}_score"];
}
查网上的资料,我对&符号的大致的了解是c/c++指针,指向地址,这样使用一个变量,相当于是另一个变量的变名。
也正是把c/c++等同起来,才造成了这次错误的出现。
下面是研究过程中的的代码:
<?php
#先看这一段
$arr = [1,2,3];
$b = "hello";
$value = &$b;
echo "$value<br>";
foreach ($arr as $key => $value) {
echo "$b";
echo $value."<br>";
}
?>
输出的结果是:
hello
11
22
33
可见 b 的 值 , 在 遍 历 数 组 b的值,在遍历数组 b的值,在遍历数组arr的过程中,也发生了变化。
再看我们的另一段代码,也就是跟我最初的代码类似的代码:
$arr = [1,2,3];
foreach ($arr as $key => &$value) {#同样的地方,同样的&用法
echo $value."<br>";
}
var_dump($value);
foreach ($arr as $key => $value) {
echo $value;
//$value = "hello";
echo $arr[2];
echo "<br>";
}
var_dump($arr);
$value = 3;
echo $arr[2];
输出的结果是
1
2
3
D:\wamp64\www\test\2.php:196:int 3
11
22
22
D:\wamp64\www\test\2.php:204:
array (size=3)
0 => int 1
1 => int 2
2 => int 2
3
不难发现,其实在我们第一个foreach()遍历完数组,其实我们并没有定义的变量$value仍还存在着。
而且$value的内存其实是储存着$arr[2]的地址,当我们假装$value这个值不存在时,再次使用$value用foreach去遍历另一个数组,as $value,相当就是给
$arr[2] = $arr 2[0]
$arr[2] = $arr 21]
$arr[2] = $arr 2[1]
这样的一次次,赋值,虽然我们在遍历,但是同时也在改变$arr[2]的值。