学习嵌入式的第三十八天
文章目录
- 天气查询
- 1.实现原理和实现目标
- 1.原理
- 2.目标
- 3.实现方法
- 1.头文件
- 2.界面函数
- 3.输出函数
- 4.主函数
- 附:使用cjson分割
天气查询
1.实现原理和实现目标
1.原理
- 利用TCP协议连接到api.k780.com网站中查询信息并打印到终端
2.目标
- 用户输入想要查询的城市,再输入想要查询的日期
- 打印出对应的天气情况
- 对于历史天气不支持查询
3.实现方法
1.头文件
#ifndef _HEAD_H_
#define _HEAD_H_#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<pthread.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<signal.h>
#include<sys/wait.h>
#include<fcntl.h>
#include<errno.h>
#include<time.h>
#include<netinet/in.h>extern void get_local_info(char *ptmp);
extern char* menu_show(void);
extern int menu_select(void);
extern void what_day(void);
extern char* log_in(char *addr);
extern int get_future_weather(char *ptmp);#endif
2.界面函数
-
展示出应用界面,引导用户输入
-
将用户输入的城市名和查询方式拼接到URL中
代码实现:
#include"head.h"char* menu_show(void){static char addr[1024] = {0};char name[20] = {0};printf("******************************\n");printf("* 天气查询系统 *\n");printf("* 请输入你要查询的城市 *\n");printf("* 输入0退出系统 *\n");printf("******************************\n");scanf("%s",name);if(strcmp(name,"0") == 0){return "quit";}sprintf(addr,"&weaid=%s&appkey=77265&sign=6856d5882decbc6dcd42d8181fd613fc&format=json HTTP/1.1\r\nHost: api.k780.com\r\n\r\n",name);return addr; } void what_day(void){printf("******************************\n");printf("* 天气查询系统 *\n");printf("* 输入编号查询对应天气 *\n");printf("* 输入0退出此界面 *\n");printf("* 1.查询当天天气 *\n");printf("* 2.查询未来天气 *\n");printf("* 3.查询历史天气(未开放) *\n");printf("******************************\n");return; } int menu_select(void){int select = 0;scanf("%d",&select);switch(select){case 0:return 0;break;case 1:return 1;break;case 2:return 2;break;case 3:return 3;break;} }
3.输出函数
-
将拼接好的URL接入到网站中,并将网站返回的信息返回
-
根据查询方式输出
代码实现:
#include"head.h"char* log_in(char *addr){int fd;char tmp[4096] = {0};static char buf[4096] = {0};fd = socket(AF_INET, SOCK_STREAM, 0);if (fd < 0) {perror("socket");return NULL;}struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(80);seraddr.sin_addr.s_addr = inet_addr("103.205.5.249");if(connect(fd, (struct sockaddr *)&seraddr, sizeof(seraddr))<0){perror("fail to connect");return NULL;}strcpy(tmp,addr);if(strcmp(tmp,"quit") == 0){close(fd);return NULL;}write(fd,tmp, strlen(tmp));int n = read(fd,buf,sizeof(buf)-1);if(n > 0) buf[n] = '\0';close(fd);return buf; }void get_local_info(char *ptmp){char buf[4096] = {0};char *p = NULL;printf("今日天气预报:\n");printf("-------------------------\n");strcpy(buf,ptmp);p = strstr(buf,"citynm");p += 9;strtok(p,"\"");printf("城市:%s\n",p);strcpy(buf,ptmp);p = strstr(buf,"temperature");p += 14;strtok(p,"\"");printf("今日温度:%s\n",p);strcpy(buf,ptmp);p = strstr(buf,"temperature_curr");p += 19;strtok(p,"\"");printf("现在温度:%s\n",p);strcpy(buf,ptmp);p = strstr(buf,"weather");p += 10;strtok(p,"\"");printf("天气:%s\n",p);strcpy(buf,ptmp);p = strstr(buf,"wind");p += 7;strtok(p,"\"");printf("风向:%s\n",p);strcpy(buf,ptmp);p = strstr(buf,"winp");p += 7;strtok(p,"\"");printf("风速:%s\n",p);printf("-------------------------\n");return; } int get_future_weather(char *ptmp) {char *q = ptmp;char info[1024] = {0};char buf[4096] = {0};char *p = NULL;printf("未来几天天气预报:\n");printf("-------------------------\n");while ((q = strstr(q, "\"weaid\":")) != NULL) {q += 8;sscanf(q, "%[^}]", info);strcpy(buf, info);p = strstr(buf, "days");if (p) {p += 7;strtok(p, "\"");printf("%s\n", p);}strcpy(buf, info);p = strstr(buf, "week");if (p) {p += 7;strtok(p, "\"");printf("%s\n", p);}strcpy(buf, info);p = strstr(buf, "citynm");if (p) {p += 9;strtok(p, "\"");printf("城市:%s\n", p);}strcpy(buf, info);p = strstr(buf, "temperature");if (p) {p += 14;strtok(p, "\"");printf("温度:%s\n", p);}strcpy(buf, info);p = strstr(buf, "humidity");if (p) {p += 11;strtok(p, "\"");printf("湿度:%s\n", p);}strcpy(buf, info);p = strstr(buf, "weather");if (p) {p += 10;strtok(p, "\"");printf("天气:%s\n", p);}strcpy(buf, info);p = strstr(buf, "wind");if (p) {p += 7;strtok(p, "\"");printf("风向:%s\n", p);}strcpy(buf, info);p = strstr(buf, "winp");if (p) {p += 7;strtok(p, "\"");printf("风速:%s\n", p);}printf("-------------------------\n");q++;}return 0; }
4.主函数
代码实现:
#include"head.h"int main(void){int num = 0;char *addr;char type[20];char req[4096];char *tmp = NULL;while(1){addr = menu_show();if(strcmp(addr,"quit") == 0){printf("感谢使用,再见!\n");break;}what_day();num = menu_select();switch(num){case 0:break;case 1:strcpy(type,"today");sprintf(req,"GET /?app=weather.%s",type);strcat(req,addr);tmp = log_in(req);get_local_info(tmp);break;case 2:strcpy(type,"future");sprintf(req,"GET /?app=weather.%s",type);strcat(req,addr);tmp = log_in(req);get_future_weather(tmp);break;case 3:printf("功能未开放,敬请期待!\n");break;}
}return 0;
}
附:使用cjson分割
-
也可以使用cjson分割网站返回的信息
-
需要加上cjson自带的cJSON.h和cJSON.c函数
-
获取这两个函数可以访问GitHub上的网址
https://github.com/DaveGamble/cJSON
-
把函数加上之后只需要修改输出函数即可
#include"head.h" #include"cJSON.h"char* log_in(char *addr){int fd;char tmp[4096] = {0};static char buf[4096] = {0};fd = socket(AF_INET, SOCK_STREAM, 0);if (fd < 0) {perror("socket");return NULL;}struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(80);seraddr.sin_addr.s_addr = inet_addr("103.205.5.249");if(connect(fd, (struct sockaddr *)&seraddr, sizeof(seraddr))<0){perror("fail to connect");return NULL;}strcpy(tmp,addr);if(strcmp(tmp,"quit") == 0){close(fd);return NULL;}write(fd,tmp, strlen(tmp));int n = read(fd,buf,sizeof(buf)-1);if(n > 0) buf[n] = '\0';close(fd);return buf; }void get_local_info(char *ptmp){cJSON *root = NULL;char *json_start = strstr(ptmp, "{");json_start = strstr(json_start+1,"{");if (json_start != NULL) {char *json_end = strrchr(json_start,'}');if(json_end != NULL){*(json_end) = '\0';}}root = cJSON_Parse(json_start);if(root == NULL){const char *error_ptr = cJSON_GetErrorPtr();if(error_ptr != NULL){fprintf(stderr,"Error before: %s\n",error_ptr);}return;}cJSON *city_item = cJSON_GetObjectItem(root,"citynm");if(cJSON_IsString(city_item)){printf("城市:%s\n",city_item->valuestring);}cJSON *temperature_item = cJSON_GetObjectItem(root,"temperature");if(cJSON_IsString(temperature_item)){printf("温度:%s\n",temperature_item->valuestring);}cJSON *temperature_curr_item = cJSON_GetObjectItem(root,"temperature_curr");if(cJSON_IsString(temperature_curr_item)){printf("当前温度:%s\n",temperature_curr_item->valuestring);}cJSON *weather_item = cJSON_GetObjectItem(root,"weather");if(cJSON_IsString(weather_item)){printf("天气:%s\n",weather_item->valuestring);}cJSON *wind_item = cJSON_GetObjectItem(root,"wind");if(cJSON_IsString(wind_item)){printf("风向:%s\n",wind_item->valuestring);}cJSON *winp_item = cJSON_GetObjectItem(root,"winp");if(cJSON_IsString(winp_item)){printf("风速:%s\n",winp_item->valuestring);}return; } int get_future_weather(char *ptmp) {cJSON *root = NULL;char *json_end;char *json_start;int i = 0;for(i = 0;i<7;i++){printf("--------------------------------------\n");if(i == 0){json_start = strstr(ptmp, "{");json_start = strstr(json_start+1,"{");if (json_start != NULL) {json_end = strstr(json_start,"}");if(json_end != NULL){*(json_end+1) = '\0';}}json_end ++;json_end ++;}else{json_start = json_end;//printf("json_start = %s\n",json_start);if (json_start != NULL) {json_end = strstr(json_start,"}");if(json_end != NULL){*(json_end+1) = '\0';}}json_end ++;json_end ++;}root = cJSON_Parse(json_start);if(root == NULL){const char *error_ptr = cJSON_GetErrorPtr();if(error_ptr != NULL){fprintf(stderr,"Error before: %s\n",error_ptr);}return -1;}cJSON *date_item = cJSON_GetObjectItem(root,"days");if(cJSON_IsString(date_item)){printf("日期:%s\n",date_item->valuestring);}cJSON *week_item = cJSON_GetObjectItem(root,"week");if(cJSON_IsString(week_item)){printf("星期:%s\n",week_item->valuestring);}cJSON *city_item = cJSON_GetObjectItem(root,"citynm");if(cJSON_IsString(city_item)){printf("城市:%s\n",city_item->valuestring);}cJSON *temperature_item = cJSON_GetObjectItem(root,"temperature");if(cJSON_IsString(temperature_item)){printf("温度:%s\n",temperature_item->valuestring);}cJSON *humidity_item = cJSON_GetObjectItem(root,"humidity");if(cJSON_IsString(humidity_item)){printf("当前湿度:%s\n",humidity_item->valuestring);}cJSON *weather_item = cJSON_GetObjectItem(root,"weather");if(cJSON_IsString(weather_item)){printf("天气:%s\n",weather_item->valuestring);}cJSON *wind_item = cJSON_GetObjectItem(root,"wind");if(cJSON_IsString(wind_item)){printf("风向:%s\n",wind_item->valuestring);}cJSON *winp_item = cJSON_GetObjectItem(root,"winp");if(cJSON_IsString(winp_item)){printf("风速:%s\n",winp_item->valuestring);}}return 0; }