天气查询
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; }