JSON|cJSON 介紹以及具體項目編寫

一、JSON介紹

JSON(JavaScript Object Notation 即JavaScript對象表示法)是一種輕量級的數據交換格式。采用完全獨立于編程語言的文本格式來存儲和表示數據。

  • JSON是一種數據交換格式.
  • JSON獨立于編程語言(你不必學習JavaScript).
  • JSON表達數據的方式對通用的編程概念都很友好.

本文主要介紹使用C語言解析JSON文件

二、JSON語法規則

數據結構

  1. 對象(Object):使用花括號{}包裹,由鍵值對組成。鍵必須是字符串,使用雙引號""包裹,鍵值對之間用逗號,分隔。
  2. 數組(Array):使用方括號[]包裹,值之間用逗號,分隔。

值的類型

  1. 字符串(String):使用雙引號""包裹的 Unicode 字符序列。
  2. 數值(Number):整數或浮點數,不使用引號,數字沒有長度限制。
  3. 布爾值(Boolean)truefalse,表示"有"或者"沒有",不使用引號。
  4. 空值(Null)null,表示沒有這項內容,它不是0,0是一個數字,本質上是在計數,不使用引號。
  5. 嵌套對象或數組:可在值中嵌套對象或數組。數組:是由方括號括起來的一組值構成

注意事項

  • 不允許使用單引號。
  • 不允許包含注釋。
  • 不允許使用未定義的變量或特殊符號(如NaNInfinity)。
  • 數組和對象可以包含不同類型的值。
  • 使用冒號:來分割名稱和值,名稱始終在左側,一定是字符串,值始終在右側可以是多種類型

三、cJSON

3.1cJSON介紹和獲取

首先在GitHub上下載開源的cjson.h以及cjson.c文件

這里給出附件

使用的時候,只需要將這兩個文件復制到工程目錄,然后包含頭文件cJSON.h即可,如下:
#include "cJSON.h"

3.2cJSON數據結構和設計思想

核心數據結構:cJSON?結構體

cJSON 使用單一結構體表示所有 JSON 類型,通過?type?字段區分不同類型。

cJSON.h中源碼如下

typedef struct cJSON {struct cJSON *next,*prev;	/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */struct cJSON *child;		/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */int type;					/* The type of the item, as above. */char *valuestring;			/* The item's string, if type==cJSON_String */int valueint;				/* The item's number, if type==cJSON_Number */double valuedouble;			/* The item's number, if type==cJSON_Number */char *string;				/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
} cJSON;

統一表示所有 JSON 類型:將其中的一條JSON數據抽象出來,也就是一個鍵值對,用上面的結構體 strcut cJSON 來表示

  • 通過?type?字段(如?JSON_Object,?JSON_Array,?JSON_Number)區分不同類型。
  • 數值類型通過?valueint?和?valuedouble?存儲,字符串類型通過?valuestring?存儲。

雙向鏈表管理數組和對象成員

  • 數組(JSON_Array)和對象(JSON_Object)使用雙向鏈表?next?和?prev?連接成員。
  • 對象的鍵值對通過?child?指針指向第一個成員,每個成員的?string?字段存儲鍵名

遞歸嵌套結構

  • 子節點可以是任意 JSON 類型,支持無限層級嵌套(如數組包含對象,對象包含數組)。

設計思想

1.輕量級與可移植性
  • 無依賴:僅依賴標準 C 庫(stdlib.h,?string.h,?math.h),無需額外依賴。
  • 單文件實現:核心代碼集中在?cJSON.c?和?cJSON.h,便于集成到嵌入式系統或資源受限環境。
2. 簡單易用的 API

提供直觀的函數接口,例如:

  • cJSON_Parse():解析 JSON 字符串為?cJSON?對象。
  • cJSON_GetObjectItem():通過鍵名獲取對象成員。
  • cJSON_Print():將?cJSON?對象序列化為 JSON 字符串。
  • cJSON_CreateObject()/cJSON_CreateArray():創建 JSON 對象 / 數組。
3. 動態內存管理
  • 使用?malloc()?和?free()?動態分配和釋放內存,需手動調用?cJSON_Delete()?釋放不再使用的對象。
  • 支持自定義內存分配函數(通過?cJSON_Hooks?結構體),適配不同環境。
