【智能家居】九、停车场车牌识别功能点(回调、解耦)

一、翔云 人工智能开放平台(车牌识别)
二、cJSON 库
三、实现代码
四、回调函数
五、人脸识别和车牌识别获取数据的区别
六、异步网络请求和同步网络请求的区别
七、解耦

一、翔云 人工智能开放平台(车牌识别)

翔云 人工智能开放平台(车牌识别)
在这里插入图片描述

API文档

在这里插入图片描述

返回的json数据格式

{
    "message": {
        "status": "0",
        "value": "识别完成"
    },
    "cardsinfo": [
        {
            "type": "19",
            "items": [
                {
                    "nID": null,
                    "index": null,
                    "desc": "车牌号",
                    "content": "粤A69L59"
                },
                {
                    "nID": null,
                    "index": null,
                    "desc": "车牌颜色",
                    "content": "蓝"
                },
                {
                    "nID": null,
                    "index": null,
                    "desc": "车牌颜色",
                    "content": "1"
                },
                {
                    "nID": null,
                    "index": null,
                    "desc": "车牌类型",
                    "content": "1"
                },
                {
                    "nID": null,
                    "index": null,
                    "desc": "整牌可信度",
                    "content": "86"
                },
                {
                    "nID": null,
                    "index": null,
                    "desc": "亮度评价",
                    "content": "233"
                },
                {
                    "nID": null,
                    "index": null,
                    "desc": "车牌运动方向",
                    "content": "0"
                },
                {
                    "nID": null,
                    "index": null,
                    "desc": "车牌位置(left_top_right_bottom)",
                    "content": "103_210_155_86"
                },
            ]
        }
    ]
}

二、cJSON 库

使用的是 cJSON 库,先确保已经安装该库或者将其包含在你的项目中。以下是一种使用 cJSON 库的方法:

  1. 下载 cJSON 库:

    • 你可以从 cJSON 的 GitHub 仓库下载源代码:cjson GitHub Repository。

    • 或者使用 git 进行克隆:

      git clone https://github.com/DaveGamble/cJSON.git
      
  2. 将 cJSON 库包含到你的项目中:

    • 将 cJSON 目录中的源代码文件(cJSON.ccJSON.h)复制到你的项目中,或者将整个 cJSON 目录拷贝到你的项目目录。
  3. 修改 Makefile 或编译配置文件:

    • 如果你使用 Makefile 进行编译,确保在 Makefile 中添加 cJSON 的源文件。示例 Makefile 可能如下:

      CC = gcc
      CFLAGS = -Wall -I/path/to/cJSON
      LDFLAGS = -lm
      SOURCES = your_source_file.c cJSON.c
      EXECUTABLE = your_executable_name
      
      all:
          $(CC) $(CFLAGS) $(SOURCES) -o $(EXECUTABLE) $(LDFLAGS)
      
    • 如果你使用其他构建工具,确保配置文件中包含 cJSON 的源文件并添加正确的头文件路径。

  4. 编译你的项目:

    • 在终端中进入你的项目目录,运行 make 或者你的构建工具指令。
  5. 链接 cJSON 库:

    • 在你的源文件中添加 #include "cJSON.h" 来包含 cJSON 头文件。

    • 编译时需要链接 cJSON 库。确保在编译命令中包含 cJSON 的源文件。

    • 在上面提供的代码示例中,已经包含了 #include <cjson/cJSON.h>,并且在编译时需要链接 cJSON 库。

以上步骤可能因你的项目和构建系统而异。请根据你的项目结构和构建工具的要求进行相应的修改。

三、实现代码

#include <stdio.h>
#include <curl/curl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <cjson/cJSON.h>

// 定义bool类型和常量
typedef unsigned int bool; // 数据类型别名用typedef
#define true 1
#define false 0

char PlateInfo[1024] = {'\0'}; // 全局变量,用来接收从JSON处理后返回车牌的数据

// 封装提取键值对的函数
char *getJsonValueByKey(cJSON *root, const char *key)
{
        cJSON *item = cJSON_GetObjectItem(root, key);
        if (cJSON_IsString(item)) {
                return strdup(item->valuestring); // 使用 strdup 复制字符串
        }
        else {
                return NULL;
        }
}

