《零基础学 PHP:从入门到实战》教程-模块四:数组与函数-1

第1章:数组基础入门

章节介绍

数组是PHP中最重要的数据结构之一,它允许我们将多个值存储在一个变量中,从而高效地管理和操作数据。无论您是处理用户信息、商品列表还是任何数据集,数组都能简化代码并提升可读性。本章将从零开始,带您深入理解数组的基本概念,包括如何创建和访问索引数组与关联数组,使用工具输出数组内容,并进行基本操作如获取长度。通过丰富的代码示例和实战项目,您将掌握数组的核心用法,为后续学习数组操作和函数打下坚实基础。本章学习时间约1.5小时,包含大量动手实践,确保您能立即应用所学知识。

核心概念讲解与代码示例

1.1 数组的定义和作用

数组是一种用于存储多个值的变量类型,每个值称为一个元素,并通过索引或键进行访问。在PHP中,数组可以包含不同类型的数据(如字符串、数字等),这使得它在处理列表、集合或映射数据时非常灵活。数组的主要作用包括:组织相关数据、简化循环处理、支持动态数据操作。例如,在Web开发中,数组常用于存储表单数据、数据库查询结果或配置信息。通过数组,我们可以避免定义多个单独变量,提高代码的可维护性和效率。

代码示例(每个示例均完整可运行,带详细注释):

php 复制代码
<?php
// 示例1: 基本数组定义和使用array()函数
// 定义一个索引数组,存储水果名称
$fruits = array("苹果", "香蕉", "橙子");
echo "水果数组: ";
print_r($fruits); // 输出数组结构
// 解释:这里使用array()函数创建数组,包含三个字符串元素

// 示例2: 使用短数组语法[](PHP 5.4+)
// 定义数字数组,存储分数
$scores = [85, 90, 78];
echo "分数数组: ";
var_dump($scores); // 输出详细类型和信息
// 解释:短数组语法更简洁,适用于现代PHP版本

// 示例3: 数组与单个变量的对比
// 不使用数组,需要多个变量
$name1 = "张三";
$name2 = "李四";
$name3 = "王五";
// 使用数组,简化存储
$names = ["张三", "李四", "王五"];
echo "单个变量: $name1, $name2, $name3\n";
echo "数组: ";
print_r($names);
// 解释:数组减少了变量数量,便于批量处理

// 示例4: 空数组的定义和后续添加
$emptyArray = array(); // 或 $emptyArray = [];
$emptyArray[] = "第一个元素"; // 添加元素
echo "空数组添加后: ";
print_r($emptyArray);
// 解释:空数组可用于动态构建数据

// 示例5: 数组存储混合数据类型
$mixedArray = ["文本", 123, true, 3.14];
echo "混合数组: ";
var_dump($mixedArray);
// 解释:PHP数组支持多种类型,增强了灵活性
?>

1.2 索引数组的创建与访问

索引数组使用数字索引(从0开始)来访问元素,适用于顺序数据存储。创建索引数组可以通过array()函数或[]语法,访问元素时使用方括号指定索引。如果索引超出范围,PHP会返回NULL或警告。索引数组常用于列表式数据,如学生名单或商品ID,它支持快速通过位置检索值。在访问数组元素时,务必使用错误处理机制如isset()检查索引是否存在,以避免未定义错误。

代码示例:

php 复制代码
<?php
// 示例1: 使用array()创建索引数组并访问元素
$colors = array("红色", "绿色", "蓝色");
echo "第一个颜色: " . $colors[0] . "\n"; // 输出: 红色
echo "第二个颜色: " . $colors[1] . "\n"; // 输出: 绿色
// 解释:索引从0开始,$colors[0]访问第一个元素

// 示例2: 使用[]语法创建和修改元素
$numbers = [10, 20, 30];
$numbers[1] = 25; // 修改第二个元素
echo "修改后的数组: ";
print_r($numbers); // 输出: Array ( [0] => 10 [1] => 25 [2] => 30 )
// 解释:通过索引直接赋值可以更新数组元素

// 示例3: 动态添加元素到索引数组
$dynamicArray = [];
$dynamicArray[] = "A"; // 自动分配索引0
$dynamicArray[] = "B"; // 自动分配索引1
echo "动态数组: ";
print_r($dynamicArray); // 输出: Array ( [0] => A [1] => B )
// 解释:空括号自动追加元素到末尾

