当前位置: 首页 > news >正文

一个基于固定 IP地址查询天气的 C 语言程序,通过调用第三方天气 API:

一、代码功能说明

该代码是一个 基于固定 IP 地址查询天气的 C 语言程序,通过调用第三方天气 API(api.k780.com),查询指定 IP 地址(113.66.98.219)对应的地理位置天气信息,包括日期、天气状况、温度、风向和湿度等数据。程序通过 TCP socket 发送 HTTP 请求,解析返回的 JSON 数据并打印结果,适用于快速获取固定 IP 所在地的天气信息。

#include <stdio.h>        // 标准输入输出库,用于打印和输入操作
#include <string.h>       // 字符串处理库,用于字符串复制、查找等操作
#include <sys/types.h>    // 系统类型定义,包含基本数据类型
#include <unistd.h>       // POSIX系统调用库,用于关闭文件描述符等操作
#include <stdlib.h>       // 标准库,用于内存分配(malloc/free)和程序退出
#include <fcntl.h>        // 文件控制库,定义文件操作相关宏
#include <sys/stat.h>     // 文件状态库,用于获取文件属性
#include <sys/socket.h>   // socket编程库,用于网络通信
#include <netinet/in.h>   // 网络地址结构库,定义IPv4地址格式
#include <arpa/inet.h>    // 网络地址转换库,用于IP地址格式转换
#include <netdb.h>        // 主机信息库,用于域名解析
#include "cJSON.h"        // cJSON库,用于解析JSON格式数据extern int h_errno;       // 声明外部变量h_errno,用于获取域名解析错误码// HTTP 请求函数:向指定主机发送 GET 请求并返回 JSON 数据
char* http_get_json(const char* host, const char* path) {// 解析域名到 IP 地址(DNS 解析)struct hostent* ht = gethostbyname(host);  // 通过域名获取主机信息(IP地址等)if (!ht) {  // 如果域名解析失败fprintf(stderr, "DNS 解析失败: %s\n", hstrerror(h_errno));  // 打印解析错误信息return NULL;  // 返回NULL表示失败}// 创建 TCP socket(IPv4 协议,流式传输)int sockfd = socket(AF_INET, SOCK_STREAM, 0);  // 创建IPv4的TCP socketif (sockfd == -1) {  // 如果socket创建失败perror("socket 创建失败");  // 打印错误原因return NULL;  // 返回NULL表示失败}// 初始化服务器地址结构struct sockaddr_in addr = {.sin_family = AF_INET,       // 使用IPv4地址族.sin_port = htons(80),       // 设置端口为80(HTTP默认端口),转换为网络字节序.sin_addr = *(struct in_addr*)ht->h_addr  // 绑定解析得到的IP地址};// 连接服务器if (connect(sockfd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {  // 与服务器建立连接perror("连接服务器失败");  // 连接失败时打印错误close(sockfd);  // 关闭socket释放资源return NULL;  // 返回NULL表示失败}// 定义 HTTP 请求缓冲区char request[1024];  // 存储HTTP请求内容的缓冲区// 格式化 HTTP GET 请求内容(包含路径、主机等信息)snprintf(request, sizeof(request),  // 拼接HTTP请求头"GET %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", path, host);// 发送 HTTP 请求到服务器if (send(sockfd, request, strlen(request), 0) <= 0) {  // 发送请求数据perror("发送请求失败");  // 发送失败时打印错误close(sockfd);  // 关闭socketreturn NULL;  // 返回NULL表示失败}// 分配内存用于存储服务器响应(16384 字节足够容纳一般响应)char* response = malloc(16384);  // 分配响应缓冲区if (!response) {  // 如果内存分配失败perror("内存分配失败");  // 打印错误close(sockfd);  // 关闭socketreturn NULL;  // 返回NULL表示失败}// 循环接收服务器响应,直到接收完毕int total = 0, n;  // total:已接收总字节数;n:每次接收的字节数while ((n = recv(sockfd, response + total, 16384 - total - 1, 0)) > 0) {  // 循环接收数据total += n;  // 累加接收的字节数}response[total] = '\0';  // 给响应字符串添加结束符close(sockfd);  // 关闭socket释放资源// 从响应中提取 JSON 数据char* json_start = strstr(response, "{");  // 找到JSON数据的起始位置(第一个'{')char* json_end = strrchr(response, '}');   // 找到JSON数据的结束位置(最后一个'}')if (!json_start || !json_end) {  // 如果未找到JSON起止标志free(response);  // 释放响应缓冲区return NULL;  // 返回NULL表示失败}// 计算 JSON 数据的长度并复制size_t len = json_end - json_start + 2;  // 计算JSON数据长度(包含结束符)char* json = malloc(len);  // 为JSON数据分配独立内存if (!json) {  // 如果内存分配失败free(response);  // 释放响应缓冲区return NULL;  // 返回NULL表示失败}snprintf(json, len, "%s", json_start);  // 复制提取的JSON数据到新缓冲区free(response);  // 释放原始响应缓冲区return json;  // 返回提取的JSON数据
}// 获取天气信息(使用固定 IP:113.66.98.219)
void get_weather_by_fixed_ip() {// 固定 IP 地址:113.66.98.219const char* fixed_ip = "113.66.98.219";  // 定义要查询的固定IP地址// 构造天气查询路径(使用固定的 cityIp 参数)// 注意:这里移除了多余的 ip 参数,解决编译警告char path[1024];  // 存储API请求路径的缓冲区snprintf(path, sizeof(path),  "/?app=weather.today&cityIp=IP&appkey=AppKey&sign=Sign&format=json");                          // 拼接天气API的请求路径,包含固定IP和认证信息// 调用 HTTP 请求函数,获取天气的 JSON 响应char* json = http_get_json("api.k780.com", path);  // 发送HTTP请求并获取JSON响应if (!json) {  // 如果获取JSON失败printf("获取天气失败\n");  // 打印提示return;  // 退出函数}// 解析 JSON 数据cJSON* root = cJSON_Parse(json);  // 解析JSON字符串为cJSON对象if (!root) {  // 如果解析失败printf("JSON 解析失败: %s\n", cJSON_GetErrorPtr());  // 打印解析错误位置free(json);  // 释放JSON缓冲区return;  // 退出函数}// 检查 API 调用是否成功cJSON* success = cJSON_GetObjectItem(root, "success");  // 获取"success"字段(API调用状态)if (success && strcmp(success->valuestring, "1") != 0) {  // 如果调用失败(success不为"1")cJSON* msg = cJSON_GetObjectItem(root, "msg");  // 获取错误信息字段if (msg) printf("API 调用失败: %s\n", msg->valuestring);  // 打印错误信息else printf("API 调用失败: 未知错误\n");  // 无错误信息时的提示cJSON_Delete(root);  // 释放cJSON对象free(json);  // 释放JSON缓冲区return;  // 退出函数}// 提取并打印天气信息cJSON* result = cJSON_GetObjectItem(root, "result");  // 获取"result"字段(天气数据主体)if (result) {  // 如果天气数据存在printf("\n===== IP: %s 对应的天气信息 =====\n", fixed_ip);  // 打印标题cJSON* days = cJSON_GetObjectItem(result, "days");  // 获取日期字段if (days) printf("日期: %s\n", days->valuestring);  // 打印日期else printf("日期: 未获取到\n");  // 未获取到时的提示cJSON* weather = cJSON_GetObjectItem(result, "weather");  // 获取天气状况字段if (weather) printf("天气: %s\n", weather->valuestring);  // 打印天气状况else printf("天气: 未获取到\n");  // 未获取到时的提示cJSON* temperature = cJSON_GetObjectItem(result, "temperature");  // 获取温度字段if (temperature) printf("温度: %s\n", temperature->valuestring);  // 打印温度else printf("温度: 未获取到\n");  // 未获取到时的提示cJSON* wind = cJSON_GetObjectItem(result, "wind");  // 获取风向字段if (wind) printf("风向: %s\n", wind->valuestring);  // 打印风向else printf("风向: 未获取到\n");  // 未获取到时的提示cJSON* humidity = cJSON_GetObjectItem(result, "humidity");  // 获取湿度字段if (humidity) printf("湿度: %s\n", humidity->valuestring);  // 打印湿度else printf("湿度: 未获取到\n");  // 未获取到时的提示} else {  // 如果未找到天气数据printf("未找到天气数据\n");  // 打印提示}// 清理资源cJSON_Delete(root);  // 释放cJSON对象,避免内存泄漏free(json);  // 释放JSON缓冲区
}int main() {printf("正在查询固定 IP (113.66.98.219) 对应的天气...\n");  // 打印程序状态提示get_weather_by_fixed_ip();  // 调用函数查询天气return 0;  // 程序正常结束
}