// 修改处理JSON数据的函数,使其返回提取的数据
char *processJsonData(const char *jsonString)
{
        char *plateNumber = NULL;
        char *plateContent = NULL;

        // 使用 cJSON 解析 JSON 数据
        cJSON *root = cJSON_Parse(jsonString);
        if (root == NULL)
        {
                fprintf(stderr, "Error parsing JSON data\n");
                return NULL;
        }

        // 获取 "cardsinfo" 数组
        cJSON *cardsinfoArray = cJSON_GetObjectItem(root, "cardsinfo");
        if (cJSON_IsArray(cardsinfoArray) && cJSON_GetArraySize(cardsinfoArray) > 0)
        {
                cJSON *firstCard = cJSON_GetArrayItem(cardsinfoArray, 0);

                // 获取 "items" 数组
                cJSON *itemsArray = cJSON_GetObjectItem(firstCard, "items");
                if (cJSON_IsArray(itemsArray) && cJSON_GetArraySize(itemsArray) > 0)
                {
                        // 提取车牌号
                        plateNumber = getJsonValueByKey(itemsArray, "desc");
                        plateContent = getJsonValueByKey(itemsArray, "content");
                }
        }

        // 释放 cJSON 对象
        cJSON_Delete(root);

        // 返回提取的数据
        PlateInfo = (plateNumber != NULL && plateContent != NULL) ? plateContent : NULL;
        return PlateInfo;
}

// 根据文档,接口调用方法为post请求
bool postUrl()
{
        CURL *curl;
        CURLcode res;

        // 根据翔云平台的接口要求  分开定义,然后字符串拼接
        char *img = getBase64FromFile("/home/orangepi/smart_home/test/car.jpg"); // 图片base64流
        char *key = "JFD5c1iBh9LVqPkkZMxxxx";
        char *secret = "76f444813fc945bd9543e4d7e086xxxx";
        int typeId = 19;
        char *format = "json";

        int len = strlen(key) + strlen(secret) + strlen(img) + 128; // 分配空间不够会>导致栈溢出
        char* postString = (char*)malloc(len);
        memset(postString, '\0', len);//因为postString是一个指针,不能用sizeof来计算其指向的大小

        // 字符串拼接
        sprintf(postString, "img=%s&key=%s&secret=%s&typeId=%d&format=%s", img, key, secret, typeId, format);

        curl = curl_easy_init();
        if (curl)
        {
                // 指定post传输内容,get请求将URL和postString一次性发送
                curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postString);
                // 指定url
                curl_easy_setopt(curl, CURLOPT_URL, "https://netocr.com/api/recogliu.do");
                // 回调函数读取返回值
                curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, readData);

                // 执行请求
                res = curl_easy_perform(curl);
                if (res != CURLE_OK) {
                        fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
                        // 处理错误
                        return false;
                }

                // 处理返回的JSON数据
                processJsonData(PlateInfo);

                // 清理资源
                curl_easy_cleanup(curl);
        }
        // 释放动态分配的内存
        free(img);
        free(postString);

        return true;
}

int main(void)
{
        postUrl();

        // 在这里,你可以直接使用 PlateInfo 来获取 OCR 后台返回的车牌信息
        printf("车牌号是%d", PlateInfo);

        return 0;
}

四、回调函数

回调函数是指在某个特定事件发生时由一个函数调用另一个函数的机制。回调函数通常是作为函数参数传递给其他函数的,以便在特定的事件发生时被调用。这种机制提供了一种灵活的方式,允许在运行时动态指定某个特定事件发生时需要执行的代码。

一般来说,回调函数有以下几个作用:

  1. 事件处理: 用于处理异步事件,如网络请求完成、用户输入等。当事件发生时,系统调用预先注册的回调函数,执行特定的处理逻辑。

  2. 定制行为: 允许用户或开发者提供自定义的行为,以便在某个算法、库或框架中插入自定义的逻辑。这提供了一种扩展和定制代码的方式。

  3. 模块解耦: 回调函数允许将一个模块的实现细节与另一个模块进行解耦。例如,一个库可以提供一个接口,允许用户提供一个回调函数,从而在不修改库源代码的情况下改变其行为。

