中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

重慶網(wǎng)站推百度網(wǎng)盤seo優(yōu)化

重慶網(wǎng)站推,百度網(wǎng)盤seo優(yōu)化,v2ex wordpress,那片海dede織夢源碼企業(yè)網(wǎng)絡(luò)公司工作室網(wǎng)站模板源碼模板php代碼概述 這段代碼實現(xiàn)了一個天氣查詢系統(tǒng),支持實時天氣、未來天氣和歷史天氣查詢。用戶可以通過終端菜單選擇查詢類型,并輸入城市名稱來獲取相應(yīng)的天氣信息。程序通過 TCP 連接發(fā)送 HTTP 請求,并解析返回的 JSON 數(shù)據(jù)來展示天氣信息。 #in…
代碼概述

這段代碼實現(xiàn)了一個天氣查詢系統(tǒng),支持實時天氣、未來天氣和歷史天氣查詢。用戶可以通過終端菜單選擇查詢類型,并輸入城市名稱來獲取相應(yīng)的天氣信息。程序通過 TCP 連接發(fā)送 HTTP 請求,并解析返回的 JSON 數(shù)據(jù)來展示天氣信息。

#include "main.h"#include "cJSON.h"
#define BUFFER_SIZE 30000
#define TEMP_BUFFER_SIZE 4096#define COLOR_FIELD "\033[34m"   // 字段藍(lán)色
#define COLOR_VALUE "\033[36m"   // 值青色
#define COLOR_WARN  "\033[33m"   // 警告黃色
#define COLOR_RESET "\033[0m"    // 重置顏色
#define COLOR_HEAD "\033[35m"    // 提示頭顏色char weather_inquiry[4][1024] = 
{{"實時天氣"},{"未來天氣"},{"歷史天氣"},{"退出查詢"},
};int pos_start = 0;
int pos_end = 4;
int focus = 0;//選擇的焦點
int menu_flag = 1;
char city[512];//儲存城市名字
int sockfd;int getch(void)
{struct termios oldt, newt;int ch;int esc_mode = 0;unsigned long key = 0;//獲取終端屬性信息tcgetattr(STDIN_FILENO, &oldt);newt = oldt;//設(shè)置非阻塞模式newt.c_lflag &= ~(ICANON | ECHO);newt.c_cc[VMIN] = 0;//讀取最小字符newt.c_cc[VTIME] = 1;//等待時間10/1秒//修改new中的ECHO和ICANON參數(shù),使得new為不回顯輸入內(nèi)容//設(shè)置終端信息tcsetattr(STDIN_FILENO, TCSANOW, &newt);//組合多字節(jié)按鍵for(int i = 0;i < 3;i++){ch = getchar();if(ch == EOF)break;key = (key << 8)|(ch & 0xFF);}//用完之后,恢復(fù)原來的終端屬性tcsetattr(STDIN_FILENO, TCSANOW, &oldt);switch(key){case 0x1B5B41:	return KEY_UP;case 0x1B5B42:	return KEY_DOWN;case 0x0A:		return KEY_ENTER;default:		return (key&0xFF);//返回首個有效字符				}
}void View_two(void)
{if(menu_flag == 2){int i = 0;printf("\033[10;35H");printf("| 	     	   天氣查詢	          |\n");printf("\033[0m");for(i = pos_start;i <pos_end;i++){if(i == focus){printf("\033[%d;50H",i+12);printf("|\033[30;43m%2d.%s\033[0m\n",i+1,weather_inquiry[i]);}else{printf("\033[%d;50H",12+i);printf("|%2d.%-20s\n",i+1,weather_inquiry[i]);}}}return;
}void city_name(void)
{		scanf("%s",city);while(getchar()!= '\n');printf("\033[0m");if(strncmp(city,"quit",4) == 0){exit(0);printf("感謝使用!\n");}
}#if 1
void view(void)
{if(menu_flag == 1){printf("\033[15;55H");printf("\033[;31m");printf("輸入quit退出\n");printf("\033[10;25H");printf("\033[;33m");printf("~歡迎來到天氣查詢系統(tǒng)~\n");printf("\033[0m");printf("\033[12;25H");printf("\033[;34m");printf("請輸入你要查詢的城市:");// 清空城市名memset(city, 0, sizeof(city));city_name();menu_flag = 2;system("clear");}else if(menu_flag == 2){View_two();}return;
}#endifvoid CreateTcpClient(void)//創(chuàng)建TCP
{int ret = 0;sockfd = socket(AF_INET,SOCK_STREAM,0);if(sockfd < 0){perror("sockfd fail");return;}struct sockaddr_in seraddr;bzero(&seraddr,sizeof(seraddr));seraddr.sin_family = AF_INET;seraddr.sin_port = htons(PORT);seraddr.sin_addr.s_addr = inet_addr(IP);if(connect(sockfd,(struct sockaddr*)&seraddr,sizeof(seraddr)) < 0){perror("connect fail");return;}
}//發(fā)送HTTP請求(參數(shù):天氣類型)
void SendHttpRequest(int sockfd,char *head)
{char tmpbuff[4096] = {0};int written = 0;const char *template ="GET %s HTTP/1.1\r\n""Host: api.k780.com\r\n""User-Agent: WeatherClient/1.0\r\n""Accept: */*\r\n""Connection: close\r\n"  // 改為短連接"\r\n";  // 必須的空行// 安全格式化(限制最大長度)written = snprintf(tmpbuff,sizeof(tmpbuff),template,head);if (written >= sizeof(tmpbuff)) {fprintf(stderr, "Request too large (max %zd bytes)\n", sizeof(tmpbuff));return;}//發(fā)送請求ssize_t sent = send(sockfd,tmpbuff,written,0);if(sent != written){perror("send fail");return;}
}void RecvSendWeather(void)
{int fd = 0;char buff[BUFFER_SIZE] = {0}; // 確保初始化為全0char cmpbuff[BUFFER_SIZE] = {0}; // 用于存儲處理后的數(shù)據(jù)char tmpbuff[TEMP_BUFFER_SIZE] = {0}; // 臨時緩沖區(qū)ssize_t nsize = 0; // recv函數(shù)接收的數(shù)據(jù)大小char *ptmp = NULL; // 臨時指針char *pstart = NULL; // 數(shù)據(jù)起始位置指針char *pend = NULL; // 數(shù)據(jù)結(jié)束位置指針fd = open("recv.txt", O_RDWR | O_CREAT | O_TRUNC, 0666);while(1){memset(tmpbuff, 0, sizeof(tmpbuff)); // 清空臨時緩沖區(qū)nsize = recv(sockfd, tmpbuff, sizeof(tmpbuff), 0);if(nsize <= 0){break;}strncat(buff, tmpbuff, (size_t)nsize); // 將接收到的數(shù)據(jù)追加到buff中if(strstr(tmpbuff, "0\r\n") != NULL)break;}//查找數(shù)據(jù)正文的起始位置ptmp = strstr(buff, "\r\n\r\n");if(ptmp != NULL){ptmp += 4; //跳過"\r\n\r\n"ptmp = strstr(ptmp, "\r\n");if(ptmp != NULL){ptmp += 2;pstart = ptmp; //標(biāo)記數(shù)據(jù)起始位置pend = strstr(ptmp, "\r\n"); //查找數(shù)據(jù)結(jié)束位置if(pend != NULL){strncat(cmpbuff, pstart, pend - pstart);}}}write(fd, cmpbuff, strlen(cmpbuff)); // 將處理后的數(shù)據(jù)寫入文件close(fd);close(sockfd);
}void real_time_weather()
{int ret = -1;int fd = -1;char *buffer = NULL;ssize_t bytes_read = 0;CreateTcpClient(); // 創(chuàng)建新的連接if(!(buffer = malloc(BUFFER_SIZE))){perror("malloc fail");return;}if((fd = open("recv.txt", O_RDONLY)) == -1){perror("open fail");return;}if((bytes_read = read(fd, buffer, BUFFER_SIZE)) <= 0){fprintf(stderr, "Read failed or empty file\n");return;}buffer[bytes_read] = '\0'; // 確保字符終止cJSON *root = cJSON_Parse(buffer);if(!root){fprintf(stderr, "JSON parse failed\n");return;}// 使用結(jié)構(gòu)體定義字段映射struct FieldMapping {const char *json_key;const char *display_name;int required;  // 1表示必須字段} fields[] = {{"days", "日期", 1},{"week", "星期", 1},{"citynm", "城市", 1},{"temperature_curr", "當(dāng)前溫度", 1},{"temp_high", "最高溫度", 0},{"temp_low", "最低溫度", 0},{"weather", "天氣狀況", 1},{"humidity", "當(dāng)前濕度", 0},{"humi_high", "最大濕度", 0},{"humi_low", "最小濕度", 0},{"wind", "風(fēng)向", 1},{"winp", "風(fēng)力", 1},{"aqi", "PM2.5", 0}};cJSON *result = cJSON_GetObjectItem(root, "result");if(!result){fprintf(stderr, "Missing result object\n");cJSON_Delete(root);return;}// 遍歷所有字段定義for(size_t i = 0; i < sizeof(fields)/sizeof(fields[0]); i++){cJSON *item = cJSON_GetObjectItem(result, fields[i].json_key);printf(COLOR_FIELD"%-8s: "COLOR_RESET, fields[i].display_name);if(item && item->valuestring){printf(COLOR_VALUE"%s\n"COLOR_RESET, item->valuestring);}else{printf(COLOR_WARN"N/A\n"COLOR_RESET);if(fields[i].required){fprintf(stderr, "Missing required field: %s\n", fields[i].json_key);cJSON_Delete(root);return;}}}ret = 0;free(buffer);cJSON_Delete(root);close(fd);
}void future_weather()
{int ret = -1;int fd = -1;char *buffer = NULL;ssize_t bytes_read = 0;CreateTcpClient(); // 創(chuàng)建新的連接if(!(buffer = malloc(BUFFER_SIZE))){perror("malloc fail");return;}if((fd = open("recv.txt",O_RDONLY)) == -1){perror("open fail");return;}if((bytes_read = read(fd,buffer,BUFFER_SIZE)) <= 0){fprintf(stderr, "Read failed or empty file\n");return;}buffer[bytes_read] = '\0';//確保字符終止cJSON *root = cJSON_Parse(buffer);if(!root){fprintf(stderr, "JSON parse failed\n");return;}// 使用結(jié)構(gòu)體定義字段映射struct FieldMapping {const char *json_key;const char *display_name;int required;  // 1表示必須字段} fields[] = {{"days", "日期", 1},{"week", "星期", 1},{"citynm", "城市", 1},{"temp_high", "最高溫度", 0},{"temp_low", "最低溫度", 0},{"weather", "天氣狀況", 1},{"wind", "風(fēng)向", 1},{"winp", "風(fēng)力", 1},};cJSON *result = cJSON_GetObjectItem(root,"result");if(!result){fprintf(stderr, "Missing result object\n");cJSON_Delete(root);}int i = 0;cJSON *item;cJSON_ArrayForEach(item,result){printf(COLOR_HEAD"=============第%d天氣預(yù)報=============\n"COLOR_RESET,i+1);// 遍歷所有字段定義for (size_t j = 0; j < sizeof(fields)/sizeof(fields[0]); j++) {cJSON *field = cJSON_GetObjectItem(item, fields[j].json_key);printf(COLOR_FIELD"%-8s: "COLOR_RESET, fields[j].display_name);if (field && field->valuestring) {printf(COLOR_VALUE"%s\n"COLOR_RESET, field->valuestring);} else {printf(COLOR_WARN"N/A\n"COLOR_RESET);if (fields[j].required) {fprintf(stderr, "Missing required field: %s\n", fields[j].json_key);}}}i++;}	cJSON_Delete(root);free(buffer);close(fd);
}void historical_weather()
{
}void MenuChoose(void)
{int key = getch();char tmpbuff[1024]={0};//ESC按鍵處理if(key == KEY_ESC){if(menu_flag == 2){menu_flag = 1;//切換到菜單一system("clear");}}switch(key){case KEY_UP:if(focus > pos_start){system("clear");focus--;}break;case KEY_DOWN:if(focus < pos_end){system("clear");focus++;}break;case KEY_ENTER:switch(focus){case 0:system("clear");CreateTcpClient();sprintf(tmpbuff,"/?app=weather.today&weaid=%s&appkey=%s&sign=%s",city,API_KEY,API_SIGN);SendHttpRequest(sockfd,tmpbuff);RecvSendWeather();real_time_weather();if (sockfd > 0) {close(sockfd);sockfd = -1;}break;case 1:system("clear");CreateTcpClient();sprintf(tmpbuff,"http://api.k780.com/?app=weather.future&weaid=%s&appkey=%s&sign=%s&format=json",city,API_KEY,API_SIGN);SendHttpRequest(sockfd,tmpbuff);RecvSendWeather();future_weather();break;case 2:break;case 3:printf("感謝使用!\n");exit(0);break;} }
}int main(int argc, const char *argv[])
{system("clear");while(1){view();MenuChoose();}return 0;
}

演示視頻

天氣查詢演示視頻

一、函數(shù)總覽

全局變量

  • weather_inquiry[4][1024]:存儲菜單選項,包括實時天氣、未來天氣、歷史天氣和退出查詢。

  • pos_startpos_end:定義菜單顯示的起始和結(jié)束位置。

  • focus:當(dāng)前用戶選擇的菜單焦點。

  • menu_flag:標(biāo)志當(dāng)前顯示的菜單層級,1 表示主菜單,2 表示二級菜單。

  • city[512]:存儲用戶輸入的城市名稱。

  • sockfd:TCP 套接字文件描述符。

第二部分:輸入處理和菜單顯示

getch()?函數(shù)

  • 功能:捕捉用戶按鍵輸入,支持方向鍵和回車鍵。

  • 實現(xiàn)

    • 使用 termios 修改終端屬性,禁用回顯和行緩沖。

    • 捕捉按鍵組合,識別上方向鍵(KEY_UP)、下方向鍵(KEY_DOWN)和回車鍵(KEY_ENTER)。

    • 恢復(fù)終端屬性。

View_two()?函數(shù)

  • 功能:顯示二級菜單,包括實時天氣、未來天氣、歷史天氣和退出查詢。

  • 實現(xiàn)

    • 根據(jù) focus 的值,高亮顯示當(dāng)前選中的菜單項。

    • 使用終端控制字符(如 \033)設(shè)置文字顏色和位置。

city_name()?函數(shù)

  • 功能:獲取用戶輸入的城市名稱,并檢查是否為退出命令。

  • 實現(xiàn)

    • 使用 scanf 獲取輸入,并清除輸入緩沖區(qū)。

    • 如果輸入為 quit,程序退出。

view()?函數(shù)

  • 功能:根據(jù) menu_flag 的值,顯示主菜單或二級菜單。

  • 實現(xiàn)

    • 主菜單顯示歡迎信息,并提示用戶輸入城市名稱。

    • 二級菜單顯示天氣查詢選項。

第三部分:TCP 連接和 HTTP 請求

CreateTcpClient()?函數(shù)

  • 功能:創(chuàng)建一個 TCP 套接字,并連接到指定的服務(wù)器。

  • 實現(xiàn)

    • 使用 socket 創(chuàng)建套接字。

    • 設(shè)置服務(wù)器地址和端口。

    • 使用 connect 建立連接。

SendHttpRequest()?函數(shù)

  • 功能:發(fā)送 HTTP GET 請求。

  • 實現(xiàn)

    • 使用 snprintf 格式化請求頭,包括目標(biāo) URL 和必要頭部信息。

    • 使用 send 發(fā)送請求。

第四部分:數(shù)據(jù)接收和處理

RecvSendWeather()?函數(shù)

  • 功能:接收服務(wù)器響應(yīng),并提取數(shù)據(jù)正文。

  • 實現(xiàn)

    • 使用 recv 循環(huán)接收數(shù)據(jù),直到遇到空行(0\r\n)。

    • 查找數(shù)據(jù)正文的起始和結(jié)束位置,提取并存儲到文件中。

第五部分:實時天氣查詢

real_time_weather()?函數(shù)

  • 功能:解析實時天氣 JSON 數(shù)據(jù),并展示相關(guān)信息。

  • 實現(xiàn)

    • 從文件讀取 JSON 數(shù)據(jù)。

    • 使用 cJSON 解析 JSON 數(shù)據(jù)。

    • 定義字段映射結(jié)構(gòu)體,遍歷字段并顯示對應(yīng)值。

    • 檢查必填字段是否存在,若缺失則報錯。

第六部分:未來天氣查詢

future_weather()?函數(shù)

  • 功能:解析未來天氣 JSON 數(shù)據(jù),并展示相關(guān)信息。

  • 實現(xiàn)

    • 從文件讀取 JSON 數(shù)據(jù)。

    • 使用 cJSON 解析 JSON 數(shù)據(jù)。

    • 定義字段映射結(jié)構(gòu)體,遍歷字段并顯示對應(yīng)值。

    • 遍歷 JSON 數(shù)組,逐條顯示未來天氣信息。

第七部分:菜單選擇和主程序

MenuChoose()?函數(shù)

  • 功能:處理用戶按鍵輸入,實現(xiàn)菜單導(dǎo)航和功能選擇。

  • 實現(xiàn)

    • 根據(jù)按鍵調(diào)整 focus 值,實現(xiàn)菜單上下導(dǎo)航。

    • 處理回車鍵,根據(jù)選中項執(zhí)行對應(yīng)功能:

      • 實時天氣查詢:構(gòu)造 URL 并發(fā)送請求,調(diào)用 real_time_weather。

      • 未來天氣查詢:構(gòu)造 URL 并發(fā)送請求,調(diào)用 future_weather。

      • 退出程序:退出并顯示感謝信息。

main()?函數(shù)

  • 功能:主程序入口,循環(huán)顯示菜單并處理用戶輸入。

  • 實現(xiàn)

    • 清屏并初始化終端。

    • 循環(huán)調(diào)用 viewMenuChoose,實現(xiàn)菜單顯示和交互。

二、重點函數(shù)

RecvSendWeather()?函數(shù)

void RecvSendWeather(void)
{int fd = 0;char buff[BUFFER_SIZE] = {0}; // 確保初始化為全0char cmpbuff[BUFFER_SIZE] = {0}; // 用于存儲處理后的數(shù)據(jù)char tmpbuff[TEMP_BUFFER_SIZE] = {0}; // 臨時緩沖區(qū)ssize_t nsize = 0; // recv函數(shù)接收的數(shù)據(jù)大小char *ptmp = NULL; // 臨時指針char *pstart = NULL; // 數(shù)據(jù)起始位置指針char *pend = NULL; // 數(shù)據(jù)結(jié)束位置指針fd = open("recv.txt", O_RDWR | O_CREAT | O_TRUNC, 0666);while(1){memset(tmpbuff, 0, sizeof(tmpbuff)); // 清空臨時緩沖區(qū)nsize = recv(sockfd, tmpbuff, sizeof(tmpbuff), 0);if(nsize <= 0){break;}strncat(buff, tmpbuff, (size_t)nsize); // 將接收到的數(shù)據(jù)追加到buff中if(strstr(tmpbuff, "0\r\n") != NULL)break;}//查找數(shù)據(jù)正文的起始位置ptmp = strstr(buff, "\r\n\r\n");if(ptmp != NULL){ptmp += 4; //跳過"\r\n\r\n"ptmp = strstr(ptmp, "\r\n");if(ptmp != NULL){ptmp += 2;pstart = ptmp; //標(biāo)記數(shù)據(jù)起始位置pend = strstr(ptmp, "\r\n"); //查找數(shù)據(jù)結(jié)束位置if(pend != NULL){strncat(cmpbuff, pstart, pend - pstart);}}}write(fd, cmpbuff, strlen(cmpbuff)); // 將處理后的數(shù)據(jù)寫入文件close(fd);close(sockfd);
}

1. 初始化與文件準(zhǔn)備

  • 定義緩沖區(qū)buff(存儲完整數(shù)據(jù))、cmpbuff(存儲處理后的數(shù)據(jù))和tmpbuff(臨時接收數(shù)據(jù))。
  • 創(chuàng)建/清空文件recv.txt用于保存最終數(shù)據(jù)。

2. 循環(huán)接收數(shù)據(jù)

  • 通過recv從套接字sockfd接收數(shù)據(jù)到tmpbuff
  • 將每次接收的數(shù)據(jù)追加到主緩沖區(qū)buff中。
  • 終止條件:當(dāng)收到包含"0\r\n"的數(shù)據(jù)時,認(rèn)為傳輸結(jié)束,退出循環(huán)。

3. 數(shù)據(jù)解析

  • 定位數(shù)據(jù)起始點
    • 查找首個\r\n\r\n,跳過HTTP頭部。
    • 繼續(xù)查找下一個\r\n,跳過可能的分塊長度字段(如5\r\n)。
  • 提取數(shù)據(jù)正文
    • pstart到下一個\r\n之間的內(nèi)容被視為有效數(shù)據(jù),復(fù)制到cmpbuff。

4. 保存與清理

  • 將處理后的數(shù)據(jù)寫入文件recv.txt
  • 關(guān)閉文件描述符和套接字。

潛在問題與改進(jìn)建議

  1. 緩沖區(qū)溢出風(fēng)險

    • 問題buffcmpbuff是固定大小,未檢查strncat是否越界。
    • 建議:增加長度檢查,或改用動態(tài)內(nèi)存分配。
  2. 分塊編碼處理不完整

    • 問題:代碼假設(shè)數(shù)據(jù)僅包含一個分塊(如5\r\nhello\r\n0\r\n),可能漏掉多分塊數(shù)據(jù)。
    • 建議:循環(huán)解析所有分塊,處理格式如長度\r\n數(shù)據(jù)\r\n。
  3. 結(jié)束標(biāo)志可靠性

    • 問題:若0\r\n被拆分成多次接收(如0\r\n),可能無法正確退出。
    • 建議:在buff中全局搜索0\r\n,而非僅檢查tmpbuff

real_time_weather()?函數(shù)

void real_time_weather()
{int ret = -1;int fd = -1;char *buffer = NULL;ssize_t bytes_read = 0;CreateTcpClient(); // 創(chuàng)建新的連接if(!(buffer = malloc(BUFFER_SIZE))){perror("malloc fail");return;}if((fd = open("recv.txt", O_RDONLY)) == -1){perror("open fail");return;}if((bytes_read = read(fd, buffer, BUFFER_SIZE)) <= 0){fprintf(stderr, "Read failed or empty file\n");return;}buffer[bytes_read] = '\0'; // 確保字符終止cJSON *root = cJSON_Parse(buffer);if(!root){fprintf(stderr, "JSON parse failed\n");return;}// 使用結(jié)構(gòu)體定義字段映射struct FieldMapping {const char *json_key;const char *display_name;int required;  // 1表示必須字段} fields[] = {{"days", "日期", 1},{"week", "星期", 1},{"citynm", "城市", 1},{"temperature_curr", "當(dāng)前溫度", 1},{"temp_high", "最高溫度", 0},{"temp_low", "最低溫度", 0},{"weather", "天氣狀況", 1},{"humidity", "當(dāng)前濕度", 0},{"humi_high", "最大濕度", 0},{"humi_low", "最小濕度", 0},{"wind", "風(fēng)向", 1},{"winp", "風(fēng)力", 1},{"aqi", "PM2.5", 0}};cJSON *result = cJSON_GetObjectItem(root, "result");if(!result){fprintf(stderr, "Missing result object\n");cJSON_Delete(root);return;}// 遍歷所有字段定義for(size_t i = 0; i < sizeof(fields)/sizeof(fields[0]); i++){cJSON *item = cJSON_GetObjectItem(result, fields[i].json_key);printf(COLOR_FIELD"%-8s: "COLOR_RESET, fields[i].display_name);if(item && item->valuestring){printf(COLOR_VALUE"%s\n"COLOR_RESET, item->valuestring);}else{printf(COLOR_WARN"N/A\n"COLOR_RESET);if(fields[i].required){fprintf(stderr, "Missing required field: %s\n", fields[i].json_key);cJSON_Delete(root);return;}}}ret = 0;free(buffer);cJSON_Delete(root);close(fd);
}
亮點分析補(bǔ)充與優(yōu)化建議
1.?模塊化設(shè)計
  • 優(yōu)勢
    將天氣查詢功能封裝為獨(dú)立函數(shù)real_time_weather(),邏輯邊界清晰,符合“高內(nèi)聚”原則。
  • 改進(jìn)空間
    • 單一職責(zé)原則:當(dāng)前函數(shù)承擔(dān)了網(wǎng)絡(luò)連接、文件操作、JSON解析、數(shù)據(jù)展示等多個職責(zé),可進(jìn)一步拆分為子函數(shù)(如fetch_weather_data()parse_json()、display_weather())。
    • 依賴解耦:文件recv.txt作為數(shù)據(jù)傳遞媒介,屬于硬編碼依賴,建議改用內(nèi)存直接傳遞(如通過函數(shù)參數(shù)傳遞數(shù)據(jù)緩沖區(qū))。
2.?動態(tài)內(nèi)存管理
  • 優(yōu)勢
    使用malloc動態(tài)分配內(nèi)存,避免棧溢出風(fēng)險,適應(yīng)大數(shù)據(jù)場景。
  • 改進(jìn)空間
    • 內(nèi)存泄漏風(fēng)險:錯誤處理路徑中未完全釋放內(nèi)存(如malloc成功但open失敗時未free(buffer)),需用gotocleanup標(biāo)簽統(tǒng)一釋放資源。
    • 緩沖區(qū)溢出read(fd, buffer, BUFFER_SIZE)未檢查bytes_read是否等于BUFFER_SIZE,可能導(dǎo)致數(shù)據(jù)截斷或越界。
3.?錯誤處理
  • 優(yōu)勢
    覆蓋文件操作、內(nèi)存分配、JSON解析等關(guān)鍵錯誤點,避免程序崩潰。
  • 改進(jìn)空間
    • 錯誤碼統(tǒng)一管理ret變量未被實際使用,建議通過返回值或全局錯誤碼明確錯誤類型。
    • 錯誤信息分級:區(qū)分“致命錯誤”(如必填字段缺失)與“警告信息”(如可選字段缺失),避免冗余報錯。
4.?數(shù)據(jù)解析
  • 優(yōu)勢
    使用cJSON庫解析復(fù)雜JSON數(shù)據(jù),通過結(jié)構(gòu)體FieldMapping實現(xiàn)字段映射,擴(kuò)展性強(qiáng)。
  • 改進(jìn)空間
    • 字段類型校驗:未檢查JSON字段實際類型(如數(shù)值型字段可能被誤讀為字符串),需增加cJSON_IsString/cJSON_IsNumber等校驗。
    • 嵌套結(jié)構(gòu)處理:若JSON層級更深(如result下包含嵌套對象),需支持遞歸解析。
5.?用戶輸出
  • 優(yōu)勢
    ANSI顏色代碼提升可讀性,字段映射表確保輸出完整性。
  • 改進(jìn)空間
    • 跨平臺兼容性:Windows終端默認(rèn)不支持ANSI顏色,需通過條件編譯適配。
    • 格式化輸出:使用固定寬度(%-8s)可能導(dǎo)致長字段顯示不全,建議動態(tài)調(diào)整列寬。

難點分析與解決方案
1.?JSON數(shù)據(jù)解析
  • 核心挑戰(zhàn)
    • 字段路徑依賴性強(qiáng)(如直接訪問root->result->temperature_curr),若服務(wù)器返回結(jié)構(gòu)變化,需修改代碼。
    • 未處理特殊字符(如轉(zhuǎn)義字符\")或Unicode編碼(如\u4e2d\u6587)。
  • 解決方案
    • 使用cJSON_GetObjectItemCaseSensitive避免大小寫敏感問題。
    • 通過cJSON_Print標(biāo)準(zhǔn)化輸出,確保轉(zhuǎn)義字符正確處理。
2.?網(wǎng)絡(luò)通信
  • 核心挑戰(zhàn)
    • CreateTcpClient()實現(xiàn)未展示,可能隱藏連接超時、重試等邏輯缺失。
    • 未處理HTTP協(xié)議細(xì)節(jié)(如狀態(tài)碼檢查、分塊傳輸編碼)。
  • 解決方案
    • 封裝HTTP客戶端庫(如libcurl)簡化網(wǎng)絡(luò)操作。
    • 增加超時機(jī)制和重試邏輯,提升魯棒性。
3.?文件操作
  • 核心挑戰(zhàn)
    • 文件讀寫與網(wǎng)絡(luò)通信耦合,可能導(dǎo)致數(shù)據(jù)不同步(如文件未及時刷新)。
  • 解決方案
    • 使用內(nèi)存映射文件(mmap)或管道(pipe)替代臨時文件。
    • 增加文件鎖(flock)避免多進(jìn)程競爭。

future_weather()?函數(shù)


void future_weather()
{int ret = -1;int fd = -1;char *buffer = NULL;ssize_t bytes_read = 0;CreateTcpClient(); // 創(chuàng)建新的連接if(!(buffer = malloc(BUFFER_SIZE))){perror("malloc fail");return;}if((fd = open("recv.txt",O_RDONLY)) == -1){perror("open fail");return;}if((bytes_read = read(fd,buffer,BUFFER_SIZE)) <= 0){fprintf(stderr, "Read failed or empty file\n");return;}buffer[bytes_read] = '\0';//確保字符終止cJSON *root = cJSON_Parse(buffer);if(!root){fprintf(stderr, "JSON parse failed\n");return;}// 使用結(jié)構(gòu)體定義字段映射struct FieldMapping {const char *json_key;const char *display_name;int required;  // 1表示必須字段} fields[] = {{"days", "日期", 1},{"week", "星期", 1},{"citynm", "城市", 1},{"temp_high", "最高溫度", 0},{"temp_low", "最低溫度", 0},{"weather", "天氣狀況", 1},{"wind", "風(fēng)向", 1},{"winp", "風(fēng)力", 1},};cJSON *result = cJSON_GetObjectItem(root,"result");if(!result){fprintf(stderr, "Missing result object\n");cJSON_Delete(root);}int i = 0;cJSON *item;cJSON_ArrayForEach(item,result){printf(COLOR_HEAD"=============第%d天氣預(yù)報=============\n"COLOR_RESET,i+1);// 遍歷所有字段定義for (size_t j = 0; j < sizeof(fields)/sizeof(fields[0]); j++) {cJSON *field = cJSON_GetObjectItem(item, fields[j].json_key);printf(COLOR_FIELD"%-8s: "COLOR_RESET, fields[j].display_name);if (field && field->valuestring) {printf(COLOR_VALUE"%s\n"COLOR_RESET, field->valuestring);} else {printf(COLOR_WARN"N/A\n"COLOR_RESET);if (fields[j].required) {fprintf(stderr, "Missing required field: %s\n", fields[j].json_key);}}}i++;}	cJSON_Delete(root);free(buffer);close(fd);
}
功能概述

該函數(shù)用于獲取并展示未來多天的天氣預(yù)報數(shù)據(jù),整體流程如下:

  1. 建立TCP連接獲取數(shù)據(jù)(依賴CreateTcpClient())。
  2. 從文件recv.txt讀取JSON格式的天氣數(shù)據(jù)。
  3. 解析JSON數(shù)據(jù)并格式化輸出未來多天的天氣信息。

亮點與改進(jìn)建議

1. 核心亮點
  • 數(shù)據(jù)遍歷邏輯
    使用cJSON_ArrayForEach遍歷天氣預(yù)報的多個結(jié)果,支持動態(tài)數(shù)量的天氣預(yù)報條目,靈活性較高。

    cJSON_ArrayForEach(item, result) {printf("第%d天天氣預(yù)報", i+1);// 遍歷字段并輸出
    }
    
  • 字段映射復(fù)用
    復(fù)用FieldMapping結(jié)構(gòu)體定義字段映射關(guān)系,與real_time_weather()保持一致性,降低維護(hù)成本。

  • 用戶交互友好
    通過顏色區(qū)分標(biāo)題、字段名和數(shù)值,輸出層次清晰:

    printf(COLOR_HEAD"=============第%d天氣預(yù)報=============\n"COLOR_RESET, i+1);
    

2. 潛在問題與改進(jìn)
問題1:內(nèi)存與資源泄漏
  • 風(fēng)險點

    • 文件打開失敗(open返回-1)時,未釋放malloc分配的buffer。
    • JSON解析失敗時,未關(guān)閉文件描述符fd。
  • 修復(fù)建議
    使用統(tǒng)一清理邏輯確保資源釋放:

    void future_weather() {int fd = -1;char *buffer = NULL;cJSON *root = NULL;// 初始化代碼...// 錯誤處理跳轉(zhuǎn)標(biāo)簽cleanup:if (buffer) free(buffer);if (root) cJSON_Delete(root);if (fd != -1) close(fd);
    }
    
問題2:JSON類型安全性
  • 風(fēng)險點
    直接訪問field->valuestring,若字段值為數(shù)值類型(如溫度),會導(dǎo)致空指針或錯誤輸出。

    // 錯誤示例:若temp_high為數(shù)值,valuestring為NULL
    printf("%s", field->valuestring);
    
  • 修復(fù)建議
    增加類型檢查,支持?jǐn)?shù)值和字符串:

    if (cJSON_IsString(field)) {printf("%s", field->valuestring);
    } else if (cJSON_IsNumber(field)) {printf("%d", field->valueint);
    }
    
