C++天气预报小软件

前言:这个东西是八月份自己捣鼓着玩的 现记录下

需要解决的问题:
1.选择对应的接口(稳定,最好使用官方提供的)
2.获取数据
2.对返回数据的处理


问题1:天气接口的获取
=>通过城市名 来获取当前城市的温度以及未来一周的天气变化(Json数据)    [返回数据为乱码]
接口:http://wthrcdn.etouch.cn/weather_mini?city=北京市

=>通过城市ID来获取当前城市温度以及未来一周的天气变化(Json数据)        [返回数据为乱码]
接口:http://wthrcdn.etouch.cn/weather_mini?citykey=101010100

城市ID:

=> 通过城市获取当前的一些信息(返回XML数据)    [返回数据正确]
接口:http://wthrcdn.etouch.cn/WeatherApi?city=北京市

=> 通过城市id(101010100)获取当前城市温度、湿度、空气质量主要参数指数、警告、昨日天气、未来天气、日出日落时间((⊙﹏⊙)b)(XML数据):
接口:http://wthrcdn.etouch.cn/WeatherApi?citykey=101010100

=> 良心API 提供了PM2.5、温度、湿度、ip查询、快递查询接口
接口:http://api.help.bj.cn/api/
http://api.help.bj.cn/apis/weather6d/?id=101280601    //根据ID来访问的一个接口

问题2 如何从页面上获取到返回数据

CInternetSession session(L"HttpClient");
    CString url = L"http://api.help.bj.cn/apis/weather6d/?id=101060101";
    //CString url = L"http://wthrcdn.etouch.cn/weather_mini?city=北京市";
    CHttpFile* pfile = (CHttpFile *)session.OpenURL(url);

    DWORD dwStatusCode;
    pfile->QueryInfoStatusCode(dwStatusCode);
    CString BackStringData = L"";
    if (dwStatusCode == HTTP_STATUS_OK)
    {
        CString data = L"";
        while (pfile->ReadString(data))    
        {
            BackStringData += data;
        }
    }
    pfile->Close();
    delete pfile;
    session.Close();

补充:
使用libcurl提供的接口 更快的访问或者上传数据

libcurl在https的协议下报错
原因:安装openssl

问题3 获取的数据都是乱码的,但是写入文本可以正常显示
这个问题出现的原因:因为系统的编码方式与得到文件的编码方式不同导致的乱码
解决方案:根据我们得到数据的编码是 UTF8的
在UNICODE编码下:将UTF8转换成Unicode即可
在多字节编码下:将UTF8转换为ASCII码即可

问题3 对返回数据的处理
=> 处理Json数据(解析Json数据)
引入一个Json开源的库 在Git上搜索Json就可以找到了 下载之
1.8.4 这是我下载的版本 
在文件夹 makefiles -> msvc2010 -> jsoncpp.sln 一波操作
编译生成一个 lib_json.lib (不同版本可能会有差异,反正就会生成一个lib文件)
带上lib文件 和 include目录下的 json文件夹
在需要用到Json的工程下 包含这两个(lib文件 和 json文件夹)
然后引入:
    包含:
    VC++ 目录 -> 库目录    (说明:这个路径是lib的包含路径)
    C/C++ -> 常规 -> 附加包含目录 (说明:这个路径是json文件夹 包含的路径,json文件夹中包含各种头文件)
    链接器 -> 输入 -> 附加依赖项 加入 lib_json.lib    (说明:就是你生成的lib的名字)

这样在工程中加入 #include "json.h"
就可以使用Json了
例子:

std::string strResult = "{\"data\":{\"yesterday\":{\"date\":\"27日 星期一\", \"temphigh\" : \"25\", \"wind\" : \"西风\"}},\"city\":\"长春\" }";
const char *str = strResult.c_str();
Json::CharReaderBuilder b;
Json::CharReader* reader(b.newCharReader());
Json::Value root;
JSONCPP_STRING errs;

bool ok = reader->parse(str, str + strlen(str), &root, &errs);
if (ok&&errs.size() == 0)  // reader将Json字符串解析到root,root将包含Json里所有子元素
{
    std::string CityName = root["city"].asString();  // 得到city = 长春
    std::string code = root["data"]["yesterday"]["date"].asString(); // 得到 27日 星期一
    cout << "CityName: " << CityName << endl;
    cout << "code: " << code << endl;
}
delete reader;    //这个是一定得要的 不然会内存泄漏

