今天去一家公司面试实习工程师,在徐家汇。我申请的是 Linux/Unix下的 C++研发实习工程师。上午 9点开始笔试,笔试时间为一个半小时,题目量比较大。笔试下来累得半死,感觉答得也不是很理想,然后马上面试。面试还蛮轻松的。他们说我可以直接来报到(在下个星期二之前),然后审查(主要是体检),审查通过后就可以签实习合同,至少要签半年,表现得好可以转正。最后还是拒绝他们了,主要是工资太低。他们说一个月给两千,实习生没有其他补贴(比如打车、伙食之类的),有时可能还要加班,加班则可以报销打车的费用。算起来一个月不加班的话 22天左右的工作时间,平均起来一天还不到 100块,实在是不太想大半年就这样待在那。我在嘉定区,离徐家汇又比较远 (不堵车的话至少要两个小时 )。在徐家汇倒是有同学,但也不能天天蹭住在那呀,至少要和他一起付一点房租吧。在上海一个月两千用下来基本上就没钱了(包括房租、吃饭、打车等,早晚两餐倒是可以在学校吃,可以便宜一点)。我有实习的同学一般就是三 千左右,这基本够用了,一般还有剩。当然,实习也不是为了要赚多少钱,但我感觉钱实在是太少了,面试时跟他们磨了很久(希望能有三千左右),要他们去跟经理说一下,他们说这是公司的制度规定,很难改的,最后还是拒绝了。
下面是笔试的题目,有一些已经记不清了。
第一部分 Unix 及软件工程知识
1 、解释软件项目中的 "Cycle life" 概念
我的回答:是指软件产品从可行性分析到需求分析、设计、实现、测试、投入使用、维护,直到软件产品不再使用(即死亡)的整个生命周期。
百度百科的解释:指软件开发全部过程、活动和任务的结构框架。软件开发包括需求、设计、编码和测试等阶段,有时也包括维护阶段。
2 、 shell 编程:根据 /etc/passwd 中的 GID 对用户分类统计,并把输出结果写入 /etc/users
我的程序:
#! /bin/bash
if [ -f /etc/users ]; then
rm /etc/users
fi
cut -f1,4,7 -d: /etc/passwd > /tmp/myfile
set $(cut -f4 -d: /etc/passwd | sort | uniq)
for gid in $@; do
echo "The users with GID $gid are: " >> /etc/users
grep ":$gid:" /tmp/myfile | cut -f1 -d: >> /etc/users
done
rm /tmp/myfile
exit 0
感觉这个脚本写得还不是很完美 ,可以再雕琢一下。主要是没有时间(这道题后来做的),大概想了一下就动笔了。
3、什么命令用来监控 Unix的进程
我的回答: ps(本来还想加上 top, nice等命令,但题目是英文出的,用的是单数 what command......,所以只写了一个命令)
还有两道题忘了
第二部分 C ++知识(选择题)
1、哪个是有效的标识符
A、好像是以下划线开头后跟几个字母
B、串中间有点号 (.)
C、 1234
D、忘了
我选的是 A
接着三道题都是分析程序输出结果,只要 C++基础比较扎实,一般不会有太大的问题
5、考哪段代码是错误的,有一个选项中是 do-while循环,但 while后面没有分号,我选了这个(但是感觉其他选项中也有错误的)
6、考对虚基类描述哪个选项是错误的。有一个选项是说虚基类的构造函数是在调用了非虚基类的构造函数之后才调用,我选了这个。显然,虚基类的构造函数应该总是最先被调用的。其他记得的选项有选项有:“若同一层次中包含多个虚基类 ,这些虚基类的构造函数按它们说明的次序调用 ;”
“若虚基类由非虚基类派生而来 ,则仍先调用基类构造函数 ,再调用派生类的构造函数 .”
显然都是正确的。
7、考对编译时多态和运行时多态的描述哪个是错误的。有一个选项说类的虚函数和模板使用的是运行时多态,这个显然错误,模板使用的是编译时多态。其他选项好像都没问题(记得有一个选项是说运行时多态产生动态绑定,这显然是对的)
好像还有一道题忘了
第三部分 数据库知识
1 、题是说下面哪个三个语句会导致事务终止
A、 ALTER
B、 INSERTE
C、 GRANT
D、 DELETE
E、 UPDATE
F、 ROLLBACK
大概是这样子的吧(记忆有点模糊了)
这道题我不太会做,唉,惭愧呀。以前数据库学得还蛮扎实的,到现在都忘了。凭分析自己选了三个,后来面试时说我做错了。
后来想了一下,应该考原子操作吧,原子操作没成功的话,会导致事务终止,并自动回滚到改变之前的状态,不知对不对。
第 2、 3道选择题忘了(因为是比较偏的题目,没有记住)
4 、移动公司关于手机付费的项目 (他们公司现在正在做这个项目)。有两个关于手机费用账单的表格 A和 B,均有两个字段。一个是手机号 bill_id,为数字型。一个为费用清单字段 detail_data,为字符串型,有 400位长,每 16位为一组,其中前 7位为费用号,后 9位为费用(表格格式如下所示)。现要对两个表格中 bill_id相同的项进行合并(并入表格 B中),若有费用号相同的,就把费用相加;若 B中没有相同的费用号,就把这个费用单的 16位组追加到尾部。请写出 SQL语句或存储过程 。
表 A
bill_id detail_data
13746894897 1023 450000 1024 235434 ......
......
表 B
bill_id detail_data
15098574963 1024 543697 2567 340849 ......
......
我的回答:由于时间很紧迫,我只写了一下思路:
( 1)要用到游标和字符串处理函数
( 2)先找出两个表中 bill_id相同的项的费用数据,在查找时要用游标来对下面查找的记录一条一条地处理。
select A.detail_data, B.detail_data
from A,B
where A.bill_id=B.bill_id
( 3)对游标处理的每一条记录,用字符串处理函数对 A.detail_data每 16位取出一个子串,用其前 7位去查找 B.detail_data的每 16位的子串,若有相同的,就用 ALTER语句修改 B中对就组的后 9位,使其为两个费用值之和;若没有相同的,就用 INSETER语句把这个 16位组插到 B.detail_data的尾部。
唉,以前大三时还写过存储过程,现在基本上都忘了(好久没用了),甚至游标的语句都忘了,看来现在需要捡回来喽 !
第四部分 开发知识
1 、 记不清了
2 、怎么判断一个程序是用 C 编译器的还是用 C++ 编译器编译的。
想了好久,不知该怎么做。后来突然想到 Linux中 ldd命令。
我的回答:使用 ldd命令可以列出程序使用了哪些共享库(即动态链接库),若使用了 C标准库 (libc.so.版本号 ),就说明程序是用 C编译器编译的,若还使用了 C++标准库,就说明程序是用 C++编译器编译的。
显然这样的回答有漏洞,根据使用哪个标准库并不能完全判断使用了哪种编译器。当时没办法呀,时间紧迫,来不及再想了。回来后上网搜了一下。答案如下:
简单的说,由于 C语言是没有重载函数的概念的,所以 C编译器编译的程序里,所有函数只有函数名对应的入口。而由于 C++语言有重载函数的概念,如果只有函数名对应入口,则会出线混淆。所以 C++编译器编译的程序,应该是函数名+参数类型列表对应到入口。
注意,因为 main函数是整个程序的入口,所以 main是不能重载的,所以,如果一个程序只有 main函数,是无法确认是 C还是 C++编译器编译的。
可以通过 nm来查看函数名入口。
如一个函数
int foo(int i,float j)
C编译的程序通过 nm查看
f 0x567xxxxxx (地址 )
C++编译程序,通过 nm
f(int,float) 0x567xxxxxx
唉,怎么就没想到呢,我对 ldd和 nm命令都比较熟悉(两个命令还是同时学习的呢),想到了 ldd,就是没想到 nm。另一方面,可能我对 C++底层理解得还不够清晰吧。看来阅读 <<深入探索 C++对象模型 >>这种探索底层的书籍的计划得提前了,本来是打算先看完了 STL,Boost, MFC, Qt等各种程序库后再看这些底层的书( Boost, MFC的程序库本身基本看完了, STL还在看, Qt还没看)。
在程序层面上,可以用 C++预编译头来控制,以判断哪一段代码是用 C编写的,哪一段是用 C++编写的。
#ifdef __cplusplus
extern "C" {
#endif
// 一段代码
#ifdef __cplusplus
}
#endif
__cplusplus 是 cpp 中的自定义宏,那么定义了这个宏的话表示这是一段 cpp 的代码,也就是说,上面的代码的含义是 : 如果这是一段 cpp 的代码,那么加入 extern "C"{ 和 } 处理其中的代码。 C 和 C++ 对函数的处理方式是不同的。 extern "C" 是使 C++ 能够调用 C 写作的库文件的一个手段,如果要对编译器提示使用 C 的方式来处理函数的话,那么就要使用 extern "C" 来说明。
3 、 int **a[3][4]; 定义的变量占用多少内存空间
我的回答: a[3][4]的每一个元素是一个 int**指针, 指针变量一般占 32位(当今各种编译器实现基本上都是这样),因此共占 3*4*4=48字节
4 、考链表。 可以使用任何一种编程语言。有一个动态链表,结点的内容是一个字母。请用编程语言描述这样的动态链表,并写一个函数,其输入是指向链表的指针,输出也是指向链表的指针,输出结果正好是原链表顺序相反。
我的程序:
struct LinkTable{
char c;
LinkTable *next;
}*LTable;
void reverse(LTable in,LTable *out){
if(in==NULL){
*out=NULL;
return;
}
int p,q,r;
p=in; q=p->next;
while(p && q){
r=q->next;
q->next=p;
p=q;
q=r;
}
*out=p;
}
第五部分 网络知识
1 、左边一列是各应用层协议 ,有 FTP,TFTP,SMTP,Telnet,HTTP,DNS,右边一列是各传输层协议及其使用端口(主要是 TCP和 UDP,每个协议后跟一端口号,有 21, 23, 25, 53等)。要求进行连线配对,使应用层协议与其使用的传输层协议及其端口对应。
我的回答:
我对这些协议还是蛮熟悉的 ,以前还专门花时间还天天上 Cisco与华为技术网,协议分析网等恶补了一番网络知识,主要是感觉以前学的网络知识太理论化、抽象化了(我们用的 Andrew S.Tanenbaum的那本网络经典教材)。可现在好久没看了,有些端口号都记得不是很清了。答的时候记得 FTP是 TCP/21, SMTP是 TCP/25, HTTP是 TCP/80, DNS是 UDP/53。后来面试官说我没有完全答对,看来其他两个的是答错了。
还有两道选择题忘了
第六部分 智力题
1 、有一个 5 升容量的桶和一个 3 升容量的桶,怎样得到 4 升的水
我的回答:
( 1)用 5升的桶装满水后,往 3升的桶里倒,倒到恰好满为止,这时 5升的桶里剩下 2升水。
( 2)倒掉 3升桶的水,并把 5升桶里的 2升水全部倒入 3升桶里。
( 3)用 5升桶再装满水,往 3升桶里倒,倒到恰好满为止,这时 5升桶里就剩下 4升水了。
2 、现在城市里的道路上进入下水道的洞都有个铁盖子,为什么这些铁盖子都是圆形的而不是方形的。
这个真正答案我也不知道。我根据的自己的想法写。
我的回答:周长一定时,圆形的面积最大(比方形大),这样空间最大,排流量就会最大。另外,因为水管是圆的,把铁盖子做成圆形,使得在维修时有得水管的进出。
回来搜了一下,答案很多,也包括我上面回答的答案。其他的一些答案:
正方形的盖子容易掉到洞里去。想一想,如果盖子真掉进去的话,那么不是发生伤人事故,就是盖子会掉到水里。为什么正方形的盖子容易掉下去呢?这是因为正方形的对角线是其边长的约 1.414倍。如果把一个正方形盖子垂直地立起来,稍微一转,它就会很容易掉到下水道里去。与此相反,圆的直径都是等长的,这使它很难掉进去。
一种诙谐回答是:下水道的洞口是圆形的,盖子当然也应该是圆的。那么为什么下水道的洞口是圆形的?答案是因为圆形的洞比方形的洞好挖。
还有另外一种答案:在进行短距离搬运时,圆形的盖子可以很方便地通过滚动的方法来搬运,而方形的盖子就不容易搬运,你需要借助手推车或者由两个人抬着走。再有一点就是用圆形盖子盖住洞口时,不需要怎么调整就可以与洞口严丝合缝。
如果为正方形、矩形或椭圆形,只要稍微转动一定的角度就可能掉下去,而圆形的话,无论你怎样旋转都不可能掉下去。
为了不掉下去(因为圆心到各边距离相等)。也为了运输方便(这是较易忽略的一点,否则仅从第一点无法解释为什么不做成等边三角形的)。
3 、 1 元钱买一瓶汽水,两个空汽水瓶换一瓶汽水。现有 20 元钱,问最多可以喝到多少瓶汽水。
这个题目我是最后 3分钟做的,根本就没仔细想,直接就用 20元钱全部一次花完。
回来搜了一下,说 39瓶或 40瓶都有道理。不过感觉 40瓶的答案应该更有说服力吧。
一开始 20瓶没有问题,随后的 10瓶和 5瓶也都没有问题,接着把 5瓶分成 4瓶和 1瓶,前 4个空瓶再换 2瓶,喝完后 2瓶再换 1瓶,此时喝完后手头上剩余的空瓶数为 2个,把这 2个瓶 换 1瓶继续喝,喝完后把这 1个空瓶换 1瓶汽水,喝完换来的那瓶再把瓶子还给人家即可,所以最多可以喝的汽水数为: 20+ 10+ 5+ 2+ 1+ 1+ 1= 40
但是题目中并没有说可以赊账,因此最后用 1个汽水瓶去换 1瓶汽水严格说并不成立 (如果不允许赊账的话 )。因此 39瓶的答案也可以说得过去。
笔试心得:
本科时也参加几个公司的笔试。其实不管做哪方面的开发,数据库、你所用的语言、算法、网络、可能还有一点软件工程方面的知识,一般都是会考的。即使你不做 Web开发,现在的开发基本上也都会用到数据库、网络(哪怕你做嵌入式开发都或多或少会用到一点),至于你所用的语言、算法、软件工程知识那就更不用说了。这些东西都是我们开发必须要用到知识,因此必须牢固掌握。我特别要提的是数据库的存储过程和网络协议的透彻理解和应用(我经历的所有面试基本上都考),因为其他几方面如语言、算法大家都知道比较重要,学校里也会系统的学习。而存储过程和协议的应用特别需要要多实践,多写代码或者多用这些协议相关的软件才能理解和掌握。做软件开发代码量是非常重要的,没有一定的代码量,很难把这些知识融会贯通。
其实这些知识说到底也是我们 IT专业的基础知识。
面试心得:
面试时其实没必要紧张。其实公司并不一定喜欢那种只会埋头钻研技术,不善于交谈的人。你要让他们感觉你比较轻松,比较健谈,说话比较和蔼而不咄咄逼人,但又不喧宾夺主,就是感觉你这个人很能谈得来,又真诚,不是那种只会埋头钻研技术的人。当然,你的技术也不然太差,是吧,他们毕竟是要找会做事的人,不会做事招你干吗,吃干饭哪?!
对这次面试,感觉还是蛮可惜的。一想到实习机会,唉,多好的机会呀,居然拒绝了(我当时就一直想,千万要镇定,不要轻易把自己给贱卖了,因为他总是把他们公司啊、福利啊说得天花乱坠,而我觉得其实跟其他公司都差不多)。可是一想到工资,又觉得没什么可惜的,不去就不去贝。我记得我的一个同学说得一句话也是有一定道理的,其实在一家小公司(他们那家公司其实还算比较大,在很多地方都有分公司)实习有时还不如呆在实验室好好学一点东西(关键是要认真学,并且要多积累代码经验),可能他们会要你做这做那,不一定能学到真技术。但我还是觉得实习能比在学校学到更多的东西,尤其是在大公司实习。要不然我也不会去投简历,找实习了。总之,心理挻矛盾的,呵呵。
我回校后,他们又打电话给我了,问我对测试的职位感不感兴趣,我说我对测试也不熟,做不好(其实是因为不感兴趣),看得出来,他们还是蛮想要我的。唉,就算是一次面试的经历吧,说不定将来就会成为面霸了!
所有评论(0)