// 示例4: 访问不存在的索引(常见错误) - 使用isset()进行错误处理
$testArray = ["一", "二"];
if (isset($testArray[2])) {
    echo "元素: " . $testArray[2];
} else {
    echo "索引2不存在\n"; // 输出警告,避免错误
}
// 解释:使用isset()检查索引是否存在,防止未定义错误;这是关键错误处理实践

// 示例5: 使用for循环遍历索引数组,并添加索引检查
$items = ["书", "笔", "纸"];
for ($i = 0; $i < count($items); $i++) {
    if (isset($items[$i])) { // 确保索引存在后再访问
        echo "物品 $i: " . $items[$i] . "\n";
    } else {
        echo "索引 $i 不存在\n"; // 处理潜在越界情况
    }
}
// 解释:count()获取长度,循环输出每个元素;添加isset()检查提升代码健壮性

// 示例6: 使用array_key_exists()作为替代错误处理方法
$sampleArray = [0 => "零", 1 => "一"];
if (array_key_exists(2, $sampleArray)) {
    echo "元素: " . $sampleArray[2];
} else {
    echo "索引2不存在,使用array_key_exists验证\n";
}
// 解释:array_key_exists()专门检查键是否存在,适用于索引和关联数组,提供另一种错误处理方式
?>

1.3 关联数组的创建与访问

关联数组使用字符串键(键名)来访问元素,适用于键值对数据,如用户信息(姓名、年龄)。创建关联数组时,指定键和值,访问时通过键名获取值。关联数组提高了代码可读性,因为它使用描述性键而非数字索引。在访问关联数组时,必须使用错误处理如isset()array_key_exists()检查键是否存在,以防止未定义错误。

代码示例:

php 复制代码
<?php
// 示例1: 使用array()创建关联数组
$user = array("name" => "张三", "age" => 25, "city" => "北京");
echo "用户名: " . $user["name"] . "\n"; // 输出: 张三
echo "年龄: " . $user["age"] . "\n"; // 输出: 25
// 解释:键名如"name"用于访问对应值

// 示例2: 使用[]语法创建关联数组
$product = ["id" => 101, "name" => "手机", "price" => 1999];
$product["price"] = 1899; // 修改价格
echo "产品信息: ";
print_r($product); // 输出修改后的数组
// 解释:通过键名直接更新值

// 示例3: 动态添加键值对
$config = [];
$config["language"] = "中文";
$config["theme"] = "黑暗";
echo "配置数组: ";
print_r($config);
// 解释:关联数组可以动态扩展

// 示例4: 访问不存在的键(使用默认值) - 强化错误处理
$data = ["a" => 1, "b" => 2];
$value = isset($data["c"]) ? $data["c"] : "默认值";
echo "键c的值: $value\n"; // 输出: 默认值
// 解释:使用三元运算符处理未定义键;isset()是推荐方法,避免未定义错误

// 示例5: 使用array_key_exists()检查键是否存在
$student = ["姓名" => "李四", "成绩" => 95];
if (array_key_exists("班级", $student)) {
    echo "班级: " . $student["班级"];
} else {
    echo "键'班级'不存在\n"; // 输出: 键'班级'不存在
}
// 解释:array_key_exists()返回布尔值,明确检查键存在性,适用于严格验证场景

// 示例6: 使用foreach循环遍历关联数组,并演示错误处理
$employee = ["姓名" => "王五", "部门" => "技术"];
foreach ($employee as $key => $value) {
    echo "$key: $value\n"; // 安全输出,因为foreach自动处理键存在性
}
// 解释:foreach循环自动迭代每个键值对,无需手动检查键,但前提是数组结构正确;在动态键访问时仍需验证
?>

1.4 使用print_r和var_dump输出数组

print_r和var_dump是PHP中用于调试和输出数组内容的函数。print_r以可读格式显示数组结构,适合快速查看;var_dump提供更详细信息,包括数据类型和长度,适用于深度调试。在开发中,这些工具帮助理解数组内容,避免错误。使用它们时,注意在生产环境中移除调试输出以保护敏感数据。

代码示例:

