20242817李臻《Linux⾼级编程实践》第9周

news2025/5/12 17:54:52

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数据库编程基本方法

  • 基本步骤
    1. 定义并初始化与数据库连接和操作相关的数据结构变量。
    2. 建立到数据库的连接。
    3. 执行相应的DDL操作,如select/delete/insert/update等语句。
    4. 关闭数据库连接释放资源。

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 TRANSACTIONCOMMITROLLBACK
  • 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_RESMYSQL_ROWMYSQL_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_preparemysql_stmt_execute等API,用于执行准备语句。

三、学习思维导图

第十章

在这里插入图片描述

mindmap
  root((Linux下的数据库编程))
    MySQL数据库简介
      基本信息
        开发背景
        所属公司
        社区版与商业版
      特点
        体积小
        速度快
        成本低
        开源
      应用场景
        Web应用
        嵌入式开发
    Linux数据库编程应用
      Web服务器
        账户信息
        购买信息
      嵌入式Linux
        传感器数据
      网络数据采集
        C语言操作
    MySQL C API
      两种形式
        libmysqlclient
          独立进程
        libmysqld
          嵌入式
          紧耦合
      使用方法
        安装MySQL服务器版
        安装MySQL Connector/C
      编译链接
        头文件
        库文件
    Linux数据库编程基本方法
      数据库连接
        初始化
        连接
      数据库操作
        DDL操作
        DML操作
      资源释放
        关闭连接
        释放内存
    MySQL数据库数据结构及API
      数据结构
        MYSQL
        MYSQL_RES
        MYSQL_ROW
        MYSQL_FIELD
        my_ulonglong
        my_bool
      API函数
        初始化与结束
        数据库连接
        查询与结果处理
        错误处理
        事务处理
    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 使用方式以适应当前的版本。
    • 排查网络问题 :使用网络诊断工具如 pingtraceroute 等检查网络连通性,查看网络延迟和丢包情况。如果网络存在问题,及时与网络管理员沟通解决,或者优化网络配置以确保数据库连接的稳定性和数据传输的可靠性。
  • 应用场景 :在 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高级编程实践》”

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

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

相关文章

开源分享:TTS-Web-Vue系列:SSML格式化功能与高级语音合成

&#x1f3af; 本文是TTS-Web-Vue系列的第十二篇文章&#xff0c;重点介绍项目新增的SSML格式化功能以及SSML在语音合成中的应用。通过自动格式化和实时预览&#xff0c;我们显著提升了SSML编辑体验&#xff0c;让用户能够更精确地控制语音合成的细节&#xff0c;实现更自然、更…

FAST-LIO笔记

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

软考中级软件设计师——UML(统一建模语言)篇

UML的词汇表包含3种构造块:事物、关系和图。事物是对模型中最具有代表性的成分的抽象;关系把事物结合在一起;图聚集了相关的事物。 一、事物 UML 事物是模型中的基本元素&#xff0c;分为 结构事物、行为事物、分组事物、注释事物。 1. 结构事物 类&#xff08;Class&#x…

TSN网络与DIOS融合:破解煤矿井下电力系统越级跳闸难题

一、引言 1.1 研究背景与意义 在现代煤矿生产中&#xff0c;井下电力系统作为整个煤矿生产的动力核心&#xff0c;其重要性不言而喻。煤矿井下的各类机械设备&#xff0c;如采煤机、刮板输送机、通风机、排水泵等&#xff0c;都依赖稳定的电力供应才能正常运行。电力系统的稳定…

SierraNet协议分析使用指导[RDMA]| 如何设置 NVMe QP 端口以进行正确解码

在解码RoCEv2数据包&#xff08;包括TCP RDMA和RoCE RDMA&#xff09;时&#xff0c;若捕获的跟踪数据无法正确解码&#xff0c;通常需要执行特定的解码步骤。对于RoCE RDMA跟踪数据的处理&#xff0c;分析器主要采用两种方式获取必要信息以实现数据包解码&#xff1a; 首先&am…

信号处理基础

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

小刚说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; } 今天内容到此结束&…

深入解析Docker:核心架构与最佳实践

文章目录 前言一、Docker 解决了什么问题&#xff1f;二、Docker 底层核心架构2.1 Docker 引擎的分层架构2.2 镜像的奥秘&#xff1a;联合文件系统&#xff08;UnionFS&#xff09;2.3 容器隔离的核心技术2.3.1 命名空间2.3.2 控制组&#xff08;Cgroups&#xff09;2.3.3 内核…

