C/C++常见面试题
来源:互联网 发布:软件代理商协议 编辑:程序博客网 时间:2024/05/29 04:37
一、常见字符串
1. 写出在母串中查找子串出现次数的代码。- int count(char* str,char* substr)
- {
- char* str1;
- char* str2;
- int num = 0;
- while(*str!='\0')
- {
- str1 = str;
- str2 = s;
- while(*str2 == *str1&&(*str2!='\0')&&(*str1!='0'))
- {
- str2++;
- str1++;
- }
- if(*str2 == '\0')
- num++;
- str++;
- }
- return num;
- }
2. 查找第一个匹配子串位置,如果返回的是str1长度len1表示没有找到。
- size_t find(char* str1,char* str2)
- {
- size_t i=0;
- size_t len1 = strlen(str1)
- size_t len2 = strlen(str2);
- if(len1-len2<0) return len1;
- for(;i<len1-len2;i++)
- {
- size_t m = i;
- size_t j=0
- for(;size_t j=0;j<len2;j++)
- {
- if(str1[m]!=str2[j])
- break;
- m++;
- }
- if(j==len)
- break;
- }
- return i<len1-len2?i:len1;
- }
3. 实现strcpy函数。
- char *strcpy(char *dst, const char *src)
- {
- assert(dst!=NULL&&src!=NULL);
- char* target = dst;
- while(*dst++=*src++);
- return target ;
- }
4. 实现字符串翻转。
- void reserve(char* str)
- {
- assert(str != NULL);
- char * p1 = str;
- char * p2 = str-1;
- while(*++p2); //一般要求不能使用strlen
- p2 -= 1;
- while(p1<p2)
- {
- char c = *p1;
- *p1++ = *p2;
- *p2-- = c;
- }
- }
5. 实现strcmp函数。
- int strcmp11(char* src,char* dst)
- {
- assert(src!=0&&r!=0);
- while(*src == *dst &&*src != '\0')
- {
- src++,
- dst++;
- }
- if(*src > *dst)
- return 1;
- else if(*src == *dst)
- return 0;
- return -1;
- }
6. 用指针的方法,将字符串“ABCD1234efgh”前后对调显示。
//不要用strlen求字符串长度,这样就没分了
- char str123[] = "ABCD1234efgh";
- char * p1 = str123;
- char * p2 = str123-1;
- while(*++p2);
- p2 -= 1;
- while(p1<p2)
- {
- char c = *p1;
- *p1++ = *p2;
- *p2-- = c;
- }
7. 给定字符串A和B,输出A和B中的最大公共子串。比如A="aocdfe" B="pmcdfa" 则输出"cdf"。
- #i nclude<stdio.h>
- #i nclude<stdlib.h>
- #i nclude<string.h>
- char *commanstring(char shortstring[], char longstring[])
- {
- int i, j;
- char *substring=malloc(256);
- if(strstr(longstring, shortstring)!=NULL) //如果……,那么返回
- return shortstring; ;
- for(i=strlen(shortstring)-1;i>0; i--) //否则,开始循环计算
- {
- for(j=0; j<=strlen(shortstring)-i; j++)
- {
- memcpy(substring, &shortstring[j], i);
- substring[i]='\0';
- if(strstr(longstring, substring)!=NULL)
- return substring;
- }
- }
- return NULL;
- }
- int main()
- {
- char *str1=malloc(256);
- char *str2=malloc(256);
- char *comman=NULL;
- gets(str1);
- gets(str2);
- if(strlen(str1)>strlen(str2)) //将短的字符串放前面
- comman=commanstring(str2, str1);
- else
- comman=commanstring(str1, str2);
- printf("the longest comman string is: %s\n", comman);
- }
8. 判断一个字符串是不是回文。
- int IsReverseStr(char *str)
- {
- int i,j;
- int found=1;
- if(str==NULL)
- return -1;
- char* p = str-1;
- while(*++p!= '\0');
- --p;
- while(*str==*p&&str<p) str++,p--;
- if(str < p)
- found = 0;
- return found;
- }
9. 写函数完成内存的拷贝。
- void* memcpy( void *dst, const void *src, unsigned int len )
- {
- register char *d;
- register char *s;
- if (len == 0)
- return dst;
- if ( dst > src ) //考虑覆盖情况
- {
- d = (char *)dst + len - 1;
- s = (char *)src + len - 1;
- while ( len >= 4 ) //循环展开,提高执行效率
- {
- *d-- = *s--;
- *d-- = *s--;
- *d-- = *s--;
- *d-- = *s--;
- len -= 4;
- }
- while ( len-- )
- {
- *d-- = *s--;
- }
- }
- else if ( dst < src )
- {
- d = (char *)dst;
- s = (char *)src;
- while ( len >= 4 )
- {
- *d++ = *s++;
- *d++ = *s++;
- *d++ = *s++;
- *d++ = *s++;
- len -= 4;
- }
- while ( len-- )
- {
- *d++ = *s++;
- }
- }
- return dst;
- }
10. 写一个函数,它的原形是int continumax(char *outputstr,char *intputstr)。
功能:
在字符串中找出连续最长的数字串,并把这个串的长度返回,并把这个最长数字串付给其中一个函数参数outputstr所指内存。例如:"abcd12345ed125ss123456789"的首地址传给intputstr后,函数将返回9,outputstr所指的值为123456789
- int continumax(char *outputstr, char *inputstr)
- {
- char *in = inputstr, *out = outputstr, *temp, *final;
- int count = 0, maxlen = 0;
- while( *in != '\0' )
- {
- if( *in > 47 && *in < 58 )
- {
- for(temp = in; *in > 47 && *in < 58 ; in++ )
- count++;
- }
- else
- in++;
- if( maxlen < count )
- {
- maxlen = count;
- count = 0;
- final = temp;
- }
- }
- for(int i = 0; i < maxlen; i++)
- {
- *out = *final;
- out++;
- final++;
- }
- *out = '\0';
- return maxlen;
- }
二、常识题
1. 请说出static和const关键字的作用,至少说出两种。
static关键字至少有下列5个作用:
⑴ 函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;
⑵ 在模块内的static全局变量可以被模块内所用函数访问,但不能被模块外其它函数
C++从入门到精通
8
访问;
⑶ 在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;
⑷ 在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
⑸ 在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量。
const关键字至少有下列5个作用:
⑴ 欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化,因为以后就没有机会再去改变它了;
⑵ 对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const;
⑶ 在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;
⑷ 对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的成员变量;
⑸ 对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为“左值”。例如:
const classA operator*(const classA& a1,const classA& a2);
operator*的返回结果必须是一个const对象。如果不是,这样的变态代码也不会编译出错:
classA a, b, c;
(a * b) = c; // 对a*b的结果赋值操作(a * b) = c显然不符合编程者的初衷,也没有任//何意义
2. 如何判断是C还是C++编译器?
#ifdefine _CPLUSPLUC
cout<<”C++”;
#else
cout <<”C””;
3. 如何避免重复包含一个头文件?
#ifndef _HEADER_
#define _HEADER_
……
#endif
4. 在什么时候需要使用“常引用”?
如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常引用。常引用声明方式:const 类型标识符 &引用名=目标变量名。
5. 引用与指针有什么区别?
⑴ 引用必须被初始化,指针不必。
⑵ 引用初始化以后不能被改变,指针可以改变所指的对象。
⑶ 不存在指向空值的引用,但是存在指向空值的指针。
⑷ 重载操作符使用引用可以完成串试操作。
6. 全局变量和局部变量在内存中是否有区别?如果有,是什么区别?
全局变量储存在全局静态存储区,局部变量在堆栈。
7. 什么是平衡二叉树?
左右子树都是平衡二叉树 且左右子树的深度差值的绝对值不大于1。
8. 什么函数不能声明为虚函数?
构造函数。
9. 冒泡排序算法和快速排序算法的时间复杂度分别是什么?
冒泡排序:O(n^2)。
快速排序 o(nlgn)。
10. 进程间通信的方式有哪些?
进程间通信的方式有:共享内存,管道,Socket,消息队列,DDE等。
11. 纯虚函数如何定义?使用时应注意什么?
virtual void f()=0;
纯虚函数是接口,子类必须要实现。
12. c和c++中的struct有什么不同?
c和c++中struct的主要区别是c中的struct不可以含有成员函数,而c++中的struct可以。c++中struct和class的主要区别在于默认的存取权限不同,struct默认为public,而class默认为private。
13. const 符号常量:
(1) const char *p
(2) char const *p
(3) char * const p
说明上面三种描述的区别?
如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指为常量;如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量。
14. 数组和链表的区别?
数组:数据顺序存储,固定大小。
连表:数据可以随机存储,大小可动态改变。
15. 线程与进程的区别和联系? 线程是否具有相同的堆栈? dll是否有独立的堆栈?
进程是死的,只是一些资源的集合,真正的程序执行都是线程来完成的,程序启动的时候操作系统就帮你创建了一个主线程。每个线程有自己的堆栈。
DLL中有没有独立的堆栈,这个问题不好回答,或者说这个问题本身是否有问题。因为DLL中的代码是被某些线程所执行,只有线程拥有堆栈,如果DLL中的代码是EXE中的线程所调用,那么这个时候是不是说这个DLL没有自己独立的堆栈?
如果DLL中的代码是由DLL自己创建的线程所执行,那么是不是说DLL有独立的堆栈?
以上讲的是堆栈,如果对于堆来说,每个DLL有自己的堆,所以如果是从DLL中动态分配的内存,最好是从DLL中删除,如果你从DLL中分配内存,然后在EXE中,或者另外一个DLL中删除,很有可能导致程序崩溃。
16. 是不是一个父类写了一个virtual 函数,如果子类覆盖它的函数不加virtual ,也能实现多态?
virtual修饰符会被隐形继承的。private 也被集成,只事派生类没有访问权限而已。virtual可加可不加。子类的空间里有父类的所有变量(static除外)。同一个函数只存在一个
C++常见面试题 王牌7
11
实体(inline除外)。子类覆盖它的函数不加virtual ,也能实现多态。在子类的空间里,有父类的私有变量。私有变量不能直接访问。
17. 请简单描述Windows内存管理的方法。
内存管理有块式管理,页式管理,段式和段页式管理。现在常用段页式管理
块式管理:把主存分为一大块、一大块的,当所需的程序片断不在主存时就分配一块主存空间,把程序片断load入主存,就算所需的程序片度只有几个字节也只能把这一块分配给它。这样会造成很大的浪费,平均浪费了50%的内存空间,但时易于管理。
页式管理:把主存分为一页一页的,每一页的空间要比一块一块的空间小很多,显然这种方法的空间利用率要比块式管理高很多。
段式管理:把主存分为一段一段的,每一段的空间又要比一页一页的空间小很多,这种方法在空间利用率上又比页式管理高很多,但是也有另外一个缺点。一个程序片断可能会被分为几十段,这样很多时间就会被浪费在计算每一段的物理地址上(计算机最耗时间的大家都知道是I/O吧)。
段页式管理:结合了段式管理和页式管理的优点。把主存分为若干页,每一页又分为若干段。
18. 下面两种if语句判断方式。请问哪种写法更好?为什么?
int n;
if (n == 10) // 第一种判断方式
if (10 == n) // 第二种判断方式
第二种好,因为如果少了个=号,编译时就会报错,减少了出错的可能行,可以检测出是否少了‘=‘。
19. C和C++有什么不同?
从机制上:c是面向过程的(但c也可以编写面向对象的程序);c++是面向对象的,提供了类。但是, c++编写面向对象的程序比c容易从适用的方向:c适合要求代码体积小的,效率高的场合,如嵌入式;c++适合更上层的,复杂的; llinux核心大部分是c写的,因为它是系统软件,效率要求极高。从名称上也可以看出,c++比c多了+,说明c++是c的超集;那为什么不叫c+而叫c++呢,是因为c++比 c来说扩充的东西太多了,所以就在c后面放上两个+;于是就成了c++ C语言是结构化编程语言,C++是面向对象编程语言。C++侧重于对象而不是过程,侧重于类的设计而不是逻辑的设计。
C++从入门到精通
12
20. 请从下述答案中选择一个正确的答案。
class A
{
virtual void func1();
void func2();
}
Class B: class A
{
void func1(){cout < < "fun1 in class B" < < endl;}
virtual void func2(){cout < < "fun2 in class B" < < endl;}
}
A, A中的func1和B中的func2都是虚函数.
B, A中的func1和B中的func2都不是虚函数.
C, A中的func2是虚函数.,B中的func1不是虚函数.
D, A中的func2不是虚函数,B中的func1是虚函数.
答:A
三、编程题
1. 写出下述程序的运行结果。
- int sum(int a)
- {
- auto int c=0;
- static int b=3;
- c+=1;
- b+=2;
- return(a+b+c);
- }
- int main()
- {
- int I;
- int a=2;
- for(I=0;I<5;I++)
- {
- printf("%d,", sum(a));
- }
- }
// static会保存上次结果,记住这一点,剩下的自己写
输出:8,10,12,14,16,
2. 求1000!的未尾有几个0?
(用素数相乘的方法来做,如72=2*2*2*3*3);求出1->1000里,能被5整除的数的个数n1,能被25整除的数的个数n2,能被125整除的数的个数n3,能被625整除的数的个数n4.1000!末尾的零的个数=n1+n2+n3+n4;
- int sum(int a)
- {
- auto int c=0;
- static int b=3;
- c+=1;
- b+=2;
- return(a+b+c);
- }
- int main()
- {
- int I;
- int a=2;
- for(I=0;I<5;I++)
- {
- printf("%d,", sum(a));
- }
- }
3. 编程实现:把十进制数(long型)分别以二进制和十六进制形式输出,不能使用printf系列库函数。
- char* test3(long num)
- {
- char* buffer = (char*)malloc(11);
- buffer[0] = '0';
- buffer[1] = 'x';
- buffer[10] = '\0';
- char* temp = buffer + 2;
- for (int i=0; i < 8; i++)
- {
- temp[i] = (char)(num<<4*i>>28);
- temp[i] = temp[i] >= 0 ? temp[i] : temp[i] + 16;
- temp[i] = temp[i] < 10 ? temp[i] + 48 : temp[i] + 55;
- }
- return buffer;
- }
4. 将一个数字字符串转换为数字."1234" -->1234。
- int atoii(char* s)
- {
- assert(s!=NULL);
- int num = 0;
- int temp;
- while(*s>'0' && *s<'9')
- {
- num *= 10;
- num += *s-'0';
- s++;
- }
- return num;
- }
5. 实现任意长度的整数相加或者相乘功能。
- void bigadd(char* num,char* str,int len)
- {
- for(int i=len;i>0;i--)
- {
- num[i] += str[i];
- int j = i;
- while(num[j]>=10)
- {
- num[j--] -= 10;
- num[j] += 1;
- }
- }
- }
6. 不用递归实现斐波拉契数。
- int Funct( int n ) // n 为非负整数
- { int a=1; int b=1;
- int c;
- if(n==0 || n == 1)
- return 1;
- for(int i=1;i<n;i++)
- {
- c=a+b;
- a=b; b=c;
- }
- return b;
- }
7. 用递归算法判断数组a[N]是否为一个递增数组。
递归的方法,记录当前最大的,并且判断当前的是否比这个还大,大则继续,否则返回false结束:
- bool fun( int a[], int n )
- {
- if( n= =1 )
- return true;
- if( n= =2 )
- return a[n-1] >= a[n-2];
- return fun( a,n-1) && ( a[n-1] >= a[n-2] );
- }
8. 写一个函数找出一个整数数组中,第二大的数。
- const int MINNUMBER = -32767 ;
- int find_sec_max( int data[] , int count)
- {
- int maxnumber = data[0] ;
- int sec_max = MINNUMBER ;
- for ( int i = 1 ; i < count ; i++)
- {
- if ( data[i] > maxnumber )
- {
- sec_max = maxnumber ;
- maxnumber = data[i] ;
- }
- else
- {
- if ( data[i] > sec_max )
- sec_max = data[i] ;
- }
- return sec_max ;
9. 已知两个链表head1 和head2 各自有序,请把它们合并成一个链表依然有序,这次要求用递归方法进行。
- Node * MergeRecursive(Node *head1 , Node *head2)
- {
- i ( head1 == NULL )
- return head2 ;
- if head2 == NULL)
- return head1 ;
- Node *head = NULL ;
- if head1->data < head2->data )
- head = head1 ;
- head->next = MergeRecursive(head1->next,head2);
- else
- head = head2 ;
- head->next = MergeRecursive(head1,head2->next);
- }
- return head ;
- }
10. 文件中有一组整数,要求排序后输出到另一个文件中。
- #include<iostream>
- #include<fstream>
- using namespace std;
- void Order(vector<int>& data) //bubble sort
- {
- int count = data.size() ;
- int tag = false ; // 设置是否需要继续冒泡的标志位
- for ( int i = 0 ; i < count ; i++)
- {
- for ( int j = 0 ; j < count - i - 1 ; j++)
- {
- if ( data[j] > data[j+1])
- tag = true ;
- int temp = data[j] ;
- data[j] = data[j+1] ;
- data[j+1] = temp ;
- }
- }
- if ( !tag )
- break ;
- }
- }
- int main( void )
- {
- vector<int>data;
- ifstream in("c:\\data.txt");
- if ( !in)
- {
- cout<<"file error!";
- exit(1);
- }
- int temp;
- while (!in.eof())
- {
- in>>temp;
- data.push_back(temp);
- }
- in.close(); //关闭输入文件流
- Order(data);
- ofstream out("c:\\result.txt");
- if ( !out)
- {
- cout<<"file error!";
- exit(1);
- }
- for ( i = 0 ; i < data.size() ; i++)
- out<<data[i]<<" ";
- out.close(); //关闭输出文件流
- }
11. 输入一个字符串,将其逆序后输出。(使用C++,不建议用伪码)
- #include <iostream>
- using namespace std;
- void main()
- {
- char a[50];memset(a,0,sizeof(a));
- int i=0,j;
- char t;
- cin.getline(a,50,'\n');
- for(i=0,j=strlen(a)-1;i <strlen(a)/2;i++,j--)
- {
- t=a[i];
- a[i]=a[j];
- a[j]=t;
- }
- cout < <a < <endl;
- }
12. 下面的代码有什么问题?
- void DoSomeThing(...)
- {
- char* p;
- ...
- p = malloc(1024); // 分配1K的空间
- if (NULL == p)
- return;
- ...
- p = realloc(p, 2048); // 空间不够,重新分配到2K
- if (NULL == p)
- return;
- ...
- }
答案 p = malloc(1024); 应该写成: p = (char *) malloc(1024); 没有释放p的空间,造成内存泄漏。
13. 下面的代码有什么问题?并请给出正确的写法。
- void DoSomeThing(char* p)
- {
- char str[16];
- int n;
- assert(NULL != p);
- sscanf(p, "%s%d", str, n);
- if (0 == strcmp(str, "something"))
- {
- ...
- }
- }
答案:sscanf(p, "%s%d", str, n); 这句改为: sscanf(p, "%s%d", str, &n);
14. 写出运行结果:
- {// test2
- union V {
- struct X {
- unsigned char s1:2;
- unsigned char s2:3;
- unsigned char s3:3;
- } x;
- unsigned char c;
- } v;
- v.c = 100;
- printf("%d", v.x.s3);
- }
运行结果:3
15. 用C++写个程序,如何判断一个操作系统是16位还是32位的?不能用sizeof()函数。
- 16位的系统下,
- int i = 65536;
- cout < < i; // 输出0;
- int i = 65535;
- cout < < i; // 输出-1;
- 32位的系统下,
- int i = 65536;
- cout < < i; // 输出65536;
- int i = 65535;
- cout < < i; // 输出65535;
16. 试编写函数判断计算机的字节存储顺序是开序(little endian)还是降序(bigendian) 。
- bool IsBigendian()
- {
- unsigned short usData = 0x1122;
- unsigned char *pucData = (unsigned char*)&usData;
- return (*pucData == 0x22);
- }
17. 简述Critical Section和Mutex的不同点。
答:
⑴ Critical Section
A.速度快
B.不能用于不同进程
C.不能进行资源统计(每次只可以有一个线程对共享资源进行存取)
⑵ Mutex
A.速度慢
B.可用于不同进程
C.不能进行资源统计
⑶ Semaphore
A.速度慢
B.可用于不同进程
C.可进行资源统计(可以让一个或超过一个线程对共享资源进行存取)
⑷ Event
A.速度慢
B.可用于不同进程
C.可进行资源统计
18. 用C 写一个输入的整数,倒着输出整数的函数,要求用递归方法。
- void fun( int a )
- {
- printf( "%d", a%10 );
- a /= 10;
- if( a <=0 )return;
- fun( a );
- }
19. 写出程序结果:
void Func(char str[100])
{
printf("%d\n", sizeof(str));
}
答: 4
20. 请问运行Test函数会有什么样的结果?
- void GetMemory(char *p)
- {
- p = (char *)malloc(100);
- }
- void Test(void)
- {
- char *str = NULL;
- GetMemory(str);
- strcpy(str, "hello world");
- printf(str);
- }
答:程序崩溃。
因为GetMemory并不能传递动态内存,Test函数中的 str一直都是 NULL。strcpy(str, "hello world");将使程序崩溃
0 0
- C常见面试题
- C常见面试题
- c/c++常见面试题
- C/C++ 常见面试题
- c/c++常见面试题
- C/C++常见面试题
- C语言常见面试题
- c/c++常见面试题
- c/c++常见面试题 .
- c/c++常见面试题
- C语言常见面试题
- C/C++常见面试题
- C语言常见面试题
- c c++ 常见面试题
- C 语言常见面试题
- C/C++常见面试题
- C++STL常见面试题
- C++STL常见面试题
- python入门——numpy-win64-py2.7
- Android 动画效果 --Animation 动画(讲解了所有的Android动画效果,是一个值得收藏的帖子)
- 我的U3D学习之旅六
- Android关于ProgressDialog按返回键关闭
- hdu 4770 Lights Against Dudely
- C/C++常见面试题
- HDOJ 题目 1166 敌兵布阵(线段树,模板)
- 正则表达式在ABAP中的应用
- 以 vim 的方式来使用 chrome 浏览器(利用 vimium 插件)
- usaco1.1.3的题解
- C++按行读取文本文件,并将每行字符串拆分为double value的坐标值
- Android之TextView、EditText控件显示表情图片
- java中虚引用PhantomReference与弱引用WeakReference(软引用SoftReference)的差别
- map