解析结果
CityName: 长春
code: 27日 星期一

demo:TestJsonData

遇到类似包含数组的情况 解决办法
例子:strResult : {“key1″:”value1″,”array”:[{"key2":"value2"},{"key2":"value3"},{"key2":"value4"}]}
这种情况怎么解析array
解决办法:
 

const char *str = strResult.c_str();
Json::CharReaderBuilder b;
Json::CharReader* reader(b.newCharReader());
Json::Value root;
JSONCPP_STRING errs;

bool ok = reader->parse(str, str + strlen(str), &root, &errs);
if (ok&&errs.size() == 0)  // reader将Json字符串解析到root,root将包含Json里所有子元素
{
    const Json::Value JsonArray = root["array"];
    for (int i=0; i<array.size(); ++array)
    {
        string strKey2 = JsonArray[i]["Key2"].asString();
        cout<<strKey2<<endl;    //输出每个Key2的值
        
    }
    cout << "CityName: " << CityName << endl;
    cout << "code: " << code << endl;
}
delete reader;

//解析Json中包含数组的格式
//参考:https://www.cnblogs.com/ytjjyy/archive/2012/04/17/2453348.html

=> 处理XML数据(解析XML)
在Git上找到TinyXML 下载之
工程tinyxml2 包含两个文件 tinyxml2.cpp 和 tinyxml2.h
可以批量编译 可选 32位和64位的DLL 或者 LIB进行编译
这里我选择的是lib 得到 tinyxml2.lib 这个文件
然后包含 tinyxml2.h 两个文件一起导入需要使用的工程中
导入方法同上
例子 有文件

<Class name="计算机软件班">
    <Students>
        <student name="张三" studentNo="13031001" sex="男" age="22">
            <phone>88208888</phone>
            <address>sssssss</address>
        </student>
        <student name="李四" studentNo="13031002" sex="男" age="20">
            <phone>88206666</phone>
            <address>2222222</address>
        </student>
    </Students>
</Class>
tinyxml2::XMLDocument *myDocument = new tinyxml2::XMLDocument();
myDocument->LoadFile("ssss.xml");
tinyxml2::XMLElement *rootElement = myDocument->RootElement(); //Class
tinyxml2::XMLElement *studentsElement = rootElement->FirstChildElement(); //Students
tinyxml2::XMLElement *studentElement = studentsElement->FirstChildElement(); //Student

while (studentElement)
{
    const tinyxml2::XMLAttribute *attribute = studentElement->FirstAttribute();    //
    while (attribute)
    {
        std::wstring strTemp = UTF8ToUnicode(attribute->Value());
        std::string strName = UnicodeToANSI(strTemp);
        std::cout << attribute->Name() << " : " << strName.c_str() << std::endl;
        attribute = attribute->Next();
    }
    tinyxml2::XMLElement* phoneElement = studentElement->FirstChildElement();
    std::cout << "phone" << " : " << phoneElement->GetText() << std::endl;
    tinyxml2::XMLElement* addressElement = phoneElement->NextSiblingElement();
    std::cout << "address" << " : " << phoneElement->GetText() << std::endl;
    studentElement = studentElement->NextSiblingElement();
}



补充一些文本的转换方法

std::string UnicodeToUTF8(const std::wstring& str)
{
    int iTextLen = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, NULL, 0, NULL, NULL);
    char *pElementText = new char[iTextLen + 1];
    memset((void*)pElementText, 0, sizeof(char) * (iTextLen + 1));
    ::WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, pElementText, iTextLen, NULL, NULL);
    std::string strText = pElementText;
    delete[] pElementText;
    return strText;
}

std::string UnicodeToANSI(const std::wstring& str)
{
    char *pElementText;
    int iTextLen = WideCharToMultiByte(CP_ACP, 0, str.c_str(), -1, NULL, 0, NULL, NULL);
    pElementText = new char[iTextLen + 1];
    memset((void*)pElementText, 0, sizeof(char) * (iTextLen + 1));
    ::WideCharToMultiByte(CP_ACP, 0, str.c_str(), -1, pElementText, iTextLen, NULL, NULL);
    std::string strText;
    strText = pElementText;
    delete[] pElementText;
    return strText;
}

