嵌入式学习day37

天气查询项目:

主逻辑:

实现一个http的客户端

  1. socket建立连接
  2. 组织http请求报文
    1. 查询当天天气 --- now.api --- 获得它的http请求
    2. 查询未来天气 --- 信息量大,处理逻辑
    3. 生活指数 --- 信息量大,要注意处理逻辑
  3. 接收响应报文
    1. 响应的头
    2. 响应行
    3. 首部行
    4. 内容
  4. 解析出想要的内容
    1. strstr
    2. char *p
  5. 打印结果

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;
}

效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值