运用场景包括但不限于:

  1. 图形用户界面(GUI)编程: 处理按钮点击、菜单选择等用户操作时,通过回调函数来执行相应的处理逻辑。

  2. 事件驱动编程: 处理异步事件,如文件读写完成、网络请求完成等,通过注册回调函数来响应这些事件。

  3. 定时器: 在定时器到期时,执行预定的回调函数。

  4. 数据结构的遍历: 在遍历数据结构时,可以使用回调函数来定义对每个元素的处理逻辑。

  5. 框架和库设计: 提供可扩展性,允许开发者通过注册回调函数来扩展和定制框架或库的行为。

回调函数在编程中是一种强大而灵活的技术,可以使代码更模块化、可复用和可扩展。

demo

在这个例子中,我们实现了一个简单的计算器,用户可以选择不同的操作,而计算器会执行相应的操作并通过回调函数返回结果。

#include <stdio.h>

// 回调函数的定义
typedef int (*OperationCallback)(int, int);

// 加法回调函数
int add(int a, int b) {
    return a + b;
}

// 减法回调函数
int subtract(int a, int b) {
    return a - b;
}

// 乘法回调函数
int multiply(int a, int b) {
    return a * b;
}

// 除法回调函数
int divide(int a, int b) {
    if (b != 0) {
        return a / b;
    } else {
        printf("Error: Division by zero\n");
        return 0;
    }
}

// 计算器函数,接受两个操作数和一个回调函数
int calculator(int a, int b, OperationCallback callback) {
    return callback(a, b);
}

int main() {
    int num1, num2;

    printf("Enter two numbers: ");
    scanf("%d %d", &num1, &num2);

    // 提供不同的操作选项
    printf("Select operation:\n");
    printf("1. Addition\n");
    printf("2. Subtraction\n");
    printf("3. Multiplication\n");
    printf("4. Division\n");

    int choice;
    scanf("%d", &choice);

    // 定义回调函数指针
    OperationCallback callback;

    // 根据用户选择设置回调函数
    switch (choice) {
        case 1:
            callback = add;
            break;
        case 2:
            callback = subtract;
            break;
        case 3:
            callback = multiply;
            break;
        case 4:
            callback = divide;
            break;
        default:
            printf("Invalid choice\n");
            return 1;
    }

    // 使用回调函数计算并输出结果
    int result = calculator(num1, num2, callback);
    printf("Result: %d\n", result);

    return 0;
}

在这个示例中,定义了四个不同的回调函数(加法、减法、乘法、除法),然后通过 calculator 函数接受两个操作数和一个回调函数,根据用户的选择调用相应的回调函数。这样就可以在运行时指定不同的操作而无需修改主计算器逻辑。这展示了回调函数的灵活性和可扩展性。

五、人脸识别和车牌识别获取数据的区别

  1. 使用的回调函数是为了在执行 CURL 请求时,通过 CURLOPT_WRITEFUNCTION 选项来指定一个回调函数,将从网络获取的数据写入到 PlateInfo 全局变量中。这样,你可以在请求执行完成后读取 PlateInfo 中的数据,以获取 OCR 后台返回的信息。

  2. 通过 cJSON 库解析 JSON 数据,然后提取了车牌号的信息,将其存储在 PlateInfo 全局变量中。这样,你不再需要回调函数,因为 processJsonData 直接对返回的 JSON 数据进行解析,并将车牌号信息存储在全局变量中。
    两者的区别在于数据获取的时机和方式:

  3. 使用回调函数:

    • 时机: 在执行 CURL 请求时,当从网络获取到数据时,回调函数会被调用。
    • 方式: 通过 CURLOPT_WRITEFUNCTION 选项,你可以指定一个回调函数,该函数将在每次有新数据到达时被调用。在这个回调函数中,你将数据写入到全局变量 PlateInfo 中。这是因为 CURL 在执行请求时是异步的,即它不会等待所有数据都被接收完毕才返回,而是在接收到一部分数据后就触发回调函数。
  4. 不使用回调函数:

    • 时机: 在 CURL 请求执行完成后,你调用 curl_easy_perform 完成请求,并在请求执行完成后直接调用 processJsonData 处理返回的 JSON 数据。
    • 方式: processJsonData 函数直接对返回的 JSON 数据进行解析,并将车牌号信息存储在全局变量 PlateInfo 中。这里是在同步的程序流程中进行的数据处理,而不需要回调函数。