php 复制代码
<?php
// 示例1: 使用print_r输出索引数组
$indexArray = [1, 2, 3];
echo "print_r输出:\n";
print_r($indexArray); // 输出: Array ( [0] => 1 [1] => 2 [2] => 3 )
// 解释:print_r简洁显示数组索引和值

// 示例2: 使用var_dump输出关联数组
$assocArray = ["键1" => "值1", "键2" => 100];
echo "var_dump输出:\n";
var_dump($assocArray); // 输出类型和值,如string(3) "值1"
// 解释:var_dump显示数据类型和长度,用于调试

// 示例3: 比较print_r和var_dump的区别
$sample = ["a" => "文本", "b" => 42];
echo "print_r:\n";
print_r($sample);
echo "var_dump:\n";
var_dump($sample);
// 解释:print_r更简洁,var_dump更详细

// 示例4: 在HTML中格式化输出数组
$webArray = ["标题" => "首页", "内容" => "欢迎"];
echo "<pre>"; // 用于HTML中保持格式
print_r($webArray);
echo "</pre>";
// 解释:<pre>标签使输出在网页中更易读

// 示例5: 输出多维数组(为后续章节铺垫)
$multiArray = ["用户" => ["姓名" => "王五", "年龄" => 30]];
echo "多维数组print_r:\n";
print_r($multiArray);
// 解释:数组可以嵌套,print_r递归显示结构

// 示例6: 使用var_dump调试未定义数组元素
$testArray = ["x" => 10];
// 假设尝试访问不存在的键
if (isset($testArray["y"])) {
    var_dump($testArray["y"]);
} else {
    echo "键'y'未定义,使用var_dump前检查:\n";
    var_dump($testArray); // 只输出已定义部分
}
// 解释:结合错误处理使用输出函数,避免调试时未定义错误,提升代码安全性
?>

1.5 数组的基本操作

基本操作包括获取数组长度、检查空数组、合并数组等,这些是处理数组的基础。例如,count()函数返回元素数量,empty()检查数组是否为空。掌握这些操作能提高代码效率,避免常见错误。在本节中,我们扩展数组合并与切片内容,添加array_merge+运算符的详细对比案例,以帮助学习者理解不同合并规则。

代码示例:

php 复制代码
<?php
// 示例1: 使用count()获取数组长度
$items = ["电脑", "鼠标", "键盘"];
$length = count($items);
echo "数组长度: $length\n"; // 输出: 3
// 解释:count()返回元素个数,常用于循环条件

// 示例2: 检查数组是否为空
$emptyCheck = [];
if (empty($emptyCheck)) {
    echo "数组为空\n";
} else {
    echo "数组非空\n";
}
// 解释:empty()函数判断数组是否有元素

// 示例3: 获取数组所有键和值
$arrayKeys = ["x" => 10, "y" => 20];
$keys = array_keys($arrayKeys);
$values = array_values($arrayKeys);
echo "键: ";
print_r($keys); // 输出: Array ( [0] => x [1] => y )
echo "值: ";
print_r($values); // 输出: Array ( [0] => 10 [1] => 20 )
// 解释:array_keys和array_values提取键和值数组

// 示例4: 数组合并使用+运算符
$array1 = ["a" => 1, "b" => 2];
$array2 = ["c" => 3, "b" => 4]; // 键b冲突
$merged = $array1 + $array2; // 保留$array1的键b
echo "合并后数组: ";
print_r($merged); // 输出: Array ( [a] => 1 [b] => 2 [c] => 3 )
// 解释:+运算符优先第一个数组的键,不覆盖重复键

// 示例5: 基本切片使用array_slice
$original = [1, 2, 3, 4, 5];
$sliced = array_slice($original, 1, 2); // 从索引1开始取2个元素
echo "切片数组: ";
print_r($sliced); // 输出: Array ( [0] => 2 [1] => 3 )
// 解释:array_slice用于提取部分数组,参数为起始索引和长度

// 示例6: 使用array_merge合并数组并处理键冲突
$indexArray1 = [1, 2];
$indexArray2 = [3, 4];
$mergedIndex = array_merge($indexArray1, $indexArray2);
echo "array_merge合并索引数组: ";
print_r($mergedIndex); // 输出: Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 )
// 解释:array_merge重新索引数字键,合并多个数组

