TypechoJoeTheme

至尊技术网

统计
登录
用户名
密码

基于C++的天气查询程序开发:网络API调用与JSON解析实战

2025-08-26
/
0 评论
/
2 阅读
/
正在检测是否收录...
08/26

引言

在现代软件开发中,网络API的调用与数据处理已成为程序员必备的核心技能。本文将详细介绍如何使用C++开发一个功能完整的天气查询程序,涵盖从网络请求到数据解析的全过程。这个项目不仅能帮助读者掌握C++网络编程技巧,还能深入理解RESTful API的工作原理。

开发环境准备

在开始编码前,我们需要搭建合适的开发环境:

cpp
// 必要的库文件

include

include <curl/curl.h> // 网络请求库

include <nlohmann/json.hpp> // JSON解析库

include

include // 用于格式化输出

开发环境配置要点:
1. 安装libcurl开发包(Ubuntu下使用sudo apt-get install libcurl4-openssl-dev
2. 添加JSON解析库(推荐使用nlohmann/json,单头文件设计,易于集成)

核心架构设计

1. 网络请求模块

网络请求是程序的基础功能,我们使用libcurl库实现:

cpp
class WeatherFetcher {
private:
static sizet WriteCallback(void* contents, sizet size, sizet nmemb, std::string* output) { sizet totalsize = size * nmemb; output->append((char*)contents, totalsize);
return total_size;
}

public:
std::string fetchWeatherData(const std::string& city) {
CURL* curl = curleasyinit();
std::string response;

    if (curl) {
        std::string api_url = "http://api.weatherapi.com/v1/current.json?key=YOUR_API_KEY&q=" + city;

        curl_easy_setopt(curl, CURLOPT_URL, api_url.c_str());
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

        CURLcode res = curl_easy_perform(curl);
        if (res != CURLE_OK) {
            std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
        }

        curl_easy_cleanup(curl);
    }

    return response;
}

};

2. JSON数据解析模块

获取到API响应后,我们需要解析JSON数据:

cpp
class WeatherParser {
public:
void parseAndDisplay(const std::string& jsonData) {
try {
auto json = nlohmann::json::parse(jsonData);

        std::cout << "=== 当前天气状况 ===" << std::endl;
        std::cout << "城市: " << json["location"]["name"] << std::endl;
        std::cout << "区域: " << json["location"]["region"] << std::endl;
        std::cout << "国家: " << json["location"]["country"] << std::endl;
        std::cout << "当地时间: " << json["location"]["localtime"] << std::endl;

        std::cout << "\n=== 气象数据 ===" << std::endl;
        std::cout << "温度: " << json["current"]["temp_c"] << "°C / " 
                  << json["current"]["temp_f"] << "°F" << std::endl;
        std::cout << "天气状况: " << json["current"]["condition"]["text"] << std::endl;
        std::cout << "风速: " << json["current"]["wind_kph"] << " km/h" << std::endl;
        std::cout << "湿度: " << json["current"]["humidity"] << "%" << std::endl;
        std::cout << "云量: " << json["current"]["cloud"] << "%" << std::endl;
        std::cout << "体感温度: " << json["current"]["feelslike_c"] << "°C" << std::endl;

    } catch (const std::exception& e) {
        std::cerr << "JSON解析错误: " << e.what() << std::endl;
    }
}

};

完整程序实现

将各模块组合起来,形成完整的天气查询程序:

cpp
int main() {
// 初始化libcurl(全局只需一次)
curlglobalinit(CURLGLOBALDEFAULT);

WeatherFetcher fetcher;
WeatherParser parser;

std::string city;
std::cout << "请输入要查询的城市名称: ";
std::getline(std::cin, city);

if (!city.empty()) {
    std::string weatherData = fetcher.fetchWeatherData(city);
    parser.parseAndDisplay(weatherData);
} else {
    std::cout << "城市名称不能为空!" << std::endl;
}

// 清理libcurl资源
curl_global_cleanup();
return 0;

}

进阶功能扩展

1. 错误处理增强

cpp
enum class WeatherError {
NoError,
NetworkError,
InvalidAPIKey,
CityNotFound,
ParseError
};

WeatherError checkForErrors(const std::string& response) {
if (response.empty()) return WeatherError::NetworkError;

try {
    auto json = nlohmann::json::parse(response);
    if (json.contains("error")) {
        if (json["error"]["code"] == 1002) return WeatherError::InvalidAPIKey;
        if (json["error"]["code"] == 1006) return WeatherError::CityNotFound;
    }
} catch (...) {
    return WeatherError::ParseError;
}

return WeatherError::NoError;

}

2. 多城市批量查询

cpp
void batchQuery(const std::vector& cities) {
WeatherFetcher fetcher;
WeatherParser parser;

for (const auto& city : cities) {
    std::cout << "\n查询城市: " << city << std::endl;
    std::string weatherData = fetcher.fetchWeatherData(city);

    WeatherError err = checkForErrors(weatherData);
    if (err != WeatherError::NoError) {
        handleWeatherError(err);
        continue;
    }

    parser.parseAndDisplay(weatherData);
}

}

API选择与密钥管理

推荐的天气API服务

  1. WeatherAPI.com(本文示例使用)
  2. OpenWeatherMap
  3. AccuWeather
  4. 中国气象局API(国内用户)

安全存储API密钥

cpp
class APIConfig {
private:
std::string apiKey;

public:
APIConfig() {
// 从环境变量或配置文件中读取密钥
const char* envKey = std::getenv("WEATHERAPIKEY");
apiKey = envKey ? envKey : "";

    if (apiKey.empty()) {
        // 尝试从配置文件读取
        std::ifstream configFile("config.json");
        if (configFile.is_open()) {
            try {
                nlohmann::json config;
                configFile >> config;
                apiKey = config["api_key"];
            } catch (...) {
                // 处理异常
            }
        }
    }
}

std::string getKey() const { 
    if (apiKey.empty()) {
        throw std::runtime_error("API密钥未配置");
    }
    return apiKey; 
}

};

性能优化建议

  1. 缓存机制:对频繁查询的城市天气数据进行缓存cpp
    std::unorderedmap<std::string, std::pair<std::string, timet>> weatherCache;

std::string getCachedWeather(const std::string& city) {
auto it = weatherCache.find(city);
if (it != weatherCache.end() && (time(nullptr) - it->second.second) < 3600) {
return it->second.first; // 1小时内缓存有效
}
return "";
}

  1. 异步请求:使用多线程处理多个城市查询cpp

include

include

std::vector<std::future> asyncFetches;
for (const auto& city : cities) {
asyncFetches.push_back(std::async(std::launch::async, &fetcher, city {
return fetcher.fetchWeatherData(city);
}));
}

  1. 连接池管理:重用CURL句柄提升性能

跨平台兼容性处理

针对不同操作系统的适配方案:

cpp

ifdef _WIN32

// Windows特定初始化
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);

