楼主,昨天晚上做了酷家乐的笔试题,本来发来说是19:00-21:00两个小时,结果登入考试系统发现倒计时只有一个小时(坑!)。不过题量很少,主要是选择题和简答题,简答题有一道是要编程的,当时内心太慌没有做出来,只能作为经验带入到下一次笔试中啦。编程题题目如下:
题目很简单,解析一个实数和运算符组成的计算式并求出最后结果,运算符只包含‘+’、‘-’、‘*’、‘/’。
分析:由于只包含简单的四种运算符,所以碰到*或者/,既是最高级运算符,可以直接计算,楼主采用了deque<>的双端队列,解析时对队列尾端操作,遇到*或者/,直接计算;解析完后,运算符队列里只剩+和-,然后顺序从队列首端出队运算即可。
代码如下:
#include<bits/stdc++.h>
using namespace std;
deque<char> sStr;
deque<double> sNum;
string str;
double x, y;
char c;
//计算一次表达式x var y
double cmpOnce(double x, double y, char var)
{
switch (var)
{
case '+':
return y + x;
break;
case '-':
return y - x;
break;
case '*':
return y * x;
break;
case '/':
return y / x;
break;
default:
break;
}
}
//操作双端队列sNum一次,i为0时操作队列尾端,其他值操作队列首端
double controlsNum(int i)
{
double d;
if (i == 0)
{
d = sNum.back();
sNum.pop_back();
}
else
{
d = sNum.front();
sNum.pop_front();
}
return d;
}
//操作双端队列sStr尾端一次
char controlsStr()
{
char c = sStr.back();
sStr.pop_back();
return c;
}
//解析从控制台获取的string表达式,将实数和运算符分开存储
void Analysis()
{
int pos = 0;
/*每次匹配到*或者/都可以直接计算,但是需要获取下一个实数,
doCmp就是判断匹配到下一个运算符是否要将前面的实数放入计算*/
bool doCmp = false;
int i;
for (i = 0; i < str.length(); i++)
{
if (str[i] == '/' || str[i] == '*' || str[i] == '+' || str[i] == '-')
{
if (!doCmp)//不需要计算
sNum.push_back(atof(str.substr(pos, i).c_str()));
else//需要计算,提取实数放入计算
{
doCmp = false;
x = atof(str.substr(pos, i).c_str());//doubel atof(const char *)string转double
y = controlsNum(0);
c = controlsStr();
sNum.push_back(cmpOnce(x,y,c));
}
pos = i + 1;
}
switch (str[i])
{
case '/':
case '*':
sStr.push_back(str[i]);
doCmp = true;
break;
case '+':
case '-':
sStr.push_back(str[i]);
break;
default:
break;
}
}
sNum.push_back(atof(str.substr(pos, i).c_str()));
}
int main()
{
while (cin >> str)
{
sStr.clear();
sNum.clear();
Analysis();
//解析完后,可能存在最后一个运算符是'/'或者'*'的情况
if (sStr.back() == '/' || sStr.back() == '*')
{
x = controlsNum(0);
y = controlsNum(0);
c = controlsStr();
sNum.push_back(cmpOnce(x,y,c));
}
//至此sStr里只有'+'和'-'运算符,从头至尾计算即可
for (char c : sStr)
{
x = controlsNum(1);
y = controlsNum(1);
sNum.push_front(cmpOnce(x,y,c));
}
cout << sNum.front() << endl;
}
}还有一道让楼主很苦恼的题是:描述下12306购票系统(查票、购票、退票)。
个人感觉这是一道结合考数据库和数据结构的题,难度也不大,主要理清楚车票系统里需要存储操作的信息就好。借鉴网上大神的想法,主要几个类如下:
所用到的枚举
enum seat_type{
upSeat,//上铺
midSeat,//中铺
lowSeat,//下铺
firstSeat,//一等座
secondSeat,//二等座
...
}
enum station{
city1,//起点站
city2,//途径站
···
cityk//终点站
}位池
/*位池文档结构,订票系统的根基,发生订票时,向余票池请求减去或增加相应票位,向待支付票池请求生成订单。*/
struct SeatInfo
{
char seat_id[25];//列车位唯一ID由“日期+列车ID+列车位ID”
enum seat_type;
enum station;
map<int, string> t;//键值表示途径城市,stirng存储此位置被身份证位*****的顾客预订了
};订票池
struct customer
{
//姓名,证件,证件号,手机号码,邮箱
char name[10];
char cer[10];
char cer_id[20];
char phone[11];
char email[20];
};
struct order
{
enum seat_type;
char set_num[25];//即位ID
char s_station[10];//出发站点
char d_station[10];//到达站点
double price;//订单价格
customer cus;//顾客信息
char s_time[11];//出发时间
char d_time[11];//到达时间
};
class BookTicket
{
char book_id[25];//订单id,由“下单人编号+下单时间+订单编号”组成
char gen_time[11]//下单时为null,下单成功后填入订单生成时间值,也标记了有效支付期的开始。
char pay_time[11]//订单支付时间,驱动程序扫描该字段,null表示未支付,存在时间值表示已支付或者已被锁定请求释放中。
char pay_info[50]//支付信息对象,初始值为null,支付成功后即写入数据。
order or;//顾客订单信息
//购票操作,访问位池
public void AddTicket(stirng cityName1, string userName);
}取票池
class GetTicket
{
char get_id[25];由‘下单人编号+下单时间+订单编号’编码而成。
enum seat_type;
char pay_time[11];//订单支付时间,驱动程序扫描该字段,null表示未支付,存在时间值表示已支付或者已被锁定请求释放中。
char pay_interface[10];//订单支付接口
char pay_info[50]//支付信息对象,为退票提供退款目标
char seat[10];//位置编号
order or;//顾客订单信息
//退票操作,访问位池
public void DropTicket(stirng cityName1);
}余票池
/*一趟列车对应的余票信息*/
class CheckTicket
{
char ticket_id[20];//由‘日期+列车ID’编码而成
enum station;
int info[25][25];//站点x到站点y所剩余票为info[x][y];
public bool checkTicket(stirng cityName1, string cityName2);
}各个池之间的逻辑关系:
1、位池接受来自订票池的请求,查找特定列车车次的某个符合位类型的列车文档
2、位池接受来自取票池的退票请求,根据请求把位池相应车位置为null
3、订票池接受位池系统的反馈订单
4、订票池向取票池发出请求生成取票文档
5、取票池向位池发送退票请求
6、余票池相应位池请求同时处理查询请求
参考地址:http://cnodejs.org/topic/5066d64701d0b801487dd635
版权声明:本文为qq_28002683原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。