$assocArray1 = ["a" => 1, "b" => 2];
$assocArray2 = ["b" => 3, "c" => 4];
$mergedAssoc = array_merge($assocArray1, $assocArray2); // 后者覆盖前者键
echo "array_merge合并关联数组: ";
print_r($mergedAssoc); // 输出: Array ( [a] => 1 [b] => 3 [c] => 4 )
// 解释:array_merge处理键冲突时,后面数组的值覆盖前面

// 示例7: 对比array_merge和+运算符的合并行为
$baseArray = ["x" => 10, "y" => 20];
$overrideArray = ["y" => 30, "z" => 40];
$mergeResult = array_merge($baseArray, $overrideArray); // y被覆盖
$plusResult = $baseArray + $overrideArray; // y保留base值
echo "array_merge结果: ";
print_r($mergeResult); // 输出: Array ( [x] => 10 [y] => 30 [z] => 40 )
echo "+运算符结果: ";
print_r($plusResult); // 输出: Array ( [x] => 10 [y] => 20 [z] => 40 )
// 解释:array_merge覆盖重复键,+运算符保留第一个数组的键;根据需求选择合并方式

// 示例8: 数组合并错误处理 - 检查数组合并前是否为空
$arrayA = [];
$arrayB = [1, 2];
$mergedSafe = array_merge($arrayA, $arrayB);
echo "安全合并: ";
print_r($mergedSafe); // 输出: Array ( [0] => 1 [1] => 2 )
// 解释:即使一个数组为空,array_merge也能正确处理,避免错误
?>

实战项目展示

本章包含两个实战项目,帮助您综合应用所学知识。项目基于真实场景设计,代码完整可运行。我们增强了项目注释和逻辑解释,以提升零基础学习者的理解度。

项目1: 创建个人信息数组并输出

项目描述 :构建一个关联数组存储个人信息(姓名、年龄、爱好),并使用循环输出所有内容。通过这个项目,学习者将熟悉数组的初始化和基本遍历,同时实践错误处理。
代码实现

php 复制代码
<?php
// 定义个人信息数组
$personalInfo = [
    "姓名" => "张三",
    "年龄" => 28,
    "爱好" => ["读书", "游泳", "编程"] // 爱好为索引数组,演示嵌套数组
];

// 使用foreach循环输出信息 - 添加详细步骤注释
echo "个人信息:\n";
foreach ($personalInfo as $key => $value) {
    // 步骤1: 检查值是否为数组,使用is_array函数
    if (is_array($value)) {
        // 如果值是数组,使用implode函数将数组元素连接为字符串输出
        echo "$key: " . implode(", ", $value) . "\n"; // implode用逗号分隔爱好
        // 解释:implode将数组转换为字符串,便于阅读;这模拟了处理多维数组的简单场景
    } else {
        // 如果值不是数组,直接输出键值对
        echo "$key: $value\n";
    }
}

// 额外:使用print_r查看数组结构,并添加错误处理检查
echo "数组结构:\n";
if (isset($personalInfo) && is_array($personalInfo)) {
    print_r($personalInfo); // 安全输出,确保数组已定义
} else {
    echo "数组未定义或不是数组类型。\n"; // 错误处理消息
}
?>

项目解释 :本项目中,我们使用关联数组存储结构化数据,并通过循环动态输出。关键点包括:使用is_array检查嵌套数组,implode处理数组值输出,以及添加数组存在性验证。这模拟了Web开发中用户资料显示的场景,帮助学习者理解数组遍历和错误处理的重要性。

项目2: 简单数字数组统计

项目描述 :创建一个索引数组存储数字,计算总和和平均值,并输出结果。项目强调基本操作如count()和循环的结合使用,同时集成错误处理。
代码实现

php 复制代码
<?php
// 定义数字数组
$numbers = [10, 20, 30, 40, 50];

// 计算总和和平均值 - 添加步骤注释和错误处理
// 步骤1: 检查数组是否为空,避免除零错误
if (empty($numbers)) {
    echo "数组为空,无法计算。\n";
    exit; // 提前退出,防止后续错误
}

// 步骤2: 使用array_sum计算总和,count获取长度
$sum = array_sum($numbers);
$average = $sum / count($numbers);

// 输出结果
echo "数字数组: ";
print_r($numbers);
echo "总和: $sum\n";
echo "平均值: " . round($average, 2) . "\n"; // 使用round保留两位小数

