游戏源码网站免费线上营销方案案例范文
游戏源码网站免费,线上营销方案案例范文,电子商务网站的建设步骤有,四川建设网入川备案网站一、翔云 人工智能开放平台#xff08;车牌识别#xff09; 二、cJSON 库 三、实现代码 四、回调函数 五、人脸识别和车牌识别获取数据的区别 六、异步网络请求和同步网络请求的区别 七、解耦
一、翔云 人工智能开放平台#xff08;车牌识别#xff09;
翔云 人工智能开放…一、翔云 人工智能开放平台车牌识别 二、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 库的方法 下载 cJSON 库 你可以从 cJSON 的 GitHub 仓库下载源代码cjson GitHub Repository。 或者使用 git 进行克隆 git clone https://github.com/DaveGamble/cJSON.git将 cJSON 库包含到你的项目中 将 cJSON 目录中的源代码文件cJSON.c 和 cJSON.h复制到你的项目中或者将整个 cJSON 目录拷贝到你的项目目录。 修改 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_nameall:$(CC) $(CFLAGS) $(SOURCES) -o $(EXECUTABLE) $(LDFLAGS)如果你使用其他构建工具确保配置文件中包含 cJSON 的源文件并添加正确的头文件路径。 编译你的项目 在终端中进入你的项目目录运行 make 或者你的构建工具指令。 链接 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 0char 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%skey%ssecret%stypeId%dformat%s, img, key, secret, typeId, format);curl curl_easy_init();if (curl){// 指定post传输内容get请求将URL和postString一次性发送curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postString);// 指定urlcurl_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;
}四、回调函数
回调函数是指在某个特定事件发生时由一个函数调用另一个函数的机制。回调函数通常是作为函数参数传递给其他函数的以便在特定的事件发生时被调用。这种机制提供了一种灵活的方式允许在运行时动态指定某个特定事件发生时需要执行的代码。
一般来说回调函数有以下几个作用 事件处理 用于处理异步事件如网络请求完成、用户输入等。当事件发生时系统调用预先注册的回调函数执行特定的处理逻辑。 定制行为 允许用户或开发者提供自定义的行为以便在某个算法、库或框架中插入自定义的逻辑。这提供了一种扩展和定制代码的方式。 模块解耦 回调函数允许将一个模块的实现细节与另一个模块进行解耦。例如一个库可以提供一个接口允许用户提供一个回调函数从而在不修改库源代码的情况下改变其行为。
运用场景包括但不限于 图形用户界面(GUI)编程 处理按钮点击、菜单选择等用户操作时通过回调函数来执行相应的处理逻辑。 事件驱动编程 处理异步事件如文件读写完成、网络请求完成等通过注册回调函数来响应这些事件。 定时器 在定时器到期时执行预定的回调函数。 数据结构的遍历 在遍历数据结构时可以使用回调函数来定义对每个元素的处理逻辑。 框架和库设计 提供可扩展性允许开发者通过注册回调函数来扩展和定制框架或库的行为。
回调函数在编程中是一种强大而灵活的技术可以使代码更模块化、可复用和可扩展。
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 函数接受两个操作数和一个回调函数根据用户的选择调用相应的回调函数。这样就可以在运行时指定不同的操作而无需修改主计算器逻辑。这展示了回调函数的灵活性和可扩展性。
五、人脸识别和车牌识别获取数据的区别 使用的回调函数是为了在执行 CURL 请求时通过 CURLOPT_WRITEFUNCTION 选项来指定一个回调函数将从网络获取的数据写入到 PlateInfo 全局变量中。这样你可以在请求执行完成后读取 PlateInfo 中的数据以获取 OCR 后台返回的信息。 通过 cJSON 库解析 JSON 数据然后提取了车牌号的信息将其存储在 PlateInfo 全局变量中。这样你不再需要回调函数因为 processJsonData 直接对返回的 JSON 数据进行解析并将车牌号信息存储在全局变量中。 两者的区别在于数据获取的时机和方式 使用回调函数 时机 在执行 CURL 请求时当从网络获取到数据时回调函数会被调用。方式 通过 CURLOPT_WRITEFUNCTION 选项你可以指定一个回调函数该函数将在每次有新数据到达时被调用。在这个回调函数中你将数据写入到全局变量 PlateInfo 中。这是因为 CURL 在执行请求时是异步的即它不会等待所有数据都被接收完毕才返回而是在接收到一部分数据后就触发回调函数。 不使用回调函数 时机 在 CURL 请求执行完成后你调用 curl_easy_perform 完成请求并在请求执行完成后直接调用 processJsonData 处理返回的 JSON 数据。方式 processJsonData 函数直接对返回的 JSON 数据进行解析并将车牌号信息存储在全局变量 PlateInfo 中。这里是在同步的程序流程中进行的数据处理而不需要回调函数。
总的来说使用回调函数适用于异步的网络请求场景它允许在数据到达时立即处理而不必等到整个请求完成。而不使用回调函数则适用于在请求执行完成后立即处理数据的同步场景。在你的具体应用场景中选择使用回调函数还是不使用回调函数取决于你对程序执行时机的要求。 回调函数的概念和使用在编程中是一种通用的机制它可以应用在不同的场景包括处理用户输入、异步操作、模块解耦、事件驱动编程等。 使用回调函数的主要目的是演示其基本概念和应用而并非专门与 XML 或 JSON 直接相关。然而回调函数在处理异步操作、事件处理等场景时常常与数据格式如 JSON 或 XML 一起使用以更灵活地处理和解析数据。 具体到 XML 和 JSON它们是用于表示和传输结构化数据的两种不同格式。XML 使用标签来表示数据结构而 JSON 使用键值对。在网络通信、数据传输等场景中你可能会遇到需要通过回调函数处理异步获取的 JSON 或 XML 数据的情况。这时你可以使用回调函数来定义在数据到达时的处理逻辑。 总体而言回调函数是一种通用的编程概念而 XML 和 JSON 则是数据格式它们可以在不同的上下文中结合使用。 六、异步网络请求和同步网络请求的区别
使用回调函数适用于异步的网络请求场景它允许在数据到达时立即处理而不必等到整个请求完成。而不使用回调函数则适用于在请求执行完成后立即处理数据的同步场景。 异步和同步是两种不同的执行模型用于描述程序中任务的执行方式。 同步Synchronous 在同步模型中任务按照固定的顺序顺序执行一个任务的执行会阻塞后续任务的执行直到当前任务完成。这意味着程序会按照严格的步骤执行每一步都需要等待前一步完成。同步操作通常是阻塞的即程序会等待一个任务完成后再执行下一个任务。这样的模型在代码中通常表现为顺序执行的结构例如函数调用。 异步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是指将一个系统的各个部分或模块、组件设计得相对独立降低它们之间的依赖性使得一个部分的修改不会直接影响到其他部分。这样的设计能够提高系统的灵活性、可维护性和可扩展性。
在软件开发中解耦通常有以下几个方面的含义 模块解耦 将系统划分为相对独立的模块每个模块负责一个明确的功能模块之间通过接口进行通信。这样修改一个模块的实现不会对其他模块产生影响从而提高了代码的可维护性。 组件解耦 将系统划分为独立的组件每个组件可以独立开发、测试、部署和升级。组件之间通过定义良好的接口进行通信使得它们可以被替换或升级而不影响系统的其他部分。 时间解耦 尽量避免在时间上的依赖关系。即一个操作的完成不依赖于其他操作的执行顺序。这样系统更具弹性能够适应不同的执行时序。 数据解耦 降低模块或组件之间的数据依赖通过定义良好的接口使得数据的变化不会对其他部分造成影响。这有助于降低系统的耦合度。
解耦的优势包括
可维护性 模块化和组件化的设计使得系统更容易理解和维护。修改一个模块的实现不会影响其他部分。可扩展性 可以更容易地添加新的功能或组件而不必修改现有的代码。灵活性 系统的不同部分可以独立开发、测试、部署和维护提高了灵活性。可测试性 独立的模块或组件更容易进行单元测试从而提高系统的可测试性。
在编程中回调函数是一种常见的解耦机制。通过将某一功能的实现通过回调函数传递给其他模块或组件可以使它们之间解耦。当某一事件发生时执行相应的回调函数而不需要直接依赖于特定的模块或组件的实现。
理解解耦的概念可以从以下几个方面入手 独立性 解耦的核心思想是使系统的各个部分相对独立一个部分的修改不应该直接影响其他部分。这意味着每个模块、组件或功能都应该尽可能独立有自己清晰的职责和接口。 依赖降低 解耦的目标之一是降低模块之间的依赖关系。模块之间的耦合越低修改其中一个模块时对其他模块的影响就越小。这有助于系统更容易扩展、维护和修改。 接口定义 定义清晰的接口是解耦的关键。一个模块通过接口与其他模块通信而不直接访问其内部实现。这样当一个模块的内部实现发生变化时只需要保持接口不变其他模块就不会受到影响。 模块化和组件化设计 将系统划分为独立的、相对自治的模块或组件。每个模块负责特定的功能模块之间通过定义的接口进行通信。这样的设计使得系统更容易被理解、维护和扩展。 单一职责原则 每个模块、类或组件应该具有单一职责即它只负责一个明确的功能。这有助于确保每个部分都是相对独立的修改一个功能时不会牵扯到其他不相关的功能。 事件驱动编程 在某些情况下使用事件驱动的方式可以帮助解耦。模块之间通过事件进行通信而不是直接调用对方的方法。当一个事件发生时相应的处理逻辑被触发而不需要知道具体的实现。 依赖注入 通过依赖注入的方式将一个模块所需要的依赖通过参数传递给它而不是在模块内部直接创建依赖。这有助于减少模块对特定实现的依赖提高了灵活性和可替换性。
通过在实际编程中应用这些原则和技术你可以逐渐培养对解耦概念的理解。在设计和修改系统时考虑模块之间的独立性、依赖关系、接口设计等因素以实现更加灵活、可维护和可扩展的代码结构。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/90118.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!