天气查询项目:
主逻辑:
实现一个http的客户端
- socket建立连接
- 组织http请求报文
- 查询当天天气 --- now.api --- 获得它的http请求
- 查询未来天气 --- 信息量大,处理逻辑
- 生活指数 --- 信息量大,要注意处理逻辑
- 接收响应报文
- 响应的头
- 响应行
- 首部行
- 内容
- 解析出想要的内容
- strstr
- char *p
- 打印结果
weather.c
#include "head.h"
int create_and_connect_socket(struct sockaddr_in *seraddr)
{
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0)
{
perror("socket fail");
return -1;
}
memset(seraddr, 0, sizeof(*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, (const struct sockaddr *)seraddr, sizeof(*seraddr)) < 0)
{
perror("connect fail");
close(fd);
return -1;
}
return fd;
}
int send_http_request(int fd, const char *city_name)
{
char request[512];
snprintf(request, sizeof(request),
"GET /?app=weather.today&weaid=%s&appkey=77258&sign=0671bc401cf49c34ffd8472cbe521173&format=json HTTP/1.1\r\n"
"Host: api.k780.com\r\n"
"User-Agent: Mozilla/5.0\r\n"
"Connection: close\r\n"
"\r\n",
city_name);
if (write(fd, request, strlen(request)) < 0)
{
perror("发送请求失败");
return -1;
}
return 0;
}
void parse_and_print_weather_response(char *response)
{
char *city = strstr(response, "\"citynm\":\"");
char *weather = strstr(response, "\"weather\":\"");
char *temp_curr = strstr(response, "\"temperature_curr\":\"");
char *humidity = strstr(response, "\"humidity\":\"");
if (city && weather && temp_curr)
{
city += strlen("\"citynm\":\"");
weather += strlen("\"weather\":\"");
temp_curr += strlen("\"temperature_curr\":\"");
char *city_end = strchr(city, '"');
char *weather_end = strchr(weather, '"');
char *temp_end = strchr(temp_curr, '"');
if (city_end && weather_end && temp_end)
{
*city_end = '\0';
*weather_end = '\0';
*temp_end = '\0';
if (humidity)
{
humidity += strlen("\"humidity\":\"");
char *hum_end = strchr(humidity, '"');
if (hum_end)
{
*hum_end = '\0';
printf("城市: %s\n天气: %s\n温度: %s\n湿度: %s\n", city, weather, temp_curr, humidity);
}
}
else
{
printf("城市: %s\n天气: %s\n温度: %s\n", city, weather, temp_curr);
}
}
}
}
int send_future_weather_request(int fd, const char *city_name)
{
char request[512];
snprintf(request, sizeof(request),
"GET /?app=weather.future&weaid=%s&appkey=77258&sign=0671bc401cf49c34ffd8472cbe521173&format=json HTTP/1.1\r\n"
"Host: api.k780.com\r\n"
"User-Agent: Mozilla/5.0\r\n"
"Connection: close\r\n"
"\r\n",
city_name);
if (write(fd, request, strlen(request)) < 0)
{
perror("发送未来天气请求失败");
return -1;
}
return 0;
}
void parse_and_print_future_weather(char *response)
{
char *result_start = strstr(response, "\"result\":[");
if (!result_start)
{
printf("未找到天气数据\n");
return;
}
char *array_start = strchr(result_start, '[');
array_start++;
char *current = array_start;
int day_count = 0;
while (*current != ']')
{
char *obj_start = current;
char *obj_end = NULL;
int brace_count = 0;
for (char *p = current; *p && brace_count >= 0; p++)
{
if (*p == '{')
{
brace_count++;
}
else if (*p == '}')
{
brace_count--;
}
if (brace_count == 0 && *p == '}')
{
obj_end = p;
break;
}
}
if (!obj_end)
{
break;
}
char obj_buffer[512] = {0};
strncpy(obj_buffer, obj_start, obj_end - obj_start + 1);
obj_buffer[obj_end - obj_start + 1] = '\0';
char *days = strstr(obj_buffer, "\"days\":\"");
char *week = strstr(obj_buffer, "\"week\":\"");
char *citynm = strstr(obj_buffer, "\"citynm\":\"");
char *temperature = strstr(obj_buffer, "\"temperature\":\"");
char *weather = strstr(obj_buffer, "\"weather\":\"");
if (days && week && citynm && temperature && weather)
{
days += strlen("\"days\":\"");
week += strlen("\"week\":\"");
citynm += strlen("\"citynm\":\"");
temperature += strlen("\"temperature\":\"");
weather += strlen("\"weather\":\"");
char *days_end = strchr(days, '"');
char *week_end = strchr(week, '"');
char *citynm_end = strchr(citynm, '"');
char *temp_end = strchr(temperature, '"');
char *weather_end = strchr(weather, '"');
if (days_end && week_end && citynm_end && temp_end && weather_end)
{
*days_end = '\0';
*week_end = '\0';
*citynm_end = '\0';
*temp_end = '\0';
*weather_end = '\0';
printf("第%d天:\n", day_count + 1);
printf(" 日期: %s\n", days);
printf(" 星期: %s\n", week);
printf(" 城市: %s\n", citynm);
printf(" 温度: %s\n", temperature);
printf(" 天气: %s\n", weather);
}
}
current = obj_end + 1;
if (*current == ',')
{
current++;
}
day_count++;
}
}
int send_lifeindex_request(int fd, const char *city_name)
{
char request[512];
snprintf(request, sizeof(request),
"GET /?app=weather.lifeindex&weaid=%s&appkey=77258&sign=0671bc401cf49c34ffd8472cbe521173&format=json HTTP/1.1\r\n"
"Host: api.k780.com\r\n"
"User-Agent: Mozilla/5.0\r\n"
"Connection: close\r\n"
"\r\n",
city_name);
if (write(fd, request, strlen(request)) < 0)
{
perror("发送生活指数请求失败");
return -1;
}
return 0;
}
void parse_and_print_lifeindex_response(char *response)
{
char *result_start = strstr(response, "\"result\":[");
if (!result_start)
{
printf("未找到生活指数数据\n");
return;
}
char *array_start = strchr(result_start, '[');
array_start++;
char *current = array_start;
int day_count = 0;
while (*current != ']')
{
char *obj_start = current;
char *obj_end = NULL;
int brace_count = 0;
for (char *p = current; *p && brace_count >= 0; p++)
{
if (*p == '{')
{
brace_count++;
}
else if (*p == '}')
{
brace_count--;
}
if (brace_count == 0 && *p == '}')
{
obj_end = p;
break;
}
}
if (!obj_end)
{
break;
}
char obj_buffer[1024] = {0};
strncpy(obj_buffer, obj_start, obj_end - obj_start + 1);
obj_buffer[obj_end - obj_start + 1] = '\0';
char *days = strstr(obj_buffer, "\"days\":\"");
char *week = strstr(obj_buffer, "\"week_1\":\"");
char *citynm = strstr(obj_buffer, "\"citynm\":\"");
char *clothes = strstr(obj_buffer, "\"lifeindex_ct_dese\":\"");
char *car_wash = strstr(obj_buffer, "\"lifeindex_xc_dese\":\"");
char *uv_index = strstr(obj_buffer, "\"lifeindex_uv_dese\":\"");
if (days && week && citynm && clothes && car_wash && uv_index)
{
days += strlen("\"days\":\"");
week += strlen("\"week_1\":\"");
citynm += strlen("\"citynm\":\"");
clothes += strlen("\"lifeindex_ct_dese\":\"");
car_wash += strlen("\"lifeindex_xc_dese\":\"");
uv_index += strlen("\"lifinedex_uv_dese\":\"");
char *days_end = strchr(days, '"');
char *week_end = strchr(week, '"');
char *citynm_end = strchr(citynm, '"');
char *clothes_end = strchr(clothes, '"');
char *car_wash_end = strchr(car_wash, '"');
char *uv_end = strchr(uv_index, '"');
if (days_end && week_end && citynm_end && clothes_end && car_wash_end && uv_end)
{
*days_end = '\0';
*week_end = '\0';
*citynm_end = '\0';
*clothes_end = '\0';
*car_wash_end = '\0';
*uv_end = '\0';
printf("第%d天:\n", day_count + 1);
printf(" 日期: %s\n", days);
printf(" 星期: %s\n", week);
printf(" 城市: %s\n", citynm);
printf(" 穿衣建议: %s\n", clothes);
printf(" 洗车建议: %s\n", car_wash);
printf(" 紫外线指数: %s\n", uv_index);
}
}
current = obj_end + 1;
if (*current == ',')
{
current++;
}
day_count++;
}
}
menu.c
#include "head.h"
#define RESET "\033[0m"
#define RED "\033[31m"
#define GREEN "\033[32m"
#define YELLOW "\033[33m"
#define BLUE "\033[34m"
#define MAGENTA "\033[35m"
#define CYAN "\033[36m"
void print_header()
{
printf(CYAN);
printf("===============================================================================\n");
printf(" 天气查询系统 v1.0 \n");
printf("===============================================================================\n");
printf(RESET);
}
void show_menu()
{
printf(GREEN);
printf("\n+-----------------------------------+\n");
printf("| 查询模式选择 |\n");
printf("+-----------------------------------+\n");
printf("| 1. 查询当天天气 (today) |\n");
printf("| 2. 查询未来天气 (future) |\n");
printf("| 3. 查询生活指数 (lifeindex) |\n");
printf("| 0. 退出 |\n");
printf("+-----------------------------------+\n");
printf(RESET);
}
void print_response_header(const char *city_name, const char *mode)
{
printf(BLUE);
printf("\n===============================================================================\n");
printf("查询城市: %s\n查询模式: %s\n", city_name, mode);
printf("===============================================================================\n");
printf(RESET);
}
int main()
{
char city_name[128];
int choice;
print_header();
printf(YELLOW "欢迎使用天气查询系统!\n" RESET);
printf("请输入要查询的城市名称: ");
if (scanf("%127s", city_name) != 1)
{
fprintf(stderr, RED "输入城市名称失败,请重新运行程序。\n" RESET);
return -1;
}
while (1)
{
show_menu();
printf("请选择模式(输入数字): ");
if (scanf("%d", &choice) != 1)
{
fprintf(stderr, RED "输入无效,请重新输入数字。\n" RESET);
}
if (choice == 0)
{
printf(MAGENTA "感谢使用天气查询系统!再见!\n" RESET);
break;
}
else if (choice >= 1 && choice <= 3)
{
const char *mode = NULL;
switch (choice)
{
case 1:
mode = "today";
break;
case 2:
mode = "future";
break;
case 3:
mode = "lifeindex";
break;
}
print_response_header(city_name, mode);
if (query_weather(city_name, mode) < 0)
{
fprintf(stderr, RED "查询失败,请检查网络或输入。\n" RESET);
}
}
else
{
printf(RED "无效的选择,请输入 0-3 之间的数字。\n" RESET);
}
}
return 0;
}
main.c
#include "head.h"
int query_weather(const char *city_name, const char *mode)
{
struct sockaddr_in seraddr;
int fd = create_and_connect_socket(&seraddr);
if (fd < 0)
{
fprintf(stderr, "无法连接到服务器\n");
return -1;
}
if (strcmp(mode, "today") == 0)
{
if (send_http_request(fd, city_name) < 0)
{
close(fd);
return -1;
}
}
else if (strcmp(mode, "future") == 0)
{
if (send_future_weather_request(fd, city_name) < 0)
{
close(fd);
return -1;
}
}
else if (strcmp(mode, "lifeindex") == 0)
{
if (send_lifeindex_request(fd, city_name) < 0)
{
close(fd);
return -1;
}
}
char response[4096] = {0};
read(fd, response, sizeof(response) - 1);
if (strcmp(mode, "today") == 0)
{
parse_and_print_weather_response(response);
}
else if (strcmp(mode, "future") == 0)
{
parse_and_print_future_weather(response);
}
else if (strcmp(mode, "lifeindex") == 0)
{
parse_and_print_lifeindex_response(response);
}
close(fd);
return 0;
}
效果

499

被折叠的 条评论
为什么被折叠?



