華爲軟件研發面試題2

C語言面試題大彙總之華爲面試題
                           Eddy整理
1、局部變量能否和全局變量重名?  
 答:能,局部會屏蔽全局。要用全局變量,需要使用"::" ;局部變量可以與全局變量同名,在函數內引用這個變量時,會用到同名的局部變量,而不會用到全局變量。對於有些編譯器而言,在同一個函數內可以定義多個同名的局部變量,比如在兩個循環體內都定義一個同名的局部變量,而那個局部變量的作用域就在那個循環體內。
   
2、如何引用一個已經定義過的全局變量?   
答:extern  可以用引用頭文件的方式,也可以用extern關鍵字,如果用引用頭文件方式來引用某個在頭文件中聲明的全局變理,假定你將那個編寫錯了,那麼在編譯期間會報錯,如果你用extern方式引用時,假定你犯了同樣的錯誤,那麼在編譯期間不會報錯,而在連接期間報錯。
  
3、全局變量可不可以定義在可被多個.C文件包含的頭文件中?爲什麼?   
答:可以,在不同的C文件中以static形式來聲明同名全局變量。   可以在不同的C文件中聲明同名的全局變量,前提是其中只能有一個C文件中對此變量賦初值,此時連接不會出錯.    
4、請寫出下列代碼的輸出內容   
#include  <stdio.h>  
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 <stdio.h>   
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 <stdio.h>
#include <string.h>
main()
{
char str[]="hello,world";
int len=strlen(str);
char t;
for(int i=0; i<len/2; i++)
{
t=str[i];
str[i]=str[len-i-1]; //小心一點
str[len-i-1]=t;
}
printf("%s",str);
return 0;
}
11.對於一個頻繁使用的短小函數,在C語言中應用什麼實現,在C++中應用什麼實現?  
 c用宏定義,c++用inline   
12.直接鏈接兩個信令點的一組鏈路稱作什麼?   
PPP點到點連接     
13.接入網用的是什麼接口?
V5接口    
14.voip都用了那些協議?  
H.323協議簇、SIP協議、Skype協議、H.248和MGCP協議 
15.軟件測試都有那些種類?  
 黑盒:針對系統功能的測試   
白盒:測試函數功能,各函數接口   
16.確定模塊的功能和模塊的接口是在軟件設計的那個隊段完成的?   
概要設計階段   
17.   
unsigned char *p1;
unsigned long *p2;
p1=(unsigned char *)0x801000; 
p2=(unsigned long *)0x810000;
請問p1+5=  ;
p2+5=  ;
答案:0x801005(相當於加上5位) 0x810014(相當於加上20位);
 
 
選擇題:   
21.Ethternet鏈接到Internet用到以下那個協議? D  
A.HDLC;B.ARP;C.UDP;D.TCP;E.ID    
22.屬於網絡層協議的是:( B C)     
  A.TCP;B.IP;C.ICMP;D.X.25  
23.Windows消息調度機制是:(C) 
  A.指令隊列;B.指令堆棧;C.消息隊列;D.消息堆棧;
  
找錯題:   
25.請問下面程序有什麼錯誤?   
int a[60][250][1000],i,j,k;   
for(k=0;kMax_GT_Length)    
{     return GT_Length_ERROR;  
 }    ....... }
答: 死循環//  
問答題:   
29.IP Phone的原理是什麼?
IP電話(又稱IP PHONE或VoIP)是建立在IP技術上的分組化、數字化傳輸技術,其基本原理是:通過語音壓縮算法對語音數據進行壓縮編碼處理,然後把這些語音數據按IP等相關協議進行打包,經過IP網絡把數據包傳輸到接收地,再把這些語音數據包串起來,經過解碼解壓處理後,恢復成原來的語音信號,從而達到由IP網絡傳送語音的目的。
30.TCP/IP通信建立的過程怎樣,端口有什麼作用?   
三次握手,確定是哪個應用程序使用該協議   
31.1號信令和7號信令有什麼區別,我國某前廣泛使用的是那一種?
  1號信令接續慢,但是穩定,可靠。
