2017酷家乐秋招笔试题——后台开发

楼主,昨天晚上做了酷家乐的笔试题,本来发来说是19:00-21:00两个小时,结果登入考试系统发现倒计时只有一个小时(坑!)。不过题量很少,主要是选择题和简答题,简答题有一道是要编程的,当时内心太慌没有做出来,只能作为经验带入到下一次笔试中啦。编程题题目如下:
题目很简单,解析一个实数和运算符组成的计算式并求出最后结果,运算符只包含‘+’、‘-’、‘*’、‘/’。
分析:由于只包含简单的四种运算符,所以碰到*或者/,既是最高级运算符,可以直接计算,楼主采用了deque<>的双端队列,解析时对队列尾端操作,遇到*或者/,直接计算;解析完后,运算符队列里只剩+和-,然后顺序从队列首端出队运算即可。
代码如下:

#include
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

你可能感兴趣的:(各公司秋招笔试编程题)