JavaSE-项目小结-IP归属地查询(本地IP地址库)

一、项目介绍

        1. 背景

           IP地址是网络通信中的重要标识,通过分析IP地址的归属地信息,可以帮助我们了解访问来源、用户行为和网络安全等关键信息。例如应用于网站访问日志分析:通过分析访问日志中的IP地址,了解网站访问者的地理位置分布和访问行为,优化网站内容和用户体验。

        2. 需求

        IP分析,返回归属地信息,要求在毫秒内完成。

        3. 涉及技术栈

        Eclipse的使用,JavaSE中面向对象,IO流,二分法查找,集合。

        4. 目的

        通过IP归属地查询项目,巩固javaSE部分所学知识,增强实战能力。

        需具备以下能力:1.面向对象程序设计。

                                     2.工具类的封装与使用。

                                     3. 文件IO流操作。

                                     4. 字符串处理。

                                     5. 二分法查找。

二、主要思路

        1. 读取提供的地址库文件,解析地址库字符串,转换为结构化数据

        2. 封装对应的数据结构,进行查询。

        3. 封装对应的相关工具类。

        4. 对外提供接口,只需要入参和出参(入参:IP地址,出参:归属地)。

三、代码开发

        创建utils包,存放工具类

        创建pojo包,存放实体类

        创建manager包,存储管理类,业务代码

        创建controller包,存储程序入口类

        1.  文件读取,封装为工具类

             编写文件读取工具类,用于读取本地IP地址库文件中的数据。当前类放于Utils包下。