4. 錯誤處理
  • 解析失敗時返回?NULL,通過?cJSON_GetErrorPtr()?獲取錯誤位置。
  • 不提供詳細錯誤信息(如行號、具體錯誤類型),適合快速解析簡單 JSON。

3.3cJSON數據封裝(含源碼分析)

封裝JSON數據的過程,其實就是創建鏈表和向鏈表中添加節點的過程。

1.創建頭指針

 cJSON* cjson_test = NULL;

2.創建頭結點,并將頭指針指向頭結點

cjson_test = cJSON_CreateObject();

3.調用函數向鏈表中插入結點


cJSON_AddNullToObject(cJSON * const object, const char * const name);cJSON_AddTrueToObject(cJSON * const object, const char * const name);cJSON_AddFalseToObject(cJSON * const object, const char * const name);cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);cJSON_AddObjectToObject(cJSON * const object, const char * const name);cJSON_AddArrayToObject(cJSON * const object, const char * const name);

輸出JSON數據

(char *) cJSON_Print(const cJSON *item);

一段完整的JSON數據就是一條長長的鏈表,cJSON提供了一個API,可以將整條鏈表中存放的JSON信息輸出到一個字符串中,使用的時候,只需要接收該函數返回的指針地址即可。

3.4cJSON數據解析(含源碼分析)

數據解析調用cJSON_Parse(const char *value)

解析JSON數據的過程,其實就是剝離一個一個鏈表節點(鍵值對)的過程