問題3:數(shù)據(jù)完整性風(fēng)險
  • 風(fēng)險點
    假設(shè)result為數(shù)組類型,若服務(wù)器返回非數(shù)組數(shù)據(jù)(如空對象),程序會錯誤遍歷。

    cJSON *result = cJSON_GetObjectItem(root, "result");
    cJSON_ArrayForEach(item, result); // 若result非數(shù)組,崩潰!
    
  • 修復(fù)建議
    驗證數(shù)據(jù)類型:

    if (!cJSON_IsArray(result)) {fprintf(stderr, "Invalid result format: expected array\n");goto cleanup;
    }
    
問題4:代碼冗余
  • 風(fēng)險點
    future_weatherreal_time_weather存在大量重復(fù)代碼(如文件操作、JSON解析),違反DRY原則。

  • 修復(fù)建議
    抽象公共邏輯為獨(dú)立函數(shù):

    // 公共函數(shù):讀取文件到緩沖區(qū)
    char* read_weather_data(const char *filename) {int fd = open(filename, O_RDONLY);// 讀取并返回buffer...
    }// 公共函數(shù):解析并打印天氣字段
    void print_weather_fields(cJSON *item, struct FieldMapping *fields, size_t count) {// 遍歷字段并輸出...
    }
    

難點與解決方案