Edge浏览器PDF字体显示错误

Edge浏览器PDF字体显示错误 软件版本信息 Edge Version: 136.0.3240.50 Word Version: Microsoft Office 专业增强版2021问题描述 在Word中使用多级列表自动编号, 并使用Word软件自带的导出为PDF文件功能, 在Word中显示正常的数字, 在Edge中查看PDF将会出现渲染错误的现象,…

Python训练营打卡——DAY22(2025.5.11)

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

实战项目4(05)

​目录 任务场景一 【sw1配置】 任务场景二 【sw1配置】 【sw2配置】 任务场景一 按照下图完成网络拓扑搭建和配置 任务要求&#xff1a; 1、在交换机SW1的E0/0/1端口进行设置&#xff0c;实现允许最多两个电脑可以正常进行通信。 2、在交换机SW1的E0/0/2端口进行设置&…

C++学习之STL学习

在经过前面的简单的C入门语法的学习后&#xff0c;我们开始接触C最重要的组成部分之一&#xff1a;STL 目录 STL的介绍 什么是STL STL的历史 UTF-8编码原理&#xff08;了解&#xff09; UTF-8编码原理 核心编码规则 规则解析 编码步骤示例 1. 确定码点范围 2. 转换为…

3. 仓颉 CEF 库封装

文章目录 1. capi 使用说明2. Cangjie CEF2. 1实现目标 3. 实现示例 1. capi 使用说明 根据上一节 https://blog.csdn.net/qq_51355375/article/details/147880718?spm1011.2415.3001.5331 所述&#xff0c; cefcapi 是libcef 共享库导出一个 C API, 而以源代码形式分发的 li…

LabVIEW多通道并行数据存储系统

在工业自动化监测、航空航天测试、生物医学信号采集等领域&#xff0c;常常需要对多个传感器通道的数据进行同步采集&#xff0c;并根据后续分析需求以不同采样率保存特定通道组合。传统单线程数据存储方案难以满足实时性和资源利用效率的要求&#xff0c;因此设计一个高效的多…

谷歌在即将举行的I/O大会之前,意外泄露了其全新设计语言“Material 3 Expressive”的细节

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

十三、基于大模型的在线搜索平台——整合function calling流程

基于大模型的在线搜索平台——整合function calling流程 一、function calling调用总结 上篇文章已经实现了信息抓取能力&#xff0c;并封装成了函数。现在最后一步将能力转换为大模型可以调用的能力&#xff0c;实现搜索功能就可以了。这篇主要实现大模型的function calling能…

力扣70题解

记录 2025.5.8 题目: 思路&#xff1a; 1.初始化&#xff1a;p 和 q 初始化为 0&#xff0c;表示到达第 0 级和第 1 级前的方法数。r 初始化为 1&#xff0c;表示到达第 1 级台阶有 1 种方法。 2.循环迭代&#xff1a;从第 1 级到第 n 级台阶进行迭代&#xff1a; p 更新为前…

电商双11美妆数据分析

1、初步了解 2.2 缺失值处理 通过上面观察数据发现sale_count,comment_count 存在缺失值,先观察存在缺失值的行的基本情况 2.3 数据挖掘寻找新的特征 给出各个关键词的分类类别 由title新生成两列类别 对是否是男性专用进行分析并新增一列 对每个产品总销量新增销售额这一列

24、TypeScript:预言家之书——React 19 类型系统

一、预言家的本质 "TypeScript是魔法世界的预言家之书&#xff0c;用静态类型编织代码的命运轨迹&#xff01;" 霍格沃茨符文研究院的巫师挥动魔杖&#xff0c;类型注解与泛型的星轨在空中交织成防护矩阵。 ——基于《国际魔法联合会》第12号类型协议&#xff0c;Ty…

第8章-1 查询性能优化-优化数据访问

上一篇&#xff1a;《第7章-3 维护索引和表》 在前面的章节中&#xff0c;我们介绍了如何设计最优的库表结构、如何建立最好的索引&#xff0c;这些对于提高性能来说是必不可少的。但这些还不够——还需要合理地设计查询。如果查询写得很糟糕&#xff0c;即使库表结构再合理、索…