// 1.創建鏈表頭指針:
cJSON* cjson_test = NULL;
//2.解析整段JSON數據,并將鏈表頭結點地址返回,賦值給頭指針:解析整段數據使用的API只有一個:
(cJSON *) cJSON_Parse(const char *value);
//3.根據鍵值對的名稱從鏈表中取出對應的值,返回該鍵值對(鏈表節點)的地址
(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
//4.如果JSON數據的值是數組,使用下面的兩個API提取數據:
(int) cJSON_GetArraySize(const cJSON *array);
(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);

3.5cJSON內存管理

cJSON的所有操作都是基于鏈表的,cJSON在使用過程中大量的使用malloc從堆中分配動態內存的,所以在使用完之后,應當及時調用下面的函數,清空cJSON指針所指向的內存,該函數也可用于刪除某一條數據:

void cJSON_Delete(cJSON *item);

3.6給出代碼示例封裝及解析

嵌套的數據封裝時遞歸封裝解析時也遞歸解析

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"// 封裝(生成)JSON 數據
char* encapsulate_json_data() {// 創建根對象cJSON *root = cJSON_CreateObject();// 創建 user 對象cJSON *user = cJSON_CreateObject();cJSON_AddNumberToObject(user, "id", 12345);cJSON_AddStringToObject(user, "name", "Alice");// 創建 contact 對象cJSON *contact = cJSON_CreateObject();cJSON_AddStringToObject(contact, "email", "alice@example.com");// 創建 phone 數組cJSON *phone = cJSON_CreateArray();cJSON_AddItemToArray(phone, cJSON_CreateString("123-456-7890"));cJSON_AddItemToArray(phone, cJSON_CreateString("098-765-4321"));cJSON_AddItemToObject(contact, "phone", phone);// 將 contact 添加到 usercJSON_AddItemToObject(user, "contact", contact);// 將 user 添加到根對象cJSON_AddItemToObject(root, "user", user);// 添加布爾值cJSON_AddBoolToObject(root, "isActive", 1);  // 1 表示 true// 添加嵌套數組cJSON *nested_array = cJSON_CreateArray();cJSON_AddItemToArray(nested_array, cJSON_CreateNumber(100));cJSON_AddItemToArray(nested_array, cJSON_CreateString("nested value"));cJSON *nested_obj = cJSON_CreateObject();cJSON_AddStringToObject(nested_obj, "key", "value");cJSON_AddItemToArray(nested_array, nested_obj);cJSON_AddItemToObject(root, "nested", nested_array);// 生成 JSON 字符串char *json_str = cJSON_Print(root);// 釋放 JSON 對象cJSON_Delete(root);return json_str;
}// 解析 JSON 數據
void parse_json_data(const char *json_str) {// 解析 JSON 字符串cJSON *root = cJSON_Parse(json_str);if (root == NULL) {const char *error_ptr = cJSON_GetErrorPtr();if (error_ptr != NULL) {fprintf(stderr, "Error before: %s\n", error_ptr);}return;}// 提取基本字段cJSON *isActive = cJSON_GetObjectItem(root, "isActive");if (cJSON_IsBool(isActive)) {printf("isActive: %s\n", isActive->valueint ? "true" : "false");}// 提取 user 對象cJSON *user = cJSON_GetObjectItem(root, "user");if (cJSON_IsObject(user)) {cJSON *id = cJSON_GetObjectItem(user, "id");cJSON *name = cJSON_GetObjectItem(user, "name");if (cJSON_IsNumber(id) && cJSON_IsString(name)) {printf("User ID: %d\n", id->valueint);printf("User Name: %s\n", name->valuestring);}// 提取 contact 對象cJSON *contact = cJSON_GetObjectItem(user, "contact");if (cJSON_IsObject(contact)) {cJSON *email = cJSON_GetObjectItem(contact, "email");if (cJSON_IsString(email)) {printf("Email: %s\n", email->valuestring);}// 提取 phone 數組cJSON *phone = cJSON_GetObjectItem(contact, "phone");if (cJSON_IsArray(phone)) {int array_size = cJSON_GetArraySize(phone);printf("Phone Numbers (%d):\n", array_size);for (int i = 0; i < array_size; i++) {cJSON *phone_item = cJSON_GetArrayItem(phone, i);if (cJSON_IsString(phone_item)) {printf("  %d: %s\n", i+1, phone_item->valuestring);}}}}}// 解析嵌套數組cJSON *nested = cJSON_GetObjectItem(root, "nested");if (cJSON_IsArray(nested)) {printf("Nested Array:\n");int array_size = cJSON_GetArraySize(nested);for (int i = 0; i < array_size; i++) {cJSON *item = cJSON_GetArrayItem(nested, i);printf("  Item %d: ", i+1);if (cJSON_IsNumber(item)) {printf("Number = %f\n", item->valuedouble);} else if (cJSON_IsString(item)) {printf("String = %s\n", item->valuestring);} else if (cJSON_IsObject(item)) {printf("Object\n");cJSON *key = cJSON_GetObjectItem(item, "key");if (cJSON_IsString(key)) {printf("    key = %s\n", key->valuestring);}}}}// 釋放 JSON 對象cJSON_Delete(root);
}int main() {// 封裝 JSON 數據char *json_str = encapsulate_json_data();if (json_str == NULL) {fprintf(stderr, "Failed to generate JSON data.\n");return 1;}// 打印生成的 JSONprintf("Generated JSON:\n%s\n\n", json_str);// 解析 JSON 數據printf("Parsing JSON data...\n");parse_json_data(json_str);// 釋放 JSON 字符串free(json_str);return 0;
}

四、cJSON項目

這個項目實現了一個使用 C 語言解析 JSON 文件的應用程序,主要內容是從包含中國行政區劃信息的 JSON 文件中提取特定省份的城市列表。

具體實現思路

因為cJSON.h中并沒有定義對文件的操作,所以通過使用標準 C 庫函數?fopenfread?和?fseek?讀取 JSON 文件內容,把文件內容讀取到字符串中,然后解析字符串,注意使用動態分配內存存儲 JSON 數據,并在使用后正確釋放,實際操作直接使用 cJSON 庫解析 JSON 數據結構,包括對象、數組的遍歷,最后通過使用?strcmp?進行字符串比較,即可定位目標省份。

代碼:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"char* read_file(const char* filename) {FILE* f = fopen(filename, "rb");if (!f) {perror("無法打開文件");return NULL;}fseek(f, 0, SEEK_END);long size = ftell(f);fseek(f, 0, SEEK_SET);char* buff = (char*)malloc(size + 1);if (buff == NULL) {perror("創建內存失敗");fclose(f);return NULL;}size_t bytes_read = fread(buff, 1, size, f);//目標緩沖區 buff,每個數據項的大小(這里是 1 字節),要讀取的數據項數量 size,以及文件流 f。if (bytes_read < size) {if (feof(f)) {//feof 函數用于檢查文件流 f 是否已經到達文件末尾。printf("警告:文件已到達末尾,讀取 %zu 字節(期望 %ld 字節)\n", bytes_read, size);}else if (ferror(f)) {perror("讀取錯誤");free(buff);fclose(f);return NULL;}}buff[bytes_read] = '\0';fclose(f);return buff;
}int main() {char* json_str = read_file("city.json");if (json_str == NULL) {return -1;}cJSON* root = cJSON_Parse(json_str);if (root == NULL) {const char* error_ptr = cJSON_GetErrorPtr();if (error_ptr != NULL) {fprintf(stderr, "JSON解析錯誤: %s\n", error_ptr);}free(json_str);return -1;}// 檢查 root 是否為數組if (root->type != cJSON_Array) {printf("JSON 根節點不是數組類型\n");cJSON_Delete(root);free(json_str);return -1;}const char* target_province = "陜西";int province_found = 0;// 遍歷所有省份int province_count = cJSON_GetArraySize(root);for (int i = 0; i < province_count; i++) {cJSON* province_item = cJSON_GetArrayItem(root, i);if (!province_item) continue;// 獲取省份名稱cJSON* name = cJSON_GetObjectItem(province_item, "label");if (!name || name->type != cJSON_String) continue;// 檢查是否為目標省份if (strcmp(name->valuestring, target_province) == 0) {printf("找到省份:%s\n", name->valuestring);province_found = 1;// 獲取城市數組cJSON* cities_array = cJSON_GetObjectItem(province_item, "children");//注意數據嵌套關系,城市在省份的children數組里if (cities_array && cities_array->type == cJSON_Array) {int city_count = cJSON_GetArraySize(cities_array);printf("包含 %d 個城市:\n", city_count);for (int j = 0; j < city_count; j++) {cJSON* city_item = cJSON_GetArrayItem(cities_array, j);if (!city_item) continue;cJSON* city_name = cJSON_GetObjectItem(city_item, "label");if (city_name && city_name->type == cJSON_String) {printf("  %d. %s\n", j + 1, city_name->valuestring);}}}else {printf("未找到該省份的城市數據\n");}break; // 找到目標省份后退出循環}}if (!province_found) {printf("未找到省份:%s\n", target_province);}cJSON_Delete(root);free(json_str);return 0;
}