std::wstring ANSIToUnicode(const std::string& str)
{
    int unicodeLen = ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0);
    wchar_t *pUnicode;
    pUnicode = new  wchar_t[unicodeLen + 1];
    memset(pUnicode, 0, (unicodeLen + 1) * sizeof(wchar_t));
    ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, (LPWSTR)pUnicode, unicodeLen);
    std::wstring  rt;
    rt = (wchar_t*)pUnicode;
    delete  pUnicode;
    return  rt;
}

std::wstring UTF8ToUnicode(const std::string& str)
{
    int unicodeLen = ::MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0);
    wchar_t *pUnicode = new  wchar_t[unicodeLen + 1];
    memset(pUnicode, 0, (unicodeLen + 1) * sizeof(wchar_t));
    ::MultiByteToWideChar(CP_UTF8,0,str.c_str(),-1,(LPWSTR)pUnicode,unicodeLen);
    std::wstring rt = (wchar_t*)pUnicode;
    delete  pUnicode;
    return  rt;
}


到这里预备知识都已就绪 下面开始进入代码

核心代码:

GetWeatherDlg.h


// GetWeatherDlg.h: 头文件
//

#pragma once
#include <map>
#include <string>
#include <vector>

// CGetWeatherDlg 对话框
class CGetWeatherDlg : public CDialogEx
{
// 构造
public:
	CGetWeatherDlg(CWnd* pParent = nullptr);	// 标准构造函数

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_GETWEATHER_DIALOG };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持

public:
	void InitCityData();
	std::string DelBlank(const std::string &str);
	void ParseJsonData(std::string str);
	void GetPageData(const CString &str);
	void ShowResult();
	void InitDateStruct();
	void GetGb2312Data(const CString &str);

// 实现
protected:
	HICON m_hIcon;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnBnClickedBtnExit();
	virtual BOOL PreTranslateMessage(MSG* pMsg);
	afx_msg void OnBnClickedBtnSearch();
	std::wstring StringToWString(const std::string & str);
	std::wstring UTF8ToUnicode(const std::string& str);


	

private:
	std::map<std::string,std::string>m_mapCity;
	typedef struct Struct
	{
		CString CityName;
		CString LifeSuggestion;
		CString CurrentTemp;
		std::vector<CString> vctDate;
		std::vector<CString> TempHight;
		std::vector<CString> Templow;
		std::vector<CString> Wind;
		std::vector<CString> Weather;
	}WeatherData;

	WeatherData m_WeatherData;
public:
	CButton m_SearchBtn;
	//afx_msg void OnEnChangeEditShowresult();
};

GetWeatherDlg.cpp


// GetWeatherDlg.cpp: 实现文件
//

#include "stdafx.h"
#include "GetWeather.h"
#include "GetWeatherDlg.h"
#include "afxdialogex.h"
#include <afxinet.h>
#include <string>
#include "json.h"
#include <iostream>
#include <fstream>
#include "MyIconv.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#ifndef ICONV_CONST
# define ICONV_CONST const
#endif

// CGetWeatherDlg 对话框
void GetIp02();

std::wstring ANSIToUnicode(const std::string& str)
{
	int len = str.length();
	int unicodeLen = ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0);
	wchar_t *pUnicode;
	pUnicode = new  wchar_t[unicodeLen + 1];
	memset(pUnicode, 0, (unicodeLen + 1) * sizeof(wchar_t));
	::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, (LPWSTR)pUnicode, unicodeLen);
	std::wstring  rt;
	rt = (wchar_t*)pUnicode;
	delete  pUnicode;
	return  rt;
}

//GB2312到UTF-8的转换 
std::string GB2312ToUTF8(const std::string strGb2312)
{
	int len = MultiByteToWideChar(CP_ACP, 0, strGb2312.c_str(), -1, NULL, 0);
	wchar_t* wstr = new wchar_t[len + 1];
	memset(wstr, 0, len + 1);
	MultiByteToWideChar(CP_ACP, 0, strGb2312.c_str(), -1, wstr, len);
	len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
	char* str = new char[len + 1];
	memset(str, 0, len + 1);
	WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);
	if (wstr) delete[] wstr;
	return str;
}


