当前位置: 首页 > news >正文

JDBC【封装工具类、SQL注入问题】

day54

JDBC

封装工具类01

创建配置文件

DBConfig.properties

driverName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/qnz01?characterEncoding=utf8&serverTimezone=UTC
username=root
password=root

新建配置文件,不用写后缀名
配置文件,不用写后缀

创建工具类

  1. 将变化的配置信息搬到配置文件中
  2. 工具类提供获取连接的方法
  3. 工具类提供关闭资源的方法
package com.qf.utils;/*** 数据库工具类*/
public class DBUtil {private static String url;private static String username;private static String password;static{//负责加载配置文件,只加载一次Properties properties = new Properties();try {properties.load(DBUtil.class.getClassLoader().getResourceAsStream("DBConfig.properties"));} catch (IOException e) {throw new RuntimeException(e);}String driverName = properties.getProperty("driverName");url = properties.getProperty("url");username = properties.getProperty("username");password = properties.getProperty("password");try {//加载驱动只加载一次Class.forName(driverName);} catch (ClassNotFoundException e) {throw new RuntimeException(e);}}/*** 获取连接对象*/public static Connection getConnection() throws SQLException {Connection connection = DriverManager.getConnection(url,username,password);return connection;}/*** 关闭资源*/public static void close(Connection connection, Statement statement, ResultSet resultSet){if(resultSet != null){try {resultSet.close();} catch (SQLException e) {throw new RuntimeException(e);}}if(statement != null){try {statement.close();} catch (SQLException e) {throw new RuntimeException(e);}}if(connection != null){try {connection.close();} catch (SQLException e) {throw new RuntimeException(e);}}}}
理解

(1)新建配置文件
把导入驱动包和获取连接对象的参数url、root、password写入配置文件
(2)将获取连接对象方法封装到工具类DBUtil
01:加载配置文件
new 一个配置文件对象,配置文件对象调用加载方法加载进来【报异常先用try-catch】
之后就可以配置文件对象调用方法拿到配置信息【注意要与配置文件的名字相同,否则找不到就是null】
02:导入驱动包

03:在获取连接对象方法里,调用方法获取连接对象,返回连接对象

04:对于关闭资源,不用每次都写,直接在工具类写个关闭资源方法传入可能关的资源,里面非空判断哪些要关就行了

注意:

通常会把加载配置文件和导入驱动包放在静态代码块里,提高效率,不用获取一次连接加载一次,加载一次就行
对于重复使用的属性先静态定义【注意静态代码块只能初始化静态的属性】

基本操作报错try-catch【例如类这里的forName类未找到异常就要么资源文件没导入,要么配置文件对应的名称没写对】,对于需要对应不同业务处理异常就需要抛异常,在外面处理

现在对于先前的增删改查就不用那么麻烦,每个都写导入驱动包和获取连接对象的一大坨代码,当然这里就涉及封装工具类
直接用工具类调用获取连接对象的方法,关闭资源方法

测试类

对day53的增删改查进行进一步优化

package com.qf.jdbc01;import com.qf.utils.DBUtil;
import org.junit.Test;import java.sql.*;public class Test01 {/*** 知识点:封装DBUtil - v1.0*///添加数据@Testpublic void test01() throws SQLException {//获取连接对象Connection connection = DBUtil.getConnection();//获取发送指令对象Statement statement = connection.createStatement();//发送SQL指令String sql = "INSERT INTO student(name,sex,age,salary,course) VALUES('柳如烟','女',28,6000,'HTML');";int num = statement.executeUpdate(sql);System.out.println("对于" + num + "行造成了影响");//关闭资源DBUtil.close(connection,statement,null);}//删除数据@Testpublic void test02() throws SQLException {//获取连接对象Connection connection = DBUtil.getConnection();//获取发送指令对象Statement statement = connection.createStatement();//发送SQL指令String sql = "DELETE FROM student WHERE id>10;";int num = statement.executeUpdate(sql);System.out.println("对于" + num + "行造成了影响");//关闭资源DBUtil.close(connection,statement,null);}//修改数据@Testpublic void test03() throws SQLException {//获取连接对象Connection connection = DBUtil.getConnection();//获取发送指令对象Statement statement = connection.createStatement();//发送SQL指令String sql = "UPDATE student SET age=21,salary=50000 WHERE id=3;";int num = statement.executeUpdate(sql);System.out.println("对于" + num + "行造成了影响");//关闭资源DBUtil.close(connection,statement,null);}//查询数据@Testpublic void test04() throws SQLException {//获取连接对象Connection connection = DBUtil.getConnection();//获取发送指令对象Statement statement = connection.createStatement();//发送SQL指令,并获取结果集对象String sql = "select * from student";ResultSet resultSet = statement.executeQuery(sql);//遍历结果集while(resultSet.next()){//判断是否有可迭代的数据行int id = resultSet.getInt("id");String name = resultSet.getString("name");String sex = resultSet.getString("sex");int age = resultSet.getInt("age");float salary = resultSet.getFloat("salary");String course = resultSet.getString("course");System.out.println(id + " -- " + name + " -- " + sex + " -- " + age + " -- " + salary + " -- " + course);}//关闭资源DBUtil.close(connection,statement,resultSet);}}

SQL注入问题

理解

ps:select * from student where name=‘’ or 1=1 #’ and passwd=‘111111’;

当输入用户名和密码
’ or 1=1 # '【对于它分不清sql命令和数据,就会or 1=1判断为true,#后面理解为注释,就直接登录进去了】
user表

sql注入问题

package com.qf.jdbc02;import com.qf.utils.DBUtil;public class Test01 {/*** 知识点:SQL注入问题** 出现原因:数据库分不清哪些是sql命令,哪些是数据** 需求:模拟登录功能*/public static void main(String[] args) throws SQLException {Connection connection = DBUtil.getConnection();Statement statement = connection.createStatement();Scanner scan = new Scanner(System.in);System.out.println("请输入账号:");String usernameVal = scan.nextLine();System.out.println("请输入密码:");String passwordVal = scan.nextLine();//select * from user where username='' or 1=1 #' and password='12312345'String sql = "select * from user where username='"+usernameVal+"' and password='"+passwordVal+"'";ResultSet resultSet = statement.executeQuery(sql);if(resultSet.next()){String username = resultSet.getString("username");String password = resultSet.getString("password");String nikeName = resultSet.getString("nike_name");System.out.println("登录成功");System.out.println(username);System.out.println(password);System.out.println(nikeName);}else{System.out.println("登录失败");}DBUtil.close(connection,statement,resultSet);}
}

解决

采用预编译对象来编程:告诉他,使用prepareStatement

sql命令中用?表示数据
注意:prepareStatement继承于statement
现在用prepareStatement拿到的sql是没有数据的,得到它的对象
再将输入的数据设置给这个对象,注意方法SetString的两个参数(下标,值)【注意下标从1开始】
sql注入问题解决

  1. 安全性,避免了SQL注入
  2. 性能,预编译,语句-编译-执行
package com.qf.jdbc02;import com.qf.utils.DBUtil;public class Test02 {/*** 知识点:SQL注入问题** 出现原因:数据库分不清哪些是sql命令,哪些是数据* 解决方案:告诉数据库哪些是sql命令,哪些是数据** 需求:模拟登录功能*/public static void main(String[] args) throws SQLException {Connection connection = DBUtil.getConnection();String sql = "select * from user where username=? and password=?";PreparedStatement statement = connection.prepareStatement(sql);//输入数据后,将数据设置给statement对象Scanner scan = new Scanner(System.in);System.out.println("请输入账号:");String usernameVal = scan.nextLine();System.out.println("请输入密码:");String passwordVal = scan.nextLine();statement.setString(1,usernameVal);statement.setString(2,passwordVal);ResultSet resultSet = statement.executeQuery();if(resultSet.next()){String username = resultSet.getString("username");String password = resultSet.getString("password");String nikeName = resultSet.getString("nike_name");System.out.println("登录成功");System.out.println(username);System.out.println(password);System.out.println(nikeName);}else{System.out.println("登录失败");}DBUtil.close(connection,statement,resultSet);}
}

封装工具类02

更新数据(添加、删除、修改):

01方法传的参数(一个sql命令,另一个数据不确定用可变参数)
02由于不知道下标和值用setObject设置给statement,但有多个参数需要遍历处理就写个方法来专门处理【处理statement对象参数数据的处理器,注意setObject下标从1开始】直接调用处理
03添加操作返回影响行数
04而考虑到关闭资源,处理异常就不会关闭资源,对代码进行try-finally,考虑作用域把定义对象放在之外

添加–主键回填:

就是添加数据后,不再是返回影响的行数,加一个查询返回主键
主键回填理解:
主键回填

查询:

以前查询就打印出来结果,现在查询的数据封装成对象,不同表封装不同的对象
01学生类:有参无参自动生成时,window+alt+回车快速生成,生成时涉及属性选择ctrl+1全选
02方法返回值设置成list集合,类型用泛型;传的参数(哪个类的对象clazz【反射创建】,一个sql,一个可变参数)
03对于拿到的结果集,需要遍历, 一个数据创建一个对象
先泛型创建对象【无数据】,获取数据字段名才可以利用反射去设置对象的属性
怎么获取:先用结果集对象调用方法获取表数据对象,再表数据对象调用方法获取字段个数,再在遍历中通过字段个数循环获取字段名,字段值

反射获取类的属性对象和设置对象的属性【对于反射设置属性回顾以前反射讲到的方法】

04然后将封装的对象添加到对象集合再返回

05而考虑到关闭资源,处理异常就不会关闭资源,对代码进行try-finally,考虑作用域把定义对象放在之外

package com.qf.utils;/*** 数据库工具类*/
public class DBUtil {private static String url;private static String username;private static String password;static{//负责加载配置文件,只加载一次Properties properties = new Properties();try {properties.load(DBUtil.class.getClassLoader().getResourceAsStream("DBConfig.properties"));} catch (IOException e) {throw new RuntimeException(e);}String driverName = properties.getProperty("driverName");url = properties.getProperty("url");username = properties.getProperty("username");password = properties.getProperty("password");try {//加载驱动只加载一次Class.forName(driverName);} catch (ClassNotFoundException e) {throw new RuntimeException(e);}}/*** 获取连接对象*/public static Connection getConnection() throws SQLException {Connection connection = DriverManager.getConnection(url,username,password);return connection;}/*** 关闭资源*/public static void close(Connection connection, Statement statement, ResultSet resultSet){if(resultSet != null){try {resultSet.close();} catch (SQLException e) {throw new RuntimeException(e);}}if(statement != null){try {statement.close();} catch (SQLException e) {throw new RuntimeException(e);}}if(connection != null){try {connection.close();} catch (SQLException e) {throw new RuntimeException(e);}}}/*** 更新数据(添加、删除、修改)*/public static int commonUpdate(String sql,Object... params) throws SQLException {Connection connection = null;PreparedStatement statement = null;try {connection = getConnection();statement = connection.prepareStatement(sql);paramHandler(statement,params);int num = statement.executeUpdate();return num;}finally {close(connection,statement,null);}}/*** 添加数据 - 主键回填(主键是int类型可以返回)*/public static int commonInsert(String sql,Object... params) throws SQLException {Connection connection = null;PreparedStatement statement = null;ResultSet resultSet = null;try {connection = getConnection();statement = connection.prepareStatement(sql,PreparedStatement.RETURN_GENERATED_KEYS);paramHandler(statement,params);statement.executeUpdate();resultSet = statement.getGeneratedKeys();int primaryKey = 0;if(resultSet.next()){primaryKey = resultSet.getInt(1);}return primaryKey;}finally {close(connection,statement,resultSet);}}/*** 查询数据*/public static <T> List<T> commonQuery(Class<T> clazz,String sql, Object... params) throws SQLException, InstantiationException, IllegalAccessException {Connection connection = null;PreparedStatement statement = null;ResultSet resultSet = null;try {connection = getConnection();statement = connection.prepareStatement(sql);paramHandler(statement,params);resultSet = statement.executeQuery();//获取表数据对象ResultSetMetaData metaData = resultSet.getMetaData();//获取字段个数int count = metaData.getColumnCount();List<T> list = new ArrayList<>();while(resultSet.next()){T t = clazz.newInstance();//获取字段名及数据for (int i = 1; i <= count; i++) {String fieldName = metaData.getColumnName(i);Object fieldVal = resultSet.getObject(fieldName);setField(t,fieldName,fieldVal);}list.add(t);}return list;} finally {DBUtil.close(connection,statement,resultSet);}}/*** 处理statement对象参数数据的处理器*/private static void paramHandler(PreparedStatement statement,Object... params) throws SQLException {for (int i = 0; i < params.length; i++) {statement.setObject(i+1,params[i]);}}/*** 获取当前类及其父类的属性对象* @param clazz class对象* @param name 属性名* @return 属性对象*/private static Field getField(Class<?> clazz,String name){for(Class<?> c = clazz;c != null;c = c.getSuperclass()){try {Field field = c.getDeclaredField(name);return field;} catch (NoSuchFieldException e) {} catch (SecurityException e) {}}return null;}/*** 设置对象中的属性* @param obj 对象* @param name 属性名* @param value 属性值*/private static void setField(Object obj,String name,Object value){Field field = getField(obj.getClass(), name);if(field != null){field.setAccessible(true);try {field.set(obj, value);} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}}
}

调用工具类的方法实现增删改查

package com.qf.jdbc03;import com.qf.utils.DBUtil;public class Test01 {/*** 知识点:封装数据库 - v2.0*///添加数据@Testpublic void test01() throws SQLException {String sql = "INSERT INTO student(name,sex,age,salary,course) VALUES(?,?,?,?,?)";int num = DBUtil.commonUpdate(sql, "天使萌", "女", 23, 10000, "HTML");System.out.println("对于" + num + "行造成了影响");}//删除数据@Testpublic void test02() throws SQLException {String sql = "delete from student where id=?";int num = DBUtil.commonUpdate(sql, 3);System.out.println("对于" + num + "行造成了影响");}//修改数据@Testpublic void test03() throws SQLException {String sql = "update student set salary=? where id=?";int num = DBUtil.commonUpdate(sql, 15000,1);System.out.println("对于" + num + "行造成了影响");}//添加数据 - 主键回填@Testpublic void test04() throws SQLException {String sql = "INSERT INTO student(name,sex,age,salary,course) VALUES(?,?,?,?,?)";int primaryKey = DBUtil.commonInsert(sql, "铃原爱蜜莉", "女", 23, 10000, "HTML");System.out.println("返回的主键是:" + primaryKey);}//查询数据@Testpublic void test05() throws SQLException, InstantiationException, IllegalAccessException {String sql = "select * from student where id<?";List<Student> list = DBUtil.commonQuery(Student.class, sql, 8);for (Student stu : list) {System.out.println(stu);}}
}

学生类

package com.qf.jdbc03;public class Student {private int id;private String name;private String sex;private int age;private float salary;private String course;public Student() {}public Student(int id, String name, String sex, int age, float salary, String course) {this.id = id;this.name = name;this.sex = sex;this.age = age;this.salary = salary;this.course = course;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public float getSalary() {return salary;}public void setSalary(float salary) {this.salary = salary;}public String getCourse() {return course;}public void setCourse(String course) {this.course = course;}@Overridepublic String toString() {return "Student{" +"id=" + id +", name='" + name + '\'' +", sex='" + sex + '\'' +", age=" + age +", salary=" + salary +", course='" + course + '\'' +'}';}
}

小结:

JDBC:封装工具类,对增删改查优化,SQL注入问题

相关文章:

JDBC【封装工具类、SQL注入问题】

day54 JDBC 封装工具类01 创建配置文件 DBConfig.properties driverNamecom.mysql.cj.jdbc.Driver urljdbc:mysql://localhost:3306/qnz01?characterEncodingutf8&serverTimezoneUTC usernameroot passwordroot新建配置文件&#xff0c;不用写后缀名 创建工具类 将变…...

Windows打开redis以及Springboot整合redis

目录 前言Windows系统打开redisSpringboot整合redis依赖实体类yml配置文件config配置各个数据存储类型分别说明记录string数据写入redis&#xff0c;并查询通过命令行查询 list插入数据到redis中从redis中读取命令读取数据 hash向redis中逐个添加map键值对获取key对应的map中所…...

MySQL使用LIKE索引是否失效的验证

1、简单的示例展示 在MySQL中&#xff0c;LIKE查询可以通过一些方法来使得LIKE查询能够使用索引。以下是一些可以使用的方法&#xff1a; 使用前导通配符&#xff08;%&#xff09;&#xff0c;但确保它紧跟着一个固定的字符。 避免使用后置通配符&#xff08;%&#xff09;&…...

封装日历uniapp,只显示年月不显示日

默认展示最新日期 子组件 <template><view class"date-picker"><picker mode"date" fields"month" change"onDateChange" :value"selectedDate"><view class"picker">{{ selectedDate…...

golang线程池ants-实现架构

1、总体架构 ants协程池&#xff0c;在使用上有多种方式(使用方式参考这篇文章&#xff1a;golang线程池ants-四种使用方法)&#xff0c;但是在实现的核心就一个&#xff0c;如下架构图&#xff1a; 总的来说&#xff0c;就是三个数据结构&#xff1a; Pool、WorkerStack、goW…...

Mysql面试合集

概念 是一个开源的关系型数据库。 数据库事务及其特性 事务&#xff1a;是一系列的数据库操作&#xff0c;是数据库应用的基本逻辑单位。 事务特性&#xff1a; &#xff08;1&#xff09;原子性&#xff1a;即不可分割性&#xff0c;事务要么全部被执行&#xff0c;要么就…...

Android Gradle 开发与应用 (五): 构建变体与自定义任务

目录 1. 概述 2. 构建变体 2.1 构建变体的概念 2.2 构建类型 2.3 产品风味 2.4 构建变体的使用 3. 自定义任务 3.1 自定义任务的概念 3.2 创建自定义任务 3.3 配置任务依赖 3.4 任务类型 3.5 动态任务 3.6 自定义任务执行顺序 4. 案例 4.1 多渠道打包 4.2 自动…...

Django学习第六天

启动项目命令 python manage.py runserver 取消模态框功能 js实现列表数据删除 第二种实现思路 使用jquery修改模态框标题 编辑页面拿到数据库数据显示默认数据功能实现 想要去数据库中获取数据时&#xff1a;对象/字典 三种不同的数据类型 使用Ajax传入数据实现表单编辑&…...

docker部署mycat,连接上面一篇的一主二从mysql

一、docker下载mycat镜像 查看安装结果 这个名称太长&#xff0c;在安装容器时不方便操作&#xff0c;设置标签为mycat docker tag longhronshens/mycat-docker mycat 二、安装容器 先安装一个&#xff0c;主要目的是获得配置文件 docker run -it -d --name mycat -p 8066:…...

VUE2拖拽组件:vue-draggable-resizable-gorkys

vue-draggable-resizable-gorkys组件基于vue-draggable-resizable进行二次开发, 用于可调整大小和可拖动元素的组件并支持冲突检测、元素吸附、元素对齐、辅助线 安装: npm install --save vue-draggable-resizable-gorkys 全局引用: import Vue from vue import vdr fro…...

容器:stack

以下是关于stack容器的一些总结&#xff1a; stack容器比较简单&#xff0c;主要包括&#xff1a; 1、构造函数&#xff1a;stack [staName] 2、添加、删除元素: push() 、pop() 3、获取栈顶元素&#xff1a;top() 4、获取栈的大小&#xff1a;size() 5、判断栈是否为空&#x…...

跨平台Ribbon UI组件QtitanRibbon全新发布v6.7.0——支持Qt 6.6.3

没有Microsoft在其办公解决方案中提供的界面&#xff0c;就无法想象现代应用程序&#xff0c;这个概念称为Ribbon UI&#xff0c;目前它是使应用程序与时俱进的主要属性。QtitanRibbon是一款遵循Microsoft Ribbon UI Paradigm for Qt技术的Ribbon UI组件&#xff0c;QtitanRibb…...

(6) 深入探索Python-Pandas库的核心数据结构:DataFrame全面解析

目录 前言1. DataFrame 简介2. DataFrame的特点3. DataFrame的创建3.1 使用字典创建DataFrame3.2 使用列表的列表&#xff08;或元组&#xff09;创建DataFrame3.3 使用NumPy数组创建DataFrame3.4 使用Series构成的字典创建DataFrame3.5 使用字典构成的字典创建DataFrame 4. 从…...

在 Azure 云中开始使用适用于 Ubuntu 的 Grafana

介绍 Grafana 是一款开源工具&#xff0c;可用于可视化和分析数据。它特别适合跟踪计算机系统的运行情况。在构建微服务或其他类型的应用程序时&#xff0c;您可能需要分析日志数据、轻松可视化数据或设置特殊警报以接收有关系统中发生的某些事件的通知。 这就是为什么你可能…...

1.Python学习笔记

一、环境配置 1.Python解释器 把程序员用编程语言编写的程序&#xff0c;翻译成计算机可以执行的机器语言 安装&#xff1a; 双击Python3.7.0-选择自定义安装【Customize installation】-勾选配置环境变量 如果没有勾选配置环境变量&#xff0c;输入python就会提示找不到命令…...

中英双语介绍百老汇著名歌剧:《猫》(Cats)和《剧院魅影》(The Phantom of the Opera)

中文版 百老汇著名歌剧 百老汇&#xff08;Broadway&#xff09;是世界著名的剧院区&#xff0c;位于美国纽约市曼哈顿。这里汇集了许多著名的音乐剧和歌剧&#xff0c;吸引了全球各地的观众。以下是两部百老汇的经典音乐剧&#xff1a;《猫》和《剧院魅影》的详细介绍。 1.…...

RpcChannel的调用过程

目录 1. RPC调用方&#xff08;caller&#xff09;的调用(消费)过程 2.在caller下创建文件&#xff1a;calluserservice.cc 3.在src的include下创建文件&#xff1a;mprpcchannel.h 4.在src下创建mprpcchannel.cc 1. RPC调用方&#xff08;caller&#xff09;的调用(消费)过…...

东芝TB6560AHQ/AFG步进电机驱动IC:解锁卓越的电机控制性能

作为一名工程师&#xff0c;一直在寻找可靠且高效的组件来应用于你的项目中。东芝的TB6560AHQ/AFG步进电机驱动IC能够提供精准且多功能的电机控制&#xff0c;完全符合现代应用的高要求&#xff0c;保证高性能和易用性。在这篇文章中&#xff0c;我们将探讨TB6560AHQ/AFG的主要…...

免杀笔记 ----> DLL注入

这段时间我们暂时没什么事情干的话我们就继续更新我们的免杀笔记力&#xff01;&#xff01;&#xff01; &#xff1a;今天我们讲DLL注入 目录 1.DLL注入 2.直接加载DLL&#xff1f; 3.远程线程注入 获取Handle 远程申请内存空间 将我们的CS的DLL加载入内存 创建远程线…...

奇迹MU 骷髅战士在哪

BOSS分布图介绍 我为大家带来各地区怪物分布图。在游戏前期&#xff0c;很多玩家可能会不知道该去哪里寻找怪物&#xff0c;也不知道哪些怪物值得打。如果选择了太强的怪物&#xff0c;弱小的玩家可能会无法抵御攻击。如果选择了低等级的boss&#xff0c;收益可能并不理想。所…...

leetcode力扣_贪心思想

455.分发饼干&#xff08;easy-自己想得出来并写好&#xff09; 假设你是一位很棒的家长&#xff0c;想要给你的孩子们一些小饼干。但是&#xff0c;每个孩子最多只能给一块饼干。对每个孩子 i&#xff0c;都有一个胃口值 g[i]&#xff0c;这是能让孩子们满足胃口的饼干的最小尺…...

Vue中Class数据绑定

Class数据绑定 数据绑定的一个常见需求场景是操作CSS class列表&#xff0c;因为class是attribute&#xff08;属性&#xff09;&#xff0c;我们可以和其他attribute一样使用v-bind 将它们和动态的字符串绑定。但是&#xff0c;在处理比较复杂的绑定时&#xff0c;通过拼接生…...

Python数据分析案例49——基于机器学习的垃圾邮件分类系统构建(朴素贝叶斯,支持向量机)

案例背景 trec06c是非常经典的邮件分类的数据&#xff0c;还是难能可贵的中文数据集。 这个数据集从一堆txt压缩包里面提取出来整理为excel文件还真不容不易&#xff0c;肯定要做一下文本分类。 虽然现在文本分类基本都是深度学习了&#xff0c;但是传统的机器学习也能做。本案…...

贪心算法-以学籍管理系统为例

1.贪心算法介绍 1.算法思路 贪心算法的基本思路是从问题的某一个初始解出发一步一步地进行&#xff0c;根据某个优化测度&#xff0c;每一 步都要确保能获得局部最优解。每一步只考虑一 个数据&#xff0c;其选取应该满足局部优化的条件。若下 一个数据和部分最优解连在一起…...

PyCharm 安装

PyCharm是一种流行的Python集成开发环境&#xff08;IDE&#xff09;&#xff0c;由JetBrains公司开发。它提供了丰富的功能&#xff0c;如智能代码补全、实时错误检查、项目导航、调试工具以及版本控制等&#xff0c;极大地提高了Python开发人员的工作效率。以下是PyCharm安装…...

C++:对象指针访问成员函数

使用箭头操作符 (->)&#xff1a;ptr->function() 是最常用和推荐的方式&#xff0c;因为它更简洁、更直观。箭头操作符 (->) 被设计为与点操作符 (.) 配合指针一起使用&#xff0c;以便通过指针访问对象的成员。 先解引用指针&#xff0c;然后使用点操作符 (.)&…...

Linux 防火墙配置指南:firewalld 端口管理应用案例(二十个实列)

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f427;Linux基础知识(初学)&#xff1a;点击&#xff01; &#x1f427;&#x1f427;Linux高级管理专栏&#xff1a;点击&#xff01; &#x1f510;Linux中firewalld防火墙&#xff1a;点击&#xff01; ⏰️…...

推荐Bulk Image Downloader插件下载网页中图片链接很好用

推荐&#xff1a;Bulk Image Downloader chome浏览器插件下载图片链接&#xff0c;很好用。 有个网页&#xff0c;上面放了数千的gif的电路图&#xff0c;手工下载会累瘫了不可。想找一个工具分析它的静态链接并下载&#xff0c;找了很多推荐的下载工具&#xff0c;都是不能分…...

详解前缀码与前缀编码

前缀编码是一种数据压缩技术&#xff0c;也被称为可变长度编码。它的基本原理是将频繁出现的字符或字符序列用较短的编码表示&#xff0c;而较少出现的字符或字符序列用较长的编码表示&#xff0c;从而达到压缩数据的目的。 概念定义 前缀码&#xff1a;给定一个编码序列的集合…...

数据库管理工具 -- Navicat Premium v17.0.8 特别版

软件简介 Navicat Premium 是一款功能强大的数据库管理工具&#xff0c;适用于Windows、Mac和Linux平台。它支持多种数据库&#xff0c;包括MySQL、MariaDB、SQL Server、PostgreSQL、Oracle、SQLite等。用户可以通过Navicat Premium轻松地连接到各种数据库服务器&#xff0c;…...