题目

为便于后文理解,这里先补上这份代码前文开的库以及宏定义:

#include<cstdio>
#include<iostream>
#include<string>
#include<map>
using namespace std;
#define f(a,b,c,d) for(register int a=b,c=d;a<=c;a++)
#define g(a,b,c,d) for(register int a=b,c=d;a>=c;a--)
typedef int i32;
typedef unsigned int u32;
typedef long long int i64;
typedef unsigned long long int u64;

开头

考虑只有两个对象:时钟(CLOCK)与世界(WORLD)

时钟的属性包括:时(Hour)、分(Mint)、秒(Secd)

时钟的方法包括:增加(add)、重设(set)、查看(show)、清零(reset)、更新(update)

世界的属性包括:时钟(x)、指令(order)

世界的方法包括:错误抛出(error_solve)、指令识别(take_in)

分析

现在分别实现时钟与世界:

时钟

首先,对于时钟对象而言,其需要两个方法,一个将字符串转数字,一个将数字转字符串

我们构造两个新方法:转数字(to_Num)与转字符串(to_s)

转数字方法较好实现,就是输入 string 类储存的字符串,类似读入优化的方式计算出单个数字。只要记得加上特判:开头可以出现若干个负号,但中间不行;以及其它判定不能转化成数字的特判,即可简单实现:

inline bool to_Num(string s,i32 &d_Num){
d_Num=0;
bool b_Neg=0,b_Start=0;
f(i,0,I,s.size()-1){
if(s[i]=='-'&&b_Start==0) b_Neg^=1;
else if(s[i]>='0'&&s[i]<='9'){
d_Num=d_Num*10+s[i]-48;
b_Start=1;
}
else return 0;
}
if(b_Neg) d_Num=-d_Num;
return 1;
}

转字符串方法考虑到一定是两位数转成字符串,所以也比较容易写出:

inline string to_s(i32 d_Num){
string s="";
if(d_Num/10) s+=d_Num/10+'0';
s+=d_Num%10+'0';
return s;
}

接下来逐一实现上述的五个方法:

增加方法

根据输入的字符串转成的数字直接转成的秒数,加至原时间上,考虑时钟的特性,需要对秒数、分数、时数依次进位处理。再考虑到有用户会输入“时 分 秒”或"时:分:秒"形式,则增加转秒数(to_Sec)方法,将该类情况转成秒数,其余同样处理。记得将该正常情况以外的一切特殊情况特判为增加失败即可。

inline void add(i64 d_Time){
d_Secd+=d_Time%60;
if(d_Secd>=60) d_Secd-=60,d_Mint++;
d_Time/=60; d_Mint+=d_Time%60;
if(d_Mint>=60) d_Mint-=60,d_Hour++;
d_Time/=60; d_Hour+=d_Time;
if(d_Hour>=24) d_Hour-=24;
}
inline bool add(string s){
i32 d_Time;
if(s.find(" ")!=string::npos) { if( !to_Sec(s,d_Time) ) return 0; }
else { if( !to_Num(s,d_Time) ) return 0; }
d_Time%=86400;
if(d_Time<0) d_Time+=86400;
add(d_Time);
return 1;
}

而转秒数方法也较好实现,依次判定可否构成时、分、秒三个数字,然后用进率转为秒数返回即可:

inline bool to_Sec(string ss,i32 &d_Time){
f(i,0,I,ss.size()-1) if(ss[i]==':') ss[i]=' '; i32 h,m,s;
string tmp;
if(ss.find(" ")==string::npos) return 0;
tmp=ss.substr( ss.find(" ")+1 );
ss=ss.substr(0, ss.find(" ") );
if( !to_Num(ss,h) ) return 0; ss=tmp;
if(ss.find(" ")==string::npos) return 0;
tmp=ss.substr( ss.find(" ")+1 );
ss=ss.substr(0, ss.find(" ") );
if( !to_Num(ss,m) ) return 0; ss=tmp;
if(ss.find(" ")!=string::npos) return 0;
if( !to_Num(ss,s) ) return 0; d_Time+=3600*h+60*m+s;
return 1;
}

