【求教】自己改的一个VC的天气预报 为何截取的内容全是乱码?

lzljz121212 2011-06-05 04:16:57
我自己试着改了一下某位大大的天气预报 自己自学了HTML 格式上应该是没什么问题了
请问为何 我下载的内容都是乱码? 难道是2进制的? 该如何改正 求大大指导
#include<stdio.h>    
#include<stdlib.h>
#include<string.h>
#include<windows.h>
#pragma comment(lib,"ws2_32.lib")
struct Weather_Info
{
char city[50];
char day[50];
char weather1[50];
char temp1[50];
char wind1[50];
char weather2[50];
char temp2[50];
char wind2[50];
};
const char* URL="http://www.weather.com.cn/textFC/jiangsu.shtml#0";
const char* day_tag="<li class=\"selected\">";
const char* weather_tag1="</td><td width=\"89\">";
const char* temp_tag1="<span class=\"conMidtabright\">-</span></td><td width=\"92\">";
const char* wind_tag1="<td width=\"162\"><span>";
const char* weather_tag2="<td width=\"98\">";
const char* temp_tag2="<span class=\"conMidtabright\">3-4级</span></td><td width=\"86\">";
const char* wind_tag2="<td width=\"177\"><span>";
bool GetWeather(Weather_Info&wi,char *html)
{
if(html==NULL)
return false;
char *temp=NULL;

if((temp=strstr(html,day_tag))==NULL)
return false;
temp+=strlen(day_tag);
memcpy(wi.day,temp,strlen(temp)-strlen(strstr(temp,"<")));

if((temp=strstr(html,weather_tag1))==NULL)
return false;
temp+=strlen(weather_tag1);
memcpy(wi.weather1,temp,strlen(temp)-strlen(strstr(temp,"<")));

if((temp=strstr(html,weather_tag2))==NULL)
return false;
temp+=strlen(weather_tag2);
memcpy(wi.weather2,temp,strlen(temp)-strlen(strstr(temp,"<")));

if((temp=strstr(html,temp_tag1))==NULL)
return false;
temp+=strlen(temp_tag1);
memcpy(wi.temp1,temp,strlen(temp)-strlen(strstr(temp,"<")));

if((temp=strstr(html,temp_tag2))==NULL)
return false;
temp+=strlen(temp_tag2);
memcpy(wi.temp2,temp,strlen(temp)-strlen(strstr(temp,"<")));

if((temp=strstr(html,wind_tag1))==NULL)
return false;
temp+=strlen(wind_tag1);
memcpy(wi.wind1,temp,strlen(temp)-strlen(strstr(temp,"<")));

if((temp=strstr(html,wind_tag2))==NULL)
return false;
temp+=strlen(wind_tag2);
memcpy(wi.wind2,temp,strlen(temp)-strlen(strstr(temp,"<")));
return true;
}





bool initsocket()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return false;
}

if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 ) {
WSACleanup( );
return false;
}
return true;

}
struct SearchInfo//搜索结构体定义
{
char host[256];//主机名
unsigned int port;//端口号
char filename[256];//要文件名
char outfile[50];//保存文件名
};
void GetUrls(char *html);//解析html代码中的URL
bool initsocket();//初始化套接字
bool initargs(SearchInfo &outinfo,int argc,char **args);//解析输入命令行参数
const char *HTTP_STR="http://";
const char* HTTP_REQUEST_HEADER= //HTTP请求头
"GET %s HTTP/1.1\r\nAccept:*/*\r\n\Accept-Language:zh-cn\r\n\User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)\r\n\Host:%s\r\n\r\n";

bool initargs(SearchInfo &outinfo,const char*city)
{
memset(&outinfo,0,sizeof(SearchInfo));//初始化

char *temp=new char[256];
memset(temp,0,256);
sprintf(temp,URL,city);
printf(temp);
temp=(strstr(temp,HTTP_STR)!=NULL)?temp+strlen(HTTP_STR):temp;//去掉前面的http:\\
// printf("Url:%s\n",temp);
strcpy(outinfo.filename,strstr(temp,"/")!=NULL?strstr(temp,"/"):"/");//分析出要下载文件名
int length=strstr(temp,"/")==NULL?strlen(temp):(strlen(temp)-strlen(strstr(temp,"/")));
//分析出主机名的长度
memcpy(outinfo.host,temp,length);//解析出主机名
if((temp=strstr(outinfo.host,":"))!=NULL)//解析端口
{
temp++;
outinfo.port=atoi(temp);
}
else//如果没有输入使用默认80
{
outinfo.port=80;
}
delete temp;
return true;

}