CGetWeatherDlg::CGetWeatherDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_GETWEATHER_DIALOG, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CGetWeatherDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_BTN_SEARCH, m_SearchBtn);
}

void CGetWeatherDlg::InitCityData()
{
	m_mapCity.swap(std::map<std::string, std::string>());
	//读取数据
	std::ifstream in("CityName.dat");
	if (!in.is_open())
	{
		//cout << "Error opening file";
		//LOG(ERROR) << "Error opening file";
		AfxMessageBox(L"配置文件不存在");
		return;
	}
	std::string strCityCode = "";
	std::string strCityName = "";
	//map<string, string> mapcity;

	//LOG(INFO) << "数据开始处理";
	while (!in.eof())
	{
		char buffer[128] = { 0 };
		in.getline(buffer, 128);
		std::string strTemp = buffer;
		int pos = strTemp.find(',');
		strCityCode = strTemp.substr(0, pos);
		strCityName = strTemp.substr(pos+1);
		m_mapCity.insert(std::pair<std::string,std::string>(strCityCode, strCityName));
	}
	//LOG(INFO) << "数据处理完成";
}

std::string CGetWeatherDlg::DelBlank(const std::string & str)
{
	std::string strSource = str;
	int pos = strSource.find(' ');
	strSource = strSource.substr(0, pos);
	return strSource;
}

void CGetWeatherDlg::ParseJsonData(std::string str)
{
	//对结构体中的数据进行处理
	InitDateStruct();

	//使用Json来解析得到的数据
	Json::CharReaderBuilder b;
	Json::CharReader* reader(b.newCharReader());
	Json::Value JsonValue;
	JSONCPP_STRING errs;
	reader->parse(&str[0], &str[str.length()], &JsonValue, &errs);

	//城市名
	std::string cityname = JsonValue["data"]["city"].asString();
	m_WeatherData.CityName = UTF8ToUnicode(cityname).c_str();

	//生活建议
	std::string suggestion = JsonValue["data"]["life"].asString();
	m_WeatherData.LifeSuggestion = UTF8ToUnicode(suggestion).c_str();

	//体感温度
	std::string currenttemp = JsonValue["data"]["temp"].asString();
	m_WeatherData.CurrentTemp = UTF8ToUnicode(currenttemp).c_str();

	//未来几天的天气 日期 + 温度 + 天气 + 风向
	const Json::Value arrayobj = JsonValue["data"]["forecast"];	//取一个数组中的数据
	for (size_t i = 0; i < arrayobj.size(); ++i)
	{
		std::string strDate = arrayobj[i]["date"].asString();
		m_WeatherData.vctDate.push_back(UTF8ToUnicode(strDate).c_str());

		std::string strtemphigh = arrayobj[i]["temphigh"].asString();
		m_WeatherData.TempHight.push_back(UTF8ToUnicode(strtemphigh).c_str());

		std::string strtemplow = arrayobj[i]["templow"].asString();
		m_WeatherData.Templow.push_back(UTF8ToUnicode(strtemplow).c_str());

		std::string strWind = arrayobj[i]["wind"].asString();
		m_WeatherData.Wind.push_back(UTF8ToUnicode(strWind).c_str());

		std::string strWeather = arrayobj[i]["weather"].asString();
		m_WeatherData.Weather.push_back(UTF8ToUnicode(strWeather).c_str());
	}

	delete reader;	//需要释放掉 否则会内存泄漏
}

BEGIN_MESSAGE_MAP(CGetWeatherDlg, CDialogEx)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BTN_EXIT, &CGetWeatherDlg::OnBnClickedBtnExit)
	ON_BN_CLICKED(IDC_BTN_SEARCH, &CGetWeatherDlg::OnBnClickedBtnSearch)
END_MESSAGE_MAP()


// CGetWeatherDlg 消息处理程序

BOOL CGetWeatherDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	InitCityData();
	GetDlgItem(IDC_EDIT_CITYNAME)->SetWindowTextW(L"深圳");
	(CEdit *)GetDlgItem(IDC_EDIT_CITYNAME)->SetFocus();
	return FALSE;
	//return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CGetWeatherDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CGetWeatherDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