总的来说,使用回调函数适用于异步的网络请求场景,它允许在数据到达时立即处理,而不必等到整个请求完成。而不使用回调函数,则适用于在请求执行完成后立即处理数据的同步场景。在你的具体应用场景中,选择使用回调函数还是不使用回调函数取决于你对程序执行时机的要求。

回调函数的概念和使用在编程中是一种通用的机制,它可以应用在不同的场景,包括处理用户输入、异步操作、模块解耦、事件驱动编程等。
使用回调函数的主要目的是演示其基本概念和应用,而并非专门与 XML 或 JSON 直接相关。然而,回调函数在处理异步操作、事件处理等场景时,常常与数据格式如 JSON 或 XML 一起使用,以更灵活地处理和解析数据。
具体到 XML 和 JSON,它们是用于表示和传输结构化数据的两种不同格式。XML 使用标签来表示数据结构,而 JSON 使用键值对。在网络通信、数据传输等场景中,你可能会遇到需要通过回调函数处理异步获取的 JSON 或 XML 数据的情况。这时,你可以使用回调函数来定义在数据到达时的处理逻辑。

总体而言,回调函数是一种通用的编程概念,而 XML 和 JSON 则是数据格式,它们可以在不同的上下文中结合使用。

六、异步网络请求和同步网络请求的区别

使用回调函数适用于异步的网络请求场景,它允许在数据到达时立即处理,而不必等到整个请求完成。而不使用回调函数,则适用于在请求执行完成后立即处理数据的同步场景。
异步和同步是两种不同的执行模型,用于描述程序中任务的执行方式。

  1. 同步(Synchronous):

    • 在同步模型中,任务按照固定的顺序顺序执行,一个任务的执行会阻塞后续任务的执行,直到当前任务完成。这意味着程序会按照严格的步骤执行,每一步都需要等待前一步完成。
    • 同步操作通常是阻塞的,即程序会等待一个任务完成后再执行下一个任务。这样的模型在代码中通常表现为顺序执行的结构,例如函数调用。
  2. 异步(Asynchronous):

    • 在异步模型中,任务的执行不按照固定的顺序进行,一个任务的开始不会等待前一个任务的完成。程序可以在等待某个任务完成的同时继续执行其他任务。
    • 异步操作通常是非阻塞的,即程序可以继续执行其他任务而不必等待当前任务完成。这样的模型在代码中通常表现为回调函数或事件处理,允许在某个事件发生时执行相应的操作。

异步网络请求和同步网络请求的区别:

  • 同步网络请求:

    • 在发起一个网络请求后,程序会阻塞等待服务器响应。这意味着程序会停止执行,直到请求完成并得到响应。
    • 如果网络连接较慢或服务器响应时间较长,程序可能会在等待中花费较长时间,造成用户体验下降。
  • 异步网络请求:

    • 在发起一个网络请求后,程序不会等待响应。相反,它可以继续执行其他任务。
    • 当请求完成并获得响应时,通过回调函数或其他机制执行相应的操作。这种方式允许程序在等待网络响应的同时继续执行其他操作,提高了程序的并发性和响应速度。

应用于编程中的例子:

// 同步网络请求的例子
int syncHttpRequest() {
    // 发起网络请求
    // 等待服务器响应
    // 处理响应数据
    return 0;
}

// 异步网络请求的例子
void asyncHttpRequest(void (*callback)(int)) {
    // 发起网络请求
    // 不等待服务器响应,继续执行其他任务
    // 请求完成后,执行回调函数处理响应数据
    int responseData = 42; // 模拟响应数据
    callback(responseData);
}