把IP换成你所在的公网IP 

把AppKey和Sign换成对应获取天气平台API的

比如我用的是控制台 - NowAPI

二、编译

gcc 通过IP获取天气.c cJSON.c -o 通过IP获取天气 -lm

http://www.lryc.cn/news/613442.html

相关文章:

  • Oracle 关闭 impdp任务
  • Oracle 12c + Pl/Sql windows系统下表空间创建、迁移,dmp备份导入,数据库字符集更改
  • 图论(1):图数据结构
  • 攻防世界WEB(新手模式)2-2-upload1
  • 【YOLO学习笔记】YOLOv8详解解读
  • 工业相机使用 YOLOv8深度学习模型 及 OpenCV 实现目标检测简单介绍
  • Moses工具的配置和小语种平行语料训练SMT完整实现
  • 商城小程序怎么做?如何开发母婴用品商城小程序?
  • 前端三大核心要素以及前后端通讯
  • mysql_mcp_server_pro源码部署及启动报错新手指南:让智能体长出手来直接获取到最底层的数据
  • Linux ISCSI服务配置
  • 聚集索引VS非聚集索引:核心差异详解
  • 将Excel数据导入SQL Server数据库,并更新源表数据
  • 安卓Handler和Looper的学习记录
  • ArkTS: McPointChart
  • Debian系统 为账号添加sudo权限
  • 远程制作《最后生还者》中的Xsens动作捕捉技术
  • Maven分模块开发实战指南
  • Windows下安装SageAttention
  • 【CodeButty + 自制MCP】给AI装上翅膀,快速绘制思维导图
  • javaweb开发之会话_过滤器_监听器
  • EtherCAT时钟DC同步的三种模式
  • 项目构想|文生图小程序
  • OpenCV 入门教程:开启计算机视觉之旅
  • C语言memcpy函数详解:高效内存复制的实用工具
  • 【代码随想录day 14】 力扣 226.反转二叉树
  • 套接字编程UDP
  • 如何快速开发符合Matter标准的智能家居设备?
  • WindowsLinux系统 安装 CUDA 和 cuDNN
  • 什么是负载均衡,有哪些常见算法?