void CGetWeatherDlg::OnBnClickedBtnExit()
{
	//TODO: 在此添加控件通知处理程序代码
	InitDateStruct();
	OnCancel();
}

BOOL CGetWeatherDlg::PreTranslateMessage(MSG* pMsg)
{
	// TODO: 在此添加专用代码和/或调用基类
	if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE)
		return FALSE;
	if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN)	//和点击查询按钮绑定在一起 就简单的实现了点击回车键 就查询的功能
	{
		//AfxMessageBox(L"你点击了回车键");	
		OnBnClickedBtnSearch();	//点击Enter进行查询
		return FALSE;
	}
	return CDialogEx::PreTranslateMessage(pMsg);
}

//通过输入的城市名称 来进行查询
void CGetWeatherDlg::OnBnClickedBtnSearch()
{
	m_SearchBtn.EnableWindow(FALSE);
	CString CityName = L"";
	GetDlgItem(IDC_EDIT_CITYNAME)->GetWindowText(CityName);

	if (CityName.IsEmpty())
	{
		AfxMessageBox(L"输入为空,请输入城市编码");
		(CButton*)GetDlgItem(IDC_BTN_SEARCH)->EnableWindow(TRUE);
		return;
	}

	USES_CONVERSION;
	std::string CityNamestr = W2A(CityName);
	std::string strCityId = "";
	for (auto ptr : m_mapCity)
	{
		std::string strCity = DelBlank(ptr.second);
		if (CityNamestr == strCity)
		{
			strCityId = ptr.first;
		}
	}

	if (strCityId == "")
	{
		AfxMessageBox(L"输入的城市不存在,请重新输入");
		CEdit *ptr = (CEdit*)GetDlgItem(IDC_EDIT_CITYNAME);
		ptr->SetWindowText(L"");
		ptr->Invalidate(TRUE);
		return;
	}

	std::wstring wcitycode = StringToWString(strCityId);
	GetPageData(wcitycode.c_str());	//获取数据为UTF8的数据

	//Debug …… 测试获取到的GB2312数据如何处理
	//GetGb2312Data(wcitycode.c_str());
	//Debug 测试结果 获取网页数据可能有误 无法转换成正确的编码方式 显示结果

}

//将UTF8的数据转换为Unicode
std::wstring CGetWeatherDlg::UTF8ToUnicode(const std::string& str)
{
	int len = str.length();
	int unicodeLen = ::MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0);
	wchar_t *pUnicode;
	pUnicode = new  wchar_t[unicodeLen + 1];
	memset(pUnicode, 0, (unicodeLen + 1) * sizeof(wchar_t));
	::MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, (LPWSTR)pUnicode, unicodeLen);
	std::wstring  rt;
	rt = (wchar_t*)pUnicode;
	delete  pUnicode;
	return  rt;
}

//将Unicode转换成ASCII
std::string UnicodeToANSI(const std::wstring& str)
{
	char *pElementText;
	int iTextLen = WideCharToMultiByte(CP_ACP, 0, str.c_str(), -1, NULL, 0, NULL, NULL);
	pElementText = new char[iTextLen + 1];
	memset((void*)pElementText, 0, sizeof(char) * (iTextLen + 1));
	::WideCharToMultiByte(CP_ACP, 0, str.c_str(), -1, pElementText, iTextLen, NULL, NULL);
	std::string strText;
	strText = pElementText;
	delete[] pElementText;
	return strText;
}


//得到UTF8的数据
void CGetWeatherDlg::GetPageData(const CString &strUrl)
{
	CString url = L"http://api.help.bj.cn/apis/weather6d/?id=";		//返回值 可以使用
	url += strUrl;

	CInternetSession session;
	CHttpFile* pFile = (CHttpFile*)session.OpenURL(url);

	DWORD dwStatusCode;
	pFile->QueryInfoStatusCode(dwStatusCode);
	
	CString Getstring = L"";
	if (dwStatusCode == HTTP_STATUS_OK)
	{
		CString strTemp = L"";
		while (pFile->ReadString(strTemp))
		{
			Getstring += strTemp;
		}
	}
	session.Close();
	pFile->Close();
	delete pFile;		//这个必须得有 否则会导致内存泄漏
	
	std::string strtemp = (const char *)Getstring.GetString();
	ParseJsonData(strtemp);	//解析数据
	ShowResult();
}