package com.zh.utils;import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;public class FileReadUtil {// 默认编码方式private static String defaultencoding = "UTF-8";public static List<String> FileRead(String filePath, String encoding) throws IOException{// 通过类加载器获取流,防止打包后无法获取IP文件InputStream is =  FileReadUtil.class.getClassLoader().getResourceAsStream(filePath);// 字节流// FileInputStream fis = new FileInputStream(filePath);// 转字符流Reader read = new InputStreamReader(is,encoding);// 缓冲流BufferedReader br = new BufferedReader(read);String temp = null;// 集合存储数据List<String> list = new ArrayList<String>();// 逐行读取while((temp = br.readLine()) != null) {list.add(temp);}br.close();return list;}// 提供无参的方法,以默认编码方式为参数,调用有参的方法public static List<String> FileRead(String filePath) throws IOException{return FileRead(filePath,defaultencoding);}}

        2.  抽象Pojo类,用于数据结构化

        根据地址库中的IP地址及其归属地的存储格式(1.0.0.0    1.0.0.255    澳大利亚 亚太互联网络信息中心),创建实体类。实体类属性包括IP起始地址,IP结束地址,归属地,IP起始地址的long类型数值,IP结束地址的long类型数值。IP地址转换为long类型,用于后续对IP地址进行排序。

        实体类实现Comparable接口,用于自定义比较规则,覆写comparaTo方法,根据起始IP地址进行比较。

        实体类实现Serializable接口,可对当前对象进行序列化操作。

package com.zh.pojo;import java.io.Serializable;import com.zh.utils.IPUtil;public class IPAndLocationPojo implements Comparable<IPAndLocationPojo>, Serializable {private static final long serialVersionUID = 1L;/*** 起始IP*/private String startIP;/*** 结束IP*/private String endIP;/*** 归属地*/private String location;/*** 起始地址转long类型*/private long startIPLong;/*** 结束地址转long类型*/private long endIPLong;public IPAndLocationPojo() {super();}public IPAndLocationPojo(String startIP, String endIP, String location) {super();this.startIP = startIP;this.endIP = endIP;this.location = location;this.startIPLong = IPUtil.ipToLong(startIP);this.endIPLong = IPUtil.ipToLong(endIP);}public String getStartIP() {return startIP;}public void setStartIP(String startIP) {this.startIP = startIP;}public String getEndIP() {return endIP;}public void setEndIP(String endIP) {this.endIP = endIP;}public String getLocation() {return location;}public void setLocation(String location) {this.location = location;}public long getStartIPLong() {return startIPLong;}public long getEndIPLong() {return endIPLong;}@Overridepublic String toString() {return "IPAndLocationPojo [startIP=" + startIP + ", endIP=" + endIP + ", location=" + location+ ", startIPLong=" + startIPLong + ", endIPLong=" + endIPLong + "]";}@Overridepublic int compareTo(IPAndLocationPojo o) {long result = this.startIPLong - o.getStartIPLong();if(result > 0) {return 1; // 正序}else if(result < 0) {return -1; // 倒序}else {return 0;}}}

        3. 结构化数据

        调用文件读取工具类,返回一个集合,集合中的每一条数据,即为文件中的一行。

        遍历集合,取出每一条数据,根据制表符(\t)分割,存储到数组中,此时数组中下标为0的位置存储的为IP起始地址的字符串,下标为1的位置存储的是IP结束地址的字符串,下标为2的位置存储的为归属地信息。

        将数组中的数据封装为对象,后添加到ArrayList集合中,此时ArrayList中每一个元素即为一个IP归属地对象。

/*** 结构化数据* @param filePath* @param encoding* @return* @throws IOException*/public static List<IPAndLocationPojo> getPojoList(String filePath, String encoding) throws IOException{// 获取数据List<String> list = FileReadUtil.FileRead(filePath, encoding);// 封装结构化后的数据List<IPAndLocationPojo> pojoList = new ArrayList<IPAndLocationPojo>();// 逐条遍历取出数据for(String string : list) {// 跳过空行if(string == null || string.trim().equals("")) {continue;}// 分割字符串String[] strs = string.split("\t");// 跳过不合规的数组if(strs.length != 3) {continue;}String startIP = strs[0];String endIP = strs[1];String location = strs[2];IPAndLocationPojo ipPojo = new IPAndLocationPojo(startIP, endIP, location);pojoList.add(ipPojo);}return pojoList;		}

        4. 集合转数组并排序

        由于实体类中存储的起始IP和结束IP为字符串类型,默认排序规则不符合要求,所以需要提供工具类,将实体类中起始IP地址和结束IP地址的字符串转换为long类型,为实体类中添加long类型的起始IP和结束IP,并实现Comparable接口,覆写comparaTo方法来自定义比较规则。

        工具类:

package com.zh.utils;import java.util.Scanner;/*** Ip地址转换*/
public class IPUtil {/*** ip地址字符串转long类型* * @param ipString* @return*/public static long ipToLong(String ipString) {String[] str = ipString.split("\\.");return (Long.parseLong(str[0]) << 24) + (Long.parseLong(str[1]) << 16) + (Long.parseLong(str[2]) << 8)+ Long.parseLong(str[3]);}/*** long 类型数转Ip地址* * @param ipLong* @return*/public static String longToIP(long ipLong) {StringBuffer sb = new StringBuffer("");sb.append(String.valueOf(ipLong >> 24)).append(".").append(String.valueOf((ipLong & 0x00ffffff) >> 16)).append(".").append(String.valueOf((ipLong & 0x0000ffff) >> 8)).append(".").append(String.valueOf(ipLong & 0x000000ff));return sb.toString();}
}
/*** 将对象集合转换为数组并排序* @param ipPojoList* @return*/public static IPAndLocationPojo[] IpPojoArray(List<IPAndLocationPojo> ipPojoList) {// 集合转数组IPAndLocationPojo[] ipPojoArray = new IPAndLocationPojo[ipPojoList.size()];ipPojoList.toArray(ipPojoArray);// 数组排序Arrays.sort(ipPojoArray);return ipPojoArray;}

        5. 二分法查找

        根据用户输入的IP地址,采用二分法在已经排序好的数组中,查找IP的归属地信息。

由于IP地址库中存储的IP为一段地址范围,所以每次判断中间索引的起始地址小于用户输入地址后,需要在判断中间索引的结束地址是否大于用户输入IP,如果满足条件说明用户输入的IP地址位于当前中间索引起始地址所在的IP地址段,直接返回中间索引的IP归属地即为用户的IP归属地,

/*** 根据用户输入的地址查寻归属地* @param userIp* @param arr* @return*/public static String searchIP(String userIp, IPAndLocationPojo[] arr) {// 将用户输入的IP转换为long型long userIP = IPUtil.ipToLong(userIp);int height = arr.length - 1;int low = 0;// 二分查找while(low <= height) {int mid =(height + low) / 2;// 当中间索引的起始IP大于用户输入IP时,结束索引等于中间索引-1if(arr[mid].getStartIPLong() > userIP) {height = mid - 1;// 当中间索引的结束IP地址大于等于用户输入IP时,返回当前归属地信息}else if(arr[mid].getEndIPLong() >= userIP){	return arr[mid].getLocation();}else {low = mid + 1;}}return null;	}

        6. 封装接口类

        封装接口,对外只提供获取归属地的方法,入参:IP地址, 出参:归属地

        静态代码块中为数组中数据的初始化工作,保证每次执行只执行一次,不需要重复结构化数据,提高效率。文中代码对排序好的数组执行了序列化操作,也可以不进行序列化。

        序列化工具类:

package com.zh.utils;import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;public class FileSerializationUtil {// 序列化对象public static void SerializationObject(String path, Object arr) {try (FileOutputStream fos = new FileOutputStream(path);BufferedOutputStream bos = new BufferedOutputStream(fos);ObjectOutputStream oos = new ObjectOutputStream(bos);) {oos.writeObject(arr);oos.flush();} catch (Exception e) {e.printStackTrace();}}// 对象反序列化public static Object DeserializationObject(String path) {Object obj = null;try (FileInputStream fis = new FileInputStream(path);BufferedInputStream bis = new BufferedInputStream(fis);ObjectInputStream ois = new ObjectInputStream(bis);){obj = ois.readObject();} catch (Exception e) {e.printStackTrace();}return obj;}}

        IP地址校验工具类:用于校验用户输入IP地址是否符合规范。

package com.zh.utils;import java.util.regex.Matcher;
import java.util.regex.Pattern;// IP地址校验
public class IPCheckUtil {// 正则表达式IP地址验证规则private static final String IP_PATTERN = "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$";// 创建匹配模式private static final Pattern pattern = Pattern.compile(IP_PATTERN);// 匹配IP地址public static boolean checkIP(String ipString) {		Matcher matcher = pattern.matcher(ipString);return matcher.matches();}
}

        管理类中代码对外提供接口的方法

private static final String IP_ILLEGAL = "IP地址不合法";private static final String SERIALIZED_FILE_PATH = "./serialized_ip_data.ser";private static IPAndLocationPojo[] arr = null;// 静态语句块只加载一次static {File serializedPath = new File(SERIALIZED_FILE_PATH);if(serializedPath.exists()) {arr = (IPAndLocationPojo[])FileSerializationUtil.DeserializationObject(SERIALIZED_FILE_PATH);}else {// 本地IP地址库String filePath = "ip_location_relation.txt";// 编码方式String encoding = "UTF-8";List<IPAndLocationPojo> list = null;try {// 数据结构化list = DataProcessManager.getPojoList(filePath, encoding);// 转换为数组并排序arr = DataProcessManager.IpPojoArray(list);FileSerializationUtil.SerializationObject(SERIALIZED_FILE_PATH, arr);} catch (IOException e) {e.printStackTrace();}}}/*** 获取IP归属地* @param ipString* @return* @throws IOException*/public static String ipLocationSer(String ipString){// 校验IP地址是否合法if (IPCheckUtil.checkIP(ipString)) {// IP地址合法,查询归属地String ipuser = DataProcessManager.searchIP(ipString, arr);return ipuser;} else {return IP_ILLEGAL;}}

        7. 入口类

        充当程序入口,执行main方法。

package com.zh.controller;import java.io.IOException;
import java.util.List;
import java.util.Scanner;import com.zh.manage.DataProcessManager;
import com.zh.pojo.IPAndLocationPojo;
import com.zh.utils.IPCheckUtil;//入口类
public class SystemController {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);System.out.println("请输入要查询的IP地址:");String ip = null;while((ip = scanner.next())!= null) {// long startTime = System.currentTimeMillis();String location = DataProcessManager.ipLocationSer(ip);System.out.println(location);// System.out.println("耗时: " + (System.currentTimeMillis() - startTime));System.out.println("请输入要查询的IP地址:");}}	
}

             管理类完整代码:

package com.zh.manage;import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;import com.zh.pojo.IPAndLocationPojo;
import com.zh.utils.FileReadUtil;
import com.zh.utils.FileSerializationUtil;
import com.zh.utils.IPCheckUtil;
import com.zh.utils.IPUtil;/*** 管理类*/
public class DataProcessManager {private static final String IP_ILLEGAL = "IP地址不合法";private static final String SERIALIZED_FILE_PATH = "./serialized_ip_data.ser";private static IPAndLocationPojo[] arr = null;// 静态语句块只加载一次static {File serializedPath = new File(SERIALIZED_FILE_PATH);if(serializedPath.exists()) {arr = (IPAndLocationPojo[])FileSerializationUtil.DeserializationObject(SERIALIZED_FILE_PATH);}else {// 本地IP地址库String filePath = "ip_location_relation.txt";// 编码方式String encoding = "UTF-8";List<IPAndLocationPojo> list = null;try {// 数据结构化list = DataProcessManager.getPojoList(filePath, encoding);// 转换为数组并排序arr = DataProcessManager.IpPojoArray(list);FileSerializationUtil.SerializationObject(SERIALIZED_FILE_PATH, arr);} catch (IOException e) {e.printStackTrace();}}}/*** 获取IP归属地* @param ipString* @return* @throws IOException*/public static String ipLocationSer(String ipString){// 校验IP地址是否合法if (IPCheckUtil.checkIP(ipString)) {// IP地址合法,查询归属地String ipuser = DataProcessManager.searchIP(ipString, arr);return ipuser;} else {return IP_ILLEGAL;}}/*** 结构化数据* @param filePath* @param encoding* @return* @throws IOException*/private static List<IPAndLocationPojo> getPojoList(String filePath, String encoding) throws IOException{// 获取数据List<String> list = FileReadUtil.FileRead(filePath, encoding);// 封装结构化后的数据List<IPAndLocationPojo> pojoList = new ArrayList<IPAndLocationPojo>();// 逐条遍历取出数据for(String string : list) {// 跳过空行if(string == null || string.trim().equals("")) {continue;}// 分割字符串String[] strs = string.split("\t");// 跳过不合规的数组if(strs.length != 3) {continue;}String startIP = strs[0];String endIP = strs[1];String location = strs[2];IPAndLocationPojo ipPojo = new IPAndLocationPojo(startIP, endIP, location);pojoList.add(ipPojo);}return pojoList;		}/*** 将对象集合转换为数组并排序* @param ipPojoList* @return*/private static IPAndLocationPojo[] IpPojoArray(List<IPAndLocationPojo> ipPojoList) {// 集合转数组IPAndLocationPojo[] ipPojoArray = new IPAndLocationPojo[ipPojoList.size()];ipPojoList.toArray(ipPojoArray);// 数组排序Arrays.sort(ipPojoArray);return ipPojoArray;}/*** 根据用户输入的地址查寻归属地* @param userIp* @param arr* @return*/private static String searchIP(String userIp, IPAndLocationPojo[] arr) {// 将用户输入的IP转换为long型long userIP = IPUtil.ipToLong(userIp);int height = arr.length - 1;int low = 0;// 二分查找while(low <= height) {int mid =(height + low) / 2;// 当中间索引的起始IP大于用户输入IP时,结束索引等于中间索引-1if(arr[mid].getStartIPLong() > userIP) {height = mid - 1;// 当中间索引的结束IP地址大于等于用户输入IP时,返回当前归属地信息}else if(arr[mid].getEndIPLong() >= userIP){	return arr[mid].getLocation();}else {low = mid + 1;}}return null;	}}

          运行结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/661376.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Duplicate entry ‘2020045-2-1‘ for key ‘index_uid‘ 解决方案

项目场景&#xff1a; 今天小编在工作中编写接口对数据库增加相同的非主键数据的时候&#xff0c;突然出现了这样的一个错误&#xff1a; 下面我来给大家解答这个错误的出现原因以及解决办法。 问题描述 Duplicate entry 2020045-2-1 for key index_uid 这个错误大概意思就是…

企业的多域名SSL证书

多域名SSL证书作为一种加密通信的方式&#xff0c;可以有效保护多个网站的用户数据在传输过程中的安全。不管个人或者企事业单位 都可以申请多域名SSL证书&#xff0c;提高网站的安全性&#xff0c;保护网站数据传输安全。今天就随SSL盾了解多域名SSL证书旗下的企业多域名SSL证…

深度解读NVMe计算存储协议-3

在NVMe计算存储架构中&#xff0c;Copy命令用于在不同类型的命名空间之间进行数据复制&#xff1a; Memory Copy命令&#xff1a;定义于SLM&#xff08;Subsystem Local Memory&#xff09;命令集&#xff0c;主要用于从非易失性存储命名空间&#xff08;NVM namespaces&#x…

ERP系统助力车间生产:班组、设备、工序一网打尽!实现生产全流程可视化!

​随着企业生产规模的扩大和业务复杂性的增加&#xff0c;车间管理在企业运营中的地位日益突出。ERP系统作为企业资源管理的核心平台&#xff0c;为车间管理提供了全面的解决方案。通过合理配置和使用ERP系统的功能模块&#xff0c;企业可以优化生产流程、提高生产效率、确保产…

SOME/IP SD 协议介绍(二) SOME/IP-SD消息格式

SOME/IP-SD消息格式 通用要求 服务发现消息应通过UDP进行支持。准备将服务发现消息传输到TCP中以供将来使用情况。服务发现消息应以SOME/IP头开始&#xff0c;如图1所示&#xff1a; • 服务发现消息应使用0xFFFF的Service-ID&#xff08;16位&#xff09;。 • 服务发现消息…

榜单!高阶智驾冲刺10%搭载率,哪些玩家占据自研感知「高地」

得「感知」者&#xff0c;是智能化尤其是智能驾驶技术变革快速演进期的受益者。尤其是对于车企来说&#xff0c;规控自研易&#xff0c;感知自研难。 尤其是过去几年时间&#xff0c;基于机器学习和深度学习&#xff0c;TransformerBEV技术进一步提高对异常行为的预测准确性&am…

CHS_06.2.3.4_2+用信号量实现进程互斥、同步、前驱关系

CHS_06.2.3.4_2用信号量实现进程互斥、同步、前驱关系 知识总览信号量机制实现进程互斥信号量机制实现进程同步信号量机制实现前驱关系 知识回顾 各位同学 大家好 在这个小节中 我们要学习怎么用信号量机制来实现进程的同步互制关系 知识总览 那么 我们之前学习了互斥的几种软…

只有一台显示器,如何实现同时显示4台主机的HDMI信号?

HDMI画面分割器概述 HDMI画面分割器属于画面分割器中的一种&#xff0c;因为其信号接口是HDMI接口而得其名&#xff0c;多用于监控、多媒体、视频会议等常见的场景 HDMI画面分割器-图 HDMI画面分割器工作原理 使用硬件方式将多路HDMI信号以多种不同的模式分割显示在同一个显示…

香蕉派BPI-M7 瑞芯微RK3588 人工智能开源硬件开发板公开发售

香蕉派(Banana Pi) BPI-M7瑞芯微K3588开源硬件单板计算机公开销售&#xff0c;支持WiFi 6和BT5.2&#xff0c;硬件有3个版本:8G Ram64G eMMC, 16G Ram128 eMMC和32G Ram128 eMMC 香蕉派BPI-M7采用睿芯最新旗舰RK3588八核64位处理器&#xff0c;最高频率为2.4GHz, 6 TOPS NPU&…

谷歌把GenAI装进Chrome

谷歌不甘示弱&#xff0c;在其Chrome浏览器中引入了新的实验性生成式AI功能&#xff0c;以简化并为用户提供更高效的浏览体验。 值得注意的是&#xff0c;微软去年推出了Edge浏览器和人工智能驱动的必应搜索引擎的集成。随着Chrome M121版本的发布&#xff0c;谷歌打算利用最新…

2024年美赛赛前复习大纲

CC数模-优质解答 引言 数学建模是一个将数学理论和方法应用于解决现实世界问题的过程。在数学建模比赛中&#xff0c;学生需要运用自己的数学知识和技能&#xff0c;解决给定的复杂问题。这不仅是一次展示自己能力的机会&#xff0c;也是一次学习和成长的过程。随着比赛的临近…

Wheeltec小车的开发实录(2)

小车初步启动控制 小车终端运行l: roslaunch turn_on_wheeltec_robot turn_on_wheeltec_robot.launch 控制终端运行&#xff08;多机通讯设置后&#xff0c;可以不必执行这一步&#xff09; export ROS_HOSTNAME192.168.224.122&#xff08;控制终端ip&#xff09;export R…

【Tomcat与网络8】从源码看Tomcat的层次结构

在前面我们介绍了如何通过源码来启动Tomcat&#xff0c;本文我们就来看一下Tomcat是如何一步步启动的&#xff0c;以及在启动过程中&#xff0c;不同的组件是如何加载的。 一般&#xff0c;我们可以通过 Tomcat 的 /bin 目录下的脚本 startup.sh 来启动 Tomcat&#xff0c;如果…

【HarmonyOS应用开发】UIAbility实践第二部分(六)

内容接上篇 【HarmonyOS应用开发】UIAbility实践第一部分&#xff08;五&#xff09; 末尾含示例源码 三、UIAbility的生命周期 当用户浏览、切换和返回到对应应用的时候&#xff0c;应用中的UIAbility实例会在其生命周期的不同状态之间转换。 UIAbility类提供了很多回调&a…

关于字符串处理

文章目录 关于字符串处理1、取字符串的长度2、跳过前面的字符3、取字符串右边的字符4、掐头去尾5、取倒数的范围6、删左留右7、删右留左8、查找替换9、大小写转换 关于字符串处理 1、取字符串的长度 [rootlocalhost ~]#strabcd1128 #定义变量 [rootlocalhost ~]#echo ${#str}…

IEEE| IceNet《IceNet for Interactive Contrast Enhancement》论文超详细解读(翻译+精读)

学习资料&#xff1a; 论文题目&#xff1a;《IceNet for Interactive Contrast Enhancement》&#xff08;用于交互式对比度增强的IceNet&#xff09;原文地址&#xff1a;export.arxiv.org/pdf/2109.05838v2.pdf 目录 ABSTRACT—摘要 翻译 精读 I. INTRODUCTION—简介 翻…

通俗易懂三大范式

通俗易懂三大范式 第一范式说的是每个字段不可再分 第二范式说的是不能存在部分依赖&#xff08;不能由联合主键的部分就可以推出其他字段&#xff0c;必须整个联合主键才能推出其他字段&#xff09; 第三范式说的是不能存在间接依赖(A&#xff08;主键&#xff09;→B,B→C…

瑞_23种设计模式_工厂模式

文章目录 1 什么是工厂模式案例案例代码 2 简单工厂模式&#xff08;Simple Factory&#xff09;2.1 简单工厂模式的结构2.2 案例改进——简单工厂模式2.3 案例改进代码实现2.4 简单工厂模式优缺点2.5 拓展——静态工厂 3 工厂方法模式&#xff08;Factory Method&#xff09;★…

【零基础学习CAPL】——CAN报文的发送(按下按钮同时周期性发送)

🙋‍♂️【零基础学习CAPL】系列💁‍♂️点击跳转 文章目录 1.概述2.面板创建3.系统变量创建4.CAPL实现4.1.函数展示4.2.全量报文展示5.效果1.概述 本章主要介绍使用CAPL和Panel在按下按钮时发送周期性CAN报文。 本章主要在“【零基础学习CAPL】——CAN报文的发送(配合P…

数组与字符串深度巩固

经过再三思考觉得今天就写一篇关于数组与字符串相关的文章吧&#xff01;其中字符串主要通过练习来巩固知识亦或是获得新知识。好接下来将进行我们的学习时刻了。 首先我们来思考一个问题&#xff0c;你真的了解数组的数组名吗&#xff1f;数组名真的就单单一个名字而已吗&…