運行結果:

這里以查找陜西省的城市為例:

五、 JSON的應用場景有哪些?

多個應用場景:

  1. Web API 數據傳輸

    • RESTful API 的請求和響應格式
    • 前后端數據交互(如 AJAX 請求)
  2. 配置文件

    • 應用程序配置(如 Node.js 的 package.json)
    • 開發工具配置(如 ESLint、Babel)
  3. 數據存儲

    • NoSQL 數據庫(如 MongoDB)存儲文檔
    • 臨時數據緩存(如 Redis)
  4. 跨語言數據交換

    • 微服務間通信(如通過消息隊列)
    • 不同系統間數據集成
  5. 移動應用開發

    • 與服務器交換數據(如 JSON API)
    • 本地存儲(如 React Native 的 AsyncStorage)
  6. 日志和監控系統

    • 結構化日志輸出
    • 監控指標傳輸
  7. 前端框架

    • React/Vue 組件屬性傳遞
    • 路由配置

優勢總結:

  • 輕量級,易于閱讀和編寫
  • 支持嵌套結構,適合復雜數據
  • 幾乎所有編程語言都有解析庫
  • 與 JavaScript 原生兼容
  • 比 XML 更簡潔,解析效率更高

尾語:項目學習并完成于2025.5.10,如果覺得有幫助有收獲可以點贊收藏,會持續更新輸出有用的內容,感興趣可以關注我!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/80511.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/80511.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/80511.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【LLaMA-Factory】使用LoRa微調訓練DeepSeek-R1-Distill-Qwen-7B