void CGetWeatherDlg::GetGb2312Data(const CString &str)
{
	m_SearchBtn.EnableWindow();
	CString url = L"http://wthrcdn.etouch.cn/weather_mini?citykey=";	//返回值
	url += str;

	CInternetSession session;
	CHttpFile* pFile = (CHttpFile*)session.OpenURL(url);

	DWORD dwStatusCode;
	pFile->QueryInfoStatusCode(dwStatusCode);
	CString Getstring = L"";
	if (dwStatusCode == HTTP_STATUS_OK)
	{
		CString strTemp = L"";
		while (pFile->ReadString(strTemp))
		{
			Getstring += strTemp;
		}
	}
	int length = Getstring.GetLength();
	std::wstring WGetString = Getstring;
	session.Close();
	pFile->Close();
	delete pFile;		//这个必须得有 否则会导致内存泄漏

	std::string strSource = (const char *)WGetString.c_str();
	//char out[1024] = { 0 };
	//char *charSource = (char*)strSource.c_str();
	 gb2312-->utf-8
	//CodeConverter cc2 = CodeConverter("gb2312", "utf-8");
	//cc2.convert((char *)WGetString.c_str(), length, out, 1024);
	
	//debug*************开始*****************测试使用转换方法 不行
	//std::string strOut = GB2312ToUTF8(strSource);
	//std::wstring strShow = UTF8ToUnicode(strOut);
	//AfxMessageBox(strShow.c_str());
	//debug*************结束********************

	//WGetString
	AfxMessageBox(WGetString.c_str());

}

void CGetWeatherDlg::InitDateStruct()
{
	m_WeatherData.CityName = L"";
	m_WeatherData.LifeSuggestion = L"";
	m_WeatherData.CurrentTemp = L"";
	m_WeatherData.vctDate.swap(std::vector<CString>());
	m_WeatherData.TempHight.swap(std::vector<CString>());
	m_WeatherData.Templow.swap(std::vector<CString>());
	m_WeatherData.Wind.swap(std::vector<CString>());
	m_WeatherData.Weather.swap(std::vector<CString>());
}

std::wstring CGetWeatherDlg::StringToWString(const std::string & str)
{
	int num = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0);
	wchar_t *wide = new wchar_t[num];
	MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, wide, num);
	std::wstring w_str(wide);
	delete[] wide;
	return w_str;
}

void CGetWeatherDlg::ShowResult()
{
	//获取当前的时间段
	time_t t = time(0);
	char temp[64];
	std::string strYearMonth;
	tm *Time = localtime(&t);
	strftime(temp, sizeof(temp), "%Y年%m月", Time); //格式化时间输出 %Y-%m-%d %H:%M:%S
	strYearMonth = temp;
	std::wstring DateHead = StringToWString(strYearMonth);

	/*
	显示格式:
	城市:
	日期
	天气
	气温
	风向
	体感温度
	建议
	*/
	CString strShowResult = L"";
	strShowResult += m_WeatherData.CityName;
	strShowResult += L"\r\n";
	strShowResult += DateHead.c_str() + m_WeatherData.vctDate[0];
	strShowResult += L"\r\n";
	strShowResult += L"天气: " + m_WeatherData.Weather[0];
	strShowResult += L"\r\n";
	strShowResult += L"最高温度: " + m_WeatherData.TempHight[0];
	strShowResult += L"℃";
	strShowResult += L"\r\n";
	strShowResult += L"最低温度: " + m_WeatherData.Templow[0];
	strShowResult += L"℃";
	strShowResult += L"\r\n";
	strShowResult += L"风向: " + m_WeatherData.Wind[0];
	strShowResult += L"\r\n";
	strShowResult += L"当前温度: " + m_WeatherData.CurrentTemp;
	strShowResult += L"℃";
	strShowResult += L"\r\n";
	strShowResult += L"建议: " + m_WeatherData.LifeSuggestion;

	CEdit *ptr = (CEdit*)GetDlgItem(IDC_EDIT_ShowResult);
	ptr->SetWindowTextW(strShowResult);
	m_SearchBtn.EnableWindow();
}

