笔试题目搜集系列推荐:
(1)笔试题目搜集1
(2)笔试题目收集2
(3)笔试题目搜集3
(4)笔试题目搜集4
(5)笔试题目搜集5
(1)下列代码编译时会产生错误的是()
#include <iostream>
using namespace std;
struct Foo
{
Foo() { }
Foo(int) { }
void fun() { }
};
int main(void)
{
Foo a(10); //语句1
a.fun(); //语句2
Foo b(); //语句3
b.fun(); //语句4
return 0;
}
A、语句1 B、语句2 C、语句3 D、语句4
说明:诈一看,是语句3报错,因为调用缺省构造函数是不需要写括号的,但事实上语句4报错。语句3其实是编译通过的,只不过被编译器理解为一个没有参数返回一个FOO 类型对象的函数.
(2)在排序方法中,元素比较次数与元素的初始排列无关的是()
A、Shell 排序 B、归并排序 C、直接插入排序 D、选择排序
说明:A、C肯定不选的,归并排序的在merge中是跟序列有关,如果有序,比较次数最少n/2,最糟是元素错落n-1。而选择排序比较次数与关键字的初始状态无关,总的比较次数N=(n-1)+(n-2)+...+1=n*(n-1)/2。所以 应该是选择排序!
(3)给你1、2、3 这三个数字 可以使用C的各种运算符 你能表示的最大的整数是()
A、2*3*sizeof(1) B、3<<(2<<sizeof(1)) C、sizeof(3)<<(sizeof(2)<<(sizeof(1))) D、(unsigned long)(2-3)*1
(4)判断一个单向链表中是否存在环的最佳方法是()
A、两重遍历 B、快慢指针 C、路径记录 D、哈希表辅助
(5)下面代码的输出是多少?
class A
{
public:
A() { cout<<"A"<<endl; }
~A() { cout<<"~A"<<endl; }
};
class B:public A
{
public:
B(A &a):_a(a)
{
cout<<"B"<<endl;
}
~B()
{
cout<<"~B"<<endl;
}
private:
A _a;
};
int main(void)
{
A a; //很简单,定义a的时候调用了一次构造函数
B b(a); //这里b里面的_a是通过成员初始化列表构造起来的
//而且是通过copy constructor构造的是b的成员对象_a的,这里是编译器默认的,因此在构造好_a前,先调用基类构造函数
//然后才是构造自身,顺序就是A()->_a->B()(局部)
//因此这里有两个A,一个B
//在return之前进行析构
/************************************************************************/
/*析构是按照定义对象的反顺序来的,而且同一个对象按照构造的反顺序来的,因此这里先
析构b然后才是a,那么b的构造顺序是上面的A()->_a->B()(局部),反过来,就是B()(局部)->_a->A()
因此得到的就是~B->~A->~A
在b之后就是析构a
最后结果就是
~B->~A->~A->~A*/
return 0;
}
(6)判断一包含n个整数a[]中是否存在i、j、k满足a[i] + a[j] = a[k]的时间复杂度最小值是()
A.O(n^3) B. O(n^2*logn) C. O(n^3) D. O(nlogn)
(7)下列序排算法中最坏情况下的时间复杂度不是n(n-1)/2的是
A.快速排序 B.冒泡排序 C.直接插入排序 D.堆排序
(8)下列说法错误的是:
A.SATA硬盘的速度大约为500Mbps/s
B.读取18XDVD光盘数据的速度为1Gbps
C.千兆以太网的数据读取速度为1Gpbs
D.读取DDR3内存数据的速度为100Gbps
分析:A和B相比,怎么光盘的速度比硬盘还快?B必错无疑啊。千兆以太网的速度是1000Mbps,也可以写成1Gbps。DDR3-1600的极限传输速度是12.8GBp/s
(9)设在内存中有P1,P2,P3三道程序,并按照P1,P2,P3的优先级次序运行,其中内部计算和IO操作时间由下表给出(CPU计算和IO资源都只能同时由一个程序占用):
P1:计算60ms---》IO 80ms---》计算20ms
P2:计算120ms---》IO 40ms---》计算40ms
P3:计算40ms---》IO 80ms---》计算40ms
完成三道程序比单道运行节省的时间是()
A.80ms
B.120ms
C.160ms
D.200ms
(10)长为n的字符串中匹配长度为m的子串的复杂度为()
A.O(N)
B.O(M+N)
C.O(N+logM)
D.O(M+logN)
(11)发射三次炮弹,射中目标的概率是0.95,请问发射一次能击中目标的概率是多少?
A.0.63
B.0.50
C.0.32
D.0.86
(12)在c++程序中,如果一个整型变量频繁使用,最好将他定义为()
A.auto
B.extern
C.static
D.register
(13)两个等价线程并发的执行下列程序,a为全局变量,初始为0,假设printf、++、--操作都是原子性的,则输出不可能是()
void foo() {
if(a <= 0) {
a++;
}
else{
a--;
}
printf("%d", a);
}
A.01
B.10
C.12
D.22
注:这道题怎么做的
(13)有N个人,其中一个明星和n-1个群众,群众都认识明星,明星不认识任何群众,群众和群众之间的认识关系不知道,现在如果你是机器人R2T2,你每次问一个人是否认识另外一个人的代价为O(1),试设计一种算法找出明星,并给出时间复杂度(没有复杂度不得分)。
遍历 1~n 这n个人;
首先取出 1号 和 2号,
如果 1 认识 2, 那么把 1 去掉;
如果1不认识2,就可以把2去掉了。
每次比较都去掉一个,如此循环;n-1次之后只有一个人了
时间复杂度: O(n-1)
(14)下列程序输出的结果:
#include<stdio.h>
int main(void)
{
int a=10,b=20,c=30;
printf("\n%d..%d..%d",a+b+c,b *=2, c*=2);
return 0;
}
答案:110..40..60
思路:因为C语言中函数参数默认是从右往左处理,而输出是从左往右
(15)循环移位的构造
b=a<<(16-n);
c=a>>n;
c=c|b;
(16)谈谈如下两式的含义以及区别(C陷阱与缺陷15~19页):
float *g();//因为()的结合优先级比*高,所以该表达式相当于float *(g()),即g是一个函数,函数的返回值为float类型的指针,这是一个函数的声明。
float (*h)();//h先和*结合,表示h是一个指针,再和()结合表示一个函数。即表示h是一个函数指针,该函数返回值为浮点类型。
(float (*)());//表示一个“指向返回值为浮点类型的函数的指针”的类型转换符。
(void (*)())0;//表示将0转换为“返回值为void类型的函数的指针”类型。
(*(void (*)())0)();//调用上面这个指针的函数。
typedef void(*funcptr)();//funcptr就可以用了定义变量,定义变量类型为返回值为void类型的函数指针。
(*(funcptr)0)();//首先将0转换为funcptr类型的函数指针,然后调用相应的函数。
void (*signal(int,void(*)(int)))(int);//首先看涂黑的地方,这是一个函数,其返回类型为一个指针。函数参数为int和一个指向“参数为int,返回类型为void”的指针。再拼起来,该语句声明了一个函数signal,其返回类型函数指针看红色的地方,即返回值为void(*)int。可以通过如下的方式来简化操作:
typedef void(*HANDLER)(int);
HANDLER signal(int,HANDLER);
int(*(*F)(int,int))(int):根据上面的分析,我们就可以轻而易举的得到(*F)(int,int)为函数指针,而返回类型为int(*)(int)的函数指针。
注:一个函数返回一个函数指针时这么写的: void (*signal(int,void(*)(int)))(int);
注:若fp是一个函数指针,则调用函数有两种方式:(*fp)()以及简写的fp()。
(17)下列的语句错在哪,并改正。(C陷阱与缺陷)
while(c=getc(in)!=EOF){
putc(c,out);
}
问题出现在优先级上,我将优先级从高到低总结为括号->取地址->单目运算->乘除加减移位比较->位与短路选择赋值->逗号。按照这个顺序赋值运算符比比较运算的优先级低,所以上式等价于这样c=(getc(in)!=EOF),这显然是不对的,与设计者的本意不符,改为:
while((c=getc(in))!=EOF){//加一个括号
putc(c,out);
}
(18)下列程序会出现在哪一行崩溃?(程序员面试宝典P71)
struct S{
int i;
int *p;
};
int main()
{
S s;
int *p=&s.i;
p[0]=4;
p[1]=3;
s.p=p;
s.p[1]=1;
s.p[0]=2;
}
我觉得指针变化是上面这样一个过程,最终s.p[1]和s.p其实是同一个地方,s.p[1]=1 表示让S.p指向地址为1的地方,s.p[0]=2,就是将地址为1的地方赋值为2,即*((int*)1)=2,出现程序崩溃。
注:(1)int *p,则p+1=p+sizeof(int)*1;
char *p,则p+1=p+sizeof(char)*1;
int *p,int p1 = (char*)p,则p+1=p+sizeof(char)*1
(2)struct 存储为连续存储(不谈对界问题)。
(19)指出下面程序使用错误的地方改正(程序员面试宝典P72)
int max(int x,int y)p根本不是一个指向函数的指针,修改为int (*p)(int,int)=&max,函数指针类型跟函数的形参和返回类型对应的。
{return x>y?x:y;}
int main()
{
int *p=&max;
...
}
注:这个地方用int (*p)(int,int)=max也是可以的,因为函数名被使用时总是由编译器把他转换为函数指针。
(20) 某计算机有64位虚地址空间,页大小是2048B.每个页表项长为4B。因为所有页表都必须包含在一页中,故使用多级页表,问一共需要多少级?
2048B=2^11
64-11=53(地址中扣除页内地址位数) 共有2^53页
一页中可以装2048/4=2^9个页表项
9*6>53 至少需要6级页表
(21)指出下面的错误:
class Test{
int tx=5,y=6;
};
错误:在定义类时,只是定义了一种导出的数据类型,并不为类分配存储空间,所以在定义类的数据成员时,不能对其进行初始化。当说明对象时,系统才为对象分配相应的存储空间。为对象分配的存储空间的大小取决于在定义类时所定义的成员的类型和成员多少。在程序执行时,通过为对象分配存储空间来创建对象。
不同对象在内存中占有不同的区域(根据C++内存分配原则,参考http://blog.csdn.net/u010064842/article/details/9004264),它们保存的数据各不相同,但对成员数据操作的成员函数的程序代码均时一样,即成员函数的代码为每个对象所共享。通常,类中定义的成员函数的代码被放在计算机内存的一个公共区域中,并供所有对象的共享。
待续。。。。