// 示例回调函数
void handleResponse(int data) {
    // 处理响应数据
    printf("Received response: %d\n", data);
}

int main() {
    // 同步网络请求
    int result = syncHttpRequest();
    printf("Result of synchronous request: %d\n", result);

    // 异步网络请求
    asyncHttpRequest(handleResponse);
    printf("Continuing with other tasks...\n");

    // 程序继续执行其他任务,不用等待异步请求完成

    return 0;
}

在这个例子中,syncHttpRequest 是一个同步的网络请求函数,会阻塞程序直到请求完成。而 asyncHttpRequest 是一个异步的网络请求函数,它不会等待响应,而是通过回调函数的方式在请求完成后处理响应数据。这允许程序在等待网络响应的同时继续执行其他任务。

七、解耦

解耦(Decoupling)是指将一个系统的各个部分(或模块、组件)设计得相对独立,降低它们之间的依赖性,使得一个部分的修改不会直接影响到其他部分。这样的设计能够提高系统的灵活性、可维护性和可扩展性。

在软件开发中,解耦通常有以下几个方面的含义:

  1. 模块解耦: 将系统划分为相对独立的模块,每个模块负责一个明确的功能,模块之间通过接口进行通信。这样,修改一个模块的实现不会对其他模块产生影响,从而提高了代码的可维护性。

  2. 组件解耦: 将系统划分为独立的组件,每个组件可以独立开发、测试、部署和升级。组件之间通过定义良好的接口进行通信,使得它们可以被替换或升级而不影响系统的其他部分。

  3. 时间解耦: 尽量避免在时间上的依赖关系。即,一个操作的完成不依赖于其他操作的执行顺序。这样,系统更具弹性,能够适应不同的执行时序。

  4. 数据解耦: 降低模块或组件之间的数据依赖,通过定义良好的接口,使得数据的变化不会对其他部分造成影响。这有助于降低系统的耦合度。

解耦的优势包括:

  • 可维护性: 模块化和组件化的设计使得系统更容易理解和维护。修改一个模块的实现不会影响其他部分。
  • 可扩展性: 可以更容易地添加新的功能或组件,而不必修改现有的代码。
  • 灵活性: 系统的不同部分可以独立开发、测试、部署和维护,提高了灵活性。
  • 可测试性: 独立的模块或组件更容易进行单元测试,从而提高系统的可测试性。

在编程中,回调函数是一种常见的解耦机制。通过将某一功能的实现通过回调函数传递给其他模块或组件,可以使它们之间解耦。当某一事件发生时,执行相应的回调函数,而不需要直接依赖于特定的模块或组件的实现。

理解解耦的概念可以从以下几个方面入手:

  1. 独立性: 解耦的核心思想是使系统的各个部分相对独立,一个部分的修改不应该直接影响其他部分。这意味着每个模块、组件或功能都应该尽可能独立,有自己清晰的职责和接口。

  2. 依赖降低: 解耦的目标之一是降低模块之间的依赖关系。模块之间的耦合越低,修改其中一个模块时对其他模块的影响就越小。这有助于系统更容易扩展、维护和修改。

  3. 接口定义: 定义清晰的接口是解耦的关键。一个模块通过接口与其他模块通信,而不直接访问其内部实现。这样,当一个模块的内部实现发生变化时,只需要保持接口不变,其他模块就不会受到影响。

  4. 模块化和组件化设计: 将系统划分为独立的、相对自治的模块或组件。每个模块负责特定的功能,模块之间通过定义的接口进行通信。这样的设计使得系统更容易被理解、维护和扩展。

  5. 单一职责原则: 每个模块、类或组件应该具有单一职责,即它只负责一个明确的功能。这有助于确保每个部分都是相对独立的,修改一个功能时不会牵扯到其他不相关的功能。

  6. 事件驱动编程: 在某些情况下,使用事件驱动的方式可以帮助解耦。模块之间通过事件进行通信,而不是直接调用对方的方法。当一个事件发生时,相应的处理逻辑被触发,而不需要知道具体的实现。

  7. 依赖注入: 通过依赖注入的方式,将一个模块所需要的依赖通过参数传递给它,而不是在模块内部直接创建依赖。这有助于减少模块对特定实现的依赖,提高了灵活性和可替换性。