7號信令的特點是:信令速度快,具有提供大量信令的潛力,具有改變和增加信令的靈活性,便於開放新業務,在通話時可以隨意處理信令,成本低。目前得到廣泛應用。
32.列舉5種以上的電話新業務
如“鬧鐘服務”、“免干擾服務”、“熱線服務”、“轉移呼叫”、“遇忙回叫”、“缺席用戶服務”、“追查惡意呼叫”、“三方通話”、“會議電話”、“呼出限制”、“來電顯示”、“虛擬網電話”等
.找錯題:
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;
答: 把循環語句內外換一下
2.#define Max_CB 500
void LmiQueryCSmd(Struct MSgCB * pmsg)
{
unsigned char ucCmdNum;
......
for(ucCmdNum=0;ucCmdNum<Max_CB;ucCmdNum++)
{
......;
}
答: 死循環,unsigned int的取值範圍是0~255
3.以下是求一個數的平方的程序,請找出錯誤:
#define SQUARE(a)((a)*(a))
int a=5;
int b;
b=SQUARE(a++);
答:結果與編譯器相關,得到的可能不是平方值.
 
微軟亞洲技術中心的面試題!!
1.進程和線程的差別。
答:線程是指進程內的一個執行單元,也是進程內的可調度實體.
與進程的區別:
(1)調度:線程作爲調度和分配的基本單位,進程作爲擁有資源的基本單位
(2)併發性:不僅進程之間可以併發執行,同一個進程的多個線程之間也可併發執行
(3)擁有資源:進程是擁有資源的一個獨立單位,線程不擁有系統資源,但可以訪問隸屬於進程的資源.
(4)系統開銷:在創建或撤消進程時,由於系統都要爲之分配和回收資源,導致系統的開銷明顯大於創建或撤消線程時的開銷。
2.測試方法
答:人工測試:個人複查、抽查和會審
機器測試:黑盒測試和白盒測試
3.Heap與stack的差別。
答:Heap是堆,stack是棧。
Stack的空間由操作系統自動分配/釋放,Heap上的空間手動分配/釋放。
Stack空間有限,Heap是很大的自由存儲區
C中的malloc函數分配的內存空間即在堆上,C++中對應的是new操作符。
程序在編譯期對變量和函數分配內存都在棧上進行,且程序運行過程中函數調用時參數的傳遞也在棧上進行
 
4.Windows下的內存是如何管理的?
  分頁管理
8.談談IA32下的分頁機制
小頁(4K)兩級分頁模式,大頁(4M)一級
9.給兩個變量,如何找出一個帶環單鏈表中是什麼地方出現環的?
一個遞增一,一個遞增二,他們指向同一個接點時就是環出現的地方
10.在IA32中一共有多少種辦法從用戶態跳到內核態?
通過調用門,從ring3到ring0,中斷從ring3到ring0,進入vm86等等
11.如果只想讓程序有一個實例運行,不能運行兩個。像winamp一樣,只能開一個窗口,怎樣實現?
用內存映射或全局原子(互斥變量)、查找窗口句柄..
FindWindow,互斥,寫標誌到文件或註冊表,共享內存。. 
12.如何截取鍵盤的響應,讓所有的'a’變成'b’?
答:鍵盤鉤子SetWindowsHookEx
14.存儲過程是什麼?有什麼用?有什麼優點?
答:我的理解就是一堆sql的集合,可以建立非常複雜的查詢,編譯運行,所以運行一次後,以後再運行速度比單獨執行SQL快很多
 
15Template有什麼特點?什麼時候用?
  答: Template可以獨立於任何特定的類型編寫代碼,是泛型編程的基礎.
     當我們編寫的類和函數能夠多態的用於跨越編譯時不相關的類型時,用Template.
     模板主要用於STL中的容器,算法,迭代器等以及模板元編程.
(C++的template是實現在庫設計和嵌入式設計中的關鍵。
template能實現抽象和效率的結合;同時template還能有效地防止代碼膨脹)
16.談談Windows DNA結構的特點和優點。
答:Windows Distributed interNet Application Architecture(Windows分佈式應用結構,簡稱Windows DNA)是微軟創建新一代高適應性商業解決方案的框架,它使公司能夠充分地挖掘數字神經系統的優點。Windows DNA是第一個將Internet、客戶/服務器、和用於計算的PC模型結合並集成在一起的爲新一類分佈式計算方案而設計的應用軟件體系結構
17. 網絡編程中設計併發服務器,使用多進程多線程,請問有什麼區別?
答:1)進程:子進程是父進程的複製品。子進程獲得父進程數據空間、堆和棧的複製品。
2)線程:相對與進程而言,線程是一個更加接近與執行體的概念,它可以與同進程的其他線程共享數據,但擁有自己的棧空間,擁有獨立的執行序列。
兩者都可以提高程序的併發度,提高程序運行效率和響應時間。
線程和進程在使用上各有優缺點:線程執行開銷小,但不利於資源管理和保護;而進程正相反。同時,線程適合於在SMP機器上運行,而進程則可以跨機器遷移。
思科
1. 用宏定義寫出swap(x,y)
答#define swap(x, y)
x = x + y;
y = x - y;
x = x - y;
2.數組a[N],存放了1至N-1個數,其中某個數重複一次。寫一個函數,找出被重複的數字.時間複雜度必須爲o(N)函數原型:
int do_dup(int a[],int N)
答:int do_dup(int a[],int N)    //未經調試
 {
      int sun = 0;
      int sum2;
      for(int i=0;i<N;++i)
      {
        Sum+=a[i];
      }
      Sum2 = (1+N-1)*N/2;
      Return (sum-sum2);
 }