【LLaMA-Factory】使用LoRa微調訓練DeepSeek-R1-Distill-Qwen-7B 本地環境說明禁用開源驅動nouveau安裝nvidia-smi安裝Git環境安裝Anaconda(conda)環境下載DeepSeek-R1-Distill-Qwen-7B模型安裝LLaMA-Factory下載LLaMA-Factory安裝LLaMA-Factory依賴修改環境變量安裝deepspeedA…

初始圖形學(7)

上一章完成了相機類的實現&#xff0c;對之前所學的內容進行了封裝與整理&#xff0c;現在要學習新的內容。 抗鋸齒 我們放大之前渲染的圖片&#xff0c;往往會發現我們渲染的圖像邊緣有尖銳的"階梯"性質。這種階梯狀被稱為"鋸齒"。當真實的相機拍照時&a…

vllm筆記

目錄 vllm簡介vllm解決了哪些問題&#xff1f;1. **瓶頸&#xff1a;KV 緩存內存管理低效**2. **瓶頸&#xff1a;并行采樣和束搜索中的內存冗余**3. **瓶頸&#xff1a;批處理請求中的內存碎片化** 快速開始安裝vllm開始使用離線推理啟動 vLLM 服務器 支持的模型文本語言模型生…

訪問網站提示“不安全”“有風險”怎么辦?

訪問網站提示“不安全”“有風險”有以下幾種解決方案 一、理解警告類型 1.“不安全”提示&#xff08;HTTP網站&#xff09; 原因&#xff1a;網站未使用HTTPS加密&#xff0c;傳輸數據&#xff08;如密碼、支付信息&#xff09;可能被竊取。 表現&#xff1a;瀏覽器地址欄顯…

vue3的響應式設計原理

Vue 3 的響應式設計是其核心特性之一&#xff0c;依賴于 Proxy 和 依賴收集機制&#xff0c;相比 Vue 2 的 Object.defineProperty&#xff0c;Vue 3 的響應式系統更加高效、靈活且易于維護。 以下是 Vue 3 響應式設計的核心原理&#xff1a; 一、核心機制概覽 使用 Proxy 實現…

C++模板筆記

Cpp模板筆記 文章目錄 Cpp模板筆記1. 為什么要定義模板2. 模板的定義2.1 函數模板2.1.1 函數模板的重載2.1.2 頭文件與實現文件形式&#xff08;重要&#xff09;2.1.3 模板的特化2.1.4 模板的參數類型2.1.5 成員函數模板2.1.6 使用模板的規則 2.2 類模板2.3 可變參數模板 模板…

遞歸函數(斐波那契數列0,1,1,2,3,5,8,13,21,34,55...)

目錄 一、斐波那契數列&#xff08;兔子問題&#xff09; 二、迭代法&#xff08;用while循環推下一項 ) 三、遞歸函數 (函數的定義中調用函數自身的一種函數定義方式) 四、遞歸函數的底層邏輯推理 (二叉樹推倒最左下節點回退法) 一、斐波那契數列&#xff08;兔子問題&…

光的本質(以暗物質維度粒子為介質的能量傳導)

一、光的概要描述 1、光的本質是能量傳導 空間中均勻分布著暗物質維度粒子。光不是粒子也不是波,而是沒有質量和形態的能量,在臨近暗物質粒子之間的一種能量傳遞。 2、光能傳遞類似牛頓鐘擺(空間中的牛頓鐘擺) 當光能能量騷動一個暗物質粒子后,該暗物質粒…

Open CASCADE學習|管道殼體生成

一、引言 在計算機輔助設計&#xff08;CAD&#xff09;和計算機圖形學領域&#xff0c;OpenCASCADE 是一款功能強大的開源 3D 建模庫。它提供了豐富的幾何和拓撲建模工具&#xff0c;其中管道殼體&#xff08;Pipe Shell&#xff09;生成是其重要功能之一。管道殼體廣泛應用于…

JS正則表達式介紹(JavaScript正則表達式)

文章目錄 JavaScript正則表達式完全指南正則表達式基礎元字符與特殊字符基本元字符. - 點號\d - 數字\D - 非數字\w - 單詞字符\W - 非單詞字符\s - 空白字符\S - 非空白字符 正則表達式標志常用標志詳解g - 全局匹配i - 忽略大小寫m - 多行匹配s - 點號匹配所有字符u - Unicod…