通过在实际编程中应用这些原则和技术,你可以逐渐培养对解耦概念的理解。在设计和修改系统时,考虑模块之间的独立性、依赖关系、接口设计等因素,以实现更加灵活、可维护和可扩展的代码结构。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

写 SVG 动画必看!SVG系列文章4-微信公众号编写

1、基础设置 1.1 上传背景图素材 使用到的图片需要上传至微信后台&#xff0c;获取线上地址&#xff1a; 1.2 导入微信文章正文 新建图文消息&#xff0c;先输入好标题、作者&#xff0c;上传好封面图。然后在正文区域输入点文字&#xff0c;打开 chrome 调试工具&#xff0…

CorelDRAW软件2024版本好用吗?有哪些功能优势

CorelDRAW是一款综合性强大的专业平面设计软件&#xff0c;其功能覆盖了矢量图形设计、高级文字编辑、精细绘图以及多页文档和页面设计。该软件不仅适用于广告设计、包装设计&#xff0c;还广泛应用于出版、网页设计和多媒体制作等多个领域。下面就给大家介绍一下CorelDRAW这款…

台式扫描电镜中的扫描速度和扫描模式如何选择?

台式扫描电镜&#xff08;SEM&#xff09;是一种利用电子束扫描样品表面&#xff0c;通过检测样品反射或发射的次级电子、背散射电子、X 射线等信号&#xff0c;来获取样品的形貌、结构、组成和分布等信息的仪器。台式扫描电镜具有体积小、操作简单、样品制备方便、分辨率高、成…

论文怎么改才能降低重复率

一、引言&#xff1a;智能工具助力&#xff0c;轻松降低论文重复率 论文的重复率是学术写作中的重要问题&#xff0c;如何有效降低重复率成为了许多研究者的关注焦点。如今&#xff0c;智能工具的发展为我们提供了更多选择。本文将介绍几种实用的智能工具&#xff0c;包括快码…

PyInstaller 打包 Python 脚本为 .exe 可执行文件闪退、No Model named XXX问题

文章目录 前言.exe 可执行文件闪退No Model named XXXPython 环境问题查看当前python路径查看当前python环境使用的site-package路径 个人简介 前言 在上一篇文章中&#xff0c;我们介绍了如何将 Python 脚本打包为 .exe 可执行文件&#xff0c;但有时候打包生成的 .exe 文件会…

EasyV易知微数字孪生助力解决实际行业问题与痛点

数字孪生技术在当前多个领域得到了广泛的应用&#xff0c;特别是在航空航天、工业、城市和医学等领域&#xff0c;它被视为许多科技企业所关注的焦点。这种技术已经成为实现智能化的重要手段&#xff0c;它可以应用于项目设计、建造和运营等各个阶段&#xff0c;能够解决实际问…

总线一:I2C简介(介绍看这一篇就够啦)

本节主要介绍以下内容&#xff1a; I2C协议简介 STM32的I2C特性及架构 I2C初始化结构体详解 一、I2C协议简介 I2C 通讯协议(Inter&#xff0d;Integrated Circuit)是由Phiilps公司开发的&#xff0c;由于它引脚少&#xff0c;硬件实现简单&#xff0c;可扩展性强&#xff…

C/C++,动态 DP 问题的计算方法与源程序

1 文本格式 #include <bits/stdc.h> using namespace std; typedef long long LL; const int maxn 500010; const int INF 0x3f3f3f3f; int Begin[maxn], Next[maxn], To[maxn], e, n, m; int size[maxn], son[maxn], top[maxn], fa[maxn], dis[maxn], p[maxn], i…

HelpLook VS Confluence:知识管理方面谁更有优势?

多年来&#xff0c;在线协作和文档工具市场一直被Confluence所主导。Confluence由Atlassian于2004年创立&#xff0c;很迅速地成为企业寻求强大而全面的协作解决方案和知识管理的热门选择。然而&#xff0c;随着新工具如Notion和HelpLook的出现&#xff0c;市场格局发生了变化&…

