10.11.2 IO之读取结构化的值

利用标准输入循环来解决一个实际问题
假定要处理一个温度读数文件,其结构为:
{year 1990}
{year 1991{month jun }}
{year 1992{month jan (1 0 61.5)} {month feb (1 1 64) (2 2 65.2)}}
{year 2000
{month feb (1 1 68)(2 3 66.66)(1 0 67.2) }
{month dec (15 15 -9.2)(15 14 -8.8) (14 0 -2)}
}


const int not_a_reading = -7777;
const int not_a_month = -1;

const int implausible_min = -200;
const int implausible_max = 200;


struct Day{
vector<double> hour;
Day();
};

Day::Day() :hour(24)
{
for(int i=0; i<hour.size();++i) hour[i] = not_a_reading;
}

struct Month{
int month;
vector<Day> day;
Month():month(not_a_month),day(32)
{

}
};

struct Year{
int year;
vector<Month> month;
Year():month(12){}
};


struct Reading{
int day;
int hour;
double temperature;
};

bool is_valid(const Reading& r)
{
if(r.day<1 || r.day > 31) return false;
if(r.hour<0 || r.hour > 23) return false;

if(r.temperature < implausible_min || implausible_max < r.temperature)
return false;

return true;
}

void end_of_loop(istream& ist, char term, const string& message )
{
if(ist.fail()) {
ist.clear();
char ch;
if(ist>>ch && ch==term) return ;
cout<<"error"<<message;
error(message);
}
}

vector<string> month_input_tbl;
vector<string> month_print_tbl;

void init_input_tbl(vector<string>& tbl )
{
tbl.push_back("jan");
tbl.push_back("feb");
tbl.push_back("mar");
tbl.push_back("apr");
tbl.push_back("may");
tbl.push_back("jun");
tbl.push_back("jul");
tbl.push_back("aug");
tbl.push_back("sep");
tbl.push_back("oct");
tbl.push_back("nov");
tbl.push_back("dec");
}

int month_to_int(string s)
{
for(int i=0; i<12; ++i)
if(month_input_tbl[i] == s) return i;
}

void init_print_tbl(vector<string>& tbl )
{
tbl.push_back("January");
tbl.push_back("February");
tbl.push_back("March");
tbl.push_back("April");
tbl.push_back("May");
tbl.push_back("June");
tbl.push_back("July");
tbl.push_back("August");
tbl.push_back("September");
tbl.push_back("October");
tbl.push_back("November");
tbl.push_back("December");
}

string int_to_month(int i)
{
if(i<0 || 12<=i) {
cout<<"error"<< "bad month index"<<i<<endl;
error("bad month index");
}
return month_print_tbl[i];
}


ostream& operator<<(ostream& os, const Reading& r )
{
return os<<'('<<r.day
<<' '<<r.hour
<<' '<<r.temperature<<')';
}

ostream& operator<<(ostream& os, const Month& m)
{
Reading r;
Day d;
os<<"{month "<<int_to_month(m.month)<<' ';
for(int i=0; i<m.day.size(); ++i) {
d = m.day[i];
for(int j=0; j<d.hour.size(); ++j) {
if(d.hour[j]!=not_a_reading) {
r.day = i;
r.hour = j;
r.temperature = d.hour[j];
os<<r;
}
}
}
return os<<"}";
}

ostream& operator<<(ostream& os, const Year& y)
{
os<<"{year "<<y.year;
for(int i=0; i<y.month.size(); ++i) {
Month m = y.month[i];
if(m.month != not_a_month)
os<<m;
}
return os<<"}"<<endl;

}

istream& operator>>(istream& is, Reading& r)
{
char ch1;
if(is>>ch1 && ch1!='('){
is.unget();

is.clear(ios_base::failbit);
return is;
}

char ch2;
int d;
int h;
double t;

is>>d>>h>>t>>ch2;
if(!is || ch2!=')') {
cout<<"error"<<"bad reading";
error("bad reading");
}

r.day = d;
r.hour = h;
r.temperature = t;
return is;
}


istream& operator>>(istream& is, Month& m)
{
char ch = 0;
if(is>>ch && ch!='{'){
is.unget();
is.clear(ios_base::failbit);
return is;
}

string month_marker;
string mm;
is>>month_marker>>mm;
if(!is || month_marker != "month") {
cout<<"error"<<"bad start of month";
error("bad start of month");

}

m.month = month_to_int(mm);


Reading r;
int duplicats = 0;
int invalids = 0;
while (is >> r)
{
if(is_valid(r)) {
if (m.day[r.day].hour[r.hour] != not_a_reading ){
cout<<m.month<<r.day<<r.hour<<endl;
++duplicats;
}

m.day[r.day].hour[r.hour] = r.temperature;
}else
++invalids;
}

if(invalids) {
cout<<"invlid readings in month "<<invalids;
error("invlid readings in month",invalids);
}
if(duplicats) {
cout<<"duplicate readings in month "<<duplicats;
error("duplicate readings in month", duplicats);
}

end_of_loop(is,'}',"bad end of month");
return is;
}

istream& operator>>(istream& is, Year& y)
{
char ch;
is>>ch;
if(ch!='{'){
is.unget();
is.clear(ios::failbit);
return is;
}

string year_marker;
int yy;
is>>year_marker>>yy;

if(!is || year_marker != "year"){
cout<<"bad start if year";
error("bad start if year");
}
y.year = yy;


Month m;
while(is>>m) {
y.month[m.month] = m;
m = Month();
}

end_of_loop(is,'}',"bad end of year");
return is;
}


void main()
{
init_input_tbl(month_input_tbl);
init_print_tbl(month_print_tbl);
cout<<"please enter input file name\n";
string name;
cin >> name;
ifstream ifs(name.c_str());
if(!ifs) error("can't open input file",name);

ifs.exceptions(ifs.exceptions() | ios_base::badbit);

//open an out put file
cout<<"please enter output file name\n";
cin>>name;
ofstream ofs(name.c_str());
if(!ofs) error( "can't open output file,", name);


vector<Year> ys;
while(true)
{
Year y;
if(!(ifs >> y)) break;
ys.push_back(y);
}

cout<<"read "<<ys.size()<<" years of readings\n";

//自定义输出
for(int j=0; j < ys.size(); j++)
{
ofs<<ys[j];
}

keep_window_open();

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值