Kubernetes 使用 containerd 實現 GPU 支持及 GPU Operator 部署指南

目錄 Kubernetes 使用 containerd 實現 GPU 支持及 GPU Operator 部署指南 一、為什么 containerd 是趨勢&#xff1f; 二、目標 三、前提條件 四、方式一&#xff1a;containerd nvidia-container-toolkit&#xff08;基礎方式&#xff09; 1?? 安裝 NVIDIA Containe…

leetcode 2918. 數組的最小相等和 中等

給你兩個由正整數和 0 組成的數組 nums1 和 nums2 。 你必須將兩個數組中的 所有 0 替換為 嚴格 正整數&#xff0c;并且滿足兩個數組中所有元素的和 相等 。 返回 最小 相等和 &#xff0c;如果無法使兩數組相等&#xff0c;則返回 -1 。 示例 1&#xff1a; 輸入&#xf…

猿人學第十二題-js入門

1. 鏈接 https://match.yuanrenxue.cn/match/12 2. 抓包分析 2.1. m參數 通過觀察&#xff0c;只有m參數要解決&#xff1a; 3. 逆向分析 3.1. 跟棧 直接跟棧吧&#xff0c;一下就出結果了&#xff1a; 可以看到m其實很簡單&#xff0c;就是固定字符串 當前頁數&#xf…

雙系統電腦中如何把ubuntu裝進外接移動固態硬盤

電腦&#xff1a;win11 ubuntu22.04 實體機 虛擬機&#xff1a;VMware17 鏡像文件&#xff1a;ubuntu-22.04.4-desktop-amd64.iso 或者 ubuntu20.4的鏡像 外接固態硬盤1個 一、首先win11中安裝vmware17 具體安裝方法&#xff0c;網上很多教程 二、磁盤分區 1.在筆…

202535| Kafka架構與重要概念+冪等性+事務

好的&#xff01;以下是關于 Kafka 架構 以及其 重要概念 的詳細介紹&#xff0c;結合 Mermaid 圖形 和 表格&#xff0c;幫助你更好地理解各個概念的關系和作用。 Kafka 架構與重要概念 Kafka 是一個分布式消息系統&#xff0c;廣泛應用于日志收集、流處理、事件驅動架構等場…

從0開始學習大模型--Day05--理解prompt工程

提示詞工程原理 N-gram&#xff1a;通過統計&#xff0c;計算N個詞共同出現的概率&#xff0c;從而預測下一個詞是什么。 深度學習模型&#xff1a;有多層神經網絡組成&#xff0c;可以自動從數據中學習特征&#xff0c;讓模型通過不斷地自我學習不斷成長&#xff0c;直到模型…

Amazing晶焱科技:系統級 EOS 測試方法 - System Level EOS Testing Method

系統上常見的EOS測試端口以AC電源、電話線&#xff08;RJ11&#xff09;、同軸電纜&#xff08;coaxial cable&#xff09;以及以太網絡&#xff08;RJ45&#xff09;最常見&#xff0c;這些端口因有機會布線至戶外的關系&#xff0c;受到EOS/Surge沖擊的幾率也大大提升。因此電…

數據結構—(概述)

目錄 一 數據結構&#xff0c;相關概念 1. 數據結構&#xff1a; 2. 數據(Data): 3. 數據元素(Data Element): 4. 數據項&#xff1a; 5. 數據對象(Data Object): 6. 容器&#xff08;container&#xff09;&#xff1a; 7. 結點&#xff08;Node&#xff09;&#xff…

Vue 兩種導航方式

目錄 一、聲明式導航 二、編程式導航 三、兩句話總結 一、聲明式導航 1. 傳參跳轉&#xff1a; <router-link :to"/user?nameCHEEMS&id114514">Query傳參 </router-link><router-link :to"/user?參數名1參數值1&參數名2參數值2&a…

QTableWidget實現多級表頭、表頭凍結效果

最終效果&#xff1a; 實現思路&#xff1a;如果只用一個表格的話寫起來比較麻煩&#xff0c;可以考慮使用兩個QTableWidget組合&#xff0c;把復雜的表頭一個用QTableWidget顯示&#xff0c;其他內容用另一個QTableWidget。 #include "mainwindow.h" #include &qu…