endif

// 程序退出时

ifdef _WIN32

WSACleanup();

endif

单元测试建议

使用Google Test框架编写测试用例:

cpp
TEST(WeatherParserTest, BasicParsing) {
WeatherParser parser;
std::string testJson = R"({
"location": {
"name": "Beijing",
"country": "China"
},
"current": {
"temp_c": 25.0
}
})";

testing::internal::CaptureStdout();
parser.parseAndDisplay(testJson);
std::string output = testing::internal::GetCapturedStdout();

EXPECT_TRUE(output.find("Beijing") != std::string::npos);
EXPECT_TRUE(output.find("25.0") != std::string::npos);

}

部署与打包

Linux系统打包

  1. 创建Makefile文件:makefile
    CXX = g++
    CXXFLAGS = -std=c++11 -Wall
    LIBS = -lcurl

weather: main.o
$(CXX) $(CXXFLAGS) -o weather main.o $(LIBS)

main.o: main.cpp
$(CXX) $(CXXFLAGS) -c main.cpp

clean:
rm -f *.o weather

  1. 打包为deb/rpm包(可选)

Windows系统打包

  1. 使用Visual Studio创建解决方案
  2. 配置libcurl依赖
  3. 生成安装程序(可使用NSIS或Inno Setup)

总结

朗读
赞(0)
版权属于:

至尊技术网

本文链接:

https://www.zzwws.cn/archives/36760/(转载时请注明本文出处及文章链接)

评论 (0)

人生倒计时

今日已经过去小时
这周已经过去
本月已经过去
今年已经过去个月

最新回复

  1. 强强强
    2025-04-07
  2. jesse
    2025-01-16
  3. sowxkkxwwk
    2024-11-20
  4. zpzscldkea
    2024-11-20
  5. bruvoaaiju
    2024-11-14

标签云