char* GetFile(const SearchInfo * psi)
{
if(psi==NULL)
{
return NULL;
}
unsigned long serverip=0;//服务器IP
if((serverip=inet_addr(psi->host))==INADDR_NONE)//如果主机名不是IP
{
hostent *phst=gethostbyname(psi->host);//用DNS解析主机IP
if(phst==NULL)//如果解析失败返回false
return NULL;
//IN_ADDR in;
if(phst->h_addr_list[0]!=0)//解析成功使用主机第一个IP
{
memcpy(&serverip,phst->h_addr_list[0],phst->h_length);
// in.S_un.S_addr=serverip;
}
// printf("IP:%s",inet_ntoa(in));
}
SOCKET s=socket(AF_INET,SOCK_STREAM,0);//创建socket(TCP连接)
if(s==INVALID_SOCKET)//创建失败
{
printf("Create socket Error!Error Code:%d\n",WSAGetLastError());
return NULL;
}
SOCKADDR_IN server_addr;//服务器address
server_addr.sin_addr.S_un.S_addr=serverip;
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(psi->port);
memset(server_addr.sin_zero,0,sizeof(server_addr.sin_zero));
printf("Begin Connect Server :%s On:%d\n",inet_ntoa(server_addr.sin_addr),psi->port);
//开始连接服务器发出请求
if(SOCKET_ERROR==connect(s,(const sockaddr*)&server_addr,sizeof(SOCKADDR_IN)))
{
printf("Connect Server Error!Error Code:%d\n",WSAGetLastError());
closesocket(s);
//如果连接失败
return NULL;
}
printf("Connect Server OK!\n");
char buffer_sendmsg[256]={0};
sprintf(buffer_sendmsg,HTTP_REQUEST_HEADER,psi->filename,psi->host);//构造HTTP请求
//printf(buffer_sendmsg);
if(send(s,buffer_sendmsg,256,0)==SOCKET_ERROR)//向服务器发送请求
{
printf("Send Request To Server Error!Error Code:%d\n",WSAGetLastError());
closesocket(s);
//发送失败
return NULL;
}
//打开文件开始保存html代码

int len=0;
char buffer_recv[1024]={0};//接收html的buffer

int sumlen=0;//html的长度
char *html=(char*)malloc(sizeof(char)*1);//总的html字符串

while((len=recv(s,buffer_recv,1024,0))!=0)
{
if(len==SOCKET_ERROR)
{
printf("Error in Recv Data!Error Code:%d\n",WSAGetLastError());
closesocket(s);

return NULL;
}
sumlen=strlen(html);
printf(buffer_recv);
//重新分配内存原来大小加len长度
if((html=(char*)realloc((void*)html,sumlen+sizeof(char)*len))!=NULL)
{
memset(html+sumlen-1,0,len);//将新分到内存初始为0
strcat(html,buffer_recv);//将收到信息写入新分到内存
}
memset(buffer_recv,0,1024);
}

closesocket(s);
closesocket(s);

return strlen(html)==0?NULL:html;
}
void PrintWeather(const Weather_Info* pwi)
{
system("cls");
printf("\n");
printf("\n");
printf("\n");
printf(" \t 天气预报\n");
printf(" \t=====================================\n");
printf(" \t城 市:%s\n",pwi->city);
printf(" \t=====================================\n");
printf(" \t 白天 晚上\n",pwi->weather1);
printf(" \t------------------------------------\n");
printf(" \t天 气:%s %s\n",pwi->weather1,pwi->weather2);
printf(" \t------------------------------------\n");
printf(" \t温 度:%s %s\n",pwi->temp1,pwi->temp2);
printf(" \t------------------------------------\n");
printf(" \t风 向:%s %s\n",pwi->wind1,pwi->wind2);
printf(" \t======================================\n");
}
int main(int argc,char**argv)
{
Weather_Info wi;
SearchInfo si;
memset(&wi,0,sizeof(Weather_Info));
strcpy(wi.city,"南京");
if(argc>=2)
strcpy(wi.city,argv[1]);
if(!initsocket())
{
printf("Socket Error~\n");
return 1;
}

memset(&si,0,sizeof(SearchInfo));
sprintf(si.host,URL,wi.city);
if(!initargs(si,wi.city))
{
printf("Connect Internet Error~\n");
return 1;
}
char *html=NULL;
if((html=GetFile(&si))==NULL)
{
printf("Get Information Error~!\n");
return 1;
}


/*由于这里会报错而终止程序 所以先封报错的部分 强制执行*/

/*if(!GetWeather(wi,html))
{
printf("Get Weather Info Error~\n");
return 1;
} */

GetWeather(wi,html);
/****************************************************/
free(html);
PrintWeather(&wi);
system("pause");
return 0;
}
...全文
239 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
lzljz121212 2011-06-08
  • 打赏
  • 举报
回复
感谢7L大大的热心指导 我试试
smwhotjay 2011-06-07
  • 打赏
  • 举报
回复
你http请求web服务器.你是gb2312. 而他却可以是utf-8. 一般http头有服务器encode编码.把他转成你自己本地的就好了
zyyoung 2011-06-07
  • 打赏
  • 举报