重设方法

读入“时 分 秒”或“时:分:秒”形式的时间,如果时、分、秒任意一个不符合规范,即可判错。当然,转不成的也可以直接判错。

inline void set(i32 h,i32 m,i32 s) { *this=CLOCK(h,m,s); }
inline bool set(string ss){
f(i,0,I,ss.size()-1) if(ss[i]==':') ss[i]=' '; i32 h,m,s;
string tmp;
if(ss.find(" ")==string::npos) return 0;
tmp=ss.substr( ss.find(" ")+1 );
ss=ss.substr(0, ss.find(" ") );
if( !to_Num(ss,h) ) return 0; ss=tmp;
if(ss.find(" ")==string::npos) return 0;
tmp=ss.substr( ss.find(" ")+1 );
ss=ss.substr(0, ss.find(" ") );
if( !to_Num(ss,m) ) return 0; ss=tmp;
if(ss.find(" ")!=string::npos) return 0;
if( !to_Num(ss,s) ) return 0; if(h<0||h>=24||m<0||m>=60||s<0||s>=60) return 0;
set(h,m,s);
return 1;
}

查看方法

直接调用前文的转字符串方法,返回“时:分:秒”形式的字符串即可

inline string show(){ return to_s(d_Hour)+":"+to_s(d_Mint)+":"+to_s(d_Secd); }

清零方法

相当于重设为“0:0:0”

inline void reset() { set(0,0,0); }

更新方法

相当于增加1秒

inline void update() { add(1); }

世界

错误抛出方法

直接输出即可

inline void error_solve() { cout<<"Input error!"<<endl; }

指令执行方法

先判定空格的有无

如果有空格,只能是增加、重设方法,否则都是输入格式错误;对于这两个方法,判定对应方法是否执行成功,不成功的需要抛出

如果无空格,只能是查看、清零、更新方法,不需要判定是否执行成功,直接执行即可

inline void take_in(string order){
if(order.find(" ")!=string::npos){
tmp=order.substr( order.find(" ")+1 );
order=order.substr(0, order.find(" ") );
if(order=="add") { if( !x.add(tmp) ) error_solve(); }
else if(order=="set") { if( !x.set(tmp) ) error_solve();}
else error_solve();
}
else{
if(order=="show") cout<<x.show()<<endl;
else if(order=="reset") x.reset();
else if(order=="update") x.update();
else error_solve();
}
}

实现

