c++面试题汇总

BuladeMian 贡献于2016-10-26

作者 softlab  创建于2006-11-13 12:14:00   修改者lingyun  修改于2011-03-13 13:00:00字数32507

文档摘要:
关键词:

C++常见面试题 希望这个贴子能给正在找工作的朋友一点帮助. SIZEOF CONST 预处理题目: 1. sizeof相关系列问题 a. 对于 struct s{char a;int b};  sizeof(s) = 8; 因为当结构体内元素长度都小于处理器位数(32位=4字节)的时候,便以结构体中最长的数据元素为对齐条件,a 按 1 字节对齐,b 按 4 字节对齐,所以s默认对其参数为8   struct A{short a1;short a2;short a3};sizeof(A)=6; 原因同上,结构体按最长元素short(2字节对齐)。 b. 对于 int a[200]; sizeof(a) = 200* sizeof(int) = 800; 对整个数组大小评测    int* a = new int[200]; sizeof(a) = 4; 对指针大小进行评测    char str[]="012345"; sizeof(str) = 7; str 是一个字符数组,数组最初大小未定,由具体值"012345"来决定,6*sizeof(char) = 6,还有隐含的"\0",所以一共7位。    char str[]="s\n";sizeof(str) = 3; 回车"\n" 是一个字符,可以查看ASCII表。还有\r、\t等等字符 c. 这种使用位域的也有,其中元素最大为1字节大小=8 bits,元素按照1字节进行对齐, sizeof(b) = 1 +  1(4 bits+2bits < 8 bits) + 1(3bits) = 3.            struct  b     {         char a:8;         char b:4;         char c:2;         char d:3;     };     写出运行结果:       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);      100 的2进制是1100100 去掉后面的5位余11放入x.s3中 结果:3 d. 对于空的类进行评测  class A {};  sizeof(A) = 1;默认空类是有一个占位符的   对于虚函数 class A{ virtual test()}; class B:public A{};sizeof(A)=4;sizeof(B) =4 任何含有虚函数的类拥有一个vptr指针,用来指向虚函数表vtable。sizeof(vptr) = 4   class A{static int a;}; sizeof(A) = 1; 对于静态成员变量是分配在全局存储区的,所以A还是相当于空类。   class C:public virtual A {}; sizeof(C)=4; 对于虚拟继承的类拥有虚函数表,所以空类C含有vptr. e.  设有以下说明和定义:   typedef union {long i; int k[5]; char c;} DATE; // sizeof(int)*5 = 20   struct data { int cat; DATE cow; double dog;} too; //4+20+8 = 32   DATE max;   则语句 printf("%d",sizeof(struct date)+sizeof(max));的执行结果是:52   对于union联合来说,取其中最大元素长度来做为联合大小。 f.  使用malloc或者new 分配内存,void *pp  = malloc(10);  sizeof(p) = 4;跟指针一样,sizeof 只能测出静态数组的长度,无法检测动态分配的或外部数组大小 h. 下面函数输出结果:对于char str[100]或者char str[] 参数都退化为char* str,这样的函数即使传入char s[10] 也是可以的   void Func(char str[100])   {       printf("%d\n", sizeof(str));   }   char s[10];  //函数对数组长度并没有检验   Func(s);     结果:sizeof(char*)=4   如何强制str为100位数组? 可以如此声明 char (&str)[100]   理解顺序:1.str声明为一个引用 2.引用一个100元素数组 3. 数组元素每个为int大小   void Func(char (&str)[100])   {       printf("%d\n", sizeof(str));   }   char s[100];   Func(s);  //这里必须给定100位长度char数组   结果:100*sizeof(char) = 100 2. CONST 常见题目: a. const 与 #define有什么不同 答案: 1. const 常量有数据类型,而宏没有数据类型。编译器可以对const 常量进行类型检查,而对宏只进行字符替换没有类型检查。         2. 有些编译器可以对const常量进行调试,但不能对宏常量进行调试         3. const 可以用来修饰函数参数、函数返回值,C++还可以用来修饰函数,定义内中某个成员函数为常量函数 3. 写一个标准宏MIN,这个宏输入两个参数并返回较小的一个 答案: #define MIN(A,B) ((A)<=(B) ? (A):(B))         1. 宏是方便的产生嵌入代码的唯一方法。         2. 三重条件操作符对编译器来说可以产生比if-then-else更优化的代码。         3. 必须把宏中的参数用括号括起来 4. 内联函数和宏的差别是什么? 答案: 内联函数和普通函数相比可以加快程序运行的速度,因为不需要中断调用。编译时内联函数代码直接嵌入到目标代码中,而宏只是字符替换。内联函数要做类型检查,相对于宏更安全可靠。 inline只用于如下情况:          1. 一个函数被不断调用。          2. 函数只有简单的几行,且函数内不包含for、while、switch等语句. 5. const 符号常量; (1)const char *p (2)char const *p (3)char * const p 说明上面三种描述的区别: 1和2相同,如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量,不能修改指针指向对象的内容 如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量,不能修改指针的指向 2)写出二分查找的代码. int bfind(int* a,int len,int val) {     int m = len/2;     int l = 0;     int r = len;     while(l!=m && r!= m)     {         if(a[m] > val)         {             r = m;             m = (m+l)/2;         }         else if(a[m] < val)         {             l = m;             m = (m+r)/2;         }         else             return m;     }     return -1;   //没有找到 } 常见字符串面试题: 1)写出在母串中查找子串出现次数的代码. int count1(char* str,char* s) {     char* s1;     char* s2;     int count = 0;     while(*str!='\0')     {         s1 = str;         s2 = s;         while(*s2 == *s1&&(*s2!='\0')&&(*s1!='\0'))         {             s2++;             s1++;         }         if(*s2 == '\0')             count++;         str++;     }     return count; } 2)查找第一个匹配子串位置,如果返回的是s1长度len1表示没有找到 size_t find(char* s1,char* s2)     {         size_t i=0;          size_t len1 = strlen(s1)         siz e_t len2 = strlen(s2);         if(len1-len2<0) return len1;         for(;i *r)         return 1;     else if(*l == *r)         return 0;     return -1; } 5) 实现字符串翻转 void reserve(char* str) {     assert(str != NULL);     char * p1 = str;     char * p2 = str-1;     while(*++p2);         //一般要求不能使用strlen     p2 -= 1;     while(p1 #i nclude #i nclude char *commanstring(char shortstring[], char longstring[]) {     int i, j;     char *substring=malloc(256);     if(strstr(longstring, shortstring)!=NULL)              //如果……,那么返回shortstring         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; } 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 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; } 11) 编写一个 C 函数,该函数在一个字符串中找到可能的最长的子字符串,且该字符串是由同一字符组成的。 char * search(char *cpSource, char ch) {          char *cpTemp=NULL, *cpDest=NULL;          int iTemp, iCount=0;          while(*cpSource)          {                  if(*cpSource == ch)                  {                           iTemp = 0;                           cpTemp = cpSource;                           while(*cpSource == ch)                                    ++iTemp, ++cpSource;                           if(iTemp > iCount)                                 iCount = iTemp, cpDest = cpTemp;                         if(!*cpSource)                             break;                  }                  ++cpSource;      }      return cpDest; }      排序算法: *7)写出快速排序或者某种排序算法代码 快速排序: int partition(int* a,int l,int r) {     int i=l-1,j=r,v=a[r];     while(1)     {         while(a[++i]v) if(j<=i) break;         if(i>=j)             break;         swap(a[i],a[j]);     }     swap(a[i],a[r]);     return i; } void qsort(int* a,int l,int r) {     if(r>l)     {         int i = partition(a,l,r);         qsort(a,l,i-1);         qsort(a,i+1,r);     } } 有兴趣可以看看下面2个。一般面试不会要求的 改进1: void qsort(int* a,int l,int r) {      while(l=0&&a[i]>key;i--)         {             a[i+1] = a[i];         }         a[i+1] = key;     } } 链表题目: 1)将一个单链表逆序 struct list_node {     list_node(int a,list_node* b):data(a),next(b)  //这个为了测试方便     {}     int data;     list_node* next; }; // 认为头节点存在,如果list类内函数不用判断头结点是否为空. 不是类内部函数得判断头结点  void reserve(list_node* phead)  {         list_node* p = phead->next;         if(p == NULL || p->next == NULL) return; //只有头节点或一个节点         list_node* p1=p->next;         p->next=NULL;         while(p1!=NULL)         {             p = p1->next;             p1->next = phead->next;             phead->next = p1;             p1 = p;         } } 测试程序:     list lt;     lt.phead = new list_node(0,0);     lt.phead->next = new list_node(1,0);     lt.phead->next->next = new list_node(2,0);     lt.phead->next->next->next =  new list_node(3,0);     lt.reserve();     list_node * p = lt.phead;     while(p)     {         cout<data<next;     } 2)循环链表的节点对换和删除。 //双向循环 list_node* earse(list_node* node) {     // if(node == rear) return node->next;    //对于头节点可判断也可不判断。最好加上     list_node*  next = node->next;     next->prev = node->prev;     node->prev->next = next;     delete node;     retrun next; } //单项循环 list_node* earse(list_node* node) {     // if(node == rear) return node->next;    //对于头节点可判断也可不判断。最好加上     list_node*  p = rear;      while(p->next != node) p=p->next;      p->next = node->next;     delete node;     retrun p->next; } 3) 有双向循环链表结点定义为: struct node { int data; struct node *front,*next; }; 有两个双向循环链表A,B,知道其头指针为:pHeadA,pHeadB,请写一函数将两链表中data值相同的结点删除 BOOL DeteleNode(Node *pHeader, DataType Value) {     if (pHeader == NULL) return;     BOOL bRet = FALSE;     Node *pNode = pHead;     while (pNode != NULL)     {         if (pNode->data == Value)         {             if (pNode->front == NULL)             {                     pHeader = pNode->next;                     pHeader->front = NULL;             }             else             {                     if (pNode->next != NULL)                     {                             pNode->next->front = pNode->front;                     }                     pNode->front->next = pNode->next;             }           Node *pNextNode = pNode->next;           delete pNode;           pNode = pNextNode;         bRet = TRUE;         / /不要break或return, 删除所有         }         else         {             pNode = pNode->next;         }    } return bRet; } void DE(Node *pHeadA, Node *pHeadB) {     if (pHeadA == NULL || pHeadB == NULL)     {         return;     }     Node *pNode = pHeadA;     while (pNode != NULL)     {         if (DeteleNode(pHeadB, pNode->data))         {             if (pNode->front == NULL)             {                     pHeadA = pNode->next;                     pHeadA->front = NULL;             }         else         {             pNode->front->next = pNode->next;             if (pNode->next != NULL)             {                 pNode->next->front = pNode->front;             }         }         Node *pNextNode = pNode->next;         delete pNode;         pNode = pNextNode;         }         else         {             pNode = pNode->next;         }     } } 4)  写出程序删除链表中的所有接点 void del_all(node *head) {     node *p;     while(head!=NULL)     {         p=head->next;         free(head);         head=p;       }      cout<<"释放空间成功!"<next!=NULL&&qa->next!=NULL)     {         if(pa->data>qa->data)         {             ra->next=qa;             qa=qa->next;         }         else         {             ra->next=pa;             pa=pa->next;         }     }     if(pa->next!=NULL)     ra->next=pa;     if(qa->next!=NULL)     ra->next==qa;     return R; } 6 怎么判断链表中是否有环? bool CircleInList(Link* pHead) {     if(pHead = = NULL || pHead->next = = NULL)//无节点或只有一个节点并且无自环         return (false);     if(pHead->next = = pHead)//自环         return (true);     Link *pTemp1 = pHead;//step 1     Link *pTemp = pHead->next;/ /step 2     while(pTemp != pTemp1 && pTemp != NULL && pTemp->next != NULL)     {         pTemp1 = pTemp1->next;         pTemp = pTemp->next->next;     }     if(pTemp = = pTemp1)         return (true);     return (false); } 常识题: 4 static有什么用途?(请至少说明两种) 1). 在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。 2). 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。 3). 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。 经常问 5. 引用与指针有什么区别? 1) 引用必须被初始化,不存在指向空值的引用,一个引用必须指向某个对象。指针不必立即初始化。 2) 引用初始化以后不能改变使其指向其他对象,但可以修改其指向对象的内容。指针可以被改变指向其他的对象。 3) 在使用引用之前不需要测试它是否为空,相反指针应该总被测试防止其为空。 4) 重载操作符必须使用引用才能完成串式操作 6. 全局变量和局部变量在内存中是否有区别?如果有,是什么区别? 全局变量储存在全局静态存储区,局部变量在堆栈 static变量和static 函数各有什么特点? 答:static变量:在程序运行期内一直有效,如果定义在函数外,则在编译单元内可见,如果在函数内,在在定义的block内可见;static函数:在编译单元内可见; static全局变量与普通的全局变量有什么区别? static全局变量只能在本模块中调用,不能在其他文件单元中被引用.而全局变量可以使用extern在任何地方引用 static函数与普通函数有什么区别: static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝 程序的局部变量存在于(堆栈)中,全局变量存在于(静态区 )中,动态申请数据存在于( 堆)中。 16. 什么是平衡二叉树? 左右子树都是平衡二叉树 且左右子树的深度差值的绝对值不大于1 7. 什么构造函数不能声明为虚函数? 答案: 虚函数采用一种虚调用的办法。虚调用是一种可以在只有部分信息的情况下工作的机制,特别允许我们调用一个只知道接口而不知道其准确对象类型的函数。但如果要创建一个对象势必要知道其准确类型因此构造函数不能为虚。 8. 冒泡排序算法的时间复杂度是什么 O(n^2)  快速排序 o(nlgn) 9. 写出float x 与“零值”比较的if语句。     if(x>0.000001&&x<-0.000001)        其实浮点0在内存中也是0,这个问题角度不太好。 10.进程间通信的方式有? 进程间通信的方式有 共享内存, 管道 ,Socket ,消息队列等 11. c和c++中的struct有什么不同? c和c++中struct的主要区别是c中的struct不可以含有成员函数,而c++中的struct可以。c++中struct和class的主要区别在于默认的存取权限不同,struct默认为public,而class默认为private 12.纯虚函数如何定义?使用时应注意什么? virtual void f()=0; 是接口,子类必须要实现 13.数组和链表的区别 数组:数据顺序存储,固定大小 连表:数据可以随机存储,大小可动态改变 14. 线程与进程的区别和联系? 线程是否具有相同的堆栈? dll是否有独立的堆栈? 进程是死的,只是一些资源的集合,真正的程序执行都是线程来完成的,程序启动的时候操作系统就帮你创建了一个主线程。 每个线程有自己的堆栈。 DLL中有没有独立的堆栈,这个问题不好回答,或者说这个问题本身是否有问题。因为DLL中的代码是被某些线程所执行,只有线程拥有堆栈,如果DLL中的代码是EXE中的线程所调用,那么这个时候是不是说这个DLL没有自己独立的堆栈?如果DLL中的代码是由DLL自 己创建的线程所执行,那么是不是说DLL有独立的堆栈? 以上讲的是堆栈,如果对于堆来说,每个DLL有自己的堆,所以如果是从DLL中动态分配的内存,最好是从DLL中删除,如果你从DLL中分配内存,然后在EXE中,或者另外一个DLL中删除,很有可能导致程序崩溃 15. 一语句实现x是否为2的若干次幂的判断 int i = 512; cout << boolalpha << ((i & (i - 1)) ? false : true) << endl; 对于2取余快速做法就是 &(2-1), & 相对于除法、取余指令要快很多,一般+ - * 等只消耗很少cpu周期(个位数),而除法至少是100个cpu周期以上. cout<print();    // 多态    pb->print();     pc->print();       print(a);     print(b);     print(c);  } 答案: A::print() B::print() C::print() A::print() B::print() C::print() A::print() A::print() A::print() 3. 写出程序运行结果 int sum(int a) { auto int c=0; static int b=3; c+=1; b+=2; return(a+b+c); } void main() {     int I;     int a=2;     for(I=0;I<5;I++)     {         printf("%d,", sum(a));     } } // static会保存上次结果,记住这一点,剩下的自己写 输出:8,10,12,14,16, 4 求函数返回值,输入x=9999; int func ( x ) {     int countx = 0;     while ( x )     {         countx ++;         x = x&(x-1);     }     return countx; } 结果呢? 知道了这是统计9999的二进制数值中有多少个1的函数,且有 9999=9×1024+512+256+15 9×1024中含有1的个数为2; 512中含有1的个数为1; 256中含有1的个数为1; 15中含有1的个数为4; 故共有1的个数为8,结果为8。 1000 - 1 = 0111,正好是原数取反。这就是原理。 用这种方法来求1的个数是很效率很高的。 不必去一个一个地移位。循环次数最少。 算法题: 1.用户输入M,N值,从1至N开始顺序循环数数,每数到M输出该数值,直至全部输出。写出C程序。 循环链表,用取余操作做 //这样写感觉不是太好,置1表示被访问过。 void joe(int n,int m) {     int *a = new int[n];     int i=0;     int pos=0;     while(i #i nclude typedef struct Node {   int index;   struct Node *next; }JosephuNode; int Josephu(int n, int m) {   int i, j;   JosephuNode *head, *tail;   head = tail = (JosephuNode *)malloc(sizeof(JosephuNode));   for (i = 1; i < n; ++i)   {     tail->index = i;     tail->next = (JosephuNode *)malloc(sizeof(JosephuNode));     tail = tail->next;   }   tail->index = i;   tail->next = head;     for (i = 1; tail != head; ++i)   {     for (j = 1; j < m; ++j)     {       tail = head;       head = head->next;     }     tail->next = head->next;     printf(" 第%4d个出局的人是:%4d号\n", i, head->index);     free(head);     head = tail->next;   }   i = head->index;   free(head);   return i; } int main() {   int n, m;   scanf("%d%d", &n, &m);   printf("最后胜利的是%d号!\n", Josephu(n, m));   system("pause");   return 0; } 2、有10亿个浮点数,求出其中最大的10000个 ,用了标准库的,不让用的话,只能自己写堆函数     vector bigs(10000,0);     vector::iterator it;     for(it=bigs.begin();it!=bigs.end();it++)     {         *it = (float)rand()/7;   //数据都是用随机数模拟的     }     cout<() );     float ff;         time_t t1,t2;     time(&t1);     for(int i=0;i<1000000000;i++)     {         ff = (float) rand()/7;         if(ff>bigs[0])         {             pop_heap(bigs.begin(),bigs.end(),greater());             bigs.pop_back();             bigs.push_back(ff);             push_heap(bigs.begin(),bigs.end(),greater());         }     }     time(&t2);     cout<<(long)(t2-t1)<0;i--)       {           fixdown(p,k,n);       }       while(n>0)       {           swap(p[n],p[1]);           fixdown(p,1,--n);       } } 3 .在不用第三方参数的情况下,交换两个参数的值 感觉比较:( , bt 而且还是基础题。 方法一:         i=i+j;         j=i-j;         i=i-j; 方法二:         i^=j;         j^=i;         i^=j; 方法三:         a = a+b-(b=a) 对于方法一、三 i=i+j 如果i、j是两个比较大的数,i+j可能越界,所以方法二更好一些 4)输出和为一个给定整数的所有组合 例如n=5 5=1+4;5=2+3(相加的数不能重复) 则输出 1,4;2,3。 #i nclude int main(void) {     unsigned long int i,j,k;     printf("please input the number\n");     scanf("%d",&i);     if( i % 2 == 0)         j = i / 2;     else         j = i / 2 + 1;     printf("The result is \n");     for(k = 0; k < j; k++)          printf("%d = %d + %d\n",i,k,i - k);     return 0; } 5) 写一段程序,找出数组中第k大小的数,输出数所在的位置。例如{2,4,3,4,7}中,第一大的数 是7,位置在4。第二大、第三大的数都是4,位置在1、3随便输出哪一个均可。函数接口为:int find_orderk(const int* narry,const int n,const int k) 要求算法复杂度不能是O(n^2),应该 o(nlgn)吧 n^2 也太容易了冒泡排序都可以 谢谢! 可以先用快速排序进行排序,其中用另外一个进行地址查找 代码如下,在VC++6.0运行通过。给分吧^-^   ,鄙视明明是个 partial_sort, 全排sort 效率差多了 贴一份标准库代码,以后把堆排序所有函数不上。 template inline     void _Partial_sort(_RanIt _First, _RanIt _Mid, _RanIt _Last, _Ty *)     {    // order [First, _Last) up to _Mid, using operator<     std::make_heap(_First, _Mid);     for (_RanIt _Next = _Mid; _Next < _Last; ++_Next)         if (*_Next < *_First)             _Pop_heap(_First, _Mid, _Next, _Ty(*_Next),                 _Dist_type(_First));    // replace top with new largest     std::sort_heap(_First, _Mid);     } 6) 求1000!的未尾有几个0(用素数相乘的方法来做,如72=2*2*2*3*3); 求出1->1000里,能被5整除的数的个数n1,能被25整除的数的个数n2,能被125整除的数的个数n3, 能被625整除的数的个数n4. 1000!末尾的零的个数=n1+n2+n3+n4; #i nclude #define NUM 1000 int find5(int num) {     int ret=0;     while(num%5==0)     {         num/=5;         ret++;     }     return ret; } int main() {     int result=0;     int i;     for(i=5;i<=NUM;i+=5)     {         result+=find5(i);     }     printf(" the total zero number is %d\n",result);     return 0; }   7). 编程实现:把十进制数(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; } 8)输入N, 打印 N*N 矩阵 比如 N = 3,打印: 螺旋矩阵 1  2  3 8  9  4 7  6  5 N = 4,打印: 1   2   3   4 12  13  14  5 11  16  15  6 10  9   8   7 解答: 1 #define N 15 int s[N][N]; void main() {     int k = 0, i = 0, j = 0;     int a = 1;     for( ; k < (N+1)/2; k++ )     {         while( j < N-k ) s[i][j++] = a++; i++; j--;         while( i < N-k ) s[i++][j] = a++; i--; j--;         while( j > k-1 ) s[i][j--] = a++; i--; j++;         while( i > k )   s[i--][j] = a++; i++; j++;     }     for( i = 0; i < N; i++ )     {         for( j = 0; j < N; j++ )         cout << s[i][j] << '\t';         cout << endl;     } } 9) 斐波拉契数列递归实现的方法如下:  int  Funct( int n ) {    if(n==0) return 1;    if(n==1) return 1;    retrurn  Funct(n-1) + Funct(n-2); } 如何不使用递归,来实现上述函数? 解答:int  Funct( int n )  //  n 为非负整数 {    int a=1;    int b=1;    int c;    if(n==0 || n == 1)         return  1;    for(int i=1;i1234 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; } 出现次数相当频繁 11). 编程实现:把十进制数(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; } 12)实现任意长度的整数相加或者相乘功能。 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;         }     } } 13、用递归算法判断数组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] ); } 14、运用四色定理,为N个局域举行配色,颜色为1、2、3、4四种,另有数组adj[][N],如adj[i][j]=1则表示i区域与j区域相邻,数组color[N],如color[i]=1,表示i区域的颜色为1号颜色。四色填充 正在看图的程序,以后补一个 15.给两个数组和他们的大小,还有一动态开辟的内存,求交集,把交集放到动态内存dongtai,并且返回交集个数 long jiaoji(long* a[],long b[],long* alength,long blength,long* dongtai[]) 如果让用库,放入两个set 中,然后调用set_difference 函数。 不让的话就先排序,然后依次比较了。 16 象搜索的输入信息是一个字符串,统计300万输入信息中的最热门的前十条,我们每次输入的一个字符串为不超过255byte,内存使用只有1G, 请描述思想,写出算发(c语言),空间和时间复杂度. 跟10亿浮点数的相同,使用堆做部分排序时间复杂度  Nlog10 。 空间?? 用10的信息空间 17.国内的一些帖吧,如baidu,有几十万个主题,假设每一个主题都有上亿的跟帖子,怎么样设计这个系统速度最好,请描述思想,写出算发(c语言),空间和时间复杂度, 每一个主题都有上亿的跟帖子,那baidu 就崩溃了。 天知道想问什么?? 18.用两个栈实现一个队列的功能?要求给出算法和思路! 设2个栈为A,B, 一开始均为空. 入队: 将新元素push入栈A; 出队: (1)判断栈B是否为空; (2)如果不为空,则将栈A中所有元素依次pop出并push到栈B; (3)将栈B的栈顶元素pop出; 19 求组合数: 求n个数(1....n)中k个数的组合.... 如:combination(5,3)   要求输出:543,542,541,532,531,521,432,431,421,321, #i nclude int pop(int *); int push(int ); void combination(int ,int ); int stack[3]={0}; top=-1; int main() {     int n,m;     printf("Input two numbers:\n");     while( (2!=scanf("%d%*c%d",&n,&m)) )     {         fflush(stdin);         printf("Input error! Again:\n");     }     combination(n,m);     printf("\n"); } void combination(int m,int n) {     int temp=m;     push(temp);     while(1)     {         if(1==temp)         {             if(pop(&temp)&&stack[0]==n) //当栈底元素弹出&&为可能取的最小值,循环退出             break;         }         else if( push(--temp))         {             printf("%d%d%d  ",stack[0],stack[1],stack[2]);             pop(&temp);         }     } } int push(int i) {     stack[++top]=i;     if(top<2)         return 0;     else         return 1; } int pop(int *i) {     *i=stack[top--];     if(top>=0)         return 0;     else         return 1; } 找错题: 1.下面是C语言中两种if语句判断方式。请问哪种写法更好?为什么?  int n;  if (n == 10) // 第一种判断方式  if (10 == n) // 第二种判断方式 如果少了个=号,编译时就会报错,减少了出错的可能行,可以检测出是否少了= 2.下面的代码有什么问题? void DoSomeThing(...) {  char* p;  ...  p = malloc(1024);  // 分配1K的空间  if (NULL == p)   return;  ...  p = realloc(p, 2048); // 空间不够,重新分配到2K  if (NULL == p)   return;  ... } A: p = malloc(1024);     应该写成: p = (char *) malloc(1024*sizeof(char));  没有释放p的空间,造成内存泄漏。 3.下面的代码有什么问题?并请给出正确的写法。 void DoSomeThing(char* p) {  char str[16];  int n;  assert(NULL != p);  sscanf(p, "%s%d", str, n);  if (0 == strcmp(str, "something"))  {   ...  } } A: sscanf(p, "%s%d", str, n);   这句该写成:scanf(p, "%s%d", str, &n); 如果 %s 在前必须指定长度,不然sscanf 不知何时取字符串结束 scanf(p) -------------------------------------------------------------------------- 4.下面代码有什么错误? Void test1()  {   char string[10];   char *str1="0123456789";  strcpy(string, str1);  }  数组越界 -------------------------------------------------------------------------- 5.下面代码有什么问题? Void test2()  {    char string[10], str1[10];    for(i=0; i<10;i++)    {       str1[i] ='a';    }    strcpy(string, str1);  }  str1没有置字符串结束符'\0' , 数组越界 -------------------------------------------------------------------------- 6.下面代码有什么问题? Void test3(char* str1)  {    char string[10];    if(strlen(str1)<=10)    {      strcpy(string, str1);    }  }  ==数组越界 ==strcpy拷贝的结束标志是查找字符串中的\0 因此如果字符串中没有遇到\0的话 会一直复制,直到遇到\0,上面的123都因此产生越界的情况   建议使用 strncpy 和 memcpy -------------------------------------------------------------------------- 7.下面代码有什么问题? #define MAX_SRM 256  DSN get_SRM_no()  {    static int SRM_no; //是不是这里没赋初值?   int I;    for(I=0;I=MAX_SRM)      return (NULL_SRM);    else      return SRM_no;  }  // 网上有写:系统会初始化static int变量为0,但该值会一直保存,所谓的不可重入..  扯淡. 答案: 函数永远返回NULL_SRM ,因为最后i是等于MAX_SRM的,SRM_no 最大会是256 ,而不是255。连个都是后++产生的问题。 8. 下面代码有什么问题? void GetMemory(char *p){   p=(char *)malloc(100); } void Test(void){   char *str=NULL;   GetMemory=(str);   strcpy(str,"hello world");   printf(str); } A:错误--参数的值改变后,不会传回,GetMemory并不能传递动态内存,Test函数中的 str一直都是 NULL。 strcpy(str, "hello world");将使程序崩溃。 9 下面这个程序执行后会有什么错误或者效果:  #define MAX 255  int main() {    unsigned char A[MAX]; //i被定义为unsigned char    for (unsigned char i=0;i<=MAX;i++)       A[i]=i; } 解答:死循环加数组越界访问(C/C++不进行数组越界检查) MAX=255  数组A的下标范围为:0..MAX-1,这是其一.. 其二.当i循环到255时,循环内执行: A[255]=255; 这句本身没有问题..但是返回for (i=0;i<=MAX;i++)语句时, 由于unsigned char的取值范围在(0..255),i++以后i又为0了..无限循环下去. 10、请找出下面代码中的所以错误 说明:以下代码是把一个字符串倒序,如“abcd”倒序后变为“dcba” 1、#i nclude"string.h" 2、main() 3、{ 4、 char*src="hello,world"; 5、 char* dest=NULL; 6、 int len=strlen(src); 7、 dest=(char*)malloc(len); 8、 char* d=dest; 9、 char* s=src[len]; 10、 while(len--!=0) 11、 d++=s--; 12、 printf("%s",dest); 13、 return 0; 14、} 答: 方法1: int main(){ char* src = "hello,world"; int len = strlen(src); char* dest = (char*)malloc(len+1);//要为\0分配一个空间 char* d = dest; char* s = &src[len-1];//指向最后一个字符 while( len-- != 0 ) *d++=*s--; *d = 0;//尾部要加\0 printf("%s\n",dest); free(dest);// 使用完,应当释放空间,以免造成内存汇泄露 return 0; } 11.找错题:   1.请问下面程序有什么错误?    int a[60][250][1000],i,j,k;    for(k=0;k<=1000;k++)     for(j=0;j<250;j++)      for(i=0;i<60;i++)       a[i][j][k]=0; 把循环语句内外换一下, 造成大量的内存页失效 14:55 | 添加评论 | 固定链接 | 引用通告 (0) | 记录它 | C++程序设计 stl应用常见问题 1. 编译器的解析 list data(istream_iterator(cin),istream_iterator()); 这不是声明一个list变量 data,而是被认为是一格函数声明. 可以使用如下方法(effective stl 有讲) istream_iterator dataBeg(cin); list data(dataBeg,istream_iterator()); 当然还有 stack> sk; >> 被解析为操作符.当然这个容易避免,中间加个空格就解决了stack > sk; 2 . front() 与 begin() 一般经常使用容器的begin() 函数,因为常用 iterator 取得返回值,而front() 返回的是容器内第一个变量的引用. vector iv; vector::iterator it = v.begin(); vector::reference ref = v.front(); 对于一些api函数如fun(int *)需要的参数,做为输入参数 &*begin()写起来总是怪异。&front()相对好一点,当然&v[0] 更自然。特别是如需从第3个元素开始。&v[3] 更是最佳选择。 vc6 里面vector的begin()返回的是原类型(如vector 是 int )。所以可以写 fun(begin())不会出错, stl 源码分析里面讲的 sgi stl 版本也是,但dev c++, vc2003 里面都明确改成了对内部类iterator的返回 。所以任何时候不要用fun(begin()),尽管有时候他能工作 3. 名称过长的警告 对于vc6使用stl(强烈建议换掉,巨多不标准,标准代码不过的地方,如list 的sort 不能指定排序比较函数 bool comp(参数1,参数2) 这样的函数) 才有这种现象,产生过多得c4786警告,影响编译速度,可以使用如下命令关闭此编译选项 #pragma warning(disable:4786) 4. 字符串 字符串长度变量要用 string::size_type 声明而不是int。基本每种容器都有这个typedef. 如需返回长度基本都是size_type类型。 判断是否到字符串结尾与 string::npos比较,跟'\0'比较时char* 字符的行为。 vc2003 的string并没有使用引用计数(dev里面使用了引用计数,好像vc6也用了), 这样 string str1 = str2; 的操作与char* 的 strcopy 效率没什么区别。 但对于 char* s = "123"; string str = s;这样的语句任何版本string 都不会使用引用计数,引用计数只有在同类之间赋值才存在 如 string s1 = "hello"; string s2 = s1; 如果使用引用计数 s1[1]='q'时系统要重新给s1分配内存。早分配还是晚分配区别并不明显? 假设str2没有使用,编译将其优化掉,那都是只分配一次内存。但没有考虑引用计数 s1[1]='q' 操作,就可以省掉对引用计数的判断。相反倒提升了速度。如果需要和s1相同指向的字符串,用引用就好了,string& s2=s1. 当然这种情况只是对字符串来说的 btw: mfc 的CString 是采用引用计数的。c 字符串不像pascal 把字符串长度放在开头。但CString 序列化到文件,是字符长度在前面的。提前知道字符串长度有利于优化 5. map 插入元素,如果开始插入map中没有的元素使用insert 函数比用 map[]=这样赋值好一些,如果是hash_map这样先查找元素,找不到才执行插入. 如: typedef map m_type; typedef m_type::value_type valType; map< string, string > m; string h = "hello"; string w = "world"; m.insert( valType(h,w)); 6. do while(0) 相信有人看到下面这样的宏,其实这样就强制你必须在应用宏时加上结束符; 这样看起来才像是一个函数 #define xxx() do {xxx } while(0) 7. 初始化数组 int a[10]; memset(a,0,10*sizeof(int)); 相信肯定有人这么做过(int a[]={0,0,0,0...} 这么干的肯定也有),其实不必这么麻烦 int a[10] = {0};这样就ok 了。如果不是初始化的时候,而且不是赋0 ,还是老老实实用 fill(a,a+10,1); (其实对于char数组他调用的还是memset,不存在效率问题) 当然对于vector 容器定义时便可指定初始值 vector v(10,1); 8. 警惕函数参数 很多函数都是有偏特化版本的,对于特殊参数保证效率或有不同处理方法,这时要警惕输入参数。想使用特化版本,参数要保持一直。虽然好的编译器在release版本可能帮你选中特化版本。但最好不要太依赖于编译器。例如fill_n 版本 template inline void fill_n(_OutIt _First, _Diff _Count, const _Ty& _Val){ ..... } inline void fill_n(char *_First, size_t _Count, int _Val) { ::memset(_First, _Val, _Count); } inline void fill_n(signed char *_First, size_t _Count, int _Val) { ::memset(_First, _Val, _Count); } inline void fill_n(unsigned char *_First, size_t _Count, int _Val) { ::memset(_First, _Val, _Count); } 针对字符串选用memset进行赋值(能提升相当效率)。下面代码: char str[300]; fill_n(str,150,97); 看似调用了fill_n(char*,size_t,int) (第二个函数), 其实调用的还是模板函数(第一个)。因为150 被编译器解释为int 类型,与fill_n(char*,size_t,int) 是不相符合的。还有 fill_n(str,(size_t)150,'a') 也没有调用优化版本,因为'a' 是char 而不是int 类型。 所以fill_n(str,150*sizeof(char),97) 这种写法才算完美。 主要注意有 size_t 参数的函数, 用size_t 声明或者多*个sizeof(type) 9. list 的 earse 对于vc2003 来说,判断了如果是end节点 则不删除。但sgi stl 没有判断。所以注意你在list 里面执行erase操作时是否会删掉这个节点。删掉的话整个链表的基石也就垮了。可以在dev 编译器(同gcc)里面执行下面程序,这个循环从begin() 开始都没得到链表节点。 int a[5] ={2,3,5,4,1}; list lt(a,a+5); lt.erase(lt.end()); //明显了点。 list::iterator it; for(it=lt.begin();it!=lt.end();it++) { cout<<*it<<" "; } 或许不能删除end节点是使用者应该注意的。但看两个库的做法,即使牛人们也难以统一意见。个人意见是不用erase判断是否为头节点,但如果去面试的话。不介意你"画蛇添足"。 对于某些面试经常抓着这点不放,你的链表删除怎么没判断是否为头节点。你可以飞出一本stl源码剖析,砸在他头上,指着他的鼻子说: 你看人家C++标准库都可以这么做。 sgi stl 一般都没有对这些边界条件做判断,没人会使用list earse()去删end节点。同样如果没有确定front()是否有元素, 也不要在deque上执行pop_front操作。 10 deque 的空间 vc 中deque跟vector相似,自增长,但deque有多个大小相同的缓冲区,使用空间只会增长不会降低。如果想删除弹出节点空间应该使用list 。 而sgi stl 实现的deque (默认对于类型长度大于int)如果一个缓冲区没有数据就删除。对于pj stl 保证了速度,sgi stl 保证了空间。比较也没有太大意义。 11 set 的比较函数对象 给set 指定比较函数对象时,重载operator() 要声明成常量函数。如 class less_key{ public: bool operator() (const foo &f1, const foo &f2) const { return (f1.key < f2.key); } }; 因为set 取得比较函数对象类型后,把该类的常量类型传递给了底层的rb_tree,所以不声明operator()为常量函数,编译便会失败。而且这种关系比较函数对象并没有改类内成员,所以任何时候最好都声明为 const . 12 vector > 一般对于原始类型声明可变数组可以不指定长度如: vector iv; iv.push_back(1); 但对于类型也是vector > vector > ivv; ivv[0].push_back(1); cout< > ivv; ivv.push_back(vector()); ivv[0].push_back(1); cout< > ivv(10); 便可以初始化10个,毕竟使用2维数组,而且两个维度都可变的情况不多。这样在这10个之内就不需要调用ivv.push_back(vector()); 13 resize 和 reserve 之区别 resize 扩展空间并且初始化元素,reserve 只扩展空间.对于 vector 调用 resize() 函数后。对 empty () 检测为 false. 而 reserve 后检查empty() 仍为 true. 由于visual assist 的帮助今天,一不小心就调用了resize() .结果白浪费好长时间调试  避免内存碎片化  许多书籍提到过内存碎片,也看到一些方法防治内存碎片。一直以来都以为频繁的分配释放内存会导致系统内存碎片过多(虽然这个想法并没有错到离谱)。后来看过计算机程序设计艺术上面关于伙伴系统的介绍,一般操作系统都采用此种方法来管理内存。频繁分配释放内存确实会导致一些系统负担,但分配的内存释放及时,内存管理系统将能够急时合并相邻空闲内存块,得到更大的空闲内存。这样并不会导致内存碎片的出现。即使相邻空间不空闲,这样产生的碎片还是比较少的   今天突然醒悟内存碎片的出现主要跟分配有关,特别是分配小而且生命周期很长的内存块时,才容易导致内存碎片的出现。对于伙伴系统,假设有16byte空间,依次分配一个1,3,5byte空间,在分配4byte,对于伙伴系统将分配不出最后的4byte,尽管还有7byte的额外空间,但这些空间只剩下1、2byte的空间块,如下图,即使这些伙伴空间都是空闲的,也难以被充分利用。而3、5byte分配后剩下的空间更是由于少于上层空间的一半而被浪费掉了,不能再进行分配。如果分配的小块内存相当多,将会浪费很多内存空间,导致内存碎片化。当然真正操作系统是32位对齐的,但情行是类似的     所以如果要动态分配的空间比较小,一般采取先分配一大块空间。然后在有内存分配需求时,从大块空间依次取出。如vc中的map list array 等便是如此设计。每个类都先使用CPlex 分配一定数量的CAssoc空间,当空间用完后,在分配相同大小的空间。当然这些空间是链接在一起的。下面是从quake3中摘出来的一部分代码,对于quake配置参数是一直存在于整个软件运行期的,这些参数依次保存在smallzone空间中。   如果分配的空间很快就会释放(如分配释放同时在一个函数内),那么就不需要考虑内存碎片问题。但是鉴于伙伴系统效率,如果存在大量频繁的分配释放,可以考虑使用桶状内存管理。即分配一块大的内存zone(当然还需要3个指针,标志zone头尾和当前写入的位置)。而后需要相对小的空间时,直接向zone中写入,如到zone尾部时,转到zone开头写入。当然以前写的东西就被覆盖了,一定要保证覆盖时这段内存中的东西已经不再需要了。如果想更省事可以考虑boost pool 内存池,不过 pool 分配的块大小总是固定的。  void func()  {       boost::pool<> p(256*sizeof(BYTE));   //指定每次分配的块的大小       for (int i = 0; i < 10000; ++i)       {         BYTE* const  p = p.malloc();  //pool分配指定大小的内存块;需要的时候,pool会向系统申请大块内存。         ... // Do something with t;          p.free( p);        //释放内存块,交还给pool,不是返回给系统。       }       //pool的析构函数会释放所有从系统申请到的内存。 } //注意必须是.c文件。 #define ZONEID 0x1d4a11 typedef enum {      TAG_FREE,      TAG_GENERAL,      TAG_BOTLIB,      TAG_RENDERER,      TAG_SMALL,      TAG_STATIC } memtag_t; typedef struct memblock_s {      int size;           // including the header and possibly tiny fragments      int     tag;            // a tag of 0 is a free block      struct memblock_s       *next, *prev;      int     id;         // should be ZONEID } memblock_t; memzone_t *mainzone; memzone_t *smallzone; //只调用一次分配足够内存空间 void Com_InitSmallZoneMemory( void ) {      s_smallZoneTotal = 512 * 1024;      smallzone = calloc( s_smallZoneTotal, 1 );      if ( !smallzone )      {           Com_Error( ERR_FATAL, "Small zone data failed to allocate %1.1f megs", (float)s_smallZoneTotal /(1024*1024) );      }      Z_ClearZone( smallzone, s_smallZoneTotal );       return; } //从大的内存空间中逐步取出足够的小块空间 void *S_Malloc( int size)  {      int  extra, allocSize;      memblock_t *start, *rover, *new, *base;      memzone_t *zone;      tag =TAG_SMALL;      zone = smallzone;      allocSize = size;      size += sizeof(memblock_t); // account for size of block header      size += 4;   // space for memory trash tester      size = (size + 3) & ~3;  // align to 32 bit boundary       base = rover = zone->rover;     start = base->prev;        do      {           if (rover == start)            {                 Com_Error( ERR_FATAL, "Z_Malloc: failed on allocation of %i bytes from the %s zone",        size, zone == smallzone ? "small" : "main");                return NULL;           }       if (rover->tag)       {            base = rover = rover->next;       } else       {            rover = rover->next;       }      } while (base->tag || base->size < size);      extra = base->size - size;      if (extra > MINFRAGMENT) {       // there will be a free fragment after the allocated block       new = (memblock_t *) ((byte *)base + size );       new->size = extra;       new->tag = 0;   // free block       new->prev = base;       new->id = ZONEID;       new->next = base->next;       new->next->prev = new;       base->next = new;       base->size = size;      }        base->tag = tag;   // no longer a free block       zone->rover = base->next; // next allocation will start looking here      zone->used += base->size; //      base->id = ZONEID;     *(int *)((byte *)base + base->size - 4) = ZONEID;     return (void *) ((byte *)base + sizeof(memblock_t)); } void Z_ClearZone( memzone_t *zone, int size ) {      memblock_t *block;       // set the entire zone to one free block      zone->blocklist.next = zone->blocklist.prev = block =       (memblock_t *)( (byte *)zone + sizeof(memzone_t) );      zone->blocklist.tag = 1; // in use block      zone->blocklist.id = 0;      zone->blocklist.size = 0;     zone->rover = block;     zone->size = size;     zone->used = 0;      block->prev = block->next = &zone->blocklist;     block->tag = 0;   // free block     block->id = ZONEID;     block->size = size - sizeof(memzone_t); } //向内存块中添加字符串 char *CopyString( const char *in ) {      char *out;      if (!in[0]) {       return ((char *)&emptystring) + sizeof(memblock_t);      }      else if (!in[1])      {           if (in[0] >= '0' && in[0] <= '9')           {                return ((char *)&numberstring[in[0]-'0']) + sizeof(memblock_t);          }     }     out = S_Malloc (strlen(in)+1);     strcpy (out, in);     return out; } C++面试试题 + 基础 + 搞玩 oicqkill(原作) (这条文章已经被阅读了841次) 时间:2003年08月04日 15:33 来源:李晓斌 教程 在的IT人 [有人说叫“挨踹人”]啊,大多浮躁得很,动不动说自己精通什么,其实,很多基础的都不知道,真是让人觉得悲哎啊。当然,我曾经也是这样的了 下面都是雕虫小技,不等大堂之雅,还望莫笑,谢谢。 1、 void main(void) { int nArrLength(400), i = 546; // 主要是考看对C++的基础知识是否了解 // 这里的int nArrLength(400)是对整数的定义,当然,明名上有问题,这里是故意这样的 // 但是,最好是变量名改为 ....[还是您自己看着办了] for (int i = 0; i< 99999999999; i++); // 这里是考对变量越界理解,同时...., // 所以,999...应该改为 ~((int)0),也就是整数中0取反 // 考对变量块作用域的理解,这里的i,在循环后就不存在了 cout << nArrLength << endl; // 这里输出 400 cout << i << endl; // 这里输出 546 } 以上代码如果有错,请该正,并写出输出结果? 2、int i = 5, b = 7; cout << (i+++b) < y? x : y; } int x = 55, y = 77; max(x, y) += 12 + 11; // 此时 y = 92; cout << "x = "x << "; y = "<< y << endl; // 输出 x = 55; y = 92; =================================== 下面的题来源与今年高程考试题 上面的是我自己弄着玩的 =================================== 4.随便咱都行,只要不查资料,不问人 int strcmp(char *s,char *t) { while(*s && *t && _______ ) // *s == *t { s++; t++; } return (______) // *s - *t } c++面试题 发表:2004-5-22 19:05:36 出处:你的博客网(yourblog.org) -------------------------------------------------------------------------------- 不使用循环,如何获得一个32位无符号数里面被至1的位的个数 这是tcl的一道面试题,想了很久没想出来, 附送另外一道简单题 如何不使用中间变量,将两个数交换值,就是swap(a,b) 注意要完美解决哦 h999999h给出 a=(a+b)/2; b=b-a; a=b+a; b=a-b*2; smartsl给出 代码: #include #include int fun(unsigned long i) { if(i<=1)return i&1; else return fun(i>>1)+(i&1); } void main() { unsigned long i; for(i=0xF0000000;i<0xF0000010;i++) { printf("%lx --> %d\n",i,fun(i)); } getch(); }在TC2和VC6下编译通过。 ㈡ a=a+b; //a=(A+B),b=B b=a-b; //a=(A+B),b=A a=a-b; //a=B,b=A 如果是float或者double可能有精确度问题。 如果是整型,也可能有溢出问题。 1、递归,smartsl给出的 2、 #include void swap(void** a, void** b) { (long)*a = (long)*a^(long)*b; (long)*b = (long)*a^(long)*b; (long)*a = (long)*a^(long)*b; } int main() { float x=10,y=20; float *a = &x; float *b = &y; swap((void*)&a,(void*)&b); printf("%f,%f\n",*a,*b); return 0; } 交换变量地址,兼容所有类型 bbkxjy给出 抄来的一个: 代码: function CountBit(X: DWORD): DWORD; {Count 1 bits in X} begin X := X and $55555555 + X shr 1 and $55555555; X := X and $33333333 + X shr 2 and $33333333; X := X and $0f0f0f0f + X shr 4 and $0f0f0f0f; X := X and $00ff00ff + X shr 8 and $00ff00ff; X := X and $0000ffff + X shr 16 and $0000ffff; Result := X; end; 在 HyperString (一个third party的Delphi函数库)里面找到的,但最初应该是在Borland的新闻组里面给出的。另外还可以用 lookup table 的办法,也比较快。 代码: unsigned long CountBit(unsigned long X) { X = X & 0x55555555 + X >> 1 & 0x55555555; X = X & 0x33333333 + X >> 2 & 0x33333333; X = X & 0x0F0F0F0F + X >> 4 & 0x0F0F0F0F; X = X & 0x00FF00FF + X >> 8 & 0x00FF00FF; X = X & 0x0000FFFF + X >> 16 & 0x0000FFFF; return(X); } 引用: 最初由 lroc 发表 如果lookup办法是拆成8x4bits,不见得比循环快啊。 32次循环全是寄存器里完成的,8次查找可以认为是1次内存、7次cache。 changxing给出 这个要看编译器了 引用: 最初由 smartsl 发表 C语言有优先级问题,应该这样写: unsigned long CountBit(unsigned long X) ........ double 也适用, struct 都没问题,只要cpu是32位的(因为是long) 代码: #include typedef struct __var { int x; float y; } _var; void swap(void** a, void** b) { (long)*a = (long)*a^(long)*b; (long)*b = (long)*a^(long)*b; (long)*a = (long)*a^(long)*b; } int main() { _var x = {10,11.1}; _var y = {20,22.2}; _var *a = &x; _var *b = &y; swap((void*)&a,(void*)&b); printf("%d,%f | %d,%f\n",a->x,a->y,b->x,b->y); return 0; } "swap.c" 23L, 428C written # gcc -Wall -oswap swap.c # ./swap 20,22.200001 | 10,11.100000 # 引用: 最初由 snowolf 发表 swap俺也想到了 a= a 异或 b; b= a 异或 b; a= a 异或 b; 今天重翻老谭的《C程序设计》,原来里面都提到了两个数互换数值不用中间变量的方法,就是异或运算。 假设a和b要互换,那么换成Newa=b,Newb=a。 Newb=(a XOR b) XOR b = a XOR b XOR b = a XOR (b XOR b) = a XOR 0 = a Newa=(a XOR b) XOR Newb = a XOR b XOR a = (a XOR a) XOR b = 0 XOR b = b

下载文档到电脑,查找使用更方便

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 10 金币 [ 分享文档获得金币 ] 2 人已下载

下载文档