// iostream iterator的使用
/*要求:从input.txt中读入数据 Rx Ry Rz Tx Ty Tz Frame。数据格式如下:
Tools Port 2: sjtu 100 s/n:36914C00 Frame Face State Rx Ry Rz Tx Ty Tz Error Markers Frame State Tx Ty Tz
1 2 159366 1 OK -42.6259 10.6095 19.0342 -53.35 -282.09 -2124.58 0.1529 0 159366
1 2 159367 1 OK -42.5965 10.643 19.1422 -53.52 -281.64 -2124.7 0.1754 0 159367
1 2 159368 1 OK -42.6655 10.6502 19.222 -53.65 -281.35 -2124.79 0.1813 0 159368
1 2 159369 1 OK -42.7368 10.6059 19.2744 -53.75 -281.22 -2124.84 0.168 0 159369
解决方法:
利用<string>类型的istream_iterator
istream_iterator<string> ins(infile), eos;
通过find()算法定位string "OK",然后通过自增运算符来定位到需要的数据位置读取相应的数据。
读取的string通过c_str()方法转换为C类型字符数组后再用atof转换为double型(只需要float 型),atol转换为long型,然后存储
*/
//******************* 数据类头文件 vec6.h 如下 **************************
#ifndef VEC6_H
#define VEC6_H
#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
using namespace std;
class Vec6
{
public:
Vec6(const long& frame,const float& Rx,const float& Ry, const float& Rz,const float& Tx, const float& Ty, const float& Tz);
static void show(vector<Vec6>& Vec6list);
static vector<Vec6> ReadFromFile(const string& strFileName); //从输入文件中读取数据构造Vec6类型的vector并返回拷贝
private:
long m_frame;
float m_Rx;
float m_Ry;
float m_Rz;
float m_Tx;
float m_Ty;
float m_Tz;
};
//constructor
Vec6::Vec6(const long &frame, const float &Rx, const float &Ry, const float &Rz, const float &Tx, const float &Ty, const float &Tz)
{
m_frame=frame;
m_Rx=Rx;
m_Ry=Ry;
m_Rz=Rz;
m_Tx=Tx;
m_Ty=Ty;
m_Tz=Tz;
}
//build vec6 vector from data file
vector<Vec6> Vec6::ReadFromFile(const std::string &strFileName)
{
vector<Vec6> vec6_result;
float* fDataBuf=new float[6];
long lframebuf=0;
ifstream inputfile;
inputfile.open(strFileName.c_str(),ios::in||ios::_Nocreate); //判断要打开的文件是否存在必须要用_Nocreate模式
if (inputfile.fail())
{
cout<<"cannot read input file!";
throw "cannot read input file!";
};
istream_iterator<string> is(inputfile),eos; //默认构造函数创造出来的eos相当于invalid iterator。 eos (default iterator) is invalid iterator
while (!inputfile.eof())
{
is=find(is,eos,"OK"); //从istream开始处向后找"OK"。不断缩小范围。
if (!is._Equal(eos)) // 用_Equals() 方法进行iterator之间的比较,以保证find找到了"OK"并返回了有效值,否则说明已经超过了最后一行,应结束操作
{
is++;
//begin input
for (int i=0;i<6;i++,++is)
{
//cout<< (*is).c_str() <<endl;
fDataBuf[i]=atof( (*is).c_str() ); // string转float型
};
for (int i=0;i<2;i++)
{
++is;
};
lframebuf=atol( (*is).c_str() ); // string转long型
Vec6* pvec6=new Vec6(lframebuf,fDataBuf[0],fDataBuf[1],fDataBuf[2],fDataBuf[3],fDataBuf[4],fDataBuf[5]);
vec6_result.push_back(*pvec6); /* vector.push_back(T& x)表面上通过引用传递参数,实际上是在内部对引用的变量进行了拷贝而不是单纯的引用,否则由于pvec6指向的变量的生存期仅为函数域这将导致vector中元素不正确。push_back(T& x)的内部实现是最终调用placement new运算符new (finish) T(&x)在vector容器finish指针所指位置以&x为参数构造了T型变量(《STL源码剖析》简中pp122、pp51)*/
//cout<<"end of a row"<<endl;
}
}
inputfile.close(); //别忘了close输入文件
return vec6_result;
}
//iterate and show vector<Vec6>
void Vec6::show(vector<Vec6>& Vec6list)
{
cout<<"begin output: "<<endl<<'\t'<<"<frame>"<<'\t'<<"<Rx>"<<'\t'<<"<Ry>"<<'\t'<<"<Rz>"<<'\t'<<"<Tx>"<<'\t'<<"<Ty>"<<'\t'<<"<Tz>"<<endl;
for (vector<Vec6>::iterator it=Vec6list.begin(); it!=Vec6list.end(); it++ )
{
cout<<"Vec6: "<< it->m_frame <<'\t'<< it->m_Rx <<'\t'<< it->m_Ry <<'\t'<< it->m_Rz <<'\t'<< it->m_Tx <<'\t'<< it->m_Ty <<'\t'<< it->m_Tz <<endl;
};
}
//
#endif
//************************* EOF vec6.h *******************
//********************* 主文件 vec6.cpp ******************
// vec6.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "vec6.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
vector<Vec6> DataSet;
try
{
DataSet = Vec6::ReadFromFile(".\\in.txt");
}
catch (...)
{
cout<<"error reading input file."<<endl;
}
if (!DataSet.empty())
{
Vec6::show(DataSet);
}
else cout<<"DataSet is empty."<<endl;
system("pause");
return 0;
}
//********************* EOF vec6.cpp ********************