// 使用循环验证总和 - 添加索引检查
$manualSum = 0;
for ($i = 0; $i < count($numbers); $i++) {
    if (isset($numbers[$i])) { // 检查每个索引是否存在
        $manualSum += $numbers[$i];
    } else {
        echo "警告: 索引 $i 不存在,跳过计算。\n"; // 处理潜在问题
    }
}
echo "手动计算总和: $manualSum\n"; // 应与array_sum一致

// 额外:演示使用isset避免未定义错误在统计中
$testArray = [1, 2, null, 4]; // 包含null元素
$safeSum = 0;
foreach ($testArray as $index => $value) {
    if (isset($value)) { // 检查值是否已设置,跳过null
        $safeSum += $value;
    }
}
echo "安全总和(跳过null): $safeSum\n"; // 输出: 7
?>

项目解释:此项目演示了数组在数学计算中的应用,强调基本操作如count()和循环的结合使用。我们添加了空数组检查、索引验证和null值处理,以提升代码健壮性。通过本项目,学习者能理解错误处理在真实场景中的必要性。

最佳实践和避坑指南

  • 使用描述性键名:在关联数组中,键名应清晰表达含义,例如用"email"而非"e",提高代码可读性。
  • 检查索引/键是否存在:访问数组前使用isset()或array_key_exists(),避免未定义错误。例如,if(isset($array['key']))。在循环中,始终验证索引或键。
  • 优先使用短数组语法:[]比array()更简洁,适用于PHP 5.4及以上版本。
  • 避免硬编码索引:在循环中使用count()动态获取长度,而不是固定数字,以处理可变大小数组。
  • 调试时选择合适工具:快速查看用print_r,详细调试用var_dump;在生产环境中移除调试输出。
  • 数组合并注意键冲突:使用+运算符时,第一个数组的键优先;array_merge覆盖重复键。根据需求选择,例如用array_merge处理关联数组覆盖,用+保留原始数据。
  • 初始化为空数组:在动态构建数组时,先初始化为[],防止未定义变量错误。
  • 错误处理集成到基本操作:在数组访问、合并和遍历中,添加条件检查,例如使用isset()防止越界访问。
  • 使用内置函数优化:如array_sum和count,它们比自定义循环更高效,减少代码量。

练习题和技能挑战