#include<cstdio>
#include<iostream>
#include<string>
#include<map>
using namespace std;
#define f(a,b,c,d) for(register int a=b,c=d;a<=c;a++)
#define g(a,b,c,d) for(register int a=b,c=d;a>=c;a--)
typedef int i32;
typedef unsigned int u32;
typedef long long int i64;
typedef unsigned long long int u64; class CLOCK{
private:
inline bool to_Num(string s,i32 &d_Num){
d_Num=0;
bool b_Neg=0,b_Start=0;
f(i,0,I,s.size()-1){
if(s[i]=='-'&&b_Start==0) b_Neg^=1;
else if(s[i]>='0'&&s[i]<='9'){
d_Num=d_Num*10+s[i]-48;
b_Start=1;
}
else return 0;
}
if(b_Neg) d_Num=-d_Num;
return 1;
}
inline string to_s(i32 d_Num){
string s="";
if(d_Num/10) s+=d_Num/10+'0';
s+=d_Num%10+'0';
return s;
}
int d_Hour,d_Mint,d_Secd;
inline void add(i64 d_Time){
d_Secd+=d_Time%60;
if(d_Secd>=60) d_Secd-=60,d_Mint++;
d_Time/=60; d_Mint+=d_Time%60;
if(d_Mint>=60) d_Mint-=60,d_Hour++;
d_Time/=60; d_Hour+=d_Time;
if(d_Hour>=24) d_Hour-=24;
}
inline void set(i32 h,i32 m,i32 s) { *this=CLOCK(h,m,s); }
inline bool to_Sec(string ss,i32 &d_Time){
f(i,0,I,ss.size()-1) if(ss[i]==':') ss[i]=' '; i32 h,m,s;
string tmp;
if(ss.find(" ")==string::npos) return 0;
tmp=ss.substr( ss.find(" ")+1 );
ss=ss.substr(0, ss.find(" ") );
if( !to_Num(ss,h) ) return 0; ss=tmp;
if(ss.find(" ")==string::npos) return 0;
tmp=ss.substr( ss.find(" ")+1 );
ss=ss.substr(0, ss.find(" ") );
if( !to_Num(ss,m) ) return 0; ss=tmp;
if(ss.find(" ")!=string::npos) return 0;
if( !to_Num(ss,s) ) return 0; d_Time+=3600*h+60*m+s;
return 1;
}
public:
CLOCK(i32 d_Hour_=0,i32 d_Mint_=0,i32 d_Secd_=0):d_Hour(d_Hour_),d_Mint(d_Mint_),d_Secd(d_Secd_) {}
~CLOCK() {}
inline bool add(string s){
i32 d_Time;
if(s.find(" ")!=string::npos) { if( !to_Sec(s,d_Time) ) return 0; }
else { if( !to_Num(s,d_Time) ) return 0; }
d_Time%=86400;
if(d_Time<0) d_Time+=86400;
add(d_Time);
return 1;
}
inline bool set(string ss){
f(i,0,I,ss.size()-1) if(ss[i]==':') ss[i]=' '; i32 h,m,s;
string tmp;
if(ss.find(" ")==string::npos) return 0;
tmp=ss.substr( ss.find(" ")+1 );
ss=ss.substr(0, ss.find(" ") );
if( !to_Num(ss,h) ) return 0; ss=tmp;
if(ss.find(" ")==string::npos) return 0;
tmp=ss.substr( ss.find(" ")+1 );
ss=ss.substr(0, ss.find(" ") );
if( !to_Num(ss,m) ) return 0; ss=tmp;
if(ss.find(" ")!=string::npos) return 0;
if( !to_Num(ss,s) ) return 0; if(h<0||h>=24||m<0||m>=60||s<0||s>=60) return 0;
set(h,m,s);
return 1;
}
inline string show(){ return to_s(d_Hour)+":"+to_s(d_Mint)+":"+to_s(d_Secd); }
inline void reset() { set(0,0,0); }
inline void update() { add(1); }
}; class WORLD{
private:
CLOCK x;
string tmp;
inline void error_solve() { cout<<"Input error!"<<endl; }
public:
WORLD() {}
~WORLD() {}
inline void take_in(string order){
if(order.find(" ")!=string::npos){
tmp=order.substr( order.find(" ")+1 );
order=order.substr(0, order.find(" ") );
if(order=="add") { if( !x.add(tmp) ) error_solve(); }
else if(order=="set") { if( !x.set(tmp) ) error_solve();}
else error_solve();
}
else{
if(order=="show") cout<<x.show()<<endl;
else if(order=="reset") x.reset();
else if(order=="update") x.update();
else error_solve();
}
}
}w; int main(){
string order;
while( getline(cin,order) ) w.take_in(order);
return 0;
}