//得到简体中文 GB2312 这里需要转换为Unicode
void GetIp02()
{
	//CString url = L"http://wthrcdn.etouch.cn/weather_mini?citykey=101010100";		//得到简体中文 GB2312 所以需要转换为Unicode进行显示
	//CString url = L"http://ip.dnsexit.com/";		//61.144.174.130
	CString url = L"http://wthrcdn.etouch.cn/WeatherApi?citykey=101010100";	//XML文件

	CInternetSession session(L"Microsoft Internet Browser");
	CHttpFile* pFile = (CHttpFile*)session.OpenURL(url);

	DWORD dwStatusCode;
	pFile->QueryInfoStatusCode(dwStatusCode);
	CString content;
	//std::string GetString = "";
	std::wstring GetString = L"";
	//std::wstring GetString = L"";

	if (dwStatusCode == HTTP_STATUS_OK)
	{
		//CString strTemp = L"";
		//while (pFile->ReadString(strTemp))
		//	content += strTemp;

		wchar_t strBuff[512] = { 0 };
		while (pFile->Read((void*)strBuff, 512))
		{
			GetString += strBuff;
		}
	}
	session.Close();
	pFile->Close();
	delete pFile;		//这个必须得有 否则会导致内存泄漏

	//size_t length = content.GetLength();
	//AfxMessageBox(content);
	//std::wstring wstrResult = GB2312ToUnicode((const char*)content.GetString());		//GB2312转换成Unicode 进行显示
	//std::wstring wstrResult = UTF8ToUnicode((const char*)content.GetString());		//GB2312转换成Unicode 进行显示

	//std::wstring wstrResult = UTF8ToUnicode(GetString);
	//std::string stringResult = UnicodeToANSI(wstrResult);

	CFile file;
	bool success = file.Open(L"Test.txt", CFile::modeWrite | CFile::modeCreate);
	if (!success)
	{
		AfxMessageBox(_T("文件创建有误……"));
		return;
	}
	file.Write(GetString.c_str(), GetString.length());
	file.Close();

	AfxMessageBox(L"保存数据结束");

	//AfxMessageBox(wstrResult.c_str());
}

最后运行效果如下:

 

最后带上整个工程的百度云地址:

链接:https://pan.baidu.com/s/1AkdWcYJOKlsflyouwBk4RA 
提取码:al87 

  • 8
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
用c++/qt写的项目,可供自己学习,项目都经测试过,真实可靠,请放心使用。Qt支持 Windows、Linux/Unix、Mac OS X、Android、BlackBerry、QNX等多种平台,并为这些不同的平台提供了统一的开发环境。 面向对象 C++是完全面向对象的,这一点和Objective-c等在开发很相似。而Qt又是基于C++一种语言的扩展,大家都知道C++ 有快速、简易、面向对象等很多优点,所以Qt自然也继承者C++这些的优点。 Qt良好的封装机制使得Qt的模块化程度非常高,可重用性较好,对用户开发来货是非常方便的。Qt提供一种为signals/slots(信号和槽) 的安全类型来替代callback,使得各个元件之间的协同工作变得十分简单。 丰富的API Qt包括多达 250 个以上的 C++ 类,还提供基于模板的 collections, serialization, file, I/Odevice, directory management, date/time 类。甚至还包括正则表达式的处理功能。 支持 2D/3D 图形渲染,支持 OpenGL。 大量的开发文档。 XML支持 Webkit 引擎的集成,可以实现本地界面与Web内容的无缝集成, 但是真正使得 Qt 在自由软件界的众多 Widgets (如 Lesstif,Gtk,EZWGL,Xforms,fltk 等等)中脱颖而出的还是基于 Qt 的重量级软件 KDE。 信号和槽机制 Qt提供了信号和槽机制用于完成见面操作的响应,是完成任意两个Qt对象之通信机制。其中,信号会在某个特定情况或动作下被触动,槽是等同于接受并处理信号的函数。 为什么方法不是直接调用的。中间用到 Signal 和槽机制不是多此一举? 其实在我们生活也是一样,老板级别的好说话,老板给助理分派任务也好说话,但是助理给老板分任务,可想而知会有什么后果,在以前的统治阶层肯定不允许这样的事发生。所以在分层思想中,我们所调用的函数也是这样的,上层可以调用下层和同一层的函数,下层函数不可以调用上层函数,否则程序的层次性会被打破,导致结构错综复杂,难以维护和管理。 那么怎样才能做到向上管理呢,有任务分配给老板怎么办? 老板会设立一个机构,也就是一个函数,用无限循环来查询助理的状态,如果助理真的有事情,这个机构就把这消息拿到老板来处理。但是这种处理方式显得有些复杂,我们想要的简单明了的方式是,如果助理有事件发生,可以直接调用老板函数处理。 说了这么多其实就是想说,信号和槽的最大优势在于,它完善了程序分层的思想,可以在不改变程序的层次性的情况下,完成由下层到上层的调用。在下层发出一个 Signal,这时上层与其想关联的 Slot 函数就会响应。
### 回答1: c++ qt天气预报项目是一个基于qt框架的气象应用程序,主要功能是提供准确的天气信息查询服务。它具有直观的用户界面,可设置城市、天气、温度、湿度、气压等信息,还可显示未来几天的天气预报,方便用户随时了解天气情况。 在实现中,项目主要分为两个部分:前端和后端。前端主要负责展示数据和用户交互,使用qt的QML语言、JavaScript和CSS等技术进行布局和设计。后端主要负责实现数据的获取和处理,使用qt的C++语言、网络通信和解析技术,从网络上获取数据,并进行解析与处理。 在该项目中,通过网络请求获得实时天气信息,如空气质量、温度、湿度、气压等,并根据用户设置的城市信息,显示对应的天气信息。同时,项目还提供城市搜索、切换、添加、删除等功能,并支持开机自启动。 此外,项目还包含了数据缓存和网络异常处理功能,当网络异常时,项目可以显示错误信息,并提示用户检查网络连接,保证用户能够正常使用。 总的来说,C++ qt天气预报项目是一款非常实用的天气应用程序,具有简单易用、界面美观、功能实用等特点,帮助用户时刻掌握天气情况,是一款非常实用和有用的工具。 ### 回答2: C++ Qt 天气预报项目是一个基于 Qt 框架开发的一款天气预报应用程序。该项目主要利用了 Qt 的 QWidget 和 QWebKit 组件来实现应用程序的界面和数据获取功能。在编写程序界面时,采用了 Qt Designer 工具进行设计,通过信号和槽机制实现用户交互和数据实时刷新。 该应用程序能够自动获取用户所在地区的天气信息,并展示当前天气情况、未来几天的天气预报等相关信息。在数据获取方面,通过 WebView 组件实现对天气网站的模拟访问,获取天气数据并进行解析和处理,最终将数据展示在界面上。 除了基本的天气信息展示功能外,该应用程序还具有自定义城市、多城市查询、背景图片更换等一些实用的功能。在多城市查询方面,用户可以添加多个城市进行查询,并支持切换城市信息。在背景图片更换方面,用户可以选择不同的背景主题,从而实现界面个性化定制。 在代码实现方面,该项目重点涉及信号和槽机制、数据处理和展示等方面的学习和应用。整个程序采用模块化架构,具有灵活性和可扩展性,非常适合初学者进行 Qt 编程练习。该项目还具有实际应用价值,能够帮助用户随时获取所在地区及其他城市的天气信息,使用户出行更加方便。 ### 回答3: C++ Qt 天气预报项目是一个使用C++ 编程语言,通过Qt GUI程序库和天气API开发的一款实用工具。它可以实现天气查询,每日天气信息的更新,城市切换、温度切换、语言切换等功能。 该项目的实现分为三个模块:天气API数据获取模块、天气信息处理模块和GUI界面设计与交互模块。天气API数据获取模块负责从API中获取天气数据,天气信息处理模块用于对天气数据进行处理, GUI界面设计与交互模块则主要实现用户界面的设计、功能按钮操作等。 在该项目的实现中,C++编程语言的高效性和良好的性能表现得到了充分的发挥。Qt GUI程序库提供了丰富的GUI组件和封装好的API,为项目开发提供了便利和支持。天气API的获取和处理模块为项目提供了可靠的数据来源和数据处理能力。 总的来说,C++ Qt 天气预报项目是一款实用、高效、易用的工具,为用户提供了便利的天气查询服务和多功能操作,同时也展示了C++编程语言和Qt GUI程序库的优异特性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值