3 一語句實現x是否爲2的若干次冪的判斷
答:方法1)int i = 512;
cout << 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<sizeof(str)/sizeof(str[0]); ++i )
if( 'a'<=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 <stdio.h>
#include <stdlib.h>
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. 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類型爲一個字節,取值範圍是[-128127]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 <string.h>
功能:把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 <memory.h>
功能:由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)
/*在下屆爲low,上界爲high的數組a中折半查找數據元素x*/
{
int mid;
if(low>high) return -1;
mid=(low+high)/2;
if(x==a[mid]) return mid;
if(x<a[mid]) return(BSearch(a,x,low,mid-1));
else return(BSearch(a,x,mid+1,high));
}
2) 非遞歸方法實現:
int BSearch(elemtype a[],keytype key,int n)
{
int low,high,mid;
low=0;high=n-1;
while(low<=high)
{
mid=(low+high)/2;
if(a[mid].key==key) return mid;
else if(a[mid].key<key) low=mid+1;
else high=mid-1;
}
return -1;
}
3. 遞歸計算如下遞歸函數的值(斐波拉契):
f(1)=1
f(2)=1
f(n)=f(n-1)+f(n-2) n>2
解:非遞歸算法:
int f(int n)
{
int i,s,s1,s2;
s1=1;/*s1用於保存f(n-1)的值*/
s2=1;/*s2用於保存f(n-2)的值*/
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;i<n;i++)
for(j=0;j<n-i;j++)   
{
if(x[j].key>x[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<n;++i)    //最多做n-1趟排序
 {
Exchange = false;
For(j=n-1;j>=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 <Winsock2.h>
#include <stdio.h>
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 <Winsock2.h>
#include <stdio.h>
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 <iostream.h>
class human
{
public:
human(){ human_num++;}; //默認構造函數
static int human_num;     //靜態成員
~human()
{
human_num--;
print();
}
void print()             //
{
cout<<"human num is: "<<human_num<<endl;
}
protected:
private:
};
int human::human_num = 0;   //類中靜態數據成員在外部定義,僅定義一次
human f1(human x)
{
x.print();
return x;
}
int main(int argc, char* argv[])
{
human h1; //調用默認構造函數,human_num變爲1
h1.print(); // 打印Human_man:1
human h2 = f1(h1); //先調用函數f1(),輸出human_num:1,而後輸出human_num爲0,
h2.print();//打印輸出:human_num:0
return 0;
} //依次調用兩個析構函數:輸出:human_num:-1,human_num:-2;
輸出:
1
1
0
0
-1
-2
----------------------------
分析:
human h1; //調用構造函數,---hum_num = 1;
h1.print(); //輸出:"human is 1"
human h2 = f1(h1); //再調用f1(h1)的過程中,由於函數參數是按值傳遞對象,調用默認的複製構造函數,h2並沒有調用定義的構造函數.
 
 
C/C++ 程序設計員應聘常見面試試題深入剖析
silver6 | 25 九月, 2006 09:07
本文的寫作目的並不在於提供C/C++程序員求職面試指導,而旨在從技術上分析面試題的內涵。文中的大多數面試題來自各大論壇,部分試題解答也參考了網友的意見。
  許多面試題看似簡單,卻需要深厚的基本功才能給出完美的解答。企業要求面試者寫一個最簡單的strcpy函數都可看出面試者在技術上究竟達到了怎樣的程度,我們能真正寫好一個strcpy函數嗎?我們都覺得自己能,可是我們寫出的strcpy很可能只能拿到10分中的2分。讀者可從本文看到strcpy 函數從2分到10分解答的例子,看看自己屬於什麼樣的層次。此外,還有一些面試題考查面試者敏捷的思維能力。 
  分析這些面試題,本身包含很強的趣味性;而作爲一名研發人員,通過對這些面試題的深入剖析則可進一步增強自身的內功。
  2.找錯題
  試題1:
void test1()
{
 char string[10];
 char* str1 = "0123456789";
 strcpy( string, str1 );
}

  試題2:
void test2()
{
 char string[10], str1[10];
 int i;
 for(i=0; i<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 /* __INCvxWorksh */

  解答:
  頭文件中的編譯宏
#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:請說出staticconst關鍵字儘可能多的作用
  解答:
  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問答題:
/*Select g_cardapply. g_applydate
From g_cardapply, g_cardapplydetail
Where g_cardapply. g_applyno=g_cardapplydetail. g_applyno
And g_cardapplydetail.g_idcard='440401430103082'*/

/*Select *From (select count(*) g_count , g_idcard
From g_cardapplydetail 
Group by g_idcard ) a
Where a. g_count >= 2*/

/*Update g_cardapply 
set g_state='07' 
where g_applyno in (select distinct g_applyno 
from g_cardapplydetail 
where g_idcard ='440401430103082') 
update g_cardapplydetail
set g_state='07'
where g_idcard='440401430103082' */

/*Delete from g_cardapplydetail
Where g_name like '李%'*/
通過測試
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 <iostream>
#include <vector>
using namespace std;
void print(vector<int>);
int main()
{
vector<int> array;
array.push_back(1);
array.push_back(6);
array.push_back(6);
array.push_back(3);
//刪除array數組中所有的6
vector<int>::iterator itor;
vector<int>::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<int> v)
{
cout << "n vector size is: " << v.size() << endl;
vector<int>::iterator p = v.begin();

我的答案是,迭代器問題,只能刪除第一個6,以後迭代器就失效了,不能刪除之後的元素。
但我不知道怎麼改
void print(const vector<int>&);
int main()
{
vector<int> 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<int>& v)
{
cout << "n vector size is: " << v.size() << endl;
copy(v.begin(), v.end(), ostream_iterator<int>(cout, " ") );
}
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> 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);
//&Eacute;&frac34;&sup3;&yacute;array&Ecirc;&yacute;×é&Ouml;&ETH;&Euml;ù&Oacute;&ETH;&micro;&Auml;6
vector<int>::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> ,編譯器從標準庫路徑開始搜索 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<j; i++) {
s[i] = new Integer(i+1).toString();
}

for(int i=0; i<j; i++) {
t = s[i];
for(int a=0; a<j; a++) {
t += s[i];
System.out.println(t); 
}
System.out.println();
}
}
}
第二題還更簡單了

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);
}
}
}
============================================================
樓上的沒看清題目,它是讓你對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;i<a.length;i++)
{
a[i]=new int[i+1];
}
for(int i=1;i<=a.length;i++)
{

for(int j=i+1;j<=a.length;j++)
{
System.out.print(i);
System.out.print(j+" ");
}
System.out.print(" ");
}

for(int i=a.length;i>0;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 <iostream>
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<<str2long(p);
getchar();
return 0;
}
STL,四行
#include <sstream>
#include <iostream>
#include <string>

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<<ToLong(s);
return 0;
}
謝謝剛纔上面的帖子提醒負數的問題,我更正了,還是隻用一行:
#include <iostream>
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<<str2long(p);
getchar();
return 0;
}
發佈了21 篇原創文章 · 獲贊 2 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章