思考题:clock类编写的更多相关文章

  1. IntelliJ IDEA 2017版 SpringBoot测试类编写

    SpringBoot的测试类编写Demo 源码见 https://github.com/liushaoye/baseone.git

  2. C# 利用MS的 EntLib的Database类编写的DbHelper

    C# 利用MS的 EntLib的Database类编写的DbHelper,由于MS的EntLib对Oracle.SQL Server和MySql已经封装,所以可以该DbHelper可以适用这三种数据库 ...

  3. Android(java)学习笔记123:Clock app编写报错01

    1.首先我们二话不说直接先看报错内容如下: 07-12 08:25:03.572: E/dalvikvm(3602): native fork pid:0 done. 07-12 08:25:03.5 ...

  4. Android(java)学习笔记125:Clock app编写报错02

    1.首先之间看错误: 07-13 10:07:55.354: E/AndroidRuntime(8008): FATAL EXCEPTION: main 07-13 10:07:55.354: E/A ...

  5. 基于junit的单元测试类编写

    首先定义抽象类BaseTest package com.geostar.gfstack.operationcenter.common.util; import com.google.gson.Gson ...

  6. 使用元类 编写ORM

    元类 一句话: 元类定制类的创建行为 知识点 1.类的创建: python这种动态语言,函数和类的定义,不是编译时定义的,而是运行时动态创建的. Python解释器遇到class定义时,仅仅是扫描一下 ...

  7. LearnOpenGL学习笔记(四)——着色器类编写

    之前我们将着色器的代码用glsl写好之后,保存为字符串指针,然后用一个函数去编译它,这是一种手段,对于简单的着色器代码可以这样.但当我们针对复杂的着色器,我们发现编写.编译.管理着色器是一件麻烦事.我 ...

  8. Android(java)学习笔记65:Clock App 编写报错02

    1. 首先之间看错误: 07-13 10:07:55.354: E/AndroidRuntime(8008): FATAL EXCEPTION: main 07-13 10:07:55.354: E/ ...

  9. Android(java)学习笔记63:Clock App 编写报错01

    1. 首先我们二话不说直接先看报错内容如下: 07-12 08:25:03.572: E/dalvikvm(3602): native fork pid:0 done. 07-12 08:25:03. ...

随机推荐

  1. Andriod studio 汉化教程

    1.找到安装目录,D:\Program Files\Android\Android Studio\lib,先保存resources_en,并且把它的名字改为resources_cn.jar 2.下载汉 ...

  2. 049-PHP输出当前文件的名称

    <?php echo __FILE__; //利用常量__FILE__输出当前文件的名称 ?>

  3. 5. 支撑高并发,高可用,海量数据备份恢复的Redis重要性

    商品详情页的架构实现 缓存架构 第一块儿,要掌握的很好的,就是redis架构 高并发,高可用,海量数据,备份,随时可以恢复,缓存架构如果要支撑这些要点,首先呢,redis就得支撑 redis架构,每秒 ...

  4. [APIO2012]派遣 可并堆

    Background 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿. Description 在这个帮派里,有一名忍者被称之为Master.除了Master以外,每名忍者 ...

  5. vzray服务端配置

    打开securecrt登陆服务器 输入命令:bash <(curl -s -L https://git.io/vzray.sh)1 回车tcp 回车端口 回车默认 回车

  6. spring源码 AutowireCapableBeanFactory接口

    对于想要拥有自动装配能力,并且想把这种能力暴露给外部引用的BeanFactory类需要实现此接口.正常情况下,不要使用此接口应该更倾向于使用BeanFactory或者ListableBeanFacto ...

  7. Tornado的XSRF防范

    XSRF XSRF即为跨站请求伪造 这个漏洞利用了浏览器的一个允许恶意攻击者在受害者网站注入脚本使未授权请求代表一个已登录用户的安全漏洞. 了解XSRF 当一个网站的图片SRC属性为另一个网站的链接时 ...

  8. 每天一点点之vue框架开发 - History 模式下线上路由报404错误

    vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载. 如果不想要很丑的 hash,我们可以用路由的 his ...

  9. 使用Linux系统,是一种什么体验?

    导读 同事,从事嵌入式软件开发多年,主要开发环境用的就是linux,最疯狂的一段时间直接把系统装成linux系统,然后在linux下面虚拟一个windows操作系统,主要有些事情必须在windows才 ...

  10. mybatis配置约束config,mapper

    MyBatis 主配置文件 config.xml(这里可以自己起,不过后面带上Config.xml) <?xml version="1.0" encoding="U ...