基于网络编程 (API)的天气查询系统的实现
平台是:VMware虚拟机ububtu,vim编辑器。
第一次写博客,试个水。用了多文件编程,一个main.c实现调用控制的作用,一个menu.c实现菜单打印的作用,一个pachong.c实现具体功能的实现,menu.h和pachong.h 起到包含.c文件单独使用的头文件、单独使用的数据类型(枚举、结构体)、单独使用的宏、声明允许外部操作函数、声明允许外部操作变量的作用。
现在把代码贴出来吧。
这是main.c文件,比较简单。
#include "pachong.h"
#include "menu.h"
int main(int argc, const char *argv[])
{
while(1)
{
MenuShow();
MenuChoose();
}
return 0;
}
这是menu.c
#include "menu.h"
#include "pachong.h"
PaChong_MENU_S gMenu = {
PaChong_MENU_LEVEL_ONE,
{
{0,2,0},
{0,3,0},
},
};
PaChong_OPT_S gOptList_One[] = {
{1,"请输入想要查询的城市",InputCity},
{2,"切换城市",Swiching},
{3,"退出软件",Exit},
};
PaChong_OPT_S gOptList_Two[] = {
{1,"此城市的实时天气", RealTime},
{2,"此城市的历史天气", History},
{3,"此城市未来一周的天气", Future},
{4,"返回上一页", Return},
};
int MenuShow(void)
{
int i = 0;
int CurStartPos = 0;
int CurEndPos = 0;
int CurFocus = 0;
CurStartPos = gMenu.MenuPos[gMenu.CurMenu].StartPos;
CurEndPos = gMenu.MenuPos[gMenu.CurMenu].EndPos;
CurFocus = gMenu.MenuPos[gMenu.CurMenu].Focus;
system("clear");
printf(" \n");
printf("\033[47:30m \033[0m\r\033[47;30m 操作指令 \033[0m\n");
printf("\033[47:30m \033[0m\r\033[47;30m 上:w 下:s 确认:e \033[0m\n");
printf("\033[47:30m \033[0m\r\033[47;30m 日期:2020/05/04 \033[0m\n");
printf(" \n");
printf("+------------------------------+\n");
printf("| |\n");
printf("| weather |\n");
printf("| |\n");
printf("+------------------------------+\n");
for(i = CurStartPos;i <= CurEndPos;i++)
{
if(CurFocus == i)
{
if(PaChong_MENU_LEVEL_ONE == gMenu.CurMenu)
{
printf("\033[46;30m \033[0m|\r|\033[46;30m%2d.%s\033[0m\n",gOptList_One[i].Id,gOptList_One[i].StrShow);
}
else if(PaChong_MENU_LEVEL_TWO == gMenu.CurMenu)
{
printf("\033[46;30m \033[0m|\r|\033[46;30m%2d.%s\033[0m\n",gOptList_Two[i].Id,gOptList_Two[i].StrShow);
}
}
else /*if(i != 0)*/
{
if(gMenu.CurMenu == PaChong_MENU_LEVEL_ONE)
{
printf(" |\r|%2d.%s\n",gOptList_One[i].Id,gOptList_One[i].StrShow);
}
else if(PaChong_MENU_LEVEL_TWO == gMenu.CurMenu)
{
printf(" |\r|%2d.%s\n",gOptList_Two[i].Id,gOptList_Two[i].StrShow);
}
}
}
printf("+------------------------------+\n");
return 0;
}
int getch(void)
{
struct termios oldt, newt;
int ch;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
ch = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
return ch;
}
int MenuChoose(void)
{
int focus = gMenu.MenuPos[gMenu.CurMenu].Focus;
int start = gMenu.MenuPos[gMenu.CurMenu].StartPos;
int end = gMenu.MenuPos[gMenu.CurMenu].EndPos;
int Key = 0;
int End = 0;
if(PaChong_MENU_LEVEL_ONE == gMenu.CurMenu)
{
End = sizeof(gOptList_One) / sizeof(gOptList_One[0]);
}
if(PaChong_MENU_LEVEL_TWO == gMenu.CurMenu)
{
End = sizeof(gOptList_Two) / sizeof(gOptList_Two[0]);
}
Key = getch();
switch (Key)
{
case 'w':if(focus > start)
{
gMenu.MenuPos[gMenu.CurMenu].Focus --;
}
else if(focus == start && start != 0)
{
gMenu.MenuPos[gMenu.CurMenu].StartPos --;
gMenu.MenuPos[gMenu.CurMenu].EndPos --;
gMenu.MenuPos[gMenu.CurMenu].Focus --;
}
break;
case 's':if(focus < end)
{
gMenu.MenuPos[gMenu.CurMenu].Focus ++;
}
else if(focus == end && end != End - 1)
{
gMenu.MenuPos[gMenu.CurMenu].StartPos ++;
gMenu.MenuPos[gMenu.CurMenu].EndPos ++;
gMenu.MenuPos[gMenu.CurMenu].Focus ++;
}
break;
case '\n':
if(PaChong_MENU_LEVEL_ONE == gMenu.CurMenu)
{
gOptList_One[gMenu.MenuPos[gMenu.CurMenu].Focus].pFun();
}
else
{
gOptList_Two[gMenu.MenuPos[gMenu.CurMenu].Focus].pFun();
}
}
return 0;
}
int InputCity(void){
memset(city, 0, sizeof(city));
gMenu.CurMenu = PaChong_MENU_LEVEL_TWO;
printf("请输入城市名字:");
gets(city);
return 0;
}
int Swiching(void){
if(0 == city[0]){
printf("请先输入城市\n");
InputCity();
}
else{
memset(city, 0, sizeof(city));
gMenu.CurMenu = PaChong_MENU_LEVEL_TWO;
printf("请输入城市名字:");
gets(city);
}
return 0;
}
int Return(void)
{
gMenu.CurMenu = PaChong_MENU_LEVEL_ONE;
return 0;
}
这是pachong.c,具体实现了从网络上爬取天气的功能。
#include "pachong.h"
#include "menu.h"
//#include <Windows.h>
char city[64] = {0};
PaChong_PC_S q[] = {
{1,"days","日期"},
{2,"week","周几"},
{3, "citynm","城市名字"},
{4, "temp_high","最高温度"},
{5, "temp_low","最低温度"},
{6, "temperature_curr","当前温度"},
{7, "humidity","湿度"},
{8, "aqi","灰尘指数"},
{9, "weather","今日天气"},
{10, "weather_curr","当前天气"},
{11, "wind","风向"},
{12, "winp","风级"},
};
PaChong_PC_S qH[] = {
{1,"week","周几"},
{2,"citynm","城市名字"},
{3,"uptime","日期时间"},
{4,"temperature","温度"},
{5,"humidity","湿度"},
{6,"aqi","灰尘指数"},
{7,"weather","天气"},
{8,"wind","风向"},
{9,"winp","风级"},
};
PaChong_PC_S qF[] = {
{1,"days","日期"},
{2,"week","周几"},
{3,"citynm","城市名字"},
{4,"humidity","湿度"},
{5,"\"weather\"","天气"},
{6,"\"wind\"","风向"},
{7,"\"winp\"","风级"},
{8,"temp_high","最高温度"},
{9,"temp_low","最低温度"},
};
/*
void gotoxy(int x,int y)//光标定位函数
{
COORD p;//定义结构体变量p
HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE);//获取当前函数句柄
p.X=x;p.Y=y;//将光标的目标移动位置传递给结构体
SetConsoleCursorPosition(handle,p);//移动光标
}
*/
int Exit()
{
exit(0);
return 0;
}
int RealTime(void){
int i = 0;
int ret = 0;
char *pstr = NULL;
int sockfd = 0;
char tembuff[4096] = {0};
char sendbuff[4096] = {0};
char recvbuff[4096] = {0};
struct sockaddr_in recvaddr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == sockfd){
perror("fail to socket");
return -1;
}
recvaddr.sin_family = AF_INET;
recvaddr.sin_port = htons(SER_PORT);
recvaddr.sin_addr.s_addr = inet_addr(SER_ADDR);
ret = connect(sockfd, (struct sockaddr *)&recvaddr, sizeof(recvaddr));
if (-1 == ret){
perror("fail to connect");
return -1;
}
sprintf(sendbuff, "GET /?app=weather.today&&weaid=%s&&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json HTTP/1.1\r\n",city);
sprintf(sendbuff, "%sReferer: http://www.k780.com/api/weather.today\r\n", sendbuff);
sprintf(sendbuff, "%sUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134\r\n", sendbuff);
sprintf(sendbuff, "%sAccept-Language: zh-CN\r\n", sendbuff);
sprintf(sendbuff, "%sAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n", sendbuff);
sprintf(sendbuff, "%sHost: api.k780.com:88\r\n", sendbuff);
sprintf(sendbuff, "%sConnection: Keep-Alive\r\n\r\n", sendbuff);
ret = send(sockfd, sendbuff, sizeof(sendbuff), 0);
if (-1 == ret){
perror("fail to send");
return -1;
}
ret = recv(sockfd, recvbuff, sizeof(recvbuff), 0);
if (-1 == ret){
perror("fail to revc");
return -1;
}
for (i = 0; i < 12; ++i){
strcpy(tembuff, recvbuff);
pstr = strstr(tembuff, q[i].sq);
strtok(pstr, ",");
pstr = strstr(pstr, ":");
printf("%s%s\n", q[i].name, pstr);
memset(tembuff, 0, sizeof(tembuff));
}
printf("请按下Enter执行接下来的操作!");
getchar();
close(sockfd);
return 0;
}
int History(void){
int i = 0;
int ret = 0;
char *pstr = NULL;
int sockfd = 0;
char Date[64] = {0};
char tembuff[4096] = {0};
char sendbuff[4096] = {0};
char recvbuff[4096] = {0};
struct sockaddr_in recvaddr;
printf("请输入想要查询的日期");
printf("格式为年-月-日,例:2020-03-04或2020-03-04 01:00:00(只可以查询整点) ");
gets(Date);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == sockfd){
perror("fail to socket");
return -1;
}
recvaddr.sin_family = AF_INET;
recvaddr.sin_port = htons(SER_PORT);
recvaddr.sin_addr.s_addr = inet_addr(SER_ADDR);
ret = connect(sockfd, (struct sockaddr *)&recvaddr, sizeof(recvaddr));
if (-1 == ret){
perror("fail to connect");
return -1;
}
sprintf(sendbuff, "GET /?app=weather.history&weaid=%s&date=%s&&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json HTTP/1.1\r\n",city,Date);
sprintf(sendbuff, "%sReferer: http://www.k780.com/api/weather.today\r\n", sendbuff);
sprintf(sendbuff, "%sUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134\r\n", sendbuff);
sprintf(sendbuff, "%sAccept-Language: zh-CN\r\n", sendbuff);
sprintf(sendbuff, "%sAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n", sendbuff);
sprintf(sendbuff, "%sHost: api.k780.com:88\r\n", sendbuff);
sprintf(sendbuff, "%sConnection: Keep-Alive\r\n\r\n", sendbuff);
ret = send(sockfd, sendbuff, sizeof(sendbuff), 0);
if (-1 == ret){
perror("fail to send");
return -1;
}
ret = recv(sockfd, recvbuff, sizeof(recvbuff), 0);
if (-1 == ret){
perror("fail to revc");
return -1;
}
for (i = 0; i < 9; ++i){
strcpy(tembuff, recvbuff);
pstr = strstr(tembuff, qH[i].sq);
strtok(pstr, ",");
pstr = strstr(pstr, ":");
printf("%s%s\n", qH[i].name, pstr);
memset(tembuff, 0, sizeof(tembuff));
}
printf("请按下Enter执行接下来的操作!");
getchar();
close(sockfd);
return 0;
}
int Future(void){
int i = 0;
int n = 0;
int day = 0;
int ret = 0;
char *pstr = NULL;
int sockfd = 0;
char tembuff[4096] = {0};
char sendbuff[4096] = {0};
char recvbuff[4096] = {0};
struct sockaddr_in recvaddr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == sockfd){
perror("fail to socket");
return -1;
}
recvaddr.sin_family = AF_INET;
recvaddr.sin_port = htons(SER_PORT);
recvaddr.sin_addr.s_addr = inet_addr(SER_ADDR);
ret = connect(sockfd, (struct sockaddr *)&recvaddr, sizeof(recvaddr));
if (-1 == ret){
perror("fail to connect");
return -1;
}
sprintf(sendbuff, "GET /?app=weather.future&weaid=%s&&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json HTTP/1.1\r\n",city);
sprintf(sendbuff, "%sReferer: http://www.k780.com/api/weather.today\r\n", sendbuff);
sprintf(sendbuff, "%sUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134\r\n", sendbuff);
sprintf(sendbuff, "%sAccept-Language: zh-CN\r\n", sendbuff);
sprintf(sendbuff, "%sAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n", sendbuff);
sprintf(sendbuff, "%sHost: api.k780.com:88\r\n", sendbuff);
sprintf(sendbuff, "%sConnection: Keep-Alive\r\n\r\n", sendbuff);
ret = send(sockfd, sendbuff, sizeof(sendbuff), 0);
if (-1 == ret){
perror("fail to send");
return -1;
}
ret = recv(sockfd, recvbuff, sizeof(recvbuff), 0);
if (-1 == ret){
perror("fail to revc");
return -1;
}
for(day = 0; day < 7; ++day){
int temnum = 0;
for (i = 0; i < 9; ++i){
strcpy(tembuff, recvbuff);
pstr = strstr(tembuff, qF[i].sq);
for (n = 1;n <= day;++n){
strncpy(tembuff,pstr + 5,4096);
pstr = strstr(tembuff,qF[i].sq);
}
strtok(pstr, ",");
pstr = strstr(pstr, ":");
// temnum = day * 7;
// gotoxy(20,temnum);
printf("%s%s\n", qF[i].name, pstr);
memset(tembuff, 0, sizeof(tembuff));
}
printf("\n");
}
printf("请按下Enter执行接下来的操作!");
getchar();
close(sockfd);
return 0;
}
这里是两个具体的.h文件(本来不想粘出来,太长了,)