回复
摆渡gsoap 天气
jamseyang 2011-06-07
  • 打赏
  • 举报
回复
顶一下南京的朋友:}
「已注销」 2011-06-06
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 lzljz121212 的回复:]

4L 的大大 复制的是 UTF8 转换成GB2312嘛? 函数接口有点看不懂啊
5L 可以说的详细点吗?
[/Quote]

1:现在的程序本身不是_UNICODE就是_MSBC,汉字也是字符,只不过和拉丁字母长的不一样,本质上对计算机来说没区别。因此在WINDOWS系统中API有两种,分别对应着两种字符集。命名大都是xxxxxxxxA,xxxxxxxxW,之所以在平时写程序时很少看到这样的名字,那是因为有MS在提供系统API时把这类的函数都加了一个预编译条件,如下面代码:


#ifdef _UINCODE
#define xxxxxxx xxxxxxxW
#else //_UINCODE
#define xxxxxxx xxxxxxxA
#endif //_UINCODE


2:知道了上面的问题,因此要确定在程序中使用哪一种函数(两种一起用也可以,但是设计很麻烦,代码少还好说,多了就费劲了,如果不是非常有钱或有时间就不要在这方面耽误功夫了。),假如使用xxxxxxW类型的函数来处理HTTP返回的内容,就要把返回的内容给转成_UNICODE类型,再用相关的函数处理就可以了。

3:1、2两个问题确定后,下面再分析HTTP返回内容何时要转,何时不用转。这里就要说到HTTP返回头协议(详细内容看RFC文档),CONTENT_TYPE 字段指示着后面跟随数据是用的哪一种变码。下面示便代码可能有些帮助:



if( CHtmlAnalyzer::SearchText(szContentType,_T("charset=utf-8")) )
m_objHtml.TakeAnapshot(pszContentBuf + 3,nRead -3,CHtmlAnalyzer::CHARSET_UTF8); // skip 0xEF,0xBB,0xBF
else if( CHtmlAnalyzer::SearchText(szContentType,_T("unicode")) )
m_objHtml.TakeAnapshot(pszContentBuf + 2,nRead -2,CHtmlAnalyzer::CHARSET_UNICODE);// skip 0xFE,0xFF
else
m_objHtml.TakeAnapshot(pszContentBuf,nRead,CHtmlAnalyzer::CHARSET_MULTIBYTE);



最后:要注意的有些返回头指示的字符集类型,不一定是后面跟随数据的实际类型,此时的代码就要注意处理了。当然这类情况非常地少,暂时可以不用考虑。

------匆匆忙忙写,也许有错误,将就着看吧--------------
lzljz121212 2011-06-06
  • 打赏
  • 举报
回复
4L 的大大 复制的是 UTF8 转换成GB2312嘛? 函数接口有点看不懂啊
5L 可以说的详细点吗?
「已注销」 2011-06-05
  • 打赏
  • 举报
回复
在HTTP返回头里面有数据的编码类型,根据编码类型转成想要的就成了。
LuciferStar 2011-06-05
  • 打赏
  • 举报
回复

void ConvertUtf8ToGBK(CString& strUtf8)
{
int len=MultiByteToWideChar(CP_UTF8, 0, (LPCTSTR)strUtf8, -1, NULL,0);
unsigned short * wszGBK = new unsigned short[len+1];
memset(wszGBK, 0, len * 2 + 2);
MultiByteToWideChar(CP_UTF8, 0, (LPCTSTR)strUtf8, -1, (LPWSTR)wszGBK, len);

len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)wszGBK, -1, NULL, 0, NULL, NULL);
char *szGBK=new char[len + 1];
memset(szGBK, 0, len + 1);
WideCharToMultiByte (CP_ACP, 0, (LPCWSTR)wszGBK, -1, szGBK, len, NULL,NULL);

strUtf8 = szGBK;
delete[] szGBK;
delete[] wszGBK;
}
偷懒,直接复制粘贴代码给你吧。
flandy_feng 2011-06-05
  • 打赏
  • 举报
回复
vc默认的是GB2312编码,而那网站可能是其他编码的,这有可能导致了乱码。
lzljz121212 2011-06-05
  • 打赏
  • 举报
回复
是因为那个网站是UTF8编码的原因吗?
该如何使得VC可以正确读出数据呢?
修改VC的设置还是在代码中填一些什么?
如果要填 该填一些什么呢?
(好吧 我<del>无耻</del>诚心的伸手求代码)
lzljz121212 2011-06-05
  • 打赏
  • 举报
回复
是因为那个网站是UTF8编码的原因吗?
该如何使得VC可以正确读出数据呢?
修改VC的设置还是在代码中填一些什么?
如果要填 该填一些什么呢?
(好吧 我<del>无耻<\del>诚心的伸手求代码)

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