一、大致步骤
第一步:将全国的气象站点的地理信息(经度纬度等)从 参数文件中的 stcode.ini 导入容器A
因为生成气象观测数据要用到地理信息中的站点编号(站点的标识)
/第二步:生成每个气象站点的观测数据,这里主要是模拟的。然后将观测数据导入容器B
/第三步:将容器B中的观测数据导入观测数据文件中(data目录下)
二、代码
#include "freecplus.h"
//
// 第一步:1.先定义一个结构体,存放站点的地址信息
struct st_stcode
{
char provname[31]; //站点所属的省份名称
char obtid[11]; //站点的编号
char cityname[31]; //站点所属的城市名
double lat; //纬度
double lon; //经度
double height; //海拔高度
};
// 第一步:2.定义一个容器,将文件中的站点地址信息导入容器
vector<struct st_stcode> vstcode;
// 第一步:3.要将文件的数据导入容器,涉及到文件操作,所以先定义一个文件操作对象\
CFile File; 我们再想想第一步的整个步骤的目的就是将文件中的地址信息导入容器\
// 我们是不是可以把这些操作放在一个方法里面呢?这是可以的。所以我们就定义一个函数\
定义一个函数要定义函数的返回值,参数,名称\
返回值:我们只需要bool 类型的就可以了,因为我只要知道导入是否成功就行了\
// 参数:因为我们是从文件中导入数据,现在我们将这个方法封装,如果使用这个方法的时候\
一定要对文件进行操作,并且文件是可变的。所以参数用文件名
bool LoadSTCode(const char *inifile);
bool LoadSTCode(const char *inifile)
{
// 1.这个函数的目的是从文件中将数据导入容器,所以涉及到文件操作,之前封装有文件操作类
// 先定义一个文件操作对象
CFile File;
// 2. 先打开文件,以读的方式
if ( File.Open(inifile,"r") == false )
{
printf("File.Open(%s)失败\n",inifile);
return false;
}
// 3.读取文件中的站点地址信息,因为不知道有多少个站点,所以用循环读取
// 将地址信息取出来了还不能直接导入容器,还要拆分。因为刚取出来的信息是一连串的字符
// 所以要定义一个字符串来存放读取出来的字符串
char strbuffer[101];
// 而容器里面的信息是分类存放的。就是结构体里面的那几个数据。所以要将取出来的字符串拆分
// 拆分之后放在站点地址信息结构体里面。再将结构体导入容器。所以要定义地址信息结构体
struct st_stcode stcode;
//拆分字符串的操作封装在一个类里面,所以要定义一个拆分字符串对象
CCmdStr CmdStr;
while(true)
{
memset(strbuffer,0,sizeof(strbuffer)); //初始化
memset(&stcode,0,sizeof(struct st_stcode)); //初始化地址信息结构体
// 3.1 要检查是否读取完了所以站点的地址信息,如果读取完了就跳出循环
if ( File.Fgets(strbuffer,100) == false ) break;
// 3.2 读取出一个站点的地址信息,就拆分到结构体里面
//地址信息的格式:安徽,58015,砀山,34.27,116.2,44.2
CmdStr.SplitToCmd(strbuffer, ",", true); //说明字符串的分割符是逗号
// 拆分字符串,赋值给结构体对应的成员
CmdStr.GetValue(0, stcode.provname);
CmdStr.GetValue(1, stcode.obtid);
CmdStr.GetValue(2, stcode.cityname);
CmdStr.GetValue(3,&stcode.lat);
CmdStr.GetValue(4,&stcode.lon);
CmdStr.GetValue(5,&stcode.height);
// 拆分之后,验证是否拆分成功
//printf("strbuffer=%s",strbuffer);
//printf("provname=%s,obtid=%s,cityname=%s,lat=%.2lf,lon=%.2lf,height=%.2f\n",\
// stcode.provname,stcode.obtid,stcode.cityname,stcode.lat,stcode.lon,stcode.height);
// 将结构体注入容器 vstcode
vstcode.push_back(stcode);
}
return true;
}
// 第二步:先模拟生成观测数据,接着将观测数据导入一个容器中
// 观测数据格式:数据时间,气温,气压,相对湿度,风向,风速,降雨量,能见度
// 定义一个结构体表示观测数据
struct st_surfdata
{
char obtid[11]; //站点代码
char ddatetime[21]; //数据时间:格式yyy-mm-dd hh:mi:ss
int t; //气温:单位 0.1摄氏度
int p; //气压:0.1百帕
int u; //相对湿度:0-100之间的值
int wd; //风向:0-360之间的值
int wf; //风速:单位 0.1m/s
int r; //降雨量: 0.1mm
int vis; //可见度:0.1米
//这里为什么要用那么多的int型呢,因为这个比浮点型的好用,
//改一下单位就可以达到浮点型的效果
};
// 因为要将观测数据结构体导入容器中,所以要声明一个容器
vector<struct st_surfdata> vsurfdata;
// 将第二步的操作放在一个函数里面,定义一个函数
//返回值:void 因为这个函数涉及的操作一般不会出错,所以可以不用返回值
//函数名:CrtSurfData
//参数:这里可以不用参数,因为要定义的变量只有观测数据的结构体,我们在这个函数体内定义就行了
void CrtSurfData()
{
//先定义一个观测数据结构体
struct st_surfdata stsurfdata;
// 生成每个站点的观测数据,怎么生成这些数据,其实是利用随机数来生成的,所以要先播种
srand(time(0)); //随机数种子
//有多个站点,并且知道站点的规模,所以用for循环来给观测数据结构体赋值
for(int ii=0; ii < vstcode.size(); ii++)
{
memset(&stsurfdata, 0, sizeof(stsurfdata)); //初始化观测数据结构体
// 生成的是每个站点的观测数据,第一个成员变量所以要从地理信息容器中获取站点编号
STRCPY(stsurfdata.obtid,11, vstcode[ii].obtid);
//第二个成员变量是时间,采用系统当前时间
LocalTime(stsurfdata.ddatetime); //LocalTime()是获取当前时间
//接下来就是用随机数生成观测数据结构体的剩下成员变量
stsurfdata.t = rand()%351; //气温:单位
stsurfdata.p = rand()%265+10000; //气压:0.1百帕
stsurfdata.u = rand()%100+1; //相对湿度:0-100之间的值
stsurfdata.wd = rand()%360; //风向
stsurfdata.wf = rand()%150; //风速
stsurfdata.r = rand()%16; //降雨量
stsurfdata.vis = rand()%5001+100000; //可见度
//最后将观测数据导入观测数据容器中
vsurfdata.push_back(stsurfdata);
}
}
/
// 第三步:将观测数据从容器vsurfdata中导入数据文件(xxx.txt)
// 把第三步封装成一个函数。这个函数的参数就用输出路径作为。
// 返回值:bool就行,是否写入成功。
bool CrtSurfFile(const char *outpath)
//要将数据写入文件,涉及到文件操作,所以定义一个文件操作对象
CFile File;
//以这样的方式写进去有点问题,就是当有多个文件时,不好区分,所以为了区分各个文件,要加一些变量\
用于区分文件。
//定义一个字符串,用于存放文件名
char strFileName[301];
memset(strFileName,0,sizeof(strFileName));
// 要在文件名加入生成的时间,所以要获取当前的时间
char strLocalTime[31];
memset(strLocalTime,0,sizeof(strLocalTime));
LocalTime(strLocalTime,"yyyymmddhh24miss");
snprintf(strFileName, 300, "%s/SURF_ZH_%s_%d.txt",outpath,strLocalTime,getpid());
//以写的方式打开文件
if ( File.Open(strFileName,"w") == false )
{
printf("File.Open(%s)失败\n",strFileName);
return false;
}
printf("可以进入\n");
//有多个站点的观测数据要写入,并且知道规模所以用for循环
for(int ii=0; ii < vsurfdata.size(); ii++)
{
File.Fprintf("%s,%s,%.1f,%.1f,%d,%d,%.1f,%.1f,%.1f\n",vsurfdata[ii].obtid,\
vsurfdata[ii].ddatetime,vsurfdata[ii].t/10.0,vsurfdata[ii].p/10.0,vsurfdata[ii].u,\
vsurfdata[ii].wd,vsurfdata[ii].wf/10.0,vsurfdata[ii].r/10.0,vsurfdata[ii].vis/10.0);
}
return true;
}
int main(int argc, char *argv[])
{
if (argc != 3)
{
printf("本程序用于生成全国气象站点的分钟观测数据.\n");
printf("Using: /home/xza/qxidc/bin/crtsurfdata 站点地理位置参数 观测数据存放的目录\n");
printf("Example: /home/xza/qxidc/bin/crtsurfdata /home/xza/qxidc/ini/stcode.ini /home/xza/qxidc/data/ftp/surfdata\n");
return -1;
}
// 第一步:从站点地理位置参数文件将数据导入容器vstcode中
if ( LoadSTCode(argv[1]) == false ) return -1;
// 第二步:将观测数据导入观测数据容器 vsurfdata中
CrtSurfData();
// 第三步:将观测数据容器中的数据写入指定目录的指定文件
if ( CrtSurfFile(argv[2]) == false )
{
printf("1\n");
return -1;
}
return 0;
}