20242817李臻《Linux⾼级编程实践》第9周
20242817李臻《Linux⾼级编程实践》第9周
一、AI对学习内容的总结
第十章 Linux下的数据库编程
10.1 MySQL数据库简介
- MySQL概述:MySQL是一个开源的关系型数据库管理系统,最初由瑞典MySQL AB公司开发,后经SUN公司收购,现属于Oracle公司。它以其体积小、速度快、成本低等优势,成为中小型网站常用的数据库选择。
- MySQL的特点:
- 支持多线程,提供完全的多线程运行模式。
- 提供了面向多种编程语言的APIs,如C、C++、Java、Perl、PHP、Python等。
- 支持多种字段类型和完整的操作符支持。
- MySQL的应用:在WEB应用中,MySQL是目前最好的RDBMS应用软件之一,搭配PHP和Apache可组成良好的开发环境。
10.1.1 Linux数据库编程应用
- Web服务器中的应用:在Linux操作系统作为Web服务器时,用户的相关信息如账户信息、购买商品信息等需要保存在服务器中,服务器端程序可通过C语言将这些信息保存到数据库服务器中,也可读取保存在其中的信息并返回给Web客户端。
- 嵌入式领域的应用:在嵌入式Linux操作系统中,开发板经常需要将外部设备如各种传感器感知的数据保存到数据库中,为了提高效率,一般采用C语言直接对嵌入式数据库(例如SQLite等)进行操作。
- 网络环境中的应用:为了高效率地采集网络设备的数据,经常采用C语言在Linux环境下操作,通过调用数据库的API实现数据的各种DDL操作。
10.1.2 MySQL API的两种形式
- libmysqlclient:客户端程序和数据库服务器处于独立的不同进程中,客户端通过网络与数据库服务器进行通信。
- libmysqld:数据库服务器嵌入在客户端应用程序中,作为应用程序的一部分,客户端与数据库服务器端的通信通过私有进程的方式进行。该方式优点是用户程序和数据库紧耦合在一起,方便应用的部署和提高效率,降低维护成本,终端用户无需关心mysql数据库。缺点是在同一时刻只能有一个程序连接该数据库。
10.1.3 MySQL CAPI的使用
- 安装方式:可通过安装MySQL服务器版或MySQL Connector/C发布版来获得MySQL CAPI。
- 编译时的注意事项:
- 在编译命令中通过-I选项指定头文件的位置。
- 通过-lmysqlclient -lz选项告诉编译器使用mysql的库文件。
- 通过-L选项指定库文件的查找路径。
10.2 Linux数据库编程基本方法
- 基本步骤:
- 定义并初始化与数据库连接和操作相关的数据结构变量。
- 建立到数据库的连接。
- 执行相应的DDL操作,如select/delete/insert/update等语句。
- 关闭数据库连接释放资源。
10.3 MySQL数据库数据结构及API
10.3.1 数据结构
- MYSQL:代表到数据库的一个连接,几乎所有MySQL操作函数都用到该数据结构。
- MYSQL_RES:代表数据库操作返回的结果集。
- MYSQL_ROW:代表数据表中的一行数据。
- MYSQL_FIELD:包括数据表中字段的元数据信息,如字段名称、字段类型、字段大小等。
- MYSQL_FIELD_OFFSET:代表字段集中的偏移量。
- my_ulonglong:用来表示数据表中行数的字段。
- my_bool:MySQL中的布尔类型。
10.3.2 MySQL操作API
- mysql_init:初始化一个MySQL结构。
- mysql_library_init:初始化MySQL CAPI。
- mysql_real_connect:连接到指定的MySQL服务器。
- mysql_query:执行一个以空字符结尾的SQL查询字符串。
- mysql_real_query:执行一个可被计数的SQL查询字符串。
- mysql_store_result:返回SQL语句执行结果的结果集给客户。
- mysql_free_result:释放结果集使用的内存。
- mysql_affected_rows:返回执行SQL查询语句影响的行数。
- mysql_num_rows:返回一个结果集中行的数量。
- mysql_num_fields:返回一个结果集中列的数量。
- mysql_fetch_row:从结果集中取得下一行。
- mysql_fetch_lengths:返回当前行中所有列的长度。
- mysql_fetch_fields:返回所有字段结构的数组。
- mysql_get_server_info:返回服务器信息。
- mysql_get_client_info:返回客户端信息。
- mysql_get_host_info:返回描述连接信息。
- mysql_fetch_field:返回表的下一个字段的类型。
- mysql_fetch_field_direct:返回字段编号所指定的字段的类型。
- mysql_errno:返回最近被调用的MySQL函数的出错编号。
- mysql_error:返回最近被调用的MySQL函数的出错消息。
- mysql_close:关闭到数据库服务器连接。
- mysql_change_user:改变在一个打开的连接上的用户和数据库。
- mysql_create_db:创建一个数据库(不推荐使用该函数,使用CREATE语句)。
- mysql_drop_db:删除一个数据库(不推荐使用该函数,使用DROP语句)。
- mysql_select_db:选择服务器中某个数据库。
- mysql_thread_id:返回当前线程的ID。
- mysql_kill:杀死一个给定的线程。
- mysql_list_dbs:返回与指定的正则表达式匹配的数据库名。
- mysql_list_tables:返回与指定的正则表达式匹配的数据表名。
- mysql_list_fields:返回与指定的正则表达式匹配的列名。
- mysql_commit:提交本次事务。
- mysql_rollback:退回本次事务。
- mysql_shutdown:关闭数据库服务器。
10.4 MySQL数据库编程实例
- 学生信息管理系统实例:
- 数据库设计:创建名为student的数据库,建立保存学生基本信息的表格stuinfo,包含学号、姓名、性别、邮箱、院系等字段。
- 实例代码:提供了使用MySQL C API实现数据库创建、数据表创建、记录插入、记录删除和记录查询等操作的完整代码示例。
实验部分
-
实验一 Linux基本命令使用:
- 实验目的:了解Linux环境,熟悉Linux常用命令和VI编辑器的使用。
- 实验内容:包括Linux基本命令、VI编辑器的使用等。
-
实验二 Linux Shell编程:
- 实验目的:熟悉Shell环境、语法和语句,了解Shell程序的调试方法。
- 实验内容:编写和调试Shell程序,完成特定任务。
-
实验三 Makefile实验:
- 实验目的:了解Linux环境,熟悉Makefile的原理和使用。
- 实验内容:编写Makefile文件,使用make命令进行编译。
-
实验四 GCC/GDB实验:
- 实验目的:了解Linux的编译调试环境,熟悉GCC和GDB的使用。
- 实验内容:使用GCC编译程序,使用GDB进行调试,创建和使用静态库和动态库。
-
实验五 Linux文件系统编程:
- 实验目的:了解系统编程概念,熟悉Linux系统编程方法和常用的系统调用。
- 实验内容:编写程序实现文件系统调用和信号处理。
-
实验六 Linux多进程与进程间通信:
- 实验目的:熟悉Linux系统编程方法和常用的系统调用。
- 实验内容:编写程序实现多进程创建和进程间通信。
二、 对AI总结的反思与补充
反思
10.1.2 MySQL API 的两种形式
- libmysqlclient :是常见的客户端连接库,适用于客户端与 MySQL 服务器的独立进程通信。
- libmysqld :是 MySQL 内嵌式服务器库,可以将 MySQL 数据库嵌入到应用程序中,通常用于在没有独立 MySQL 服务器的情况下运行数据库。不过,libmysqld 已不再是主流选择,在现代的 MySQL 版本中已经逐渐不被推荐或被淘汰。
10.1.3 MySQL CAPI 的使用
在安装方式上,可以通过 “安装 MySQL 服务器版或 MySQL Connector/C 发布版来获得 MySQL CAPI” 这一描述是正确的。而更明确的说法是:MySQL Connector/C 是 MySQL 提供的官方 C 语言连接器库,它包含了 MySQL C API。
10.3 MySQL 数据库数据结构及 API
-
mysql_real_query 和 mysql_query
- mysql_query :是一个比较基础的 API,用于执行 SQL 查询。
- mysql_real_query :与 mysql_query 功能相似,但它提供了对字符集的更好支持,例如能够处理多字节字符集。对于简单查询,通常使用 mysql_query而对于;更复杂的查询,特别是涉及字符集问题时,推荐使用 mysql_real_query。
-
mysql_list_dbs, mysql_list_tables 和 mysql_list_fields :这些函数在 MySQL 的新版本中已经不推荐使用,并且被标记为过时(deprecated)。现在推荐使用 SHOW DATABASES、SHOW TABLES 和 SHOW COLUMNS 来替代这些函数。
10.4 MySQL 数据库编程实例
- 学生信息管理系统实例 :
- 在数据库设计部分,可以进一步详细描述,比如提供表格 stuinfo 的创建 SQL 语句,以及详细阐述如何通过 C 语言实现增删改查等操作,以便让读者更好地理解如何实际操作数据库。
补充
10.1 MySQL数据库简介
- MySQL的事务支持:MySQL支持ACID(原子性、一致性、隔离性、持久性)事务,确保在数据库操作中的数据一致性和可靠性。常用的事务控制命令包括
START TRANSACTION
、COMMIT
和ROLLBACK
。 - MySQL的存储引擎:MySQL提供多个存储引擎,每个引擎在性能、功能等方面有所不同。常见的存储引擎有
InnoDB
(支持事务、外键)和MyISAM
(不支持事务、外键,但速度更快)。 - MySQL的复制功能:MySQL支持主从复制,可以将数据从一个主数据库复制到多个从数据库,增强数据的可用性和容错性。
10.2 Linux数据库编程基本方法
- MySQL连接池:对于高并发的Web应用,频繁的创建和销毁数据库连接会导致性能问题。使用数据库连接池可以复用现有连接,提高效率。
- 错误处理:在数据库编程中,需要特别注意错误处理。可以使用
mysql_errno()
和mysql_error()
获取详细的错误信息,并根据错误代码处理异常,保证系统的健壮性。 - SQL注入防护:SQL注入是Web应用中常见的安全漏洞之一。在进行数据库操作时,建议使用准备语句(Prepared Statements)来防止SQL注入,MySQL C API也支持该特性。
10.3 MySQL数据库数据结构及API
MYSQL_RES
与MYSQL_ROW
:MYSQL_RES
是SQL查询结果的容器,包含一个或多个MYSQL_ROW
。一个MYSQL_ROW
就是数据库查询结果中的一行数据,它通常以一个字符串数组的形式返回。- 批量处理与事务:对于大规模数据的插入操作,MySQL C API可以通过开启事务(
mysql_query("START TRANSACTION")
)来提高效率。在执行完一批插入后,通过COMMIT
提交事务,从而减少了单次插入的网络延迟。 - MySQL的错误处理:除了
mysql_errno()
和mysql_error()
外,还可以通过mysql_get_client_version()
获取客户端库的版本信息,进行调试时非常有帮助。
10.4 MySQL数据库编程实例
- 代码优化与索引使用:在设计数据库时,合理的索引可以极大提高查询性能。尤其是在进行复杂查询或大量数据处理时,创建合适的索引至关重要。编写代码时,可以使用
EXPLAIN
命令来分析SQL语句的执行计划,从而优化数据库查询效率。 - Prepared Statements:在编写C语言与MySQL交互时,使用准备语句不仅能防止SQL注入,还能提高查询效率。MySQL C API提供了
mysql_stmt_prepare
和mysql_stmt_execute
等API,用于执行准备语句。
三、学习思维导图
第十章
mindmaproot((Linux下的数据库编程))MySQL数据库简介基本信息开发背景所属公司社区版与商业版特点体积小速度快成本低开源应用场景Web应用嵌入式开发Linux数据库编程应用Web服务器账户信息购买信息嵌入式Linux传感器数据网络数据采集C语言操作MySQL C API两种形式libmysqlclient独立进程libmysqld嵌入式紧耦合使用方法安装MySQL服务器版安装MySQL Connector/C编译链接头文件库文件Linux数据库编程基本方法数据库连接初始化连接数据库操作DDL操作DML操作资源释放关闭连接释放内存MySQL数据库数据结构及API数据结构MYSQLMYSQL_RESMYSQL_ROWMYSQL_FIELDmy_ulonglongmy_boolAPI函数初始化与结束数据库连接查询与结果处理错误处理事务处理MySQL数据库编程实例学生信息管理系统数据库设计数据库:student表:stuinfo功能实现数据库创建数据表创建数据插入数据删除数据查询实验与练习Linux基本命令使用Shell编程Makefile实验GCC/GDB实验文件系统编程多进程与进程间通信
四、基于AI的学习
1、关于 MySQL API
我:我在学习 MySQL 操作 API 相关知识点,请你以苏格拉底的方式对我进行提问,一次一个问题。
AI:好的,开始啦。请你先说说,你对 MySQL 操作 API 目前有了哪些了解呢?
我:MySQL 操作 API 是用来和 MySQL 数据库进行交互的工具,不同的编程语言都有对应的 API,像 Python 有 PyMySQL,Java 有 JDBC 等,能让开发者在代码里执行 SQL 语句,完成对数据库数据的增删改查操作。
AI:明白了,那你觉得使用 MySQL 操作 API 最关键的步骤有哪些呢?
我:首先是建立数据库连接,要提供正确的主机地址、端口、用户名、密码等信息。然后是创建操作数据库的游标对象,接着执行 SQL 语句,无论是查询还是更新数据。如果是查询,要获取结果集并处理数据;最后记得关闭游标和连接,不然可能会浪费数据库资源。
AI:很棒呀,那请你思考一下,在执行 SQL 查询操作时,一般会用到哪些方法呢?
我:在 Python 的 PyMySQL 里,游标对象有 cursor.fetchall()、cursor.fetchone()、cursor.fetchmany(size) 这些方法。fetchall() 是获取查询结果集里的所有数据;fetchone() 获取下一行数据;fetchmany(size) 就是获取指定数量的多行数据。
AI:很好,那你知道在执行更新操作(比如插入、删除、修改数据)后,为什么一定要调用连接对象的 commit() 方法吗?
我:因为数据库默认是开启了事务的,如果不调用 commit() 方法,之前执行的更新操作不会真正地保存到数据库里,只有 commit 提交之后,数据变更才会生效,这样也能保证数据更新的完整性和一致性。
AI:非常棒!那在实际开发中,使用 MySQL 操作 API 时,如何有效处理异常情况呢?
我:在代码里要使用 try…except…finally 结构。在 try 块里执行数据库操作,捕获可能出现的异常,比如数据库连接错误、SQL 语句语法错误等。在 except 块里记录错误信息,进行相应的错误处理。在 finally 块里确保关闭游标和连接,防止资源泄漏。
AI:很好,请你思考一下,使用 MySQL 操作 API 时,如何避免 SQL 注入攻击呢?
我:不能直接拼接用户输入来构造 SQL 语句。要使用参数化查询,把用户输入当作参数传入,让 API 自动进行转义处理。像在 PyMySQL 中,执行 SQL 语句时用 %s 作为参数占位符,然后把参数以元组或字典形式传给 execute() 方法。
AI:不错呀,那你觉得在处理大量数据查询时,有什么比较好的优化方法呢?
我:一方面可以在 SQL 查询语句里加上合理的限制条件,比如利用 where 子句精准过滤数据,减少返回的数据量。另一方面可以对查询结果进行分页处理,每次只获取一部分数据展示,降低单次查询的压力。
AI:好了,关于 MySQL 操作 API 的知识点就交流到这里。你的理解是什么?
我:你觉得我掌握这些知识了吗?上述回答就是我的理解。
AI:从你的回答来看,你对 MySQL 操作 API 的基本使用流程、关键方法、异常处理、安全防护(避免 SQL 注入)以及查询优化策略等方面都有比较清晰的认识,能够准确地阐述各个要点,这说明你对这个知识点已经有了不错的掌握。
不过,可以进一步深入的地方是,对于不同编程语言的 MySQL 操作 API 在细节上可能存在的差异,以及一些高级特性(如事务的隔离级别设置在 API 中的具体操作)可以再深入研究一下。总之,你现在的理解已经很扎实啦,继续加油!
2、关于 Linux Shell编程
我:我在学习 Linux Shell 编程的相关知识点,请你以苏格拉底的方式对我进行提问,一次一个问题。
AI:好的,开始吧。那你想先和我分享一下你对 Linux Shell 编程的初步认知吗?
我:Linux Shell 就像是一个命令行界面的“翻译官”,我们日常敲入的各种指令都是通过它来跟操作系统交流的,它能帮我们快速地执行各种操作,像文件管理、程序运行这些。而且 Shell 脚本就像是把这些指令组合起来,变成一个个能自动完成特定任务的小程序。
AI:那你觉得编写一个简单的 Shell 脚本,必不可少的步骤都有哪些呢?
我:首先得用文本编辑器新建一个文件,比如用 vi 或 nano。然后在脚本开头写上 “#!/bin/bash”,这是告诉系统用哪个 shell 解释器来运行脚本。接着就是写具体的命令,实现我们想要的功能,写完保存后,还要用 “chmod +x 脚本名” 给脚本加上可执行权限,最后就能用 “./脚本名” 来运行啦。
AI:很好呀,那你知道在 Shell 脚本里,变量是怎么定义和使用的吗?
我:定义变量很简单,直接写 “变量名=值”,中间不能有空格。要是想引用变量,就在变量名前加个美元符号 “$”,像 “echo $变量名”,这样就能把变量的值取出来用到命令里。
AI:棒棒哒!那条件语句在 Shell 脚本中很常用,你来说说 “if…elif…else” 这个结构大概长什么样呀。
我:基本格式大概是这样:
if [ 条件1 ]; then# 条件1成立时执行的命令
elif [ 条件2 ]; then# 条件2成立时执行的命令
else# 以上条件都不成立时执行的命令
fi
先判断条件 1,要是成立就执行对应部分;要是不成立就接着判断条件 2,以此类推,最后的 else 就是兜底的。
AI:不错哦,那循环结构也是编程里少不了的。在 Shell 脚本里,for 循环常用,那它的一般写法是什么呢?
我:
一种是像这样对固定列表循环:
for 变量 in 元素1 元素2 ... 元素N; do# 循环体,能用 $变量获取当前元素
done
还有一种是结合文件或者数字范围,比如遍历文本文件的每一行,或者从 1 到 10 这样的数字区间。
AI:太棒啦!那你知道如何在 Shell 脚本里接收用户输入吗?
我:用 “read” 命令就行啦。比如 “read -p ‘请输入你的名字:’ name”,这样就能提示用户输入,输入的内容会存到变量 name 里,后面就能通过 “$name” 来用啦。
AI:很好,那在 Shell 编程中,函数是怎么定义和调用的呢?
我:定义函数就是写个函数名,然后加上括号,接着把函数体写在大括号里,像这样:
函数名 () {# 函数体,写要执行的命令
}
调用的话就简单啦,直接写 “函数名” 就行,要是函数需要参数,调用的时候按顺序把参数写在后面就行,像 “函数名 参数1 参数2”。
AI:棒极啦!那你觉得在实际的 Shell 编程过程中,有什么容易出错或者需要注意的地方吗?
我:我觉得变量名一定要注意别和系统的关键字或者内置变量重名,不然容易出岔子。还有在写条件判断的时候,括号和空格得严格按照格式来,不然 Shell 解释器会报错。再就是脚本的权限,要是忘记加可执行权限,就老跑不起来啦。
AI:你的理解很到位呀,那你觉得你现在对 Linux Shell 编程的知识点掌握得怎么样啦?上面就是我的理解啦。
从你的回答来看,你对 Linux Shell 编程的基础概念、脚本编写流程、变量定义使用、条件语句、循环结构、用户输入接收以及函数定义调用等方面已经有比较扎实的理解,而且对实际操作中容易踩的坑也有一定警觉,这说明你对这个知识点有了不错的掌握程度啦。
不过呢,要是能再多探索一下 Shell 脚本和其他 Linux 工具结合的高级玩法,比如跟 find、xargs 这些命令搭配做批量文件处理,或者深入研究一下 Shell 中的重定向、管道在复杂场景下的巧妙运用,那你的 Shell 编程技能肯定会更上一层楼哦。继续加油,你已经很棒啦!
五、基于AI的代码实践
使用Gitee进行代码托管
仓库链接:
https://gitee.com/li-zhen1215/homework/tree/master/Week9
例1
ex1.c
#include "mysql.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>struct student { // 对应于表的列属性int id; // 学号char name[20]; // 姓名char sex[6]; // 性别char mailbox[40]; // 邮箱地址char studep[100]; // 所在院系
};/*初始化数据库*/
MYSQL *initial(MYSQL *con) {if (mysql_library_init(0, NULL, NULL)) {fprintf(stderr, "Could not initialize MySQL library.\n");return NULL;}con = mysql_init(NULL);return con;
}/*连接数据库*/
MYSQL *myconnect(MYSQL *con, char *username, char *passwd, char *hostip, char *db) {if (mysql_real_connect(con, "localhost", "root", "123456", db, 0, NULL, 0) == NULL) {fprintf(stderr, "connect failed\n");return NULL;}return con;
}void createDB(MYSQL *con, char *cmd) {if (mysql_query(con, cmd)) {printf("createdb failed");} else {printf("Create Database successful\n");}
}void createTable(MYSQL *con, char *db, char *cmd) {if (mysql_select_db(con, db)) {printf("select DB failed\n");}if (mysql_query(con, cmd)) {printf("createTable failed\n");} else {printf("Create table successful\n");}
}void displayTable(MYSQL *con, char *query) {MYSQL_RES *mysql_res;MYSQL_ROW mysql_row;unsigned long *lengths; // 声明 lengths 指针int i, j;int num_row, num_col;if (mysql_real_query(con, query, (unsigned int)strlen(query)) != 0) {printf("Query failed\n");}// 保存查询结果if ((mysql_res = (MYSQL_RES *)mysql_store_result(con)) == NULL) { // 显式类型转换printf("Store result failed\n");}// 获取查询结果的行数、列数num_row = mysql_num_rows(mysql_res);num_col = mysql_num_fields(mysql_res);printf("row number = %lu, col number = %lu\n", (unsigned long)num_row, (unsigned long)num_col);printf("********************\n");// 逐行显示结果for (i = 0; i < num_row; i++) {// 从保存的查询结果中获取下一行内容if ((mysql_row = mysql_fetch_row(mysql_res)) == NULL) { // 修正比较运算符break;}// 获取列长度的数组lengths = mysql_fetch_lengths(mysql_res); // 修正函数调用for (j = 0; j < num_col; j++) {printf("Column[%u] length=%lu\n", j, lengths[j]);// 打印一行中各列的值printf("%s\t", mysql_row[j] ? mysql_row[j] : "NULL");}printf("\n");}printf("********************\n");// 释放保存的查询结果mysql_free_result(mysql_res);
}void insertData(MYSQL *con) {struct student student1;char query[1024];printf("please input student id : \n");scanf("%d", &student1.id);getchar();printf("please input student name:\n ");scanf("%s", student1.name);getchar();printf("please input student sex(male/female):\n ");scanf("%s", student1.sex);getchar();printf("please input student phone: \n");scanf("%s", student1.mailbox);getchar();printf("please input student department: \n");scanf("%s", student1.studep);getchar();sprintf(query, "insert into stuinfo(id, stuname, gender, mailbox, studep) values(%d, '%s', '%s', '%s', '%s')", student1.id, student1.name, student1.sex, student1.mailbox, student1.studep);if (mysql_real_query(con, query, (unsigned int)strlen(query)) != 0) {mysql_rollback(con);printf("insert failed\n");}mysql_commit(con);displayTable(con, "select * from stuinfo");
}void deleteData(MYSQL *con) {int id;char query[1024];printf("please input student id to be deleted\n");scanf("%d", &id);sprintf(query, "delete from stuinfo where id=%d", id);if (mysql_real_query(con, query, (unsigned int)strlen(query)) != 0) {mysql_rollback(con);printf("delete failed\n");}mysql_commit(con);if (mysql_affected_rows(con) > 0) {printf("delete successful\n");}displayTable(con, "select * from stuinfo");
}int menu() {int choose;printf("*********student information system*********\n");printf("1. create database\n");printf("2. create table\n");printf("3. insert data\n");printf("4. delete data\n");printf("5. update data\n");printf("please input choose\n");scanf("%d", &choose);getchar();return choose;
}void handleMenu(MYSQL *mysql) {int choose;while (1) {choose = menu();switch (choose) {case 1: createDB(mysql, "Create database student"); break;case 2: createTable(mysql, "student", "create table stuinfo(id INT, stuname TEXT, gender TEXT, mailbox TEXT, studep TEXT)"); break;case 3: insertData(mysql); break;case 4: deleteData(mysql); break;case 5: // updateData(mysql); break;case 0: printf("exit\n"); return; break;}}
}int main(void) {MYSQL *mysql_handle = NULL;mysql_handle = initial(mysql_handle);if (NULL == mysql_handle) {fprintf(stderr, "initialize failed");exit(1);}mysql_handle = myconnect(mysql_handle, "root", "123456", "localhost", "");handleMenu(mysql_handle);mysql_close(mysql_handle);mysql_library_end();return 0;
}
实践截图
习题1
Linux 下对 MySQL 进行 C 编程的主要应用场景和作用包括通过 MySQL 提供的 C API(如 libmysqlclient)实现高效的数据库操作,适用于需要直接与 MySQL 交互的高性能应用程序开发。这种编程方式常用于嵌入式系统、服务器后端或需要低层级控制的场景,例如定制数据库工具、批量数据处理或实时系统。通过 C 语言直接调用 MySQL,开发者可以优化查询性能、管理连接池或实现特定业务逻辑,同时避免其他语言可能带来的额外开销。此外,C 编程还能与 Linux 系统调用结合,实现更底层的资源管理或进程通信。
习题2
MySQL 的 C API(如 libmysqlclient)不仅支持基本的数据库操作(如查询、插入、更新和删除),还支持存储过程、事务管理、预处理语句等高级功能。对于存储过程,开发者可以通过 mysql_query() 或 mysql_real_query() 直接执行 CALL 语句来调用存储过程,并使用结果集处理函数(如 mysql_store_result() 或 mysql_use_result())获取返回数据。此外,MySQL C API 还支持预处理语句(Prepared Statements),通过 mysql_stmt_init()、mysql_stmt_prepare() 和 mysql_stmt_execute() 等函数高效执行参数化查询,减少 SQL 注入风险并提升性能。虽然 MySQL C API 主要针对 MySQL 设计,但通过 ODBC 或第三方库(如 Connector/C++ 或 DBI)可以间接支持其他数据库,但原生功能仍以 MySQL 为核心。
习题3
xt4.c
#include "mysql.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>struct student { // 对应于表的列属性int id; // 学号char name[20]; // 姓名char sex[6]; // 性别char mailbox[40]; // 邮箱地址char studep[100]; // 所在院系
};struct score { // 成绩表结构体int student_id; // 学号char course[20]; // 课程名称float grade; // 成绩
};/*初始化数据库*/
MYSQL *initial(MYSQL *con) {if (mysql_library_init(0, NULL, NULL)) {fprintf(stderr, "Could not initialize MySQL library.\n");return NULL;}con = mysql_init(NULL);return con;
}/*连接数据库*/
MYSQL *myconnect(MYSQL *con, char *username, char *passwd, char *hostip, char *db) {if (mysql_real_connect(con, "localhost", "root", "123456", db, 0, NULL, 0) == NULL) {fprintf(stderr, "connect failed\n");return NULL;}return con;
}void createDB(MYSQL *con, char *cmd) {if (mysql_query(con, cmd)) {printf("createdb failed");} else {printf("Create Database successful\n");}
}void createTable(MYSQL *con, char *db, char *cmd) {if (mysql_select_db(con, db)) {printf("select DB failed\n");}if (mysql_query(con, cmd)) {printf("createTable failed\n");} else {printf("Create table successful\n");}
}void displayTable(MYSQL *con, char *query) {MYSQL_RES *mysql_res;MYSQL_ROW mysql_row;unsigned long *lengths;int i, j;int num_row, num_col;if (mysql_real_query(con, query, (unsigned int)strlen(query)) != 0) {printf("Query failed\n");}if ((mysql_res = (MYSQL_RES *)mysql_store_result(con)) == NULL) {printf("Store result failed\n");}num_row = mysql_num_rows(mysql_res);num_col = mysql_num_fields(mysql_res);printf("row number = %lu, col number = %lu\n", (unsigned long)num_row, (unsigned long)num_col);printf("********************\n");for (i = 0; i < num_row; i++) {if ((mysql_row = mysql_fetch_row(mysql_res)) == NULL) {break;}lengths = mysql_fetch_lengths(mysql_res);for (j = 0; j < num_col; j++) {printf("Column[%u] length=%lu\n", j, lengths[j]);printf("%s\t", mysql_row[j] ? mysql_row[j] : "NULL");}printf("\n");}printf("********************\n");mysql_free_result(mysql_res);
}void insertData(MYSQL *con) {struct student student1;char query[1024];printf("please input student id : \n");scanf("%d", &student1.id);getchar();printf("please input student name:\n ");scanf("%s", student1.name);getchar();printf("please input student sex(male/female):\n ");scanf("%s", student1.sex);getchar();printf("please input student phone: \n");scanf("%s", student1.mailbox);getchar();printf("please input student department: \n");scanf("%s", student1.studep);getchar();sprintf(query, "insert into stuinfo(id, stuname, gender, mailbox, studep) values(%d, '%s', '%s', '%s', '%s')", student1.id, student1.name, student1.sex, student1.mailbox, student1.studep);if (mysql_real_query(con, query, (unsigned int)strlen(query)) != 0) {mysql_rollback(con);printf("insert failed\n");}mysql_commit(con);displayTable(con, "select * from stuinfo");
}void deleteData(MYSQL *con) {int id;char query[1024];printf("please input student id to be deleted\n");scanf("%d", &id);sprintf(query, "delete from stuinfo where id=%d", id);if (mysql_real_query(con, query, (unsigned int)strlen(query)) != 0) {mysql_rollback(con);printf("delete failed\n");}mysql_commit(con);if (mysql_affected_rows(con) > 0) {printf("delete successful\n");}displayTable(con, "select * from stuinfo");
}void insertScore(MYSQL *con) {struct score score1;char query[1024];printf("please input student id : \n");scanf("%d", &score1.student_id);getchar();printf("please input course name:\n ");scanf("%s", score1.course);getchar();printf("please input grade:\n ");scanf("%f", &score1.grade);getchar();sprintf(query, "insert into score(student_id, course, grade) values(%d, '%s', %f)", score1.student_id, score1.course, score1.grade);if (mysql_real_query(con, query, (unsigned int)strlen(query)) != 0) {mysql_rollback(con);printf("insert score failed\n");}mysql_commit(con);displayTable(con, "select * from score");
}void displayScoreTable(MYSQL *con) {displayTable(con, "select * from score");
}void updateScore(MYSQL *con) {int student_id;char course[20];float grade;char query[1024];printf("please input student id : \n");scanf("%d", &student_id);getchar();printf("please input course name:\n ");scanf("%s", course);getchar();printf("please input new grade:\n ");scanf("%f", &grade);getchar();sprintf(query, "update score set grade=%f where student_id=%d and course='%s'", grade, student_id, course);if (mysql_real_query(con, query, (unsigned int)strlen(query)) != 0) {mysql_rollback(con);printf("update score failed\n");}mysql_commit(con);if (mysql_affected_rows(con) > 0) {printf("update score successful\n");}displayTable(con, "select * from score");
}void deleteScore(MYSQL *con) {int student_id;char course[20];char query[1024];printf("please input student id : \n");scanf("%d", &student_id);getchar();printf("please input course name:\n ");scanf("%s", course);getchar();sprintf(query, "delete from score where student_id=%d and course='%s'", student_id, course);if (mysql_real_query(con, query, (unsigned int)strlen(query)) != 0) {mysql_rollback(con);printf("delete score failed\n");}mysql_commit(con);if (mysql_affected_rows(con) > 0) {printf("delete score successful\n");}displayTable(con, "select * from score");
}void deleteStudentAndScore(MYSQL *con) {int id;char query[1024];printf("please input student id to be deleted\n");scanf("%d", &id);getchar();// 删除成绩信息sprintf(query, "delete from score where student_id=%d", id);if (mysql_real_query(con, query, (unsigned int)strlen(query)) != 0) {mysql_rollback(con);printf("delete score failed\n");}// 删除学生信息sprintf(query, "delete from stuinfo where id=%d", id);if (mysql_real_query(con, query, (unsigned int)strlen(query)) != 0) {mysql_rollback(con);printf("delete student failed\n");}mysql_commit(con);if (mysql_affected_rows(con) > 0) {printf("delete student and score successful\n");}displayTable(con, "select * from stuinfo");displayTable(con, "select * from score");
}int menu() {int choose;printf("*********student information system*********\n");printf("1. create database\n");printf("2. create table\n");printf("3. insert student data\n");printf("4. delete student data\n");printf("5. insert score data\n");printf("6. display score table\n");printf("7. update score data\n");printf("8. delete score data\n");printf("9. delete student and score data\n");printf("0. exit\n");printf("please input choose\n");scanf("%d", &choose);getchar();return choose;
}void handleMenu(MYSQL *mysql) {int choose;while (1) {choose = menu();switch (choose) {case 1: createDB(mysql, "Create database student"); break;case 2: createTable(mysql, "student", "create table stuinfo(id INT PRIMARY KEY, stuname TEXT, gender TEXT, mailbox TEXT, studep TEXT)");createTable(mysql, "student", "create table score(student_id INT, course TEXT, grade FLOAT, PRIMARY KEY(student_id, course), FOREIGN KEY(student_id) REFERENCES stuinfo(id) ON DELETE CASCADE)");break;case 3: insertData(mysql); break;case 4: deleteData(mysql); break;case 5: insertScore(mysql); break;case 6: displayScoreTable(mysql); break;case 7: updateScore(mysql); break;case 8: deleteScore(mysql); break;case 9: deleteStudentAndScore(mysql); break;case 0: printf("exit\n"); return; break;}}
}int main(void) {MYSQL *mysql_handle = NULL;mysql_handle = initial(mysql_handle);if (NULL == mysql_handle) {fprintf(stderr, "initialize failed");exit(1);}mysql_handle = myconnect(mysql_handle, "root", "123456", "localhost", "");handleMenu(mysql_handle);mysql_close(mysql_handle);mysql_library_end();return 0;
}
实践截图
六、学习实践过程遇到的问题与解决方式
1、MySQL API 使用失败原因及解决方法
-
MySQL API 使用失败(MySQL API Failure) :是指在使用 Linux 系统下的 MySQL API 进行数据库操作时,由于各种因素导致无法正常执行相关操作。常见的失败情况包括数据库连接失败、SQL 查询执行错误、数据插入或更新失败等,这将影响基于 MySQL 数据库的应用程序正常运行,导致数据无法正确存储、读取或更新。
-
失败的原因 :
- 连接配置错误 :错误的数据库主机地址、用户名、密码或端口号等连接配置信息,导致无法与 MySQL 数据库建立连接。例如,使用了错误的主机名或 IP 地址,或者用户名和密码拼写错误。
- 数据库服务问题 :MySQL 数据库服务未正常启动,或者数据库服务器出现故障、过载等情况,使得 API 无法连接到数据库。比如,数据库服务因系统故障意外停止,或者在高并发访问时响应缓慢甚至拒绝连接。
- 权限不足 :使用的数据库用户账号缺乏对相应数据库或表的访问、操作权限,导致执行某些 SQL 操作时失败。例如,尝试向一个表中插入数据,但用户账号没有该表的插入权限。
- SQL 语句错误 :编写的 SQL 语句存在语法错误、拼写错误或者逻辑错误,使得 MySQL 无法正确理解和执行该语句。比如,SQL 关键字拼写错误,或者表名、列名错误等。
- 客户端与服务器版本不兼容 :使用的 MySQL API 客户端版本与服务器版本存在不兼容的情况,可能导致连接失败或某些功能无法正常使用。
- 网络问题 :如果数据库服务器与应用程序服务器不在同一台机器上,网络连接故障、网络延迟过高或网络带宽不足等问题可能会影响 MySQL API 的正常使用,导致连接超时或数据传输错误。
-
解决方法 :
- 检查连接配置 :仔细核对 MySQL 连接配置信息,包括主机地址、端口号、用户名和密码等,确保其正确无误。可以通过在命令行中使用
mysql -h host -u user -p
命令尝试连接数据库,来验证连接配置是否正确。 - 确认数据库服务状态 :在数据库服务器上,使用命令如
systemctl status mysql
(对于 systemd 管理的服务)或查看 MySQL 服务的相关日志文件,确认数据库服务是否正常运行。如果服务未启动,及时启动服务;如果出现故障,根据错误日志进行相应的修复操作。 - 检查并授予权限 :登录到 MySQL 数据库,使用
SHOW GRANTS FOR user
语句查看用户权限,根据需要使用GRANT
语句为用户授予相应的权限。例如,GRANT INSERT, SELECT, UPDATE ON数据库名.表名 TO '用户名'@'主机名'
。 - 排查 SQL 语句错误 :使用 MySQL 客户端工具或其他 SQL 编辑器,对有问题的 SQL 语句进行语法检查和调试,确保其正确性。也可以查看 MySQL 的错误日志,其中可能包含 SQL 语句执行错误的详细信息,帮助定位问题所在。
- 检查版本兼容性 :查看 MySQL 客户端和服务器的版本信息,确保它们之间的兼容性。如果存在版本不兼容问题,考虑升级客户端或服务器端的版本,或者调整 API 使用方式以适应当前的版本。
- 排查网络问题 :使用网络诊断工具如
ping
、traceroute
等检查网络连通性,查看网络延迟和丢包情况。如果网络存在问题,及时与网络管理员沟通解决,或者优化网络配置以确保数据库连接的稳定性和数据传输的可靠性。
- 检查连接配置 :仔细核对 MySQL 连接配置信息,包括主机地址、端口号、用户名和密码等,确保其正确无误。可以通过在命令行中使用
-
应用场景 :在 Linux 系统环境下开发基于 MySQL 数据库的应用程序时,MySQL API 使用失败是较为常见的问题。掌握其失败原因和解决方法,有助于开发人员快速定位和修复数据库相关的问题,保障应用程序的正常运行和数据的准确处理,提高系统的可用性和稳定性。
2、关于Linux Shell编程
问题描述
不清楚 Linux Shell 编程中错误发生的原因和解决方法。
解决方式
-
Linux Shell 编程错误(Shell Script Failure) :是指在编写与执行 Linux Shell 脚本过程中,由于种种原因导致脚本无法按预期正常运行。这可能表现为命令未找到、权限不足、语法错误、变量未定义等,会阻碍脚本任务的完成以及后续相关流程的推进。
-
错误的原因 :
- 命令错误 :输入了错误的命令名称,或者命令的选项、参数使用不当。例如,将 “cp” 命令写成 “cpoy”,或者在 “ls” 命令后错误地使用了不支持的选项。
- 权限问题 :脚本文件本身没有执行权限,或者要操作的文件、目录权限不足,导致无法读取、写入或执行相应操作。
- 语法错误 :Shell 脚本中的语法不符合规范,像缺少 “fi” 导致的 if 语句不完整、循环结构书写错误、变量引用未用正确符号等。
- 变量问题 :变量未定义就使用,或者变量的赋值、引用存在错误,例如忘记用等号连接变量名和值、未将变量值用双引号引起来导致在特定情况下值被错误解析等。
- 环境差异 :不同的 Linux 发行版或运行环境可能导致一些命令的行为不同,或者所需的依赖工具未安装,从而引发脚本错误。
-
解决方法 :
- 检查命令 :仔细核对脚本中的每个命令拼写,查看命令的选项和参数是否正确,可以通过在终端中单独运行命令并查看帮助信息(如 “man 命令名”)来确认。
- 设置权限 :使用 “chmod” 命令为脚本文件添加执行权限,如 “chmod +x script.sh”。对于文件和目录权限问题,根据需要合理使用 “chmod” 和 “chown” 等命令进行权限调整。
- 检查语法 :利用 Shell 的检查功能,如在脚本中加入 “set -n” 选项,可以在不执行脚本的情况下检查语法错误。也可以使用一些在线的 Shell 语法检查工具来辅助发现语法问题。
- 变量处理 :在使用变量前确保已正确定义和赋值,引用变量时养成用双引号的好习惯,如 “echo “$variable””,避免变量值为空或包含特殊字符时出现意外情况。
- 环境适配 :明确脚本所依赖的 Linux 发行版环境以及所需的工具,提前在目标运行环境中安装好这些依赖工具,并在脚本开头注明适用的 Shell 解释器版本等信息,以提高脚本的兼容性。
-
应用场景 :Linux Shell 编程错误在自动化任务处理、系统管理脚本编写以及软件部署等众多场景下都容易出现。了解这些错误原因和解决方法,有助于开发者快速定位问题并修复脚本,保障脚本在不同环境下稳定、高效地执行任务,提高工作效率和系统运维的便捷性。
七、参考资料
- AI工具(你使用的AI工具及其链接)
- 问小白
- Kimi
- 图书
- 《Linux编程基础.李养群》电子版
- 网站
- CSDN
“20242817李臻 原创作品转载请注明出处 《Linux高级编程实践》”
相关文章:

20242817李臻《Linux⾼级编程实践》第9周
20242817李臻《Linux⾼级编程实践》第9周 一、AI对学习内容的总结 第十章 Linux下的数据库编程 10.1 MySQL数据库简介 MySQL概述:MySQL是一个开源的关系型数据库管理系统,最初由瑞典MySQL AB公司开发,后经SUN公司收购,现属于O…...
查看YOLO版本的三种方法
查看YOLO版本的三种方法: 一、通过命令行直接查询 使用Python交互式查询: from ultralytics import __version__ print(__version__) # 示例输出: 11.0.5二、检查PyTorch环境兼容性 import torch, ultralytics print(f"PyTorch: {torch.__versi…...
双流 JOIN 与维表 JOIN 的区别
Flink 双流 JOIN 与维表 JOIN 的区别 1. 数据关联的实时性与更新机制 维表 JOIN 基于当前快照 关联外部存储(如 MySQL、HBase)的 最新状态,仅反映处理时间的当前数据,历史结果不会随维表更新而修正。无状态回溯 无法关联历史版…...
MySQL OCP和Oracle OCP怎么选?
近期oracle 为庆祝 MySQL 数据库发布 30 周年,Oracle 官方推出限时福利:2025 年 4 月 20 日至 7 月 31 日期间,所有人均可免费报考 MySQL OCP(Oracle Certified Professional)认证考试(具体可查看MySQL OCP…...
汽车为什么需要以太网?带宽?实时?
一、传统总线“堵车”:为什么CAN、LIN扛不住了? 1. 带宽危机 案例:一辆L3级自动驾驶汽车每秒产生约4GB数据(激光雷达摄像头),而CAN FD总线最高仅8Mbps。若用CAN传输,需 500秒才能传完1秒的数据—…...

开源分享:TTS-Web-Vue系列:SSML格式化功能与高级语音合成
🎯 本文是TTS-Web-Vue系列的第十二篇文章,重点介绍项目新增的SSML格式化功能以及SSML在语音合成中的应用。通过自动格式化和实时预览,我们显著提升了SSML编辑体验,让用户能够更精确地控制语音合成的细节,实现更自然、更…...
[人机交互]理解界面对用户的影响
零.重点 – 什么是情感因素 – 富有表现力的界面 – 用户的挫败感 – 拟人化在交互设计中的应用 – 虚拟人物:代理 一.什么是情感方面 情感是指某事物对心理造成的一种状态 二.计算机科学中存在的两个相关的研究领域 2.1情感计算 机器如何能感知其他代理的情感&…...

FAST-LIO笔记
1.FAST-LIO FAST-LIO 是一个计算效率高、鲁棒性强的激光-惯性里程计系统。该系统通过紧耦合的迭代扩展卡尔曼滤波器(IEKF)将激光雷达特征点与IMU数据进行融合,使其在快速运动、噪声较大或环境复杂、存在退化的情况下仍能实现稳定的导航。 1…...

软考中级软件设计师——UML(统一建模语言)篇
UML的词汇表包含3种构造块:事物、关系和图。事物是对模型中最具有代表性的成分的抽象;关系把事物结合在一起;图聚集了相关的事物。 一、事物 UML 事物是模型中的基本元素,分为 结构事物、行为事物、分组事物、注释事物。 1. 结构事物 类(Class&#x…...

TSN网络与DIOS融合:破解煤矿井下电力系统越级跳闸难题
一、引言 1.1 研究背景与意义 在现代煤矿生产中,井下电力系统作为整个煤矿生产的动力核心,其重要性不言而喻。煤矿井下的各类机械设备,如采煤机、刮板输送机、通风机、排水泵等,都依赖稳定的电力供应才能正常运行。电力系统的稳定…...
python 实现文件批量重命名
以下是使用Python实现文件批量重命名的示例代码。该代码可以将指定目录下的文件按照一定规则进行重命名,这里以将文件重命名为带有编号的文件名为例: import osdef batch_rename(directory):if not os.path.isdir(directory):print(...

SierraNet协议分析使用指导[RDMA]| 如何设置 NVMe QP 端口以进行正确解码
在解码RoCEv2数据包(包括TCP RDMA和RoCE RDMA)时,若捕获的跟踪数据无法正确解码,通常需要执行特定的解码步骤。对于RoCE RDMA跟踪数据的处理,分析器主要采用两种方式获取必要信息以实现数据包解码: 首先&am…...
Nodejs核心机制
文章目录 前言 前言 结合 Node.js 的核心机制进行说明: 解释事件循环的各个阶段。 答案 Node.js 事件循环分为 6 个阶段,按顺序执行: Timers:执行 setTimeout 和 setInterval 的回调。 Pending I/O Callbacks:处理系…...
Win全兼容!五五 Excel Word 转 PDF 工具解决多场景转换难题
各位办公小能手们!今天给你们介绍一款超牛的工具——五五Excel Word批量转PDF工具V5.5版。这玩意儿专注搞批量格式转换,能把Excel(.xls/.xlsx)和Word(.doc/.docx)文档唰唰地变成PDF格式。 先说说它的核心功…...
【Bluedroid】HID DEVICE 连接的源码分析
本文分析Android Bluetooth协议栈中HID device设备连接流程的完整实现,从应用层接口到协议栈底层的交互细节。通过关键函数(如connect()、BTA_HdConnect()、HID_DevConnect()等)的代码解析,重点关注btif、bta、HID协议栈三层的协同机制,揭示BTA_HD_CONN_STATE_EVT事件传递…...
【AI大模型】SpringBoot整合Spring AI 核心组件使用详解
目录 一、前言 二、Spring AI介绍 2.1 Spring AI介绍 2.2 Spring AI主要特点 2.3 Spring AI核心组件 2.4 Spring AI应用场景 2.5 Spring AI优势 2.5.1 与 Spring 生态无缝集成 2.5.2 模块化设计 2.5.3 简化 AI 集成 2.5.4 支持云原生和分布式计算 2.5.5 安全性保障…...
Redis的操作以及Spring Cache框架
Redis是一种开源的内存数据结构存储,用作数据库、缓存和消息代理。它支持多种数据结构,如字符串、哈希、列表、集合、有序集合等。在Spring应用中,可以使用Spring Cache框架结合Redis来实现高效的缓存机制。本文将详细介绍Redis的基本操作以及…...
C#输出参数:使用、要求与新特性
在C#编程中,输出参数是一种强大的工具,用于从方法体内把数据传出到调用代码。它的行为与引用参数类似,但也有自己的特点。今天我们就来详细了解一下C#中的输出参数。 输出参数的基本要求 修饰符的使用 输出参数必须在声明和调用中都使用修…...

信号处理基础
一、目的 掌握信号处理的基本思想,理解采样信号的频谱特性,加强信号采样与重建的有关基本概念的理解,深入理解线性时不变系统输出与输入的关系,了解数字信号采样率转换前后信号频谱的特征。 二、内容与设计思想 1、给定序列,绘…...

小刚说C语言刷题—1058 - 求出100至999范围内的所有水仙花数
1.题目描述 2.参考代码(C语言版) #include <stdio.h> int main(void) { int i; int bai,shi,ge; for( i100;i<999;i) { baii/100; shii/10%10; gei%10; if((bai*bai*bai)(shi*shi*shi)(ge*ge*ge)i) printf("%d\n",i); } return 0; } 今天内容到此结束&…...
cat、more和less的区别
在 Linux 系统中,cat、more 和 less 都是用于查看文件内容的命令,但它们在功能和使用场景上有显著区别。以下是它们的详细对比: 1. cat 命令 功能: - 直接输出整个文件:一次性将文件内容全部显示在终端上ÿ…...

深入解析Docker:核心架构与最佳实践
文章目录 前言一、Docker 解决了什么问题?二、Docker 底层核心架构2.1 Docker 引擎的分层架构2.2 镜像的奥秘:联合文件系统(UnionFS)2.3 容器隔离的核心技术2.3.1 命名空间2.3.2 控制组(Cgroups)2.3.3 内核…...
HVV面试题汇总合集
应急响应的命令 Linux ps -aux 查看进程 netstat -antlp 查看端口 top查看 cpu使用情况 Windows tasklist 查看进程 netstat -an 查看端口struts2原理特征 原理: 045:默认的content-type解析器会把用户传来的数据直接当成代码执行,造成rce 特征:ognl表达式&…...
什么是深度神经网络
深度神经网络(DNN)详细介绍 1. 定义与核心原理 深度神经网络(Deep Neural Network, DNN)是一种具有多个隐藏层的人工神经网络模型,其核心在于通过层次化的非线性变换逐步提取输入数据的高层次抽象特征。与浅层神经网络相比,DNN的隐藏层数量通常超过三层,例如VGGNet、R…...
Node.js 24.0 正式发布:性能跃升与开发体验全面升级
Node.js v24.0.0 震撼发布!V8 13.6、npm 11、权限模型稳定化等重磅更新 2025年5月6日 —— Node.js 社区迎来重大里程碑!Node.js v24.0.0 正式发布,带来一系列激动人心的新特性、性能优化和 API 改进。本次更新涵盖 V8 JavaScript 引擎升级至…...
Linux/AndroidOS中进程间的通信线程间的同步 - 信号量
1 概述 本文将介绍 POSIX 信号量,它允许进程和线程同步对共享资源的访问。有两种类型的 POSIX 信号量: 命名信号量:这种信号量拥有一个名字。通过使用相同的名字调用 sem_open(),不相关的进程能够访问同一个信号量。未命名信号量…...
Python Cookbook-7.10 在 MySQL 数据库中储存 BLOB
任务 想把一个二进制的大对象(BLOB)存入MySQL数据库 解决方案 MySQLdb 模块并不支持完整的占位符,不过可以使用模块的escape_string 函数来解决: import MySQLdb,cPickle #连接到数据库,用你的本机来测试数据库,并获得游标 connection = MySQLdb.connect(db = "tes…...

Edge浏览器PDF字体显示错误
Edge浏览器PDF字体显示错误 软件版本信息 Edge Version: 136.0.3240.50 Word Version: Microsoft Office 专业增强版2021问题描述 在Word中使用多级列表自动编号, 并使用Word软件自带的导出为PDF文件功能, 在Word中显示正常的数字, 在Edge中查看PDF将会出现渲染错误的现象,…...
计算机网络与多线程同步机制详解
一、IP地址与子网划分 在互联网世界中,IP地址就像是每个设备的"门牌号",它使得数据包能够准确送达目的地。IP地址的划分与管理就像城市的规划,通过合理的子网划分,能够高效地管理网络资源。 子网掩码的工作原理 子网…...

Python训练营打卡——DAY22(2025.5.11)
复习日 学习参考如何使用kaggle平台,写下使用注意点,并对下述比赛提交代码 泰坦尼克号——来自灾难的机器学习 数据来源: kaggle泰坦里克号人员生还预测 挑战 泰坦尼克号沉没是历史上最臭名昭著的海难之一。 1912年4月15日,在被普…...