设计5-8个练习题,涵盖概念理解、代码编写和实际应用,帮助巩固知识。每个练习包括说明和提示。我们扩展了练习题数量,并增加实际应用场景题目,以增强实用性。

  1. 选择题 :以下哪个是创建索引数组的正确语法?

    A. $arr = array("a" => 1, "b" => 2)

    B. $arr = [1, 2, 3]

    C. $arr = array(1 => "a", 2 => "b")

    D. $arr = []
    答案:B和D(B为索引数组,D为空数组)。解释:A和C是关联数组。

  2. 代码填空:补全代码,创建一个关联数组存储产品(键:名称、价格),并输出价格。

    php 复制代码
    $product = [______ => "手机", "price" => 2000];
    echo "价格: " . $product[______];

    答案:第一空填"name",第二空填"price"。提示:使用字符串键访问。

  3. 代码调试:以下代码有错误,请修复并说明原因。

    php 复制代码
    $arr = [1, 2, 3];
    echo $arr[3];

    答案:索引3不存在,应改为$arr[2]或添加检查。修复代码:

    php 复制代码
    $arr = [1, 2, 3];
    if (isset($arr[3])) {
        echo $arr[3];
    } else {
        echo "索引3不存在";
    }

    解释:索引从0开始,最大为2;使用isset()避免未定义错误。

  4. 开放任务 :创建一个数组存储5个朋友的名字,使用for循环输出每个名字及其索引。添加错误处理,检查索引是否存在。
    示例答案

    php 复制代码
    $friends = ["Alice", "Bob", "Charlie", "Diana", "Eve"];
    for ($i = 0; $i < count($friends); $i++) {
        if (isset($friends[$i])) {
            echo "索引 $i: $friends[$i]\n";
        } else {
            echo "索引 $i 不存在\n";
        }
    }
  5. 技能挑战 :编写一个脚本,定义两个数组(一个索引、一个关联),使用print_r和var_dump分别输出,并比较差异。添加代码检查数组是否定义。
    提示:关注输出格式和详细信息,使用isset()确保数组存在。

  6. 应用题 :模拟一个购物车,创建一个数组存储3个商品名称,然后添加一个新商品,并输出最终列表。使用错误处理确保添加操作安全。
    示例答案

    php 复制代码
    $cart = ["书", "笔"];
    if (is_array($cart)) {
        $cart[] = "笔记本";
        print_r($cart);
    } else {
        echo "购物车未初始化\n";
    }
  7. 扩展练习 :使用关联数组存储学生信息(姓名、年龄、成绩),计算平均成绩(假设成绩为数字)。添加输入验证,检查成绩是否为数字。
    提示 :用array_sum和count,注意数据类型;使用is_numeric验证。
    示例答案

    php 复制代码
    $students = [
        ["姓名" => "张三", "成绩" => 85],
        ["姓名" => "李四", "成绩" => "90"] // 成绩为字符串
    ];
    $total = 0;
    $count = 0;
    foreach ($students as $student) {
        if (isset($student["成绩"]) && is_numeric($student["成绩"])) {
            $total += $student["成绩"];
            $count++;
        }
    }
    if ($count > 0) {
        echo "平均成绩: " . ($total / $count);
    } else {
        echo "无有效成绩数据";
    }
  8. 错误处理挑战 :写一个代码片段,尝试访问不存在的数组键,并使用isset()和array_key_exists()两种方法避免错误。比较这两种方法。
    示例

    php 复制代码
    $data = ["a" => 1];
    // 方法1: isset
    if (isset($data["b"])) {
        echo $data["b"];
    } else {
        echo "键b不存在(isset)\n";
    }
    // 方法2: array_key_exists
    if (array_key_exists("b", $data)) {
        echo $data["b"];
    } else {
        echo "键b不存在(array_key_exists)\n";
    }
    // 解释:isset()检查键存在且值不为null,array_key_exists()只检查键存在。
  9. 实际应用场景题目 :模拟表单数据存储,创建一个数组接收用户输入(例如姓名、邮箱),然后输出数据。添加验证确保输入非空。
    示例答案

    php 复制代码
    // 模拟表单数据
    $formData = [];
    $formData["姓名"] = "赵六"; // 假设用户输入
    $formData["邮箱"] = "zhao@example.com";
    // 验证并输出
    if (!empty($formData)) {
        foreach ($formData as $key => $value) {
            if (!empty(trim($value))) {
                echo "$key: $value\n";
            } else {
                echo "$key 为空,跳过输出\n";
            }
        }
    } else {
        echo "无表单数据\n";
    }

章节总结

本章介绍了数组的基本概念,包括定义、索引数组和关联数组的创建与访问、输出工具print_r和var_dump的使用,以及基本操作如获取长度和合并。通过大量代码示例和实战项目,您学会了如何初始化数组、遍历元素和处理常见场景。关键要点包括:数组简化数据管理、索引从0开始、关联数组使用键值对、调试工具增强代码理解,以及错误处理(如使用isset())提升代码健壮性。练习和挑战帮助巩固了动手能力,新增的实际应用题目增强了实用性。在下一章,我们将深入数组操作和遍历技巧,构建更动态的应用。继续实践这些基础,为高级主题做好准备。

相关推荐
t198751281 小时前
基于因子图与和积算法的MATLAB实现
开发语言·算法·matlab
APIshop1 小时前
Java爬虫第三方平台获取1688关键词搜索接口实战教程
java·开发语言·爬虫
请为小H留灯1 小时前
Java快捷健(详细版)
java·开发语言
小年糕是糕手1 小时前
【C++同步练习】C++入门
开发语言·数据结构·c++·算法·pdf·github·排序算法
Lethehong1 小时前
openGauss在教育领域的AI实践:基于Java JDBC的学生成绩预测系统
java·开发语言·人工智能·sql·rag
零匠学堂20251 小时前
OfficeOnlineServer文件在线浏览方案之OWA部署方法
开发语言·officeonline
未来之窗软件服务1 小时前
幽冥大陆(三十六)S18酒店门锁SDK rust语言——东方仙盟筑基期
开发语言·c++·rust·智能门锁·东方仙盟sdk·东方仙盟一体化
e***19351 小时前
MySQL-触发器(TRIGGER)
android·数据库·mysql
不会写代码的猴子2 小时前
Android16
android