C++ 面试题

C语言面试题大汇总之华为面试题 Eddy整理 1、局部变量能否和全局变量重名?    答:能,局部会屏蔽全局。要用全局变量,需要使用"::" ;局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。对于有些编译器而言,在同一个函数内可以定义多个同名的局部变量,比如在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内。    2、如何引用一个已经定义过的全局变量?    答:extern  可以用引用头文件的方式,也可以用extern关键字,如果用引用头文件方式来引用某个在头文件中声明的全局变理,假定你将那个编写错了,那么在编译期间会报错,如果你用extern方式引用时,假定你犯了同样的错误,那么在编译期间不会报错,而在连接期间报错。    3、全局变量可不可以定义在可被多个.C文件包含的头文件中?为什么?    答:可以,在不同的C文件中以static形式来声明同名全局变量。   可以在不同的C文件中声明同名的全局变量,前提是其中只能有一个C文件中对此变量赋初值,此时连接不会出错.     4、请写出下列代码的输出内容    #include    int main(void)    {     int a,b,c,d;   a=10;     b=a++;     c=++a;      d=10*a++;     printf("b,c,d:%d,%d,%d",b,c,d);     return 0;    }    答:10,12,120     5、static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?    答: 1) 全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这两者的区别在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用, 因此可以避免在其它源文件中引起错误。    2) 从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。   3) static函数与普通函数作用域不同,仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件    综上所述: static全局变量与普通的全局变量有什么区别: static全局变量只初使化一次,防止在其他文件单元中被引用;    static局部变量和普通局部变量有什么区别: static局部变量只被初始化一次,下一次依据上一次结果值;    static函数与普通函数有什么区别: static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝    6、程序的局部变量存在于(堆栈)中,全局变量存在于(静态区 )中,动态申请数据存在于( 堆)中。    7、设有以下说明和定义:     typedef union { long i; int k[5]; char c; } DATE;    struct data { int cat; DATE cow; double dog; } too;    DATE max;    则语句 printf("%d",sizeof(struct data)+sizeof(max));的执行结果是:___52____ 考点:区别struct与union.(一般假定在32位机器上)   答:DATE是一个union, 变量公用空间. 里面最大的变量类型是int[5], 占用20个字节. 所以它的大小是20. data是一个struct, 每个变量分开占用空间. 依次为int4 + DATE20 + double8 = 32. 所以结果是 20 + 32 = 52. 当然...在某些16位编辑器下, int可能是2字节,那么结果是 int2 + DATE10 + double8 = 20    8、队列和栈有什么区别?      队列先进先出,栈后进先出    9、写出下列代码的输出内容    #include    int inc(int a)    { return(++a); }    int multi(int*a,int*b,int*c)    {   return(*c=*a**b); }   typedef int(FUNC1)(int in);    typedef int(FUNC2) (int*,int*,int*);     void show(FUNC2 fun,int arg1, int*arg2)     {     FUNC1 p=&inc;      int temp =p(arg1);      fun(&temp,&arg1, arg2);      printf("%dn",*arg2);    }    main()    {      int a;    //局部变量a为0;   show(multi,10,&a);     return 0;    }    答:110     10、请找出下面代码中的所有错误 (题目不错,值得一看)   说明:以下代码是把一个字符串倒序,如“abcd”倒序后变为“dcba”    #include"string.h"    main()    {    char*src="hello,world";    char* dest=NULL;    int len=strlen(src);    dest=(char*)malloc(len);    char* d=dest;    char* s=src[len];   while(len--!=0)    d++=s--;    printf("%s",dest);    return 0;    }    答:    方法1:一共有4个错误;    int main()    {     char* src = "hello,world";     int len = strlen(src);     char* dest = (char*)malloc(len+1);//要为分配一个空间    char* d = dest;     char* s = &src[len-1]; //指向最后一个字符    while( len-- != 0 )      *d++=*s--;     *d = 0; //尾部要加’/0’     printf("%sn",dest);     free(dest); // 使用完,应当释放空间,以免造成内存汇泄露 dest = NULL;   //防止产生野指针  return 0;    } 方法2: (方法一需要额外的存储空间,效率不高.) 不错的想法 #include #include main() { char str[]="hello,world"; int len=strlen(str); char t; for(int i=0; i<< boolalpha << ((i & (i - 1)) ? false : true) << endl; //位与为0,则表示是2的若干次幂 2)return (x>>N==1); 4.unsigned int intvert(unsigned int x,int p,int n)实现对x的进行转换,p为起始转化位,n为需要转换的长度,假设起始点在右边.如x=0b0001 0001,p=4,n=3转换后x=0b0110 0001 答:unsigned int intvert(unsigned int x,int p,int n) //假定p=4,n=3 { unsigned int _t = 0; unsigned int _a = 1; for(int i = 0; i < n; ++i)//循环的目的主要是-t { _t |= _a; //位或 _a = _a << 1; } _t = _t << p; //转换后_t变为1110000 x ^= _t; /异或,将原来的位取反 return x; } 慧通: 1. 什么是预编译,何时需要预编译: 答: 就是指程序执行前的一些预处理工作,主要指#表示的. 何时需要预编译? 1)、总是使用不经常改动的大型代码体。 2)、程序由多个模块组成,所有模块都使用一组标准的包含文件和相同的编译选项。在这种情况下,可以将所有包含文件预编译为一个预编译头。 2. 下述三个有什么区别? char * const p; char const * p const char *p 解答: char * const p; //常量指针,p的值不可以修改 char const * p;//指向常量的指针,指向的常量值不可以改 const char *p; //和char const *p 3. 解释下列输出结果 char str1[] = "abc"; char str2[] = "abc"; const char str3[] = "abc"; const char str4[] = "abc"; const char *str5 = "abc"; const char *str6 = "abc"; char *str7 = "abc"; char *str8 = "abc"; cout << ( str1 == str2 ) << endl; cout << ( str3 == str4 ) << endl; cout << ( str5 == str6 ) << endl; cout << ( str7 == str8 ) << endl; 结果是:0 0 1 1 解答:str1,str2,str3,str4是数组变量,它们有各自的内存空间; 而str5,str6,str7,str8是指针,它们指向相同的常量区域。 4. 以下代码中的两个sizeof用法有问题吗?[C易] void UpperCase( char str[] ) // 将 str 中的小写字母转换成大写字母 { for( size_t i=0; i<=str[i] && str[i]<='z' ) str[i] -= ('a'-'A' ); } char str[] = "aBcDe"; cout << "str字符长度为: " << sizeof(str)/sizeof(str[0]) << endl; UpperCase( str ); cout << str << endl; 答:函数内的sizeof有问题。根据语法,sizeof如用于数组,只能测出静态数组的大小,无法检测动态分配的或外部数组大小。函数外的str是一个静态定义的数组,因此其大小为6,函数内的str实际只是一个指向字符串的指针,没有任何额外的与数组相关的信息,因此sizeof作用于上只将其当指针看,一个指针为4个字节,因此返回4。 注意:数组名作为函数参数时,退化为指针. 数组名作为sizeof()参数时,数组名不退化,因为sizeof不是函数. 4. 一个32位的机器,该机器的指针是多少位 指针是多少位只要看地址总线的位数就行了。80386以后的机子都是32的数据总线。所以指针的位数就是4个字节了。 5. 指出下面代码的输出,并解释为什么。(不错,对地址掌握的深入挖潜) main() { int a[5]={1,2,3,4,5}; int *ptr=(int *)(&a+1); printf("%d,%d",*(a+1),*(ptr-1)); } 输出:2,5 *(a+1)就是a[1],*(ptr-1)就是a[4],执行结果是2,5 &a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int) int *ptr=(int *)(&a+1); 则ptr实际是&(a[5]),也就是a+5 原因如下: &a是数组指针,其类型为 int (*)[5]; 而指针加1要根据指针类型加上一定的值, 不同类型的指针+1之后增加的大小不同 a是长度为5的int数组指针,所以要加 5*sizeof(int) 所以ptr实际是a[5] 但是prt与(&a+1)类型是不一样的(这点很重要) 所以prt-1只会减去sizeof(int*) a,&a的地址是一样的,但意思不一样,a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5]. 6.请问以下代码有什么问题: 1). int main() { char a; char *str=&a; strcpy(str,"hello"); printf(str); return 0; } 答;没有为str分配内存空间,将会发生异常 问题出在将一个字符串复制进一个字符变量指针所指地址。虽然可以正确输出结果,但因为越界进行内在读写而导致程序崩溃。 Strcpy的在库函数string.h中.程序的主要错误在于越界进行内存读写导致程序崩溃// 2). char* s="AAA"; printf("%s",s); s[0]='B'; printf("%s",s); 有什么错? 答: "AAA"是字符串常量。s是指针,指向这个字符串常量,所以声明s的时候就有问题。 cosnt char* s="AAA"; 然后又因为是常量,所以对是s[0]的赋值操作是不合法的。 1、写一个“标准”宏,这个宏输入两个参数并返回较小的一个。 答:#define Min(X, Y) ((X)>(Y)?(Y):(X)) //结尾没有; 2、嵌入式系统中经常要用到无限循环,你怎么用C编写死循环。 答:while(1){}或者for(;;) //前面那个较好 3、关键字static的作用是什么? 答:1)定义静态局部变量,作用域从函数开始到结束. 2) 在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内; 3) 在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝 4、关键字const有什么含意? 答 :1)表示常量不可以修改的变量。 2)可以修饰参数,作为输入参数. 3)修饰函数,防止以外的改动. 4)修饰类的成员函数,不改变类中的数据成员. 5、关键字volatile有什么含意?并举出三个不同的例子? 答: 提示编译器对象的值可能在编译器未监测到的情况下改变。 例子: 硬件时钟;多线程中被多个任务共享的变量等 6. int (*s[10])(int) 表示的是什么啊 int (*s[10])(int) 函数指针数组,每个指针指向一个int func(int param)的函数。 1.有以下表达式: int a=248; b=4;int const c=21;const int *d=&a; int *const e=&b;int const *f const =&a; 请问下列表达式哪些会被编译器禁止?为什么? 答:*c=32;d=&b;*d=43;e=34;e=&a;f=0x321f; *c 这是个什么东东,禁止 *d 说了是const, 禁止 e = &a 说了是const 禁止 const *f const =&a; 禁止 2.交换两个变量的值,不使用第三个变量。即a=3,b=5,交换之后a=5,b=3; 答:有两种解法, 一种用算术算法, 一种用^(异或) a = a + b; b = a - b; a = a - b; or a = a^b;// 只能对int,char.. b = a^b; a = a^b; or a ^= b ^= a; 3.c和c++中的struct有什么不同? 答: c和c++中struct的主要区别是c中的struct不可以含有成员函数,而c++中的struct可以。c++中struct和class的主要区别在于默认的存取权限不同,struct默认为public,而class默认为private. 4.#include #include void getmemory(char *p) { p=(char *) malloc(100); } int main( ) { char *str=NULL; getmemory(str); strcpy(p,"hello world"); printf("%s/n",str); free(str); return 0; } 答: 程序崩溃,getmemory中的malloc 不能返回动态内存, free()对str操作很危险 5.char szstr[10]; strcpy(szstr,"0123456789"); 产生什么结果?为什么? 答;正常输出,长度不一样,会造成非法的OS,覆盖别的内容. 6.列举几种进程的同步机制,并比较其优缺点。 答:原子操作 信号量机制 自旋锁 管程,会合,分布式系统 7.进程之间通信的途径 答 共享存储系统 消息传递系统 管道:以文件系统为基础 面试经典试题 silver6 | 02 一月, 2007 11:41 面试经典试题 Author:Vince ————即使你是个编程高手,你在面试前也应该要看看这套题,她也许会给你带来好运,否则你有可能后悔当初为什么没有看而跳楼自杀,这样我会很内疚的。这套题看似简单,但你未必能得高分,即使你看不懂也要把她背下来! 欢迎转载此文,转载时请注明文章来源:文斯测试技术研究中心 http://blog.csdn.net/vincetest 1 编程基础 1.1 基本概念 1. const的理解:const char*, char const*, char*const的区别问题几乎是C++面试中每次 都会有的题目。 事实上这个概念谁都有只是三种声明方式非常相似很容易记混。 Bjarne在他的The C++ Programming Language里面给出过一个助记的方法: 把一个声明从右向左读。 char * const cp; ( * 读成 pointer to ) cp is a const pointer to char const char * p; p is a pointer to const char; char const * p; 同上因为C++里面没有const*的运算符,所以const只能属于前面的类型。 2. c指针 int *p[n];-----指针数组,每个元素均为指向整型数据的指针。 int (*p)[n];------p为指向一维数组的指针,这个一维数组有n个整型数据。 int *p();----------函数带回指针,指针指向返回的值。 int (*p)();------p为指向函数的指针。 3. 数组越界问题 (这个题目还是有点小险的) 下面这个程序执行后会有什么错误或者效果: #define MAX 255 int main() { unsigned char A[MAX],i; for (i=0;i<=MAX;i++) A[i]=i; } 解答:MAX=255,数组A的下标范围为:0..MAX-1,这是其一,其二 当i循环到255时,循环内执行: A[255]=255;这句本身没有问题,但是返回for (i=0;i<=MAX;i++)语句时,由于unsigned char的取值范围在(0..255),i++以后i又为0了..无限循环下去. 注:char类型为一个字节,取值范围是[-128,127],unsigned char [0 ,255] 4. C++:memset ,memcpy 和strcpy 的根本区别? 答:#include "memory.h" memset用来对一段内存空间全部设置为某个字符,一般用在对定义的字符串进行初始化为' '或'';例:char a[100];memset(a, '', sizeof(a)); memcpy用来做内存拷贝,你可以拿它拷贝任何数据类型的对象,可以指定拷贝的数据长度;例:char a[100],b[50]; memcpy(b, a, sizeof(b));注意如用sizeof(a),会造成b的内存地址溢出。 strcpy就只能拷贝字符串了,它遇到'/0'就结束拷贝;例:char a[100],b[50];strcpy(a,b);如用strcpy(b,a),要注意a中的字符串长度(第一个'/0'之前)是否超过50位,如超过,则会造成b的内存地址溢出。 strcpy 原型:extern char *strcpy(char *dest,char *src); { ASSERT((dest!=NULL)&&(src!=NULL)); Char *address = dest; While((*dest++=*src++)!=’/0’) Continue; Return dest; } 用法:#include 功能:把src所指由NULL结束的字符串复制到dest所指的数组中。 说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。 返回指向dest的指针。 memcpy 原型:extern void *memcpy(void *dest, void *src, unsigned int count); { ASSERT((dest!=NULL)&&(src!=NULL)); ASSERT((dest>src+count)||(src>dest+count));//防止内存重叠,也可以用restrict修饰指针 Byte* bdest = (Byte*)dest; Byte* bsrc = (Byte*) src; While(count-->0) *bdest++ = **bsrc++; Return dest; } 用法:#include 功能:由src所指内存区域复制count个字节到dest所指内存区域。 说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针。 Memset 原型:extern void *memset(void *buffer, char c, int count); 用法:#include 功能:把buffer所指内存区域的前count个字节设置成字符c。 说明:返回指向buffer的指针。 5. ASSERT()是干什么用的 答:ASSERT()是一个调试程序时经常使用的宏,在程序运行时它计算括号内的表达式,如果表达式为FALSE (0), 程序将报告错误,并终止执行。如果表达式不为0,则继续执行后面的语句。这个宏通常原来判断程序中是否出现了明显非法的数据,如果出现了终止程序以免导致严重后果,同时也便于查找错误。例如,变量n在程序中不应该为0,如果为0可能导致错误,你可以这样写程序: ...... ASSERT( n != 0); k = 10/ n; ...... ASSERT只有在Debug版本中才有效,如果编译为Release版本则被忽略。 assert()的功能类似,它是ANSI C标准中规定的函数,它与ASSERT的一个重要区别是可以用在Release版本中。 6. system("pause");作用? 答:系统的暂停程序,按任意键继续,屏幕会打印,"按任意键继续。。。。。" 省去了使用getchar(); 7. 请问C++的类和C里面的struct有什么区别? 答:c++中的类具有成员保护功能,并且具有继承,多态这类oo特点,而c里的struct没有 c里面的struct没有成员函数,不能继承,派生等等. 8. 请讲一讲析构函数和虚函数的用法和作用? 答:析构函数也是特殊的类成员函数,它没有返回类型,没有参数,不能随意调用,也没有重载。只是在类对象生命期结束的时候,由系统自动调用释放在构造函数中分配的资源。这种在运行时,能依据其类型确认调用那个函数的能力称为多态性,或称迟后联编。另: 析构函数一般在对象撤消前做收尾工作,比如回收内存等工作, 虚拟函数的功能是使子类可以用同名的函数对父类函数进行覆盖,并且在调用时自动调用子类覆盖函数,如果是纯虚函数,则纯粹是为了在子类覆盖时有个统一的命名而已。 注意:子类重新定义父类的虚函数的做法叫覆盖,override,而不是overload(重载),重载的概念不属于面向对象编程,重载指的是存在多个同名函数,这些函数的参数表不同..重载是在编译期间就决定了的,是静态的,因此,重载与多态无关.与面向对象编程无关. 含有纯虚函数的类称为抽象类,不能实例化对象,主要用作接口类// 9. 全局变量和局部变量有什么区别?是怎么实现的?操作系统和编译器是怎么知道的? 答;全局变量的生命周期是整个程序运行的时间,而局部变量的生命周期则是局部函数或过程调用的时间段。其实现是由编译器在编译时采用不同内存分配方法。 全局变量在main函数调用后,就开始分配, 静态变量则是在main函数前就已经初始化了。 局部变量则是在用户栈中动态分配的(还是建议看编译原理中的活动记录这一块) 10. 8086是多少位的系统?在数据总线上是怎么实现的? 答:8086系统是16位系统,其数据总线是20位。 12 程序设计 1. 编写用C语言实现的求n阶阶乘问题的递归算法: 答:long int fact(int n) { If(n==0||n==1) Return 1; Else Return n*fact(n-1); } 2. 二分查找算法: 1) 递归方法实现: int BSearch(elemtype a[],elemtype x,int low,int high) { int mid; if(low>high) return -1; mid=(low+high)/2; if(x==a[mid]) return mid; if(x<=high) { mid=(low+high)/2; if(a[mid].key==key) return mid; else if(a[mid].key2 解:非递归算法: int f(int n) { int i,s,s1,s2; s1=1; s2=1; s=1; for(i=3;i<=n;i++) { s=s1+s2; s2=s1; s1=s; } return(s); } 递归算法: Int f(int n) { If(n==1||n==2) Rerurn 1; Else Rerutn f(n-1)+f(n-2); } 4. 交换两个数,不用第三块儿内存: 答:int a = ……; int b = ……; a = a + b; b = a - b; a = a - b; 5. 冒泡排序: 答:void BubbleSort(elemtype x[],int n) //时间复杂度为0(n*n); { int i,j; elemtype temp; for(i=1;ix[j+1].key) { temp=x[j]; x[j]=x[j+1]; x[j+1]=temp; } } } //补充一个改进的冒泡算法: void BubbleSort(elemtype x[],int n) { Int i,j; BOOL exchange; //记录交换标志 for(i=1;i=i;--j) { If(x[j]>x[j+1]) { x[0] = x[j]; X[j] = x[j+1]; X[j+1] = x[0]; Exchange = true; //发生了交换,设置标志为真. } } if (!Exchange ) //为发生替换,提前终止算法 return; } } 6. c语言 文件读写 #include "stdio.h" main() { FILE *fp; char ch,filename[10]; scanf("%s",filename); if((fp=fopen(filename,"w")==NULL) { printf("cann't open filen"); exit(0); } ch=getchar(); while(ch!='#') { fputc(ch,fp); putchar(ch); ch=getchar(); } fclose(fp); } 7. winsocket编程 //这个不错 // 服务器代码 #include #include void main() { WORD wVersionRequested; //版本号 WSADATA wsaData; //数据 int err; wVersionRequested = MAKEWORD(1,1); err = WSAStartup(wVersionRequested,&wsaData); if( err != 0) { return; } if(LOBYTE( wsaData.wVersion ) != 1|| HIBYTE( wsaData.wVersion) != 1) { WSACleanup(); return; } SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0); //建立套接字 SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY); addrSrv.sin_family=AF_INET; addrSrv.sin_port=htons(6000); bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); //绑定端口 listen(sockSrv,5); //转换socket套接子为侦听套接子 SOCKADDR_IN addrClient; int len=sizeof(SOCKADDR); while(1) //无限循环 { SOCKET sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len); char sendBuf[100]; sprint(sendBuf,"Welcome %s to http://www.sunxin.org", inet_ntoa(addrClient.sin_addr)); send(sockConn,sendBuf,strlen(sendBuf)+1,0); char recvBuf[100]; recv(sockConn,recvBuf); printf("%sn",recvBuf); closesocket(sockConn); WSACleanup(); } } 注:这是Server端;File->New->Win32 Console Application,工程名:TcpSrv;然后,File->New->C++ Source File,文件名:TcpSrv;在该工程的Setting的Link的Object/library modules项要加入ws2_32.lib #include #include void main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(1,1); err = WSAStartup(wVersionRequested,&wsaData); //启动winsock Dll if( err != 0) { return; } if(LOBYTE( wsaData.wVersion ) != 1|| HIBYTE( wsaData.wVersion) != 1) { WSACleanup(); return; } SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0); SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1"); addrSrv.sin_family=AF_INET; addrSrv.sin_port = htons(6000); connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); char recvBuf[100]; recv(sockClient,recvBuf,100,0); printf("%sn",recvBuf); send(sockClient,"This is zhangsan",strlen("This is zhangsan")+1,0); closesocket(sockClient); WSACleanup(); } 注:这是Client端;File->New->Win32 Console Application,工程名:TcpClient;然后,File->New->C++ Source File,文件名:TcpClient;同理,在该工程的Setting的Link的Object/library modules项要加入ws2_32.lib 8. 类的知识 (非常不错的一道题目).. C++ #include class human { public: human(){ human_num++;}; //默认构造函数 static int human_num; //静态成员 ~human() { human_num--; print(); } void print() // { cout<<"human num is: "<<<10; i++)  {   str1[i] = 'a';  }  strcpy( string, str1 ); }   试题3: void test3(char* str1) {  char string[10];  if( strlen( str1 ) <= 10 )  {   strcpy( string, str1 );  } }   解答:   试题1字符串str1需要11个字节才能存放下(包括末尾的’’),而string只有10个字节的空间,strcpy会导致数组越界;   对试题2,如果面试者指出字符数组str1不能在数组内结束可以给3分;如果面试者指出strcpy(string, str1)调用使得从str1内存起复制到string内存起所复制的字节数具有不确定性可以给7分,在此基础上指出库函数strcpy工作方式的给10 分;   对试题3,if(strlen(str1) <= 10)应改为if(strlen(str1) < 10),因为strlen的结果未统计’’所占用的1个字节。   剖析:   考查对基本功的掌握:   (1)字符串以’/0’结尾;   (2)对数组越界把握的敏感度;   (3)库函数strcpy的工作方式,如果编写一个标准strcpy函数的总分值为10,下面给出几个不同得分的答案:   2分 void strcpy( char *strDest, char *strSrc ) {   while( (*strDest++ = * strSrc++) != '’ ); }   4分 void strcpy( char *strDest, const char *strSrc ) //将源字符串加const,表明其为输入参数,加2分 {   while( (*strDest++ = * strSrc++) != '’ ); }   7分 void strcpy(char *strDest, const char *strSrc) {  //对源地址和目的地址加非0断言,加3分  assert( (strDest != NULL) && (strSrc != NULL) );  while( (*strDest++ = * strSrc++) != '’ ); }   10分 //为了实现链式操作,将目的地址返回,加3分! char * strcpy( char *strDest, const char *strSrc ) {  assert( (strDest != NULL) && (strSrc != NULL) );  char *address = strDest;  while( (*strDest++ = * strSrc++) != '’ );   return address; }   从2分到10分的几个答案我们可以清楚的看到,小小的strcpy竟然暗藏着这么多玄机,真不是盖的!需要多么扎实的基本功才能写一个完美的strcpy啊!   (4)对strlen的掌握,它没有包括字符串末尾的''。   读者看了不同分值的strcpy版本,应该也可以写出一个10分的strlen函数了,完美的版本为: int strlen( const char *str ) //输入参数const {  assert( strt != NULL ); //断言字符串地址非0  int len;  while( (*str++) != '' )  {   len++;  }  return len; }   试题4: void GetMemory( char *p ) {  p = (char *) malloc( 100 ); } void Test( void ) {  char *str = NULL;  GetMemory( str );  strcpy( str, "hello world" );  printf( str ); }   试题5: char *GetMemory( void ) {  char p[] = "hello world";  return p; } void Test( void ) {  char *str = NULL;  str = GetMemory();  printf( str ); }   试题6: void GetMemory( char **p, int num ) {  *p = (char *) malloc( num ); } void Test( void ) {  char *str = NULL;  GetMemory( &str, 100 );  strcpy( str, "hello" );  printf( str ); }   试题7: void Test( void ) {  char *str = (char *) malloc( 100 );  strcpy( str, "hello" );  free( str );  ... //省略的其它语句 }   解答:   试题4传入中GetMemory( char *p )函数的形参为字符串指针,在函数内部修改形参并不能真正的改变传入形参的值,执行完 char *str = NULL; GetMemory( str );   后的str仍然为NULL;   试题5中 char p[] = "hello world"; return p;   的p[]数组为函数内的局部自动变量,在函数返回后,内存已经被释放。这是许多程序员常犯的错误,其根源在于不理解变量的生存期。   试题6的GetMemory避免了试题4的问题,传入GetMemory的参数为字符串指针的指针,但是在GetMemory中执行申请内存及赋值语句 *p = (char *) malloc( num );   后未判断内存是否申请成功,应加上: if ( *p == NULL ) {  ...//进行申请内存失败处理 }   试题7存在与试题6同样的问题,在执行 char *str = (char *) malloc(100);   后未进行内存是否申请成功的判断;另外,在free(str)后未置str为空,导致可能变成一个“野”指针,应加上: str = NULL;   试题6的Test函数中也未对malloc的内存进行释放。   剖析:   试题4~7考查面试者对内存操作的理解程度,基本功扎实的面试者一般都能正确的回答其中50~60的错误。但是要完全解答正确,却也绝非易事。   对内存操作的考查主要集中在:   (1)指针的理解;   (2)变量的生存期及作用范围;   (3)良好的动态内存申请和释放习惯。   再看看下面的一段程序有什么错误: swap( int* p1,int* p2 ) {  int *p;  *p = *p1;  *p1 = *p2;  *p2 = *p; }   在swap函数中,p是一个“野”指针,有可能指向系统区,导致程序运行的崩溃。在VC++中DEBUG运行时提示错误“Access Violation”。该程序应该改为: swap( int* p1,int* p2 ) {  int p;  p = *p1;  *p1 = *p2;  *p2 = p; }   3.内功题   试题1:分别给出BOOL,int,float,指针变量 与“零值”比较的 if 语句(假设变量名为var)   解答:    BOOL型变量:if(!var)    int型变量: if(var==0)    float型变量:    const float EPSINON = 0.00001;    if ((x >= - EPSINON) && (x <= EPSINON)    指针变量:  if(var==NULL)   剖析:   考查对0值判断的“内功”,BOOL型变量的0判断完全可以写成if(var==0),而int型变量也可以写成if(!var),指针变量的判断也可以写成if(!var),上述写法虽然程序都能正确运行,但是未能清晰地表达程序的意思。   一般的,如果想让if判断一个变量的“真”、“假”,应直接使用if(var)、if(!var),表明其为“逻辑”判断;如果用if判断一个数值型变量(short、int、long等),应该用if(var==0),表明是与0进行“数值”上的比较;而判断指针则适宜用if(var==NULL),这是一种很好的编程习惯。   浮点型变量并不精确,所以不可将float变量用“==”或“!=”与数字比较,应该设法转化成“>=”或“<=”形式。如果写成if (x == 0.0),则判为错,得0分。   试题2:以下为Windows NT下的32位C++程序,请计算sizeof的值 void Func ( char str[100] ) {  sizeof( str ) = ? } void *p = malloc( 100 ); sizeof ( p ) = ?   解答: sizeof( str ) = 4 sizeof ( p ) = 4   剖析:   Func ( char str[100] )函数中数组名作为函数形参时,在函数体内,数组名失去了本身的内涵,仅仅只是一个指针;在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。   数组名的本质如下:   (1)数组名指代一种数据结构,这种数据结构就是数组;   例如: char str[10]; cout << sizeof(str) << endl;   输出结果为10,str指代数据结构char[10]。   (2)数组名可以转换为指向其指代实体的指针,而且是一个指针常量,不能作自增、自减等操作,不能被修改; char str[10]; str++; //编译出错,提示str不是左值    (3)数组名作为函数形参时,沦为普通指针。   Windows NT 32位平台下,指针的长度(占用内存的大小)为4字节,故sizeof( str ) 、sizeof ( p ) 都为4。   试题3:写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。另外,当你写下面的代码时会发生什么事? least = MIN(*p++, b);   解答: #define MIN(A,B) ((A) <= (B) ? (A) : (B))   MIN(*p++, b)会产生宏的副作用   剖析:   这个面试题主要考查面试者对宏定义的使用,宏定义可以实现类似于函数的功能,但是它终归不是函数,而宏定义中括弧中的“参数”也不是真的参数,在宏展开的时候对“参数”进行的是一对一的替换。   程序员对宏定义的使用要非常小心,特别要注意两个问题:   (1)谨慎地将宏定义中的“参数”和整个宏用用括弧括起来。所以,严格地讲,下述解答: #define MIN(A,B) (A) <= (B) ? (A) : (B) #define MIN(A,B) (A <= B ? A : B )   都应判0分;   (2)防止宏的副作用。   宏定义#define MIN(A,B) ((A) <= (B) ? (A) : (B))对MIN(*p++, b)的作用结果是: ((*p++) <= (b) ? (*p++) : (*p++))   这个表达式会产生副作用,指针p会作三次++自增操作。   除此之外,另一个应该判0分的解答是: #define MIN(A,B) ((A) <= (B) ? (A) : (B));   这个解答在宏定义的后面加“;”,显示编写者对宏的概念模糊不清,只能被无情地判0分并被面试官淘汰。   试题4:为什么标准头文件都有类似以下的结构? #ifndef __INCvxWorksh #define __INCvxWorksh #ifdef __cplusplus extern "C" { #endif #ifdef __cplusplus } #endif #endif   解答:   头文件中的编译宏 #ifndef __INCvxWorksh #define __INCvxWorksh #endif   的作用是防止被重复引用。   作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在symbol库中的名字与C语言的不同。例如,假设某个函数的原型为: void foo(int x, int y);   该函数被C编译器编译后在symbol库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。_foo_int_int这样的名字包含了函数名和函数参数数量及类型信息,C++就是考这种机制来实现函数重载的。   为了实现C和C++的混合编程,C++提供了C连接交换指定符号extern "C"来解决名字匹配问题,函数声明前加上extern "C"后,则编译器就会按照C语言的方式将该函数编译为_foo,这样C语言中就可以调用C++的函数了。  试题5:编写一个函数,作用是把一个char组成的字符串循环右移n个。比如原来是“abcdefghi”如果n=2,移位后应该是“hiabcdefgh”   函数头是这样的: //pStr是指向以''结尾的字符串的指针 //steps是要求移动的n void LoopMove ( char * pStr, int steps ) {  //请填充... }   解答:   正确解答1: void LoopMove ( char *pStr, int steps ) {  int n = strlen( pStr ) - steps;  char tmp[MAX_LEN];  strcpy ( tmp, pStr + n );  strcpy ( tmp + steps, pStr);  *( tmp + strlen ( pStr ) ) = '';  strcpy( pStr, tmp ); }   正确解答2: void LoopMove ( char *pStr, int steps ) {  int n = strlen( pStr ) - steps;  char tmp[MAX_LEN];  memcpy( tmp, pStr + n, steps );  memcpy(pStr + steps, pStr, n );  memcpy(pStr, tmp, steps ); }   剖析:   这个试题主要考查面试者对标准库函数的熟练程度,在需要的时候引用库函数可以很大程度上简化程序编写的工作量。   最频繁被使用的库函数包括:   (1) strcpy   (2) memcpy   (3) memset   试题6:已知WAV文件格式如下表,打开一个WAV文件,以适当的数据结构组织WAV文件头并解析WAV格式的各项信息。   WAVE文件格式说明表 偏移地址 字节数 数据类型 内 容 文件头 00H 4 Char "RIFF"标志 04H 4 int32 文件长度 08H 4 Char "WAVE"标志 0CH 4 Char "fmt"标志 10H 4 过渡字节(不定) 14H 2 int16 格式类别 16H 2 int16 通道数 18H 2 int16 采样率(每秒样本数),表示每个通道的播放速度 1CH 4 int32 波形音频数据传送速率 20H 2 int16 数据块的调整数(按字节算的) 22H 2 每样本的数据位数 24H 4 Char 数据标记符"data" 28H 4 int32 语音数据的长度   解答:   将WAV文件格式定义为结构体WAVEFORMAT: typedef struct tagWaveFormat {  char cRiffFlag[4];  UIN32 nFileLen;  char cWaveFlag[4];  char cFmtFlag[4];  char cTransition[4];  UIN16 nFormatTag ;  UIN16 nChannels;  UIN16 nSamplesPerSec;  UIN32 nAvgBytesperSec;  UIN16 nBlockAlign;  UIN16 nBitNumPerSample;  char cDataFlag[4];  UIN16 nAudioLength; } WAVEFORMAT;   假设WAV文件内容读出后存放在指针buffer开始的内存单元内,则分析文件格式的代码很简单,为: WAVEFORMAT waveFormat; memcpy( &waveFormat, buffer,sizeof( WAVEFORMAT ) );   直接通过访问waveFormat的成员,就可以获得特定WAV文件的各项格式信息。   剖析:   试题6考查面试者组织数据结构的能力,有经验的程序设计者将属于一个整体的数据成员组织为一个结构体,利用指针类型转换,可以将memcpy、memset等函数直接用于结构体地址,进行结构体的整体操作。 透过这个题可以看出面试者的程序设计经验是否丰富。   试题7:编写类String的构造函数、析构函数和赋值函数,已知类String的原型为: class String {  public:   String(const char *str = NULL); // 普通构造函数   String(const String &other); // 拷贝构造函数   ~ String(void); // 析构函数   String & operate =(const String &other); // 赋值函数  private:   char *m_data; // 用于保存字符串 };   解答: //普通构造函数 String::String(const char *str) {  if(str==NULL)  {   m_data = new char[1]; // 得分点:对空字符串自动申请存放结束标志''的空   //加分点:对m_data加NULL 判断   *m_data = '/0';  }  else  {   int length = strlen(str);   m_data = new char[length+1]; // 若能加 NULL 判断则更好   strcpy(m_data, str);  } } // String的析构函数 String::~String(void) {  delete [] m_data; // 或delete m_data; } //拷贝构造函数 String::String(const String &other)    // 得分点:输入参数为const型 {  int length = strlen(other.m_data);  m_data = new char[length+1];     //加分点:对m_data加NULL 判断  strcpy(m_data, other.m_data); } //赋值函数 String & String::operate =(const String &other) // 得分点:输入参数为const型 {  if(this == &other)   //得分点:检查自赋值   return *this;  delete [] m_data;     //得分点:释放原有的内存资源  int length = strlen( other.m_data );  m_data = new char[length+1];  //加分点:对m_data加NULL 判断  strcpy( m_data, other.m_data );  return *this;         //得分点:返回本对象的引用 }   剖析:   能够准确无误地编写出String类的构造函数、拷贝构造函数、赋值函数和析构函数的面试者至少已经具备了C++基本功的60%以上!   在这个类中包括了指针类成员变量m_data,当类中包括指针类成员变量时,一定要重载其拷贝构造函数、赋值函数和析构函数,这既是对C++程序员的基本要求,也是《Effective C++》中特别强调的条款。   仔细学习这个类,特别注意加注释的得分点和加分点的意义,这样就具备了60%以上的C++基本功!   试题8:请说出static和const关键字尽可能多的作用   解答:   static关键字至少有下列n个作用:   (1)函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;   (2)在模块内的static全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;   (3)在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;   (4)在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;   (5)在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量。   const关键字至少有下列n个作用:   (1)欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化,因为以后就没有机会再去改变它了;   (2)对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const;   (3)在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;   (4)对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的成员变量;   (5)对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为“左值”。例如: const classA operator*(const classA& a1,const classA& a2);   operator*的返回结果必须是一个const对象。如果不是,这样的变态代码也不会编译出错: classA a, b, c; (a * b) = c; // 对a*b的结果赋值   操作(a * b) = c显然不符合编程者的初衷,也没有任何意义。   剖析:   惊讶吗?小小的static和const居然有这么多功能,我们能回答几个?如果只能回答1~2个,那还真得闭关再好好修炼修炼。   这个题可以考查面试者对程序设计知识的掌握程度是初级、中级还是比较深入,没有一定的知识广度和深度,不可能对这个问题给出全面的解答。大多数人只能回答出static和const关键字的部分功能。   4.技巧题   试题1:请写一个C函数,若处理器是Big_endian的,则返回0;若是Little_endian的,则返回1   解答: int checkCPU() {  {   union w   {    int a;    char b;   } c;   c.a = 1;   return (c.b == 1);  } }   剖析:  嵌入式系统开发者应该对Little-endian和Big-endian模式非常了解。采用Little-endian模式的CPU对操作数的存放方式是从低字节到高字节,而Big-endian模式对操作数的存放方式是从高字节到低字节。例如,16bit宽的数0x1234在Little- endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为: 内存地址 存放内容 0x4000 0x34 0x4001 0x12   而在Big-endian模式CPU内存中的存放方式则为: 内存地址 存放内容 0x4000 0x12 0x4001 0x34   32bit宽的数0x12345678在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为: 内存地址 存放内容 0x4000 0x78 0x4001 0x56 0x4002 0x34 0x4003 0x12   而在Big-endian模式CPU内存中的存放方式则为: 内存地址 存放内容 0x4000 0x12 0x4001 0x34 0x4002 0x56 0x4003 0x78   联合体union的存放顺序是所有成员都从低地址开始存放,面试者的解答利用该特性,轻松地获得了CPU对内存采用Little-endian还是Big-endian模式读写。如果谁能当场给出这个解答,那简直就是一个天才的程序员。   试题2:写一个函数返回1+2+3+…+n的值(假定结果不会超过长整型变量的范围)   解答: int Sum( int n ) {  return ( (long)1 + n) * n / 2;  //或return (1l + n) * n / 2; }   剖析:   对于这个题,只能说,也许最简单的答案就是最好的答案。下面的解答,或者基于下面的解答思路去优化,不管怎么“折腾”,其效率也不可能与直接return ( 1 l + n ) * n / 2相比! int Sum( int n ) {  long sum = 0;  for( int i=1; i<=n; i++ )  {   sum += i;  }  return sum; }   所以程序员们需要敏感地将数学等知识用在程序设计中。 终于明白了:按值传递意味着当将一个参数传递给一个函数时,函数接收的是原始值的一个副本。因此,如果函数修改了该参数,仅改变副本,而原始值保持不变。按引用传递意味着当将一个参数传递给一个函数时,函数接收的是原始值的内存地址,而不是值的副本。因此,如果函数修改了该参数,调用代码中的原始值也随之改变。 不管是在c/c++中还是在java函数调用都是传值调用,. 当参数是对象的时候,传递的是对象的引用,这个和c/c++传递指针是一个道理,在函数中改变引用本身,不会改变引用所指向的对象. 华为面试题 4、SQL问答题 SELECT * FROM TABLE 和 SELECT * FROM TABLE WHERE NAME LIKE '%%' AND ADDR LIKE '%%' AND (1_ADDR LIKE '%%' OR 2_ADDR LIKE '%%' OR 3_ADDR LIKE '%%' OR 4_ADDR LIKE '%%' ) 的检索结果为何不同? 答: 前者检索全部,后者有三种情况检索不出:NAME=null或ADDR=null或1_ADDR LIKE 2_ADDR 3_ADDR 4_ADDR其一为null. 前者检索所有记录,后者只能检索出 NAME 和ADDR中非Null的记录。 5、SQL问答题 表结构: 1、 表名:g_cardapply 字段(字段名/类型/长度): g_applyno varchar 8;//申请单号(关键字) g_applydate bigint 8;//申请日期 g_state varchar 2;//申请状态 2、 表名:g_cardapplydetail 字段(字段名/类型/长度): g_applyno varchar 8;//申请单号(关键字) g_name varchar 30;//申请人姓名 g_idcard varchar 18;//申请人身份证号 g_state varchar 2;//申请状态 其中,两个表的关联字段为申请单号。 题目: 1、 查询身份证号码为440401430103082的申请日期 select A.g_applydate from g_cardapply A inner join g_cardapplydetail B on A.g_applyno = B.g_applyno where B.g_idCard = '440401430103082' 2、 查询同一个身份证号码有两条以上记录的身份证号码及记录个数 select g_idCard,count(*) as Cnt from g_cardapplydetail group by g_idcard having count(*) > 1 3、 将身份证号码为440401430103082的记录在两个表中的申请状态均改为07 update g_cardapplydetail set g_state = '07' where g_idcard = '440401430103082' update A set g_state = '07' from g_cardapply A inner join g_cardapplydetail B on A.g_applyno = B.g_applyno where B.g_idcard = '440401430103082' 4、 删除g_cardapplydetail表中所有姓李的记录 delete from g_cardapplydetail where g_name like '李%' 3、 将身份证号码为440401430103082的记录在两个表中的申请状态均改为07 update g_cardapplydetail set g_state = '07' where g_idcard = '440401430103082' update A set g_state = '07' from g_cardapply A inner join g_cardapplydetail B on A.g_applyno = B.g_applyno where B.g_idcard = '440401430103082' 5、SQL问答题: 通过测试 PS:偶GF做的,自己先汗一下 金山公司几道面试题 4. In C++, there're four type of Casting Operators, please enumerate and explain them especially the difference. 解析: C++类型转换问题 答案: reinterpret_cast,static_cast,const_cast,dynamic_cast static_cast 数制转换 dynamic_cast 用于执行向下转换和在继承之间的转换 const_cast 去掉const reinterpret_cast 用于执行并不安全的orimplmentation_dependent类型转换 7 以下代码有什么问题,如何修改? #include #include using namespace std; void print(vector); int main() { vector array; array.push_back(1); array.push_back(6); array.push_back(6); array.push_back(3); //删除array数组中所有的6 vector::iterator itor; vector::iterator itor2; itor=array.begin(); for(itor=array.begin(); itor!=array.end(); ) { if(6==*itor) { itor2=itor; array.erase(itor2); } itor++; } print(array); return 0; } void print(vector v) { cout << "n vector size is: " << v.size() << endl; vector::iterator p = v.begin(); } 我的答案是,迭代器问题,只能删除第一个6,以后迭代器就失效了,不能删除之后的元素。 但我不知道怎么改 void print(const vector&); int main() { vector array; array.push_back(1); array.push_back(6); array.push_back(6); array.push_back(3); //删除array数组中所有的6 array.erase( remove( array.begin(), array.end(), 6 ) , array.end() ); print(array); return 0; } void print(const vector& v) { cout << "n vector size is: " << v.size() << endl; copy(v.begin(), v.end(), ostream_iterator(cout, " ") ); } #include #include using namespace std; int main() { vector array; array.push_back(1); array.push_back(6); array.push_back(6); array.push_back(6); array.push_back(6); array.push_back(6); array.push_back(3); array.push_back(9); array.push_back(8); array.push_back(5); //ɾ³ýarrayÊý×éÖÐËùÓеÄ6 vector::iterator itor; itor=array.begin(); for(itor=array.begin(); itor!=array.end();++itor ) { if(6==*itor) { itor=array.erase(itor); --itor; } } cout << "vector size is: " << array.size() << endl; for(itor=array.begin(); itor!=array.end();++itor ) { cout<<*itor<<" "; } system("pause"); return 0; } 答案: 执行itor=array.erase(itor);这句话后,itor不会移动,而只是把删除的数后面的数都往前移一位,所以删除了第一个6后,指针指向第2个6,然后在来个itor++,指针就指向array.end()了,给你画个草图: 1 6 6 3 array.end() //最开始指针itor指向第一个6; 1 6 3 array.end() //删除第一个6后,指向第二个6 1 6 3 array.end() //itor++后,就指向3了,所以不能删除 2. What are three ways in which a thread can enter the waiting state? 答: CPU调度给优先级更高的thread,原先thread进入waiting 阻塞的thread获得资源或者信号,进入waiting 还有什么 面试与被面试总结 我从事技术工作, 这几年的面试与被面试总结 先说我去被面试的经验吧。 回答清楚了2个问题,就能顺利过关了。 1。为什么要离开上一家公司。 2。公司为什么要雇佣你。 问第一个问题的是hr(或老板),呵呵 ,即使你技术过关,hr那里没有好的影响,结果是一个字,难! 如何回答呢? hr想推论出你在他的公司能呆多久。这个时候,你甚至可以明确告诉他,我在贵公司至少能呆n(n>=1)年----当然,你没有把握的话,绝对不能乱说,社会上混,要讲信用的。 有一次,我就在这个问题上吃了大亏,我看公司环境还不错,就我自做主张回答1年,结果,hr心目中是m(m>=2)年,呵呵,结果可想而知了。要知道,技术面试都过关了,Hr面试是2选1,在回家的路上,我只能祈祷对手自动放弃或找到了其他更好的工作。:) 问第二个问题的是技术官。你要让他知道你已经做过哪些商业作品。一定要是商业作品。在里面负责哪方面具体工作,对于你熟悉的地方要多说。最好就是能争取笔试或上机,因为用用口说的话,大家理解都不一样,误差可能很大,结果对你相当不利。在这个问题上我也吃过亏的,曾有一个我很看好的职位,认为把握很大,业务理解上也很有优势,和技术官一谈,结果是game over。要知道,在其他公司的上机和笔试中,我都能在应聘者中取得高分。 再说我去面试别人的经验吧。 当时,我的任务是出题,给分。若你觉得题很难,那么,请千万不要放弃,显然,你的对手也觉得难。只要坚持,我会认为这人有耐心很毅力,在以后的工作中也是好的合作者。题一定要做完,表现出认真的态度,若有疑问或卡壳,还可以寻求面试官的帮助,这些不会减分,相反,会增加你和他们的接触机会,面试官会评估你的沟通能力。 有一次,有1个人来面试,题没有完全ok,但很规范,态度很认真,他把他知道的都做上去了,我给了他技术类的高分。后来,顺利进入公司,再后来进步很快,成了重要角色。 若文章对你有帮助的话,请在此讨论。 祝你成功 面试题 1.链表和数组的区别在哪里? 2.编写实现链表排序的一种算法。说明为什么你会选择用这样的方法? 3.编写实现数组排序的一种算法。说明为什么你会选择用这样的方法? 4.请编写能直接实现strstr()函数功能的代码。 5.编写反转字符串的程序,要求优化速度、优化空间。 6.在链表里如何发现循环链接? 7.给出洗牌的一个算法,并将洗好的牌存储在一个整形数组里。 8.写一个函数,检查字符是否是整数,如果是,返回其整数值。(或者:怎样只用4行代码 ,编写出一个从字符串到长整形的函数?) 9.给出一个函数来输出一个字符串的所有排列。 10.请编写实现malloc()内存分配函数功能一样的代码。 11.给出一个函数来复制两个字符串A和B。字符串A的后几个字节和字符串B的前几个字节重叠。 12.怎样编写一个程序,把一个有序整数数组放到二叉树中? 13.怎样从顶部开始逐层打印二叉树结点数据?请编程。 14.怎样把一个链表掉个顺序(也就是反序,注意链表的边界条件并考虑空链表)? 另外: 一、单项选择题:(共12题,每题2分,共24分) 1. 下面哪一个不是C++的标准数据类型? ( D) A. int B. char C. bool D. real 2. break关键字在哪一种语法结构中不能使用? (C) A. for语句 B. switch语句 C. if语句 D. while语句 3. 类的继承方式有几种? (B ) A. 两种 B. 三种 C. 四种 D. 六种 4. extern关键字的作用是什么? (D) A. 声明外部链接 B. 声明外部头文件引用 C. 声明使用扩展C++语句 D. 声明外部成员函数、成员数据。 5. C库函数strstr的功能是? (A ) A. 查找子串 B. 计算字符串长度 C. 字符串比较 D. 连结字符串 6. stl::deque是一种什么数据类型? (A ) A. 动态数组 B. 链表 C. 堆栈 D. 树 7. STL库里含有下面的哪一种泛型算法? (D ) A. KMP查找 B. 折半查找 C. 冒泡排序 D. 快速排序 8. 现在最快且最通用的排序算法是什么? (A ) A. 快速排序 B. 冒泡排序 C. 选择排序 D. 外部排序 9. Win32下的线程的哪一种优先级最高? ( C) A. THREAD_PRIORITY_HIGHEST 高优先级 B. THREAD_PRIORITY_IDLE 最低优先级,仅在系统空闲时执行 C. THREAD_PRIORITY_TIME_CRITICAL 最高优先级 D. THREAD_PRIORITY_ABOVE_NORMAL 高于普通优先级 10. 下面四个选项中,哪一个不是WinMain函数的参数? (D ) A. HINSTANCE B. INT C. LPSTR D. WPARAM 11. VC++的编译器中,运算符new底层的实现是什么? (B ) A. VirtualAlloc() B. HeapAlloc() C. GlobalAlloc() D. AllocateUserPhysicalPages() 12. 下面哪一本C++参考书最厚? ( C) A. 《Think in C++》 B. 《深入浅出MFC》 C. 《C++ Primer》 D. 《Effective C++》 13. 当调用Windows API函数InvalidateRect,将会产生什么消息(A) A. WM_PAINT B. WM_CREATE C. WM_NCHITTEST D. WM_SETFOCUS 14. 关于virtual void Draw()=0,下面说法正确的有几个(C) (1)它是纯虚函数(对) (2)它在定义它的类中不能实现(对) (3)定义它的类不可实例化(对) (4)如果一个类要继承一个ADT类,必须要实现其中的所有纯虚函数(错)//可以不实现,派生之后的类仍旧作为一个抽象类. A. 1 B. 2 C. 3 D. 4 二、不定项选择题:(共6题,每题3分,共18分,多选、错选、漏选均不给分) 1. vector::iterator重载了下面哪些运算符? (ACD) A. ++ B. >> C. *(前置) D. == 2. CreateFile( )的功能有哪几个? (AB ) A. 打开文件 B. 创建新文件 C. 文件改名 D. 删除文件 3. 下面哪些是句柄(HANDLE)? (ABCD ) A. HINSTANCE 实例句柄B. HWND 窗口句柄 C. HDC 设备描述符号句柄 D. HFONT 字体句柄 4. 下面哪些不是OpenGL标准几何元素的绘制模式? (A ) A. GL_FOG B. GL_LINE_STRIP C. GL_POINTS D. GL_TRIANGLE_FAN 5. 下面哪些运算符不能被重载? (ABD ) A. 做用域运算符“::” B. 对象成员运算符“.” C. 指针成员运算符“->” D. 三目运算符“? :” 6. 下面哪些人曾参与了世界上第一个C++编译器的开发? ( ) A. Bill Gates B. Stanley Lippman C. Anderson Hejlsberg D. Bjarne Stroustrup 7. 以下说法正确的是? ( ABC) A. 头文件中的 ifndef/define/endif 是为了防止该头文件被重复引用。 B. 对于#include ,编译器从标准库路径开始搜索 filename.h 对于#include “filename.h” ,编译器从用户的工作路径开始搜索 filename.h C. C++语言支持函数重载,C语言不支持函数重载。函数被C++编译后在库中的名字与C 语言的不同。假设某个函数的原型为: void foo(int x, int y); 该函数被C编译器编译后在库 中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。C++提供了C连接交换指定符号extern“C”来解决名字匹配问题。 D. fopen函数只是把文件目录信息调入内存。//错,fopen是把整个文件读入内存 三、填空题:(共8题,每题3分,共24分) 1. 一个大小为320 X 192,颜色为灰度索引色的设备相关位图有______字节。如果此位图颜色为24位真彩色,则它的大小有______字节。 2. Windows API的中文意义是____ windows应用程序接口___。 3. 计算反正弦的库函数是__asin()____;计算浮点数绝对值的库函数是__fabs()____;计算浮点数n次方的库函数是__pow()____;将浮点数转化为字符串的库函数是___fcvt()___。 4. 如果i等于5,那么( ++i ) - -的返回值是__6__。 5. API LoadBitmap()的功能是从__指定的模块和或应用程序实例__中读取位图数据到内存。 6. new和__delete___对应,malloc和_free___对应,他们之间_ 不能__交叉混用。calloc的功能是__为数组动态分配内存___,realloc的功能是_改变原有内存区域的大小_。 7. SendMessage和PostMessage都会向窗体发送一个消息,但SendMessage__将一条消息发送到指定窗口,立即处理__而PostMessage__将一条消息投递到指定窗口的消息队列,不需要立即处理___。 8. 输出指定圆心、半径、边数的圆上的点: const int nCount = 12; const double dOrgX = 5.0, dOrgY = 3.0; const double dRadius = 2.0; for( int i = 0; i < nCount; i++ ) { double dAngle = M_PI * 2.0 / (double)nCount * i; cout << "第" << i << "点:X = " << ________; cout << ", Y = " << __________ << endl; } 三、判断题:(共12题,每题2分,共24分) 1. 一个类必须要有一个不带参数的构造函数。 错 2. 你不能写一个虚的构造函数。 对 3. 类里面所有的函数都是纯虚函数时才是纯虚类。 错 4. const成员函数对于任何本类的数据成员都不能进行写操作。 对 5. 函数中带默认值的参数必须位于不带默认值的参数之后。 对 6. char *p = "Test"; p[0] = 'R'; 错 7. cout << "Test"; 对 8. stl::list不支持随机访问叠代器。 对 9. stl::vector的效率比stl::list高。 错 10. VC和VC++是一回事,而VC++是一种比C++更难一些的语言。 错 11. 理论上,new和malloc造成的内存泄露都会由操作系统回收。 错 12. 在C++中struct和class的差别很大,所以从语法上不能混用。对 四、简述题(共3题,每题5分,共15分) 1. 请简述PeekMessage和GetMessage的区别。 答: Peekmessage和Getmessage都是向系统的消息队列中取得消息,两个函数的不同在于取不到消息的时候,若Getmessage()向消息队列中取不到消息,则程序的主线程会被OS(操作系统)挂起,等到有合适的消息时才返回;若是用Peekmessage()在消息队列中取不到消息,则程序会取得OS控制权,运行一段时间。 另外,在处理消息的时候,GetMessag()会将消息从队列中删除,而PeekMessage()可以设置最后一个参数wRemoveMsg来决定是否将消息保留在队列中。 2. 请列出你所知道的在Windows SDK平台上,实现计时功能的方法。 答:可以使用SetTimer函数创建一个计时器,SetTimer的函数原型如下: UINT_PTR SetTimer( HWND hWnd, UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc 3. 请简述你所知道的const的各种用法。 答: const 常量 const 修饰类的数据成员 const 修饰指针 const 应用在函数声明中 const 应用在类成员函数 五、编程题:(共3题,第1小题7分,第2小题14分,第3小题24分) 1. 深度遍历二叉树。 struct Node { Node *Parent; Node *Left, *Right; }; void Through(Node *Root) { } 2. 二分法查找。 int DicFind( int *Array, int Count, int Value ) { } 3. 写出字符串类String的默认构造函数、析构函数和重载赋值运算符。 已知类String的原型为: class String { public: String( const char *pStr = NULL ); // 默认构造函数 ~String( void ); // 析构函数 String &operate = ( const String &Source ); // 重载赋值运算符 private: char *m_pData; // 指向字符串的指针 }; 今天下午的两道面试题 1。 一人岁数的3次方是四位数,四次方是六位数,并知道此人岁数的3次方和4次方用遍了0~9十个数字。编写一程序求此人的岁数。 2。对1,2,3, 4, 5 这五个数任意取出两个数,列出他们的所有组合。 public static int getAge() { int age; int third; int fourth; for (int i = 11; true; i++) { if (i < 200) { third = (int) Math.pow(i, 3); fourth = (int) Math.pow(i, 4); if (getLength(third, fourth) == 10) { age = i; break; } } } return age; } public static int getLength(int args1, int args2) { String str1 = String.valueOf(args1); String str2 = String.valueOf(args2); String str = str1 + str2; if (str.length() != 10) { return -1; } int[] intarray = new int[10]; for (int i = 0; i < str.length(); i++) { intarray[i] = Integer.parseInt(str.substring(i,i+1)); } Arrays.sort(intarray); if(intarray[0]!=0 && intarray[9]!=9) return -1; return 10; } 第二题还更简单了 for(int i=1; i<6; i++){ for(int j=1; j<6; j++){ if(i==j){ System.out.println(j+""+j); }else{ System.out.println(i+""+j); System.out.println(j+""+i); } } } public class A { // http://community.csdn.net/Expert/topic/4667/4667929.xml?temp=.57922 public static void main(String[] args) { String t; String[] s = new String[5]; int j = s.length; for(int i=0; i<6; i++){ for(int j=1; j<6; j++){ if(i==j){ System.out.println(j+""+j); }else{ System.out.println(i+""+j); System.out.println(j+""+i); } } } ============================================================ 楼上的没看清题目,它是让你对1,2,3, 4, 5 这五个数任意取出两个数,列出他们的所有组合,所以重复的数字不应该算在里面。 第二题应该改为: for(int i=1; i<6; i++){ for(int j=1; j<6; j++){ if(i==j){ break; }else{ System.out.println(i+""+j); System.out.println(j+""+i); } } } public class B { public static void main(String[] args) { for (int i = 1; i < 6; i++) { int t = i; for(int a = 0; a<5; a++) { int c = a+1; if(c == t) { continue; }else { System.out.println(t*10+c); } } System.out.println(); } } } 第二题 public class Test { public static void main(String[] args) { int[][] a=new int[5][]; for(int i=0;i0;i--) { for(int j=i-1;j>0;j--) { System.out.print(i); System.out.print(j+" "); } System.out.print(" "); } } } public class Test { public static int getDigits(String str) { int[] intarr = new int[10]; for (int i = 0; i < 10; i++) intarr[i] = 0; for (int i = 0; i < str.length(); i++) { int j = Integer.parseInt(str.substring(i, i + 1)); intarr[j] = 1; } int num = 0; for (int i = 0; i < 10; i++) num = num + intarr[i]; return num; } private static int getAge() { int age; int third; int fourth; for (age = 1; age < 100; age++) { third = (int) Math.pow(age, 3); fourth = (int) Math.pow(age, 4); if (third < 1000 || third >= 10000) continue; if (fourth < 100000 || fourth >= 1000000) continue; String str = String.valueOf(third) + String.valueOf(fourth); if (getDigits(str) == 10) return age; } return 0; } } 第二道题 class Combine { public static void main(String[] args) { for(int i=1; i<5; i++) { for(int j=i+1; j<6; j++) { System.out.println(i+""+j); System.out.println(j+""+i); } } } public class Age { public static void main(String [] args) { String str1 = null; String str2 = null; String str3 = null; String str4 = "0123456789"; for(int i=10;i<50;i++) { str1 = Integer.toString(i*i*i); str2 = Integer.toString(i*i*i*i); str3 = str1+str2; if((str1.length() == 4) && (str2.length() ==6)) { boolean flag = true; for(int j=0;j<10;j++) if(str3.indexOf(str4.charAt(j))==-1) flag = false; if(flag){ System.out.println(">>>"+i); System.out.println(str3); } } } } } 比赛贴~微软又一道笔试题 silver6 | 04 四月, 2006 09:48 怎样只用4行代码编写出一个从字符串到长整形的转换函数? 我的方法,不过好象比4行多 *_#!~ long atol(char *str) { char c = *str; if( !isdigit(c) ) str++; for(long value = 0; *str != ''; value = value * 10 + (*str -'0'),str++); return c == '-' ? -value : value ; } void stol(const char * des, long& num) { for (int base = 1, i = 0; des[i] != ''; base = 10, ++i) { num *= base; num += (int)(des[i] - '0'); } } num 要初始化为0 void stol(const char * des, long& num) { for (int i=num=0; des[i] != ''; i++) { num *= 10; num += (int)(des[i] - '0'); } } void stol(char *str, long &num) { while(*str != '') { num = num * 10 + (*str - '0'); str++; } } void stol(const char * des, long& num) { char p = des[0]; for (int b = 1, pos = 1, base = 1; des[pos] != ''; b = 10, ++pos, base *= 10) { (num *= b) += (int)(des[pos] - '0'); } p == '-' ? (num *= -1) : (num = (int)(des[0] - '0') * base + num); } 改了一下 真的是微软的笔试题么? 我只用了一行。 #include using namespace std; long str2long(char* p,long xxx=0L) { return *p==''?xxx:str2long(p,xxx*10+(*p+++0-'0')); } int main() { char *str="123456789",*p=str; cout< #include #include using namespace std; long ToLong(string& s) { long l; istringstream iss(s); iss>>l; return l; } int main(int argc, _TCHAR* argv[]) { string s = "-12356"; cout< using namespace std; long str2long(char* p,long xxx=0L,bool IsPositive=true) { return *p==''?(IsPositive?xxx:xxx*(-1)):(*p=='-'?str2long(++p,0L,false):str2long(p,xxx*10+*p+++0-'0',IsPositive)); } int main() { char *str="-123456789",*p=str; cout<

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值