1. 動態(tài)數(shù)組遍歷
  • 難點
    需處理未知數(shù)量的天氣預(yù)報條目,且每個條目需完整解析字段。
  • 方案
    使用cJSON_ArrayForEach宏安全遍歷數(shù)組,避免手動索引越界。
2. 多層級JSON解析
  • 難點
    若JSON結(jié)構(gòu)復(fù)雜(如嵌套對象),需遞歸解析。
  • 方案
    設(shè)計遞歸解析函數(shù),處理嵌套結(jié)構(gòu):
    void parse_nested(cJSON *node, int depth) {if (cJSON_IsObject(node)) {cJSON_ArrayForEach(child, node) {parse_nested(child, depth + 1);}}
    }

http://www.risenshineclean.com/news/11553.html

相關(guān)文章:

  • 小程序免費(fèi)制作網(wǎng)站2021年10月新聞?wù)?/a>
  • 風(fēng)鈴做的網(wǎng)站能否推廣seo搜索引擎優(yōu)化的內(nèi)容
  • 中山做網(wǎng)站哪個公司好如何優(yōu)化搜索引擎
  • 用vs做網(wǎng)站的登錄百度關(guān)鍵詞搜索量統(tǒng)計
  • 做網(wǎng)站的工作流程成都網(wǎng)站seo設(shè)計
  • 成都定制網(wǎng)站建設(shè)網(wǎng)站如何做seo排名
  • 網(wǎng)站技術(shù)的解決方案鄭州網(wǎng)絡(luò)營銷哪個好
  • 做京東網(wǎng)站需要哪些手續(xù)強(qiáng)強(qiáng)seo博客
  • app設(shè)計素材網(wǎng)站鄭州怎么優(yōu)化網(wǎng)站排名靠前
  • 常州網(wǎng)站制作報價php視頻轉(zhuǎn)碼
  • 做簡歷網(wǎng)站成人營銷管理培訓(xùn)班
  • 關(guān)注網(wǎng)站制作廣州各區(qū)最新動態(tài)
  • 制作釣魚網(wǎng)站移動網(wǎng)站推廣如何優(yōu)化
  • 企業(yè)做網(wǎng)頁還是網(wǎng)站網(wǎng)站優(yōu)化資源
  • cdn網(wǎng)絡(luò)對網(wǎng)站開發(fā)有影響嗎全網(wǎng)推廣代理
  • 中國建筑總公司官網(wǎng)首頁windows優(yōu)化大師怎么下載
  • 網(wǎng)站app下載平臺怎么做的代運(yùn)營公司是怎么運(yùn)營的
  • 南海佛山網(wǎng)站建設(shè)百度廣告代理公司
  • 網(wǎng)站平臺由什么搭建百度推廣登錄平臺登錄
  • 新建網(wǎng)站百度怎么收錄怎么做seo
  • 農(nóng)村服務(wù)建設(shè)有限公司網(wǎng)站google推廣工具
  • 南通網(wǎng)站建設(shè)報價專業(yè)培訓(xùn)seo的機(jī)構(gòu)
  • 長沙招聘網(wǎng)站有哪些seo網(wǎng)站推廣招聘
  • 廣州專業(yè)做外貿(mào)網(wǎng)站手機(jī)app開發(fā)
  • 紹興做網(wǎng)站鼎成手機(jī)游戲性能優(yōu)化軟件
  • 國內(nèi)知名域名注冊網(wǎng)站網(wǎng)站推廣排名教程
  • 太原廣告公司網(wǎng)站建設(shè)中國企業(yè)網(wǎng)官方網(wǎng)站
  • 制作企業(yè)網(wǎng)站的新聞顯示重慶百度競價開戶
  • 金湖網(wǎng)站設(shè)計中國搜索引擎份額排行
  • 網(wǎng)站建設(shè) 功能需求滬指重上3000點