OpenVINS学习3——初始化原理学习

一、OpenVINS初始化概述 VIO初始化的主要意义有&#xff1a; &#xff08;1&#xff09;对齐相机的世界坐标系和惯性系&#xff0c;因此需要估计重力方向。 &#xff08;2&#xff09;为后续的VIO算法提供较为准确的初始参数和状态&#xff08;尺度、IMU bias、初始速度&…

记录hive/spark取最新且不为null的方法

听标题可能听不懂我想表达的意思&#xff0c;我来描述一下我要做的事&#xff1a; 比如采集同学对某一网站进行数据采集&#xff0c;同一个用户每天会有很多条记录&#xff0c;所以我们要取一条这个用户最新的状态&#xff0c;比如用户改了N次昵称&#xff0c;我们只想得到最后…

C++STL之List的实现

首先我们要实现List的STL,我们首先要学会双向带头链表的数据结构。那么第一步肯定是要构建我们的节点的数据结构。 首先要有数据域&#xff0c;前后指针域即可。 再通过模板类进行模板化。 然后再写List的构造函数&#xff0c;这个地方用T&,通过引用就可以减少一次形参拷…

坑爹的奥数(枚举法)

枚举法是一种解决问题的基本方法&#xff0c;它通过列举问题的所有可能情况来找到问题的解。这种方法适用于问题的解空间相对较小&#xff0c;可以通过穷举所有可能的解来找到最优解或满足特定条件的解。 以下是枚举法的一般步骤&#xff1a; 定义问题&#xff1a; 确定问题的…

学习-面试java基础-(集合)

String 为什么不可变&#xff1f; 1线程安全 2支持hash映射和缓存。因为String的hash值经常会使用到&#xff0c;比如作为 Map 的键&#xff0c;不可变的特性使得 hash 值也不会变&#xff0c;不需要重新计算。 3出于安全考虑。网络地址URL、文件路径path、密码通常情况下都是以…

易点易动设备管理系统:助力企业高效巡检的智能选择

在现代企业管理中&#xff0c;设备巡检是确保设备正常运行和生产高效的重要环节。然而&#xff0c;传统的巡检方式常常面临着效率低下、信息不准确等问题。为了解决这些挑战&#xff0c;易点易动设备管理系统应运而生。本文将详细介绍易点易动设备管理系统如何助力企业实现高效…

红队攻防实战之DEATHNOTE

难道向上攀爬的那条路&#xff0c;不是比站在顶峰更让人热血澎湃吗 渗透过程 获取ip 使用Kali中的arp-scan工具扫描探测 端口扫描 可以看到开放了22和80端口。 访问80端口&#xff0c;重定向到 修改hosts文件&#xff0c;将该域名解析到ip 如图 修改完再次访问&#xff0…

Python 递归、闭包与装饰器的编程魔法

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 在Python编程中&#xff0c;递归、闭包和装饰器是一些强大的工具&#xff0c;它们能够为代码增色不少&#xff0c;提高代码的可读性和灵活性。本文将深入探讨这三种编程魔法的原理和应用&#xff0c;通过丰富的示…

040.Python面向对象_设计原则

我 的 个 人 主 页&#xff1a;&#x1f449;&#x1f449; 失心疯的个人主页 &#x1f448;&#x1f448; 入 门 教 程 推 荐 &#xff1a;&#x1f449;&#x1f449; Python零基础入门教程合集 &#x1f448;&#x1f448; 虚 拟 环 境 搭 建 &#xff1a;&#x1f449;&…

【工具栏】idea安装翻译工具

然后重启idea 打开设置 翻译方式&#xff1a; 选中要翻译的文本 然后右键 运行项目的时候&#xff0c;方便查找错误

快速幂+高精乘(填坑)洛谷1226+1045

引言 最近在刷题的时候偶然见到这样一个题目&#xff0c;见下图 大致的意思是&#xff0c;让我们计算a的b次方取模p的结果&#xff0c;再我了解了关于快速幂的内容之后&#xff0c;很快便解决了这道题&#xff0c;每次乘完a后取模最后就可以得到结果。但是在这之后&#xff0c…