4. static有什麼用途?(請至少說明兩種) 1,在函數中定義的STATIC變量在函數重複調用時維持其值不變,不在執行此變量的初始化代碼。 2可以定義一個作用鬱爲當前文件的變量。 2, 7. 引用與指針有什麼區別? 1) 引用必須被初始化,指針不必。 2) 引用初始化以後不能被改變,指針可以改變所指的對象。 2) 不存在指向空值的引用,但是存在指向空值的指針。 ?8. 描述實時系統的基本特性 在特定時間內完成特定的任務,實時性與可靠性 9. 全局變量和局部變量在內存中是否有區別?如果有,是什麼區別? 全局變量儲存在靜態數據庫,局部變量在堆棧 ?10. 什麼是平衡二叉樹? 左右子樹都是平衡二叉樹 且左右子樹的深度差值的絕對值不大於1 11. 堆棧溢出一般是由什麼原因導致的? 沒有回收垃圾資源。 ?12. 什麼函數不能聲明爲虛函數 構造函數,友元函數 ?13. 冒泡排序算法的時間複雜度是什麼? O(n^2) 14. 寫出float x 與“零值”比較的if語句。 if(x〈0.000001&&x〉-0.000001) ?16. Internet採用哪種網絡協議?該協議的主要層次結構? tcp/ip 應用層/傳輸層/網絡層/數據鏈路層/物理層 ?17. Internet物理地址和IP地址轉換採用什麼協議? ARP (Address Resolution Protocol)(地址解析協議) ?18.IP地址的編碼分爲哪倆部分? IP地址由兩部分組成,網絡號和主機號。不過是要和“子網掩碼”按位與上之後才能區分哪些是網絡位哪些是主機位。 ????月色夫環寫一下2.用戶輸入M,N值,從1至N開始順序循環數數,每數到M輸出該數值,直至全部輸出。寫出C程序。 循環鏈表,用取餘操作做 3.不能做switch()的參數類型是: switch的參數不能爲實型。 =========================================================================== 華為 1、局部變量能否和全局變量重名? 答:能,局部會屏蔽全局。要用全局變量,需要使用"::" 局部變量可以與全局變量同名,在函數內引用這個變量時,會用到同名的局部變量,而不會用到全局變量。對於有些編譯器而言,在同一個函數內可以定義多個同名的局部變量,比如在兩個循環體內都定義一個同名的局部變量,而那個局部變量的作用域就在那個循環體內 ?2、如何引用一個已經定義過的全局變量? 答:extern可以用引用頭文件的方式,也可以用extern關鍵字,如果用引用頭文件方式來引用某個在頭文件中聲明的全局變理,假定你將那個變寫錯了,那麼在編譯期間會報錯,如果你用extern方式引用時,假定你犯了同樣的錯誤,那麼在編譯期間不會報錯,而在連接期間報錯 3、全局變量可不可以定義在可被多個.C文件包含的頭文件中?爲什麼? 答:可以,在不同的C文件中以static形式來聲明同名全局變量。 可以在不同的C文件中聲明同名的全局變量,前提是其中只能有一個C文件中對此變量賦初值,此時連接不會出錯 4、語句for( ;1 ;)有什麼問題?它是什麼意思? 答:和while(1)相同。 5、do……while和while……do有什麼區別? 答:前一個循環一遍再判斷,後一個判斷以後再循環 6、請寫出下列代碼的輸出內容 #i nclude<stdio.h> main() { 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 ??1、static全局變量與普通的全局變量有什麼區別?static局部變量和普通局部變量有什麼區別?static函數與普通函數有什麼區別? 全局變量(外部變量)的說明之前再冠以static 就構成了靜態的全局變量。全局變量本身就是靜態存儲方式, 靜態全局變量當然也是靜態存儲方式。 這兩者在存儲方式上並無不同。這兩者的區別雖在於非靜態全局變量的作用域是整個源程序, 當一個源程序由多個源文件組成時,非靜態的全局變量在各個源文件中都是有效的。 而靜態全局變量則限制了其作用域, 即只在定義該變量的源文件內有效, 在同一源程序的其它源文件中不能使用它。由於靜態全局變量的作用域侷限於一個源文件內,只能爲該源文件內的函數公用, 因此可以避免在其它源文件中引起錯誤。 從以上分析可以看出, 把局部變量改變爲靜態變量後是改變了它的存儲方式即改變了它的生存期。把全局變量改變爲靜態變量後是改變了它的作用域, 限制了它的使用範圍。 static函數與普通函數作用域不同。僅在本文件。只在當前源文件中使用的函數應該說明爲內部函數(static),內部函數應該在當前源文件中說明和定義。對於可在當前源文件以外使用的函數,應該在一個頭文件中說明,要使用這些函數的源文件要包含這個頭文件 ?static全局變量與普通的全局變量有什麼區別:static全局變量只初使化一次,防止在其他文件單元中被引用; static局部變量和普通局部變量有什麼區別:static局部變量只被初始化一次,下一次依據上一次結果值; static函數與普通函數有什麼區別:static函數在內存中只有一份,普通函數在每個被調用中維持一份拷貝 2、程序的局部變量存在於(堆棧)中,全局變量存在於(靜態區 )中,動態申請數據存在於( 堆)中。 3、設有以下說明和定義: typedef union {long i; int k[5]; char c;} DATE;
struct da DATE max; 則語句 printf("%d",sizeof(struct date)+sizeof(max));的執行結果是:___52____ 答:DATE是一個union, 變量公用空間. 裏面最大的變量類型是int[5], 佔用20個字節. 所以它的大小是20
da 所以結果是 20 + 32 = 52. 當然...在某些16位編輯器下, int可能是2字節,那麼結果是 int2 + DATE10 + double8 = 20 4、隊列和棧有什麼區別? 隊列先進先出,棧後進先出 5、寫出下列代碼的輸出內容 #i nclude<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) { INCp=&inc; int temp =p(arg1); fun(&temp,&arg1, arg2); printf("%d\n",*arg2); } main() { int a; show(multi,10,&a); return 0; } 答:110 7、請找出下面代碼中的所以錯誤 說明:以下代碼是把一個字符串倒序,如“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; } 方法2: #i nclude <stdio.h> #i nclude <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; } 1.-1,2,7,28,,126請問28和126中間那個數是什麼?爲什麼? 第一題的答案應該是4^3-1=63 規律是n^3-1(當n爲偶數0,2,4) n^3+1(當n爲奇數1,3,5) 答案:63 2.用兩個棧實現一個隊列的功能?要求給出算法和思路! 設2個棧爲A,B, 一開始均爲空. 入隊: 將新元素push入棧A; 出隊: (1)判斷棧B是否爲空; (2)如果不爲空,則將棧A中所有元素依次pop出並push到棧B; (3)將棧B的棧頂元素pop出; 這樣實現的隊列入隊和出隊的平攤複雜度都還是O(1), 比上面的幾種方法要好。3.在c語言庫函數中將一個字符轉換成整型的函數是atool()嗎,這個函數的原型是什麼? 函數名: atol 功 能: 把字符串轉換成長整型數 用 法: long atol(const char *nptr); 程序例: #i nclude <stdlib.h> #i nclude <stdio.h> int main(void) { long l; char *str = "98765432"; l = atol(lstr); printf("string = %s integer = %ld\n", str, l); return(0); } 2.對於一個頻繁使用的短小函數,在C語言中應用什麼實現,在C++中應用什麼實現? c用宏定義,c++用inline 3.直接鏈接兩個信令點的一組鏈路稱作什麼? PPP點到點連接 4.接入網用的是什麼接口? 5.voip都用了那些協議? 6.軟件測試都有那些種類? 黑盒:針對系統功能的測試 白合:測試函數功能,各函數接口 7.確定模塊的功能和模塊的接口是在軟件設計的那個隊段完成的? 概要設計階段 8.enum string { x1, x2, x3=10, x4, x5, }x; 問x= 0x801005,0x8010f4 ; 9.unsigned char *p1; unsigned long *p2; p1=(unsigned char *)0x801000; p2=(unsigned long *)0x810000; 請問p1+5= ; p2+5= ; 三.選擇題: 1.Ethternet鏈接到Internet用到以下那個協議? A.HDLC;B.ARP;C.UDP;D.TCP;E.ID 2.屬於網絡層協議的是: A.TCP;B.IP;C.ICMP;D.X.25 3.Windows消息調度機制是: A.指令隊列;B.指令堆棧;C.消息隊列;D.消息堆棧; 4.unsigned short hash(unsigned short key) { return (key>>)%256 } 請問hash(16),hash(256)的值分別是: A.1.16;B.8.32;C.4.16;D.1.32 四.找錯題: 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++) { ......; } 死循環 3.以下是求一個數的平方的程序,請找出錯誤: #define SQUARE(a)((a)*(a)) int a=5; int b; b=SQUARE(a++); 4.typedef unsigned char BYTE
int examply_fun(BYTE gt_len; BYTE *gt_co { BYTE *gt_buf; gt_buf=(BYTE *)MALLOC(Max_GT_Length); ...... if(gt_len>Max_GT_Length) { return GT_Length_ERROR; } ....... } 五.問答題: 1.IP Phone的原理是什麼? IPV6 2.TCP/IP通信建立的過程怎樣,端口有什麼作用? 三次握手,確定是哪個應用程序使用該協議 3.1號信令和7號信令有什麼區別,我國某前廣泛使用的是那一種? 4.列舉5種以上的電話新業務? 高級題 6、已知一個單向鏈表的頭,請寫出刪除其某一個結點的算法,要求,先找到此結點,然後刪除。 slnodetype *Delete(slnodetype *Head,int key){}中if(Head->number==key) { Head=Pointer->next; free(Pointer); break; } Back = Pointer; Pointer=Pointer->next; if(Pointer->number==key) { Back->next=Pointer->next; free(Pointer); break; } void delete(Node* p) { if(Head = Node) while(p) } 有一個16位的整數,每4位爲一個數,寫函數求他們的和。 解釋: 整數1101010110110111 和 1101+0101+1011+0111 感覺應該不難,當時對題理解的不是很清楚,所以寫了一個函數,也不知道對不對。 疑問: 既然是16位的整數,1101010110110111是2進制的,那麼函數參數怎麼定義呢,請大蝦指教。 答案:用十進制做參數,計算時按二進制考慮。 /* n就是16位的數,函數返回它的四個部分之和 */ char SumOfQuaters(unsigned short n) { char c = 0; int i = 4; do { c += n & 15; n = n >> 4; } while (--i); return c; } 有1,2,....一直到n的無序數組,求排序算法,並且要求時間複雜度爲O(n),空間複雜度O(1),使用交換,而且一次只能交換兩個數.(華爲) #i nclude<iostream.h> int main() { int a[] = {10,6,9,5,2,8,4,7,1,3}; int len = sizeof(a) / sizeof(int); int temp; for(int i = 0; i < len; ) { temp = a[a[i] - 1]; a[a[i] - 1] = a[i]; a[i] = temp; if ( a[i] == i + 1) i++; } for (int j = 0; j < len; j++) cout<<a[j]<<","; return 0; } 華爲面試題:怎麼判斷鏈表中是否有環? 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); } 兩個字符串,s,t;把t字符串插入到s字符串中,s字符串有足夠的空間存放t字符串 void insert(char *s, char *t, int i) { memcpy(&s[strlen(t)+i],&s[i],strlen(s)-i); memcpy(&s[i],t,strlen(t)); s[strlen(s)+strlen(t)]='\0'; } 1。編寫一個 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; } 2。請編寫一個 C 函數,該函數在給定的內存區域搜索給定的字符,並返回該字符所在位置索引值。 int search(char *cpSource, int n, char ch) { int i; for(i=0; i<n && *(cpSource+i) != ch; ++i); return i; } 一個單向鏈表,不知道頭節點,一個指針指向其中的一個節點,問如何刪除這個指針指向的節點? 將這個指針指向的next節點值copy到本節點,將next指向next->next,並隨後刪除原next指向的節點。 #i nclude <stdio.h> void foo(int m, int n) { printf("m=%d, n=%d\n", m, n); } int main() { int b = 3; foo(b+=3, ++b); printf("b=%d\n", b); return 0; } 輸出:m=7,n=4,b=7(VC6.0) 這種方式和編譯器中得函數調用關係相關即先後入棧順序。不過不同 編譯器得處理不同。也是因爲C標準中對這種方式說明爲未定義,所以 各個編譯器廠商都有自己得理解,所以最後產生得結果完全不同。 因爲這樣,所以遇見這種函數,我們首先要考慮我們得編譯器會如何處理 這樣得函數,其次看函數得調用方式,不同得調用方式,可能產生不同得 結果。最後是看編譯器優化。 2.寫一函數,實現刪除字符串str1中含有的字符串str2. 第二個就是利用一個KMP匹配算法找到str2然後刪除(用鏈表實現的話,便捷於數組) ==============================================================================
微軟亞洲技術中心的面試題!!! 1.進程和線程的差別。 線程是指進程內的一個執行單元,也是進程內的可調度實體. 與進程的區別: (1)調度:線程作爲調度和分配的基本單位,進程作爲擁有資源的基本單位 (2)併發性:不僅進程之間可以併發執行,同一個進程的多個線程之間也可併發執行 (3)擁有資源:進程是擁有資源的一個獨立單位,線程不擁有系統資源,但可以訪問隸屬於進程的資源. (4)系統開銷:在創建或撤消進程時,由於系統都要爲之分配和回收資源,導致系統的開銷明顯大於創建或撤消線程時的開銷。 2.測試方法 人工測試:個人複查、抽查和會審 機器測試:黑盒測試和白盒測試 2.Heap與stack的差別。 Heap是堆,stack是棧。 Stack的空間由操作系統自動分配/釋放,Heap上的空間手動分配/釋放。 Stack空間有限,Heap是很大的自由存儲區 C中的malloc函數分配的內存空間即在堆上,C++中對應的是new操作符。 程序在編譯期對變量和函數分配內存都在棧上進行,且程序運行過程中函數調用時參數的傳遞也在棧上進行 3.Windows下的內存是如何管理的? 4.介紹.Net和.Net的安全性。 5.客戶端如何訪問.Net組件實現Web Service? 6.C/C++編譯器中虛表是如何完成的? 7.談談COM的線程模型。然後討論進程內/外組件的差別。 8.談談IA32下的分頁機制 小頁(4K)兩級分頁模式,大頁(4M)一級 9.給兩個變量,如何找出一個帶環單鏈表中是什麼地方出現環的? 一個遞增一,一個遞增二,他們指向同一個接點時就是環出現的地方 10.在IA32中一共有多少種辦法從用戶態跳到內核態? 通過調用門,從ring3到ring0,中斷從ring3到ring0,進入vm86等等 11.如果只想讓程序有一個實例運行,不能運行兩個。像winamp一樣,只能開一個窗口,怎樣實現? 用內存映射或全局原子(互斥變量)、查找窗口句柄.. FindWindow,互斥,寫標誌到文件或註冊表,共享內存。. 12.如何截取鍵盤的響應,讓所有的‘a’變成‘b’? 鍵盤鉤子SetWindowsHookEx 13.Apartment在COM中有什麼用?爲什麼要引入? 14.存儲過程是什麼?有什麼用?有什麼優點? 我的理解就是一堆sql的集合,可以建立非常複雜的查詢,編譯運行,所以運行一次後,以後再運行速度比單獨執行SQL快很多 15.Template有什麼特點?什麼時候用? 16.談談Windows DNA結構的特點和優點。 網絡編程中設計併發服務器,使用多進程 與 多線程 ,請問有什麼區別? 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) 3 一語句實現x是否爲2的若干次冪的判斷 int i = 512; cout << boolalpha << ((i & (i - 1)) ? false : true) << endl; 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){ unsigned int _t = 0; unsigned int _a = 1; for(int i = 0; i < n; ++i){ _t |= _a; _a = _a << 1; } _t = _t << p; x ^= _t; return x; } ===============================================================================
慧通: 什麼是預編譯 何時需要預編譯: 1、總是使用不經常改動的大型代碼體。 2、程序由多個模塊組成,所有模塊都使用一組標準的包含文件和相同的編譯選項。在這種情況下,可以將所有包含文件預編譯爲一個預編譯頭。 char * const p; char const * p const char *p 上述三個有什麼區別? char * const p; //常量指針,p的值不可以修改 char const * p;//指向常量的指針,指向的常量值不可以改 const char *p; //和char const *p 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是指針,它們指向相同的常量區域。 12. 以下代碼中的兩個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。 一個32位的機器,該機器的指針是多少位 指針是多少位只要看地址總線的位數就行了。80386以後的機子都是32的數據總線。所以指針的位數就是4個字節了。 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]. 1.請問以下代碼有什麼問題: int main() { char a; char *str=&a; strcpy(str,"hello"); printf(str); return 0; } 沒有爲str分配內存空間,將會發生異常 問題出在將一個字符串複製進一個字符變量指針所指地址。雖然可以正確輸出結果,但因爲越界進行內在讀寫而導致程序崩潰。 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的作用是什麼? 定義靜態變量 4、關鍵字const有什麼含意? 表示常量不可以修改的變量。 5、關鍵字volatile有什麼含意?並舉出三個不同的例子? 提示編譯器對象的值可能在編譯器未監測到的情況下改變。 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.#i nclude <stdio.h> #i nclude <stdlib.h> void getmemory(char *p) { p=(char *) malloc(100); strcpy(p,"hello world"); } int main( ) { char *str=NULL; getmemory(str); printf("%s/n",str); free(str); return 0; } 程序崩潰,getmemory中的malloc 不能返回動態內存, free()對str操作很危險 5.char szstr[10]; strcpy(szstr,"0123456789"); 產生什麼結果?爲什麼? 長度不一樣,會造成非法的OS 6.列舉幾種進程的同步機制,並比較其優缺點。 原子操作 信號量機制 自旋鎖 管程,會合,分佈式系統 7.進程之間通信的途徑 共享存儲系統 消息傳遞系統 管道:以文件系統爲基礎 11.進程死鎖的原因 資源競爭及進程推進順序非法 12.死鎖的4個必要條件 互斥、請求保持、不可剝奪、環路 13.死鎖的處理 鴕鳥策略、預防策略、避免策略、檢測與解除死鎖 15. 操作系統中進程調度策略有哪幾種? FCFS(先來先服務),優先級,時間片輪轉,多級反饋 8.類的靜態成員和非靜態成員有何區別? 類的靜態成員每個類只有一個,非靜態成員每個對象一個 9.純虛函數如何定義?使用時應注意什麼? virtual void f()=0; 是接口,子類必須要實現 10.數組和鏈表的區別 數組:數據順序存儲,固定大小 連表:數據可以隨機存儲,大小可動態改變 12.ISO的七層模型是什麼?tcp/udp是屬於哪一層?tcp/udp有何優缺點? 應用層 表示層 會話層 運輸層 網絡層 物理鏈路層 物理層 tcp /udp屬於運輸層 TCP 服務提供了數據流傳輸、可靠性、有效流控制、全雙工操作和多路複用技術等。 與 TCP 不同, UDP 並不提供對 IP 協議的可靠機制、流控制以及錯誤恢復功能等。由於 UDP 比較簡單, UDP 頭包含很少的字節,比 TCP 負載消耗少。 tcp: 提供穩定的傳輸服務,有流量控制,缺點是包頭大,冗餘性不好 udp: 不提供穩定的服務,包頭小,開銷小 1:(void *)ptr 和 (*(void**))ptr的結果是否相同?其中ptr爲同一個指針 .(void *)ptr 和 (*(void**))ptr值是相同的 2:int main() { int x=3; printf("%d",x); return 1;
} 問函數既然不會被其它函數調用,爲什麼要返回1? mian中,c標準認爲0表示成功,非0表示錯誤。具體的值是某中具體出錯信息 1,要對絕對地址0x100000賦值,我們可以用 (unsigned int*)0x100000 = 1234; 那麼要是想讓程序跳轉到絕對地址是0x100000去執行,應該怎麼做? *((void (*)( ))0x100000 ) ( ); 首先要將0x100000強制轉換成函數指針,即: (void (*)())0x100000 然後再調用它: *((void (*)())0x100000)(); 用typedef可以看得更直觀些: typedef void(*)() voidFuncPtr; *((voidFuncPtr)0x100000)(); 2,已知一個數組table,用一個宏定義,求出數據的元素個數 #define NTBL #define NTBL (sizeof(table)/sizeof(table[0])) 面試題: 線程與進程的區別和聯繫? 線程是否具有相同的堆棧? dll是否有獨立的堆棧? 進程是死的,只是一些資源的集合,真正的程序執行都是線程來完成的,程序啓動的時候操作系統就幫你創建了一個主線程。 每個線程有自己的堆棧。 DLL中有沒有獨立的堆棧,這個問題不好回答,或者說這個問題本身是否有問題。因爲DLL中的代碼是被某些線程所執行,只有線程擁有堆棧,如果DLL中的代碼是EXE中的線程所調用,那麼這個時候是不是說這個DLL沒有自己獨立的堆棧?如果DLL中的代碼是由DLL自己創建的線程所執行,那麼是不是說DLL有獨立的堆棧? 以上講的是堆棧,如果對於堆來說,每個DLL有自己的堆,所以如果是從DLL中動態分配的內存,最好是從DLL中刪除,如果你從DLL中分配內存,然後在EXE中,或者另外一個DLL中刪除,很有可能導致程序崩潰 unsigned short A = 10; printf("~A = %u\n", ~A); char c=128; printf("c=%d\n",c); 輸出多少?並分析過程 第一題,~A =0xfffffff5,int值 爲-11,但輸出的是uint。所以輸出4294967285 第二題,c=0x10,輸出的是int,最高位爲1,是負數,所以它的值就是0x00的補碼就是128,所以輸出-128。 這兩道題都是在考察二進制向int或uint轉換時的最高位處理。 分析下面的程序: void GetMemory(char **p,int num) { *p=(char *)malloc(num);
} int main() { char *str=NULL;
GetMemory(&str,100);
strcpy(str,"hello");
free(str);
if(str!=NULL) { strcpy(str,"world"); }
printf("\n str is %s",str); getchar(); } 問輸出結果是什麼?希望大家能說說原因,先謝謝了 輸出str is world。 free 只是釋放的str指向的內存空間,它本身的值還是存在的. 所以free之後,有一個好的習慣就是將str=NULL. 此時str指向空間的內存已被回收,如果輸出語句之前還存在分配空間的操作的話,這段存儲空間是可能被重新分配給其他變量的, 儘管這段程序確實是存在大大的問題(上面各位已經說得很清楚了),但是通常會打印出world來。 這是因爲,進程中的內存管理一般不是由操作系統完成的,而是由庫函數自己完成的。 當你malloc一塊內存的時候,管理庫向操作系統申請一塊空間(可能會比你申請的大一些),然後在這塊空間中記錄一些管理信息(一般是在你申請的內存前面一點),並將可用內存的地址返回。但是釋放內存的時候,管理庫通常都不會將內存還給操作系統,因此你是可以繼續訪問這塊地址的,只不過。。。。。。。。樓上都說過了,最好別這麼幹。 char a[10],strlen(a)爲什麼等於15?運行的結果 #i nclude "stdio.h" #i nclude "string.h" void main() { char aa[10]; printf("%d",strlen(aa)); } sizeof()和初不初始化,沒有關係; strlen()和初始化有關。 char (*str)[20];/*str是一個數組指針,即指向數組的指針.*/ char *str[20];/*str是一個指針數組,其元素爲指針型數據.*/ long a=0x801010; a+5=? 0x801010用二進制表示爲:“1000 0000 0001 0000 0001 0000”,十進制的值爲8392720,再加上5就是8392725羅 1)給定結構struct A { char t:4; char k:4; unsigned short i:8; unsigned long m; };問sizeof(A) = ? 給定結構struct A { char t:4; 4位 char k:4; 4位 unsigned short i:8; 8位 unsigned long m; // 偏移2字節保證4字節對齊 }; // 共8字節 2)下面的函數實現在一個數上加一個數,有什麼錯誤?請改正。 int add_n ( int n ) { static int i = 100; i += n; return i; } 當你第二次調用時得不到正確的結果,難道你寫個函數就是爲了調用一次?問題就出在 static上? // 幫忙分析一下 #i nclude<iostream.h> #i nclude <string.h> #i nclude <malloc.h> #i nclude <stdio.h> #i nclude <stdlib.h> #i nclude <memory.h> typedef struct AA { int b1:5; int b2:2; }AA; void main() { AA aa; char cc[100]; strcpy(cc,"0123456789abcdefghijklmnopqrstuvwxyz"); memcpy(&aa,cc,sizeof(AA)); cout << aa.b1 <<endl; cout << aa.b2 <<endl; } 答案是 -16和1 首先sizeof(AA)的大小爲4,b1和b2分別佔5bit和2bit. 經過strcpy和memcpy後,aa的4個字節所存放的值是: 0,1,2,3的ASC碼,即00110000,00110001,00110010,00110011 所以,最後一步:顯示的是這4個字節的前5位,和之後的2位 分別爲:10000,和01 因爲int是有正負之分 所以:答案是-16和1 求函數返回值,輸入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的個數是很效率很高的。 不必去一個一個地移位。循環次數最少。 int a,b,c 請寫函數實現C=a+b ,不可以改變數據類型,如將c改爲long int,關鍵是如何處理溢出問題 bool add (int a, int b,int *c) { *c=a+b; return (a>0 && b>0 &&(*c<a || *c<b) || (a<0 && b<0 &&(*c>a || *c>b))); } 分析: struct bit { int a:3; int b:2; int c:3; }; int main() { bit s; char *c=(char*)&s; cout<<sizeof(bit)<<endl; *c=0x99; cout << s.a <<endl <<s.b<<endl<<s.c<<endl; int a=-1; printf("%x",a); return 0; } 輸出爲什麼是 4 1 -1 -4 ffffffff 因爲0x99在內存中表示爲 100 11 001 , a = 001, b = 11, c = 100 當c爲有符合數時, c = 100, 最高1爲表示c爲負數,負數在計算機用補碼錶示,所以c = -4;同理 b = -1; 當c爲有符合數時, c = 100,即 c = 4,同理 b = 3 |
中興軟件測試題
1. Const 和 #define 區別?
2. #include <filename.h> 和 #include “filename.h”有什麼區別?
3. 編寫一個宏,輸入2個參數,輸出結果爲兩個參數的乘積
4. Char str[]=“Hello” 計算sizeof(str)的數值
5. 寫出與float x與“零值”比較的 if 語句
6. 寫出char *p 與“零值”比較的if語句
?7. 寫一個函數,判定運算環境(16位以上字長)是little-endian還是big-endian
8. 結構體和聯合體的主要區別?
9. 操作系統的主要組成部分?
(1)對CPU的使用進行管理的進程調度程序
(2)對內存分配進行管理的內存管理程序
(3)對輸入輸出設備進行管理的設備驅動程序
(4)對外存中信息進行管理的文件系統
10.操作系統中進程調度策略有哪幾種?
在unix系統中,由進程調度程序對進程運行進行合理安排,有分時和實時兩種調度策略。
1、進程調度程序完成挑選進程,分配CPU的工作。
2、缺省情況下,UNIX操作系統使用分時調度策略,在運行中動態地調整進程的優先級,
以提供最佳響應時間。
3、UNIX系統同時提供一種實時調度策略,允許用戶爲每個進程指定一個固定的優先級,優
先級最高的實時用戶將一直佔據CPU,只要他不主動放棄CPU,即使是系統核心進程也不
能投入運行。
4、UnixWare 7系統不是以實際的進程爲基礎進行調度的,而是以輕負荷進程(LWPs)
爲基礎實現進程調度的。
11.進程間主要的通訊方式?
? 信號(signal)通信機制;
? 共享存儲區(shared memory)通信機制;
? 共享文件(shared file)通信機制;
? 消息傳遞(message passing)通信機制。
採用消息傳遞機制後,一個正在執行的進程可在任何時刻向另一個正在執行的進程發送消息;一個正在執行的進程也可在任何時刻向正在執行的另一個進程請求消息。
12.寫出進程的主要狀態?
運行態 是指當前進程已分配到CPU,它的程序正在處理機上執行時的狀態。處於這
種狀態的進程個數不能大於CPU的數目。
就緒態 是指進程已具備運行條件,但因爲其他進程正在佔用CPU,所以暫時不能運行
而等待分配CPU的狀態。一旦把CPU分配給它,它立即就可運行。
封鎖態 是指進程因爲等待某種事件的發生而暫時不能運行的狀態。即處於封鎖態的
進程尚不具備運行條件,即使CPU空閒,它也無法使用。這種狀態有時也稱
爲不可運行狀態或掛起狀態。
8.1.2 進程和程序的區別
1、 程序是靜態概念,本身可以作爲一種軟件資源長期保存;而進程是程序的執行過程,它是動態概念,有一定的生命期,是動態地產生和消亡的。
2、 進程是一個能獨立運行的單位,能與其他進程併發執行,進程是作爲資源申請調度單位存在的,而通常的程序段是不能作爲一個獨立運行的單位的。
3、 程序和進程無一一對應關係。一個程序可以由多個進程共用;另一方面,一個進程在活動中有可順序地執行若干個程序。進程不能脫離具體程序而虛設,程序規定了相應進程所要完成的動作。
13.Internet採用哪種網絡協議?該協議的主要層次結構?
14.以太網物理地址和IP地址轉換採用什麼協議?
15.IP地址的編碼分爲哪兩部分?
16.寫出以太網數據幀格式
//17.8031和8051的主要區別?
18.請講述一下你做過的最滿意的一個項目或課題,或者最滿意的課程,並談一
下你做完(學完)後的感受。
19.C++中的空類,默認產生哪些類成員函數?
分析以下程序的執行結果
#include<iostream.h>
class base
{
public:
base(){cout<< “constructing base class”<<endl;}
~base(){cout<<”destructing base class”<<endl;}
};
class subs:public base
{
public:
subs(){cout<<”constructing sub class”<<endl;}
~subs(){cout<<”destructing sub class”<<endl;}
};
void main()
{
subs s;
}
20.指出下面程序的錯誤
#define SIZE 5
struct String
{
char *pData;
};
void main()
{
char *pData;
};
void main()
{
char acValue1[SIZE]={‘H’,’E’,’L’,’L’,’O’};
char acValue2[SIZE]={‘W’,’O’,’L’,’D’};
struct String a,b,c;
a.pData=malloc(SIZE*sizeof(char));
memcpy(a.pData,acValuel,SIZE);
b.pData=malloc(SIZE*sizeof(char));
mempcpy(b.pData,acValue2,SIZE);
b=a;
free(a.pData);
c=b;
}
21.指出下面兩段程序的區別
【1】
main()
{
int loop=1;
int arr[10];
int i=0;
while(loop<5)
{
for(;i<=10;i++)
{
arr[i]=1;
}
loop++;
}
}
【2】
main()
{
int arr[10];
int loop=1;
int i=0;
while(loop<5)
{
for(i=0;i<=10;i++)
{
arr[i]=1;
}
loop++;
}
}
22.指出下面程序的錯誤(函數GetValue返回 unsigned char類型的值)
#define MAXNUM 400;
unsigned char uclndex,uclnputVar,aucArray[MAXNUM];
for(ucIndx =0;ucIndex<=MAXNUM;ucIndex++)
{
aucArray[ucIndex]=aucArray[ucIndex]+1;
}
ucInputVar=GetValue();
for(ucIndex=0;ucIndex>(ucInputVar-1);ucIndex++)
{
aucArray[ucIndex]=aucArray[ucIndex]*2+1;
}
點擊科技筆試題目
1、 什麼是com和ActiveX,簡述DCOM。
答:COM(Component Object Mode)即組件對象模型,是組件之間相互接口的規範。其作用是使各種軟件構件和應用軟件能夠用一種統一的標準方式進行交互。COM不是一種面向對象的語言,而是一種與源代碼無關的二進制標準。
ActiveX是Microsoft提出的一套基於COM的構件技術標準,實際上是對象嵌入與煉接(OLE)的新版本。基於分佈式環境下的COM被稱作DCOM(Distribute COM,分佈式組件對象模型),它實現了COM對象與遠程計算機上的另一個對象之間直接進行交互。DCOM規範定義了分散對象創建和對象間通信的機制,DCOM是ActiveX的基礎,因爲ActiveX主要是針對Internet應用開發(相比OLE)的技術,當然也可以用於普通的桌面應用程序。
2、 區別C#和VC.NET
答:C#是微軟推出的一種新的語言,是其提出的.NET架構支持的標準語言。
VC.NET是針對C++的集成開發環境(IDE),而非一門語言。其相對VC++,增加了不多的一些特性。
3、 列出3個常用網絡協議使用的端口。
答:HTTP協議用80端口,FTP協議用21端口,POP3協議用110端口
4、 什麼是ODBC?
答:ODBC(Open Database Connectivity,開放數據庫互連)是微軟公司開放服務結構(WOSA,Windows Open Services Architecture)中有關數據庫的一個組成部分,它建立了一組規範,並提供了一組對數據庫訪問的標準API(應用程序編程接口)。ODBC的最大優點是能以統一的方式(用它提供的API訪問數據庫)處理所有的數據庫。
5、 結構化編程和goto語句的區別和關係?
答:結構化編程設計思想採用了模塊分解與功能抽象和自頂向下、分而治之的方法,從而有效地將一個較複雜的程序系統設計任務分解成許多易於控制和處理的子程序,便於開發和維護。goto語句可以實現無條件跳轉,改變程序流向,破壞結構化編程設計風格。但goto語句在結構化編程中並非不可使用,只是要受到限制的使用。
6、 MFC中SendMessage和PostMessage的區別?
答:PostMessage 和SendMessage的區別主要在於是否等待應用程序做出消息處理。PostMessage只是把消息放入隊列,然後繼續執行;而SendMessage必須等待應用程序處理消息後才返回繼續執行。這兩個函數的返回值也不同,PostMessage的返回值表示PostMessage函數執行是否正確,而SendMessage的返回值表示其他程序處理消息後的返回值。
微軟研究院筆試題目
注意,以下程序中#include後面因爲<<符號屬於html的註釋符,內容都不能顯現,你如果要調試這些程序,應該明確#include後面的頭文件是stdio.h和String.h,請自行添加。
1.改錯
#include
#include
class CBuffer
{
char * m_pBuffer;
int m_size;
public:
CBuffer()
{
m_pBuffer=NULL;
}
~CBuffer()
{
Free();
}
void Allocte(int size) (3) {
m_size=size;
m_pBuffer= new char[size];
}
private:
void Free()
{
if(m_pBuffer!=NULL)
{
delete m_pBuffer;
m_pBuffer=NULL;
}
}
public:
void SaveString(const char* pText) const
{
strcpy(m_pBuffer, pText);
}
char* GetBuffer() const
{
return m_pBuffer;
}
};
void main (int argc, char* argv[])
{
CBuffer buffer1;
buffer1.SaveString("Microsoft");
printf(buffer1.GetBuffer());
}
答:改正後
主要改正SaveString函數
將
void SaveString(const char* pText) const
{
strcpy(m_pBuffer, pText);
}
改爲
void SaveString(const char* pText) (1)
{
Allocte(strlen(pText)+1); (2)
strcpy(m_pBuffer, pText);
}
原因:
(1) const成員函數表示不會修改數據成員,而SaveString做不到,去掉const聲明
(2) m_pBuffer指向NULL,必須用Allocte分配空間才能賦值。
(3) 另外需要將Allocte成員函數聲明爲私有成員函數更符合實際
2.下來程序想打印“Welcome MSR Asia”,改正錯誤
#include
#include
char * GetName (void)
{
//To return “MSR Asia” String
char name[]="MSR Asia";
return name;
}
void main(int argc, char* argv[])
{
char name[32];
//Fill in zeros into name
for(int i=0;i<=32;i++)
{
name[i]='\0';
}
//copy “Welcome” to name
name="Welcome";
//Append a blank char
name[8]=" ";
//Append string to name
strcat(name,GetName());
//print out
printf(name);
}
答:改正後爲
#include
#include
char * GetName (void)
{
//To return “MSR Asia” String
//char name[]="MSR Asia"; (1)
char *name=(char *)malloc(strlen("MSR Asia")+1);
strcpy(name,"MSR Asia");
return name;
}
void main(int argc, char* argv[])
{
char name[32];
//Fill in zeros into name
for(int i=0;i<=32;i++)
{
name[i]='\0';
}
//copy “Welcome” to name
//name="Welcome"; (2)
strcat(name,"Welcome ");
//Append a blank char
// name[8]=' '; (3)
//Append string to name
char *p=GetName(); (4)
strcat(name,p);
free (p);
//print out
printf(name);
}
原因:(1)在函數內部定義的變量在函數結束時就清空了,必須動態分配內存
(2)字符串賦值語句錯誤,應該用strcat
(3)該語句無效,可去掉
(4)定義一個指針指向動態分配的內存,用完後需用free語句釋放
3.寫出下面程序的輸出結果
#include
class A
{
public:
void FuncA()
{
printf("FuncA called\n");
}
virtual void FuncB()
{
printf("FuncB called\n");
}
};
class B: public A
{
public:
void FuncA()
{
A::FuncA();
printf("FuncAB called\n");
}
virtual void FuncB()
{
printf("FuncBB called\n");
}
};
void main(void)
{
B b;
A *pa;
pa=&b;
A *pa2=new A;
b.FuncA(); (1)
b.FuncB(); (2)
pa->FuncA(); (3)
pa->FuncB(); (4)
pa2->FuncA(); (5)
pa2->FuncB();
delete pa2;
}
答:
1.b.FuncA(); 輸出
FuncA called
FuncAB called
2.b.FuncB();輸出
FuncBB called
上兩者好理解,直接調用類B的相應成員函數
3.pa->FuncA();輸出
FuncA called 調用類A的FuncA()
4.pa->FuncB();輸出
FuncBB called調用類B的FuncB(),原因是C++的動態決議機制,當基類函數聲明爲virtual時,指向派生類對象的基類指針來調用該函數會選擇派生類的實現,除非派生類沒有才調用基類的虛函數。還有一點注意的是:指向基類類型的指針可以指向基類對象也可以指向派生類對象,如pa=&b;
5. pa2->FuncA();
pa2->FuncB();輸出
FuncA called
FuncB called
這也好理解,直接調用類A的相應成員函數
4.In the main() function, after ModifyString(text) is called, what’s the value of ‘text’?
#include
#include
int FindSubString(char* pch)
{
int count=0;
char* p1=pch;
while(*p1!='\0')
{
if(*p1==p1[1]-1)
{
p1++;
count++;
}
else
{
break;
}
}
int count2=count;
while(*p1!='\0')
{
if(*p1==p1[1]+1)
{
p1++;
count2--;
}
else
{
break;
}
}
if(count2==0)
return count;
return 0;
}
void ModifyString(char* pText)
{
char* p1=pText;
char* p2=p1;
while(*p1!='\0')
{
int count=FindSubString(p1);
if(count>0)
{
*p2++=*p1;
sprintf(p2, "%I", count);
while(*p2!= '\0')
{
p2++;
}
p1+=count+count+1;
}
else
{
*p2++=*p1++;
}
}
}
void main(void)
{
char text[32]="XYBCDCBABABA";
ModifyString(text);
printf(text);
}
答:我不知道這個結構混亂的程序到底想考察什麼,只能將最後運行結果寫出來是XYBCDCBAIBAAP
廣東北電筆試題
2. Programming (Mandatory)
Linked list
a. Implement a linked list for integers,which supports the insertafter (insert a node after a specified node) and removeafter (remove the node after a specified node) methods;
b. Implement a method to sort the linked list to descending order.
答:題目的意思是實現一個整型鏈表,支持插入,刪除操作(有特殊要求,都是在指定節點後進行操作),並寫一個對鏈表數據進行降序排序的方法。
那我們不妨以一個線性鏈表進行編程。
// 單鏈表結構體爲
typedef struct LNode
{
int da
struct LNode *next;
}LNode, *pLinkList;
// 單鏈表類
class LinkList
{
private:
pLinkList m_pList;
int m_listLength;
public:
LinkList();
~LinkList();
bool InsertAfter(int afternode, int da
bool RemoveAfter(int removenode);//刪除
void sort();//排序
};
實現方法
//insert a node after a specified node
bool LinkList::InsertAfter(int afternode, int da
{
LNode *pTemp = m_pList;
int curPos = -1;
if (afternode > m_listLength ) // 插入點超過總長度
{
return false;
}
while (pTemp != NULL) // 找到指定的節點
{
curPos++;
if (curPos == afternode)
break;
pTemp = pTemp->next;
}
if (curPos != afternode) // 節點未尋到,錯誤退出
{
return false;
}
LNode *newNode = new LNode; // 將新節點插入指定節點後
newNode->da
newNode->next = pTemp->next;
pTemp->next = newNode;
m_listLength++;
return true;
}
//remove the node after a specified node
bool LinkList::RemoveAfter(int removenode)
{
LNode *pTemp = m_pList;
int curPos=-1;
if (removenode > m_listLength) // 刪除點超過總長度
{
return false;
}
// 找到指定的節點後一個節點,因爲刪除的是後一個節點
while (pTemp != NULL)
{
curPos++;
if (curPos == removenode+1)
break;
pTemp = pTemp->next;
}
if (curPos != removenode) // 節點未尋到,錯誤退出
{
return false;
}
LNode *pDel = NULL; // 刪除節點
pDel = pTemp->next;
pTemp->next = pDel->next;
delete pDel;
m_listLength--;
return true;
}
//sort the linked list to descending order.
void LinkList::sort()
{
if (m_listLength<=1)
{
return;
}
LNode *pTemp = m_pList;
int temp;
// 選擇法排序
for(int i=0;i<M_LISTLENGTH-1;I++)
for(int j=i+1;j<M_LISTLENGTH;J++)
if (pTemp[i].da
{
temp=pTemp[i].da
pTemp[i].da
pTemp[j].da
}
}
前兩個函數實現了要求a,後一個函數sort()實現了要求b
3. Debugging (Mandatory)
a. For each of the following recursive methods, enter Y in the answer box if the method terminaters (assume i=5), Otherwise enter N.
(題目意思:判斷下面的遞歸函數是否可以結束)
static int f(int i){
return f(i-1)*f(i-1);
}
Ansewr: N,明顯沒有返回條件語句,無限遞歸了
static int f(int i){
if(i==0){return 1;}
else {return f(i-1)*f(i-1);}
}
Ansewr:Y,當i=0時可結束遞歸
static int f(int i){
if(i==0){return 1;}
else {return f(i-1)*f(i-2);}
}
Ansewr:N,因爲i=1時,f(i-2)=f(-1),進入一個無限遞歸中
2.編程
將整數轉換成字符串:void itoa(int,char);
例如itoa(-123,s[])則s=“-123”;
答:
char* itoa(int value, char* string)
{
char tmp[33];
char* tp = tmp;
int i;
unsigned v;
char* sp;
// 將值轉爲正值
if (value < 0)
v = -value;
else
v = (unsigned)value;
// 將數轉換爲字符放在數組tmp中
while (v)
{
i = v % 10;
v = v / 10;
*tp++ = i+'0';
}
// 將tmp裏的字符填入string指針裏,並加上負號(如果有)
sp = string;
if (value < 0)
*sp++ = '-';
while (tp > tmp)
*sp++ = *--tp;
*sp = 0;
return string;
}
Sony筆試題
1. 完成下列程序
*
*.*.
*..*..*..
*...*...*...*...
*....*....*....*....*....
*.....*.....*.....*.....*.....*.....
*......*......*......*......*......*......*......
*.......*.......*.......*.......*.......*.......*.......*.......
#include
#define N 8
int main()
{
int i;
int j;
int k;
---------------------------------------------------------
│ │
│ │
│ │
---------------------------------------------------------
return 0;
}
答:#define N 8
int main()
{
int i;
int j;
int k;
for(i=0;i<N;I++)
{
for(j=0;j<I+1;J++)
{
printf("*");
for(k=0;k<I;K++)
printf(".");
}
printf("\n");
}
return 0;
}
2.完成程序,實現對數組的降序排序
#include
void sort( );
int main()
{
int array[]={45,56,76,234,1,34,23,2,3}; //數字任意給出
sort( );
return 0;
}
void sort( )
{
---------------------------------------------------------
│ │
│ │
│ │
---------------------------------------------------------
}
答:使用選擇排序法,我爲sort函數多加了兩個形參,至少第一個是必須的,否則無法傳入待排序數組。不知道這樣做是否符合題意。
void sort(int *array,int num)
{
int temp;
for(int i=0;i<NUM-1;I++)
for(int j=i+1;j<NUM;J++)
if (array[i]<ARRAY[J])
{
temp=array[i];
array[i]=array[j];
array[j]=temp;
}
}
2. 費波那其數列,1,1,2,3,5……編寫程序求第十項。可以用遞歸,也可以用其他方法,但要說明你選擇的理由。
#include
int Pheponatch(int);
int main()
{
printf("The 10th is %d",Pheponatch(10));
return 0;
}
int Pheponatch(int N)
{
--------------------------------
│ │
│ │
--------------------------------
}
答:
使用遞歸,理由是遞歸編程簡單,代碼容易理解,但缺點是效率不高,而且有深度限制,如果深度太深,則堆棧會溢出。
int Pheponatch(int N)
{
if (N==3)
return 2;
else if (N==2||N==1)
return 1;
else
return Pheponatch(N-1)+Pheponatch(N-2);
}
4.下列程序運行時會崩潰,請找出錯誤並改正,並且說明原因。
#include “stdio.h”
#include “malloc.h”
typedef struct TNode
{
TNode* left;
TNode* right;
int value;
}TNode;
TNode* root=NULL;
void append(int N);
int main()
{
append(63);
append(45);
append(32);
append(77);
append(96);
append(21);
append(17); // Again, 數字任意給出
return 0;
}
void append(int N)
{
TNode* NewNode=(TNode *)malloc(sizeof(TNode));
NewNode->value=N;
NewNode->left=NULL; //新增
NewNode->right=NULL; //新增
if(root==NULL)
{
root=NewNode;
return;
}
else
{
TNode* temp;
temp=root;
while((N>=temp->value && temp->left!=NULL)||(Nvalue && temp-
>right!=NULL))
{
while(N>=temp->value && temp->left!=NULL)
temp=temp->left;
while(Nvalue && temp->right!=NULL)
temp=temp->right;
}
if(N>=temp->value)
temp->left=NewNode;
else
temp->right=NewNode;
return;
}
}
答:因爲新節點的左右指針沒有賦NULL值,至使下面的while循環不能正確結束而導致內存越界,最後崩潰(注意結束條件是temp->left!=NULL或temp->right!=NULL)。改正就是增加兩條賦值語句,如上文紅色部分字體就是新增的兩條語句。
最新摩托羅拉筆試題
?1.打印如下圖案,共19行,只能有一個for循環(題目已經提供)
*
***
*****
*******
*********
***********
*************
***************
*****************
*******************
*****************
***************
*************
***********
*********
*******
*****
***
*
for(i=0;i<19;i++)
{
}
答:
#include "stdio.h"
void main()
{
for(int i=0;i<19;i++)
{
int j=0;
while (j<19)
{
if (i<=9)
{
if (j<=9)
{
if (i+j>=9)
printf("*");
else
printf(" ");
}
else
if (j-i<=9)
printf("*");
else
printf(" ");
}
else
{
if (j<=9)
{
if (i-j<=9)
printf("*");
else
printf(" ");
}
else
if (j+i<=27)
printf("*");
else
printf(" ");
}
j++;
}
printf("\n");
}
}
2.
void fun(int x)
{
if(x/2>0)fun(x/2);
printf("%d",x);
}
求fun(10)的輸出結果
答:依次輸出fun(1),fun(2),fun(5),fun(10),得到結果12510
3.
#define f1(n) (n)*(n)
int i=5;
int k=0;
k=f1(i++);
printf("%d %d",i,k);
輸出結果:
答:7 25
4.下面那個for循環是無限循環
for(int i=010;i==10;i+=0)
for(int i=10;(i++^--i)==0;i+=0)
還有幾個忘了
答:
第一不是,因爲010表示8進制,i=8;
第二是,因爲i++^--i表示數字10與10進行異或運算,確實爲0
?5.Email relay 和Email access分別用了什麼協議?(其他還有很多,略)
答:SMTP,POP3
6.stack da
A.rom, B .flash C .eeprom D.ram E .none of the above
答:D.ram。這題稍微涉及到一點硬件知識,ROM的全稱是Read On
?7.
int i;
int x=0x12345678;
unsigned char *p=(unsigned char *)&x;
for(i=0;i<SIZEOF(X);I++)
printf("%2x",*(p+i));
在80x86pc機器上運行結果?
答:x在PC機上的內存存放順序爲78 56 34 12,高字節在前,低字節在後,因此輸出78563412
Sun Sparc Unix上運行結果?
?8.
char a[2][2][3]={{{1,6,3},{5,4,15}},{{3,5,33},{23,12,7}} };
for(int i=0;i<12;i++)
printf("%d ",_______);
在空格處填上合適的語句,順序打印出a中的數字
答:*(*(*(a+i/6)+(i/3%2))+i%3)
這題主要是要將輸出的序號依次寫出一些,如000,001,002,010,011,012,100,101...然後找序號變化規律
9.
void fun(char *a,char *b)
{
a=b;
(*a)++;
}
void main()
{
char s1='A',s2='a';
char *p1=&s1;
char *p2=&s2;
fun(p1,p2);
printf("%c%c",s1,s2);
}
輸出結果:?
答:輸出結果爲:Ab,因爲在fun函數裏,指針a指向s2存儲區(a=b),接着讓s2存儲區的值加1得'b' ((*a)++),所以s2等於'b',s1不變。
10.寫一個strstr()函數
最新的中磊筆試題
中磊研發中心是中怡數寬科技(蘇州)有限公司投資的研發機構,該公司主要着重於各種網絡服務器的研究開發。
1、 請用標準C語言實現一個雙向循環鏈表的查找與刪除。
typedef struct doublecyclelink{
int key;
struct doublecyclelink *prev;
struct doublecyclelink *next;
}DoubleCycleLinkT;
DoubleCycleLinkT *findKey(DoubleCycleLinkT *link,int key);
遍歷整個雙向循環鏈表,將第一個與key值相同的結點移出鏈表,並返回。
若沒有找到則返回NULL。
答:
函數爲
DoubleCycleLinkT *findKey(DoubleCycleLinkT *link,int key)
{
DoubleCycleLinkT *p;
p=link->next;
while (p->next!=link) // 鏈表結尾
{
if (p->key==key) // 查找到key值相同,刪除該節點,並返回
{
p->prev->next=p->next;
p->next->prev=p->prev;
free(p);
return link;
}
else
p=p->next; // 否則查找下一節點
}
if (p->next == link) return NULL; //沒找到,返回NULL
}
2、請用程序打印下列圖型
*
* *
* * *
* * * *
* * * * *
void printTriangle(const unsigned char line);
輸入行數,打印三角形。
答:
函數爲
void printTriangle(const unsigned char line)
{
for(int i=1;i<=line;i++)
{
for(int j=0;j<(line*2-1);j++) // 5行每行需打印9個字符
{
if (i%2==1) // 奇數行
{
if (j%2==(line-1)%2 && j>=(line-1-i/2*2) && j<=(line-1+i/2*2))
printf("*");// 列從0計數
else
printf(" ");
}
else
if (j%2==(line)%2 && j>=(line-2-(i/2-1)*2) && j<=(line+(i/2-1)*2))
printf("*");
else
printf(" ");
}
printf("\n");
}
}
3、請用標準C語言實現下列標準庫函數,設計中不得使用其他庫函數。
char *strstr(char *str1,char *str2);
在字符串str1中,尋找字串str2,若找到返回找到的位置,否則返回NULL。
答:
函數爲
char * strstr ( const char * str1, const char * str2 )
{
char *cp = (char *) str1;
char *s1, *s2;
if ( !*str2 )
return((char *)str1);
while (*cp)
{
s1 = cp;
s2 = (char *) str2;
while ( *s1 && *s2 && !(*s1-*s2) )
s1++, s2++;
if (!*s2)
return(cp);
cp++;
}
return(NULL);
}
?4、請問這段代碼循環多少次?
main()
{
char i=0;
while(i<10)
{
if(i<1)continue;
if(i==5)break;
i++;
}
......
}
答:是個死循環,無限次啊,無限次。
5、用預處理指令#define聲明一個常數,用以表明1年中有多少秒(忽略閏年問題)
答: #define MIN (365*24*60*60)
6、請問運行main函數會有什麼樣的結果?
main()
{
int x=10,y=3;
printf("%d\n",y=x/y);
}
答:結果爲3,考察強制類型轉換
7、有以下程序
#define P 3
void F(int x)
{
return(P*x*x);
}
main()
{
printf("%d\n",F(3+5));
}
程序運行結果爲:?
答:程序運行後的輸出結果是129,此題爲故意混淆概念,直接用F(8)計算得答案,而非計算3*3+5*3+5;
8、若int佔2個字節,char佔1個字節,float佔4個字節,則定義如下:
struct stu
{
union{
char bj[5];
int bh[2];
}class;
char xm[8];
float cj;
}xc;
則sizeof(xc)的值爲?
答:20,一道邊界對齊的題目,很多地方有講,此處注意下聯合的內存大小取決於其中字節數最多的成員就可。
9、請問traceroute的工作原理
答:
主機先發出一個TTL(Time To Live,生存時間)爲1的ICMP數據包。這個數據包到達一個路由器後,路由器將TTL減1到0,並將並送回一個「ICMP time exceeded」消息,以說明這個數據包不能繼續向前傳送,因爲其TTL已經過期了。traceroute 收到這個消息後,便知道這個路由器存在於這個路徑上,接着traceroute 再送出另一個TTL是2 的數據包,發現第2 個路由器......這個重複的動作一直持續到某個datagram 抵達目的地。
普天C++筆試題
普天是南京一家通信公司,全稱爲:南京普天通信股份有限公司
1. 實現雙向鏈表刪除一個節點P,在節點P後插入一個節點,寫出這兩個函數;
答:
假設線性表的雙向鏈表存儲結構
typedef struct DulNode{
struct DulNode *prior; //前驅指針
ElemType da
struct DulNode *next; //後繼指針
}DulNode,*DuLinkList;
刪除操作
Status ListDelete_DuL(DuLinkList &L,int i,ElemType &e)
{
if(!(p=GetElemP_DuL(L,i)))
return ERROR;
e=p->da
p->prior->next=p->next;
p->next->prior=p->pror;
free(p);
return OK;
}
插入操作
Status ListInsert_DuL(DuLinkList &L,int i,ElemType &e)
{
if(!(p=GetElemP_DuL(L,i)))
return ERROR;
if(!(s=(DuLinkList)malloc(sizeof(DuLNode))))
return ERROR;
s->da
s->prior=p->prior;
p->prior->next=s;
s->next=p;
p->prior=s;
return OK;
}
2.寫一個函數,將其中的\t都轉換成4個空格。
答:
該函數命名爲convert,參數的意義爲:
*strDest目的字符串,*strSrc源字符串,length源字符串的長度
函數實現爲:
char* convert(char *strDest, const char *strSrc,int length)
{
char * cp = strDest;
int i=0;
while(*strSrc && i
{
if (*strSrc=='\t') //將\t轉換成4個空格
{
for(int j=0;j<4;j++)
*cp++=' ';
}
else //否則直接拷貝
*cp++=*strSrc;
strSrc++;
i++;
}
return strDest;
}
3.Windows程序的入口是哪裏?寫出Windows消息機制的流程。
答:
Windows程序的入口是WinMain函數
消息機制:系統將會維護一個或多個消息隊列,所有產生的消息都會被放入或是插入隊列中。系統會在隊列中取出每一條消息,根據消息的接收句柄而將該消息發送給擁有該窗口的程序的消息循環。每一個運行的程序都有自己的消息循環,在循環中得到屬於自己的消息並根據接收窗口的句柄調用相應的窗口過程。而在沒有消息時消息循環就將控制權交給系統。
4.如何定義和實現一個類的成員函數爲回調函數?
答:
所謂的回調函數,就是預先在系統的對函數進行註冊,讓系統知道這個函數的存在,以後,當某個事件發生時,再調用這個函數對事件進行響應。
定義一個類的成員函數時在該函數前加CALLBACK即將其定義爲回調函數,函數的實現和普通成員函數沒有區別
5.C++裏面是不是所有的動作都是main()引起的?如果不是,請舉例。
答:不是,比如中斷引起的中斷處理不是直接由main()引起的,而是由外部事件引起的。
6.C++裏面如何聲明const void f(void)函數爲C程序中的庫函數
答:在該函數前添加extern “C”聲明
7.下列哪兩個是等同的
int b;
A const int* a = &b;
B const* int a = &b;
C const int* const a = &b;
D int const* const a = &b;
答:
各式表示的意思分別爲:
A const int* a = &b; //*a是const,但指針a可變
B const* int a = &b; //a是const,但*a可變
C const int* const a = &b; //a和*a都是const,常量和指針的值都不能改變
D int const* const a = &b; //a和*a都是const,常量和指針的值都不能改變
因此C,D兩者是相同的。
總結個技巧:如果const位於星號的左側,則const就是用來修飾指針所指向的變量,即指針指向爲常量;如果const位於星號的右側,const就是修飾指針本身,即指針本身是常量。
8. 內聯函數在編譯時是否做參數類型檢查
答:做類型檢查,因爲內聯函數就是在程序編譯時,編譯器將程序中出現的內聯函數的調用表達式用內聯函數的函數體來代替。
華爲筆試題
華爲從事通信網絡技術與產品的研究、開發、生產與銷售,是中國電信市場的主要供應商之一,並已成功進入全球電信市場。
1.寫出判斷ABCD四個表達式的是否正確, 若正確, 寫出經過表達式中 a的值(3分)
int a = 4;
(A)a += (a++); (B) a += (++a) ;(C) (a++) += a;(D) (++a) += (a++);
a = ?
答:C錯誤,左側不是一個有效變量,不能賦值,可改爲(++a) += a;
改後答案依次爲9,10,10,11
2.某32位系統下, C++程序,請計算sizeof 的值(5分).
char str[] = “www.ibegroup.com”
char *p = str ;
int n = 10;
請計算
sizeof (str ) = ?(1)
sizeof ( p ) = ?(2)
sizeof ( n ) = ?(3)
void Foo ( char str[100]){
請計算
sizeof( str ) = ?(4)
}
void *p = malloc( 100 );
請計算
sizeof ( p ) = ?(5)
答:(1)17 (2)4 (3) 4 (4)4 (5)4
3. 回答下面的問題. (4分)
(1).頭文件中的 ifndef/define/endif 幹什麼用?預處理
答:防止頭文件被重複引用
(2). #include 和 #include “filename.h” 有什麼區別?
答:前者用來包含開發環境提供的庫頭文件,後者用來包含自己編寫的頭文件。
(3).在C++ 程序中調用被 C 編譯器編譯後的函數,爲什麼要加 extern “C”聲明?
答:函數和變量被C++編譯後在符號庫中的名字與C語言的不同,被extern "C"修飾的變量和函數是按照C語言方式編譯和連接的。由於編譯後的名字不同,C++程序不能直接調用C 函數。C++提供了一個C 連接交換指定符號extern“C”來解決這個問題。
(4). switch()中不允許的數據類型是?
答:實型
4. 回答下面的問題(6分)
(1).Void GetMemory(char **p, int num){
*p = (char *)malloc(num);
}
void Test(void){
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
}
請問運行Test 函數會有什麼樣的結果?
答:輸出“hello”
(2). void Test(void){
char *str = (char *) malloc(100);
strcpy(str, “hello”);
free(str);
if(str != NULL){
strcpy(str, “world”);
printf(str);
}
}
請問運行Test 函數會有什麼樣的結果?
答:輸出“world”
(3). char *GetMemory(void){
char p[] = "hello world";
return p;
}
void Test(void){
char *str = NULL;
str = GetMemory();
printf(str);
}
請問運行Test 函數會有什麼樣的結果?
答:無效的指針,輸出不確定
5. 編寫strcat函數(6分)
已知strcat函數的原型是char *strcat (char *strDest, const char *strSrc);
其中strDest 是目的字符串,strSrc 是源字符串。
(1)不調用C++/C 的字符串庫函數,請編寫函數 strcat
答:
VC源碼:
char * __cdecl strcat (char * dst, const char * src)
{
char * cp = dst;
while( *cp )
cp++; /* find end of dst */
while( *cp++ = *src++ ) ; /* Copy src to end of dst */
return( dst ); /* return dst */
}
(2)strcat能把strSrc 的內容連接到strDest,爲什麼還要char * 類型的返回值?
答:方便賦值給其他變量
6.MFC中CString是類型安全類麼?
答:不是,其它數據類型轉換到CString可以使用CString的成員函數Format來轉換
7.C++中爲什麼用模板類。
答:(1)可用來創建動態增長和減小的數據結構
(2)它是類型無關的,因此具有很高的可複用性。
(3)它在編譯時而不是運行時檢查數據類型,保證了類型安全
(4)它是平臺無關的,可移植性
(5)可用於基本數據類型
8.CSingleLock是幹什麼的。
答:同步多個線程對一個數據類的同時訪問
9.NEWTEXTMETRIC 是什麼。
答:物理字體結構,用來設置字體的高寬大小
10.程序什麼時候應該使用線程,什麼時候單線程效率高。
答:1.耗時的操作使用線程,提高應用程序響應
2.並行操作時使用線程,如C/S架構的服務器端併發線程響應用戶的請求。
3.多CPU系統中,使用線程提高CPU利用率
4.改善程序結構。一個既長又複雜的進程可以考慮分爲多個線程,成爲幾個獨立或半獨立的運行部分,這樣的程序會利於理解和修改。
其他情況都使用單線程。
11.Windows是內核級線程麼。
答:見下一題
12.Linux有內核級線程麼。
答:線程通常被定義爲一個進程中代碼的不同執行路線。從實現方式上劃分,線程有兩種類型:“用戶級線程”和“內核級線程”。 用戶線程指不需要內核支持而在用戶程序中實現的線程,其不依賴於操作系統核心,應用進程利用線程庫提供創建、同步、調度和管理線程的函數來控制用戶線程。這種線程甚至在象 DOS 這樣的操作系統中也可實現,但線程的調度需要用戶程序完成,這有些類似 Windows 3.x 的協作式多任務。另外一種則需要內核的參與,由內核完成線程的調度。其依賴於操作系統核心,由內核的內部需求進行創建和撤銷,這兩種模型各有其好處和缺點。用戶線程不需要額外的內核開支,並且用戶態線程的實現方式可以被定製或修改以適應特殊應用的要求,但是當一個線程因 I/O 而處於等待狀態時,整個進程就會被調度程序切換爲等待狀態,其他線程得不到運行的機會;而內核線程則沒有各個限制,有利於發揮多處理器的併發優勢,但卻佔用了更多的系統開支。
Windows NT和OS/2支持內核線程。Linux 支持內核級的多線程
13.C++中什麼數據分配在棧或堆中,New分配數據是在堆還是棧中?
答:棧: 存放局部變量,函數調用參數,函數返回值,函數返回地址。由系統管理
堆: 程序運行時動態申請,new 和 malloc申請的內存就在堆上
14.使用線程是如何防止出現大的波峯。
答:意思是如何防止同時產生大量的線程,方法是使用線程池,線程池具有可以同時提高調度效率和限制資源使用的好處,線程池中的線程達到最大數時,其他線程就會排隊等候。
15函數模板與類模板有什麼區別?
答:函數模板的實例化是由編譯程序在處理函數調用時自動完成的,而類模板的實例化必須由程序員在程序中顯式地指定。
16一般數據庫若出現日誌滿了,會出現什麼情況,是否還能使用?
答:只能執行查詢等讀操作,不能執行更改,備份等寫操作,原因是任何寫操作都要記錄日誌。也就是說基本上處於不能使用的狀態。
17 SQL Server是否支持行級鎖,有什麼好處?
答:支持,設立鎖機制主要是爲了對併發操作進行控制,對干擾進行封鎖,保證數據的一致性和準確性,行級封鎖確保在用戶取得被更新的行到該行進行更新這段時間內不被其它用戶所修改。因而行級鎖即可保證數據的一致性又能提高數據操作的迸發性。
18如果數據庫滿了會出現什麼情況,是否還能使用?
答:見16
19 關於內存對齊的問題以及sizof()的輸出
答:編譯器自動對齊的原因:爲了提高程序的性能,數據結構(尤其是棧)應該儘可能地在自然邊界上對齊。原因在於,爲了訪問未對齊的內存,處理器需要作兩次內存訪問;然而,對齊的內存訪問僅需要一次訪問。
20 int i=10, j=10, k=3; k*=i+j; k最後的值是?
答:60,此題考察優先級,實際寫成: k*=(i+j);,賦值運算符優先級最低
21.對數據庫的一張表進行操作,同時要對另一張表進行操作,如何實現?
答:將操作多個表的操作放入到事務中進行處理
22.TCP/IP 建立連接的過程?(3-way shake)
答:在TCP/IP協議中,TCP協議提供可靠的連接服務,採用三次握手建立一個連接。
第一次握手:建立連接時,客戶端發送syn包(syn=j)到服務器,並進入SYN_SEND狀態,等待服務器確認;
第二次握手:服務器收到syn包,必須確認客戶的SYN(ack=j+1),同時自己也發送一個SYN包(syn=k),即SYN+ACK包,此時服務器進入SYN_RECV狀態;
第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=k+1),此包發送完畢,客戶端和服務器進入ESTABLISHED狀態,完成三次握手。
23.ICMP是什麼協議,處於哪一層?
答:Internet控制報文協議,處於網絡層(IP層)
24.觸發器怎麼工作的?
答:觸發器主要是通過事件進行觸發而被執行的,當對某一表進行諸如UPDATE、 INSERT、 DELETE 這些操作時,數據庫就會自動執行觸發器所定義的SQL 語句,從而確保對數據的處理必須符合由這些SQL 語句所定義的規則。
25.winsock建立連接的主要實現步驟?
答:服務器端:socker()建立套接字,綁定(bind)並監聽(listen),用accept()等待客戶端連接。
客戶端:socker()建立套接字,連接(connect)服務器,連接上後使用send()和recv(),在套接字上寫讀數據,直至數據交換完畢,closesocket()關閉套接字。
服務器端:accept()發現有客戶端連接,建立一個新的套接字,自身重新開始等待連接。該新產生的套接字使用send()和recv()寫讀數據,直至數據交換完畢,closesocket()關閉套接字。
26.動態連接庫的兩種方式?
答:調用一個DLL中的函數有兩種方法:
1.載入時動態鏈接(load-time dynamic linking),模塊非常明確調用某個導出函數,使得他們就像本地函數一樣。這需要鏈接時鏈接那些函數所在DLL的導入庫,導入庫向系統提供了載入DLL時所需的信息及DLL函數定位。
2.運行時動態鏈接(run-time dynamic linking),運行時可以通過LoadLibrary或LoadLibraryEx函數載入DLL。DLL載入後,模塊可以通過調用GetProcAddress獲取DLL函數的出口地址,然後就可以通過返回的函數指針調用DLL函數了。如此即可避免導入庫文件了。
27.IP組播有那些好處?
答:Internet上產生的許多新的應用,特別是高帶寬的多媒體應用,帶來了帶寬的急劇消耗和網絡擁擠問題。組播是一種允許一個或多個發送者(組播源)發送單一的數據包到多個接收者(一次的,同時的)的網絡技術。組播可以大大的節省網絡帶寬,因爲無論有多少個目標地址,在整個網絡的任何一條鏈路上只傳送單一的數據包。所以說組播技術的核心就是針對如何節約網絡資源的前提下保證服務質量。
Paper2:
1. 找錯
void test1()
{
char string[10];
char* str1="0123456789";
strcpy(string, str1);
}
答:表面上並且編譯都不會錯誤。但如果string數組原意表示的是字符串的話,那這個賦值就沒有達到意圖。最好定義爲char string[11],這樣最後一個元素可以存儲字符串結尾符'\0';
void test2()
{
char string[10], str1[10];
for(int I=0; I<10;I++)
{
str1[I] ='a';
}
strcpy(string, str1);
}
答:strcpy使用錯誤,strcpy只有遇到字符串末尾的'\0'纔會結束,而str1並沒有結尾標誌,導致strcpy函數越界訪問,不妨讓str1[9]='\0',這樣就正常了。
void test3(char* str1)
{
char string[10];
if(strlen(str1)<=10)
{
strcpy(string, str1);
}
}
答:這又會出現第一道改錯題的錯誤了。strlen(str1)算出來的值是不包含結尾符'\0'的,如果str1剛好爲10個字符+1結尾符,string就得不到結尾符了。可將strlen(str1)<=10改爲strlen(str1)<10。
2. 找錯
#define MAX_SRM 256
DSN get_SRM_no()
{
static int SRM_no;
int I;
for(I=0;I<MAX_SRM;I++,SRM_NO++)
{
SRM_no %= MAX_SRM;
if(MY_SRM.state==IDLE)
{
break;
}
}
if(I>=MAX_SRM)
return (NULL_SRM);
else
return SRM_no;
}
答:我不知道這段代碼的具體功能,但明顯有兩個錯誤
1,SRM_no沒有賦初值
2,由於static的聲明,使該函數成爲不可重入(即不可預測結果)函數,因爲SRM_no變量放在程序的全局存儲區中,每次調用的時候還可以保持原來的賦值。這裏應該去掉static聲明。
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));
}
}
答:8,10,12,14,16
該題比較簡單。只要注意b聲明爲static靜態全局變量,其值在下次調用時是可以保持住原來的賦值的就可以。
4.
int func(int a)
{
int b;
switch(a)
{
case 1: b=30;
case 2: b=20;
case 3: b=16;
default: b=0;
}
return b;
}
則func(1)=?
答:func(1)=0,因爲沒有break語句,switch中會一直計算到b=0。這是提醒我們不要忘了break。呵呵。
5:
int a[3];
a[0]=0; a[1]=1; a[2]=2;
int *p, *q;
p=a;
q=&a[2];
則a[q-p]=?
答:a[q-p]=a[2]=2;這題是要告訴我們指針的運算特點
6.
定義 int **a[3][4], 則變量佔有的內存空間爲:_____
答:此處定義的是指向指針的指針數組,對於32位系統,指針佔內存空間4字節,因此總空間爲3×4×4=48。
7.
編寫一個函數,要求輸入年月日時分秒,輸出該年月日時分秒的下一秒。如輸入2004年12月31日23時59分59秒,則輸出2005年1月1日0時0分0秒。
答:
/*輸入年月日時分秒,輸出年月日時分秒的下一秒,輸出仍然在原內存空間*/
void NextMinute(int *nYear,int *nMonth,int *nDate,int *nHour,int *nMinute,int *nSecond)
{
int nDays;
(*nSecond)++; // 秒加1
if(*nSecond>=60) // 秒滿60,做出特殊處理,下面時,日,月等類同
{
*nSecond=0;
(*nMinute)++;
if(*nMinute>=60)
{
*nMinute=0;
(*nHour)++;
if(*nHour>=24)
{
*nHour=0;
(*nDate)++;
switch(*nMonth)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
nDays=31;
break;
case 2:// 判斷閏年
if(*nYear%400==0||*nYear%100!=0&&*nYear%4==0)
{
nDays=29;
}
else
{
nDays=28;
}
break;
default:
nDays=30;
break;
}
if(*nDate>nDays)
{
*nDate=1;
(*nMonth)++;
if(*nMonth>12)
{
*nMonth=1;
(*nYear)++;
}
}
}
}
}
}
/*示例可運行代碼*/
void main()
{
int nYear=2004,nMonth=12,nDate=31,nHour=59,nMinute=59,nSecond=59;
NextMinute(&nYear,&nMonth,&nDate,&nHour,&nMinute,&nSecond);
printf("The result:%d-%d-%d %d:%d:%d",nYear,nMonth,nDate,nHour,nMinute,nSecond);
}
paper3:
1.請你分別畫出OSI的七層網絡結構圖和TCP/IP的五層結構圖。
答:OSI七層網絡結構圖
應用層
表示層
會話層
傳輸層
網絡層
數據鏈路層
物理層
TCP/IP的五層結構圖
應用層
運輸層
網絡層
數據鏈路層
物理層
2.請你詳細地解釋一下IP協議的定義,在哪個層上面?主要有什麼作用?TCP與UDP呢?
答:IP是Internet Protocol的簡稱,是網絡層的主要協議,作用是提供不可靠、無連接的數據報傳送。TCP是Transmit Control Protocol(傳輸控制協議)的縮寫,在運輸層,TCP提供一種面向連接的,可靠的字節流服務;UDP是User Datagram Protocol(用戶數據報協議)的縮寫,在運輸層,UDP提供不可靠的傳輸數據服務
3.請問交換機和路由器各自的實現原理是什麼?分別在哪個層次上面實現的?
答:交換機屬於OSI第二層即數據鏈路層設備。它根據MAC地址尋址,通過站表選擇路由,站表的建立和維護由交換機自動進行。路由器屬於OSI第三層即網絡層設備,它根據IP地址進行尋址,通過路由表路由協議產生。交換機最大的好處是快速,路由器最大的好處是控制能力強。
4.請問C++的類和C裏面的struct有什麼區別?
答:struct的成員的默認訪問說明符爲Public,而class的成員的默認訪問說明符爲Private。其他沒有區別
5.請講一講析構函數和虛函數的用法和作用。
答:析構函數是在對象生存期結束時自動調用的函數,用來釋放在構造函數分配的內存。
虛函數是指被關鍵字virtual說明的函數,作用是使用C++語言的多態特性
6.全局變量和局部變量有什麼區別?是怎麼實現的?操作系統和編譯器是怎麼知道的?
答:一些變量在整個程序中都是可見的,它們稱爲全局變量。一些變量只能在一個函數中可知,稱爲局部變量。這就是他們的區別。
在任何函數外面定義的變量就是全局變量,在函數內部定義的變量是局部變量,這是它們在程序中的實現過程。
操作系統和編譯器是根據程序運行的內存區域知道他們的,程序的全局數據放在所分配內存的全局數據區,程序的局部數據放在棧區。
7.8086是多少位的系統?在數據總線上是怎麼實現的?
答:8086的機器字長是16位,8086使用40個引腳的16個做地址/數據複用引腿來傳輸數據,一次讀寫過程由一個基本總線週期完成,它由4個時鐘(CLK)週期組成,按時間順序定義爲T1、T2、T3、T4。在T1期間8086發出訪問目的地的地址信號和地址鎖存選通信號ALE;T2期間發出讀寫命令信號RD、WR及其它相關信號;T3期間完成數據的訪問;T4結束該總線週期。可見,地址與數據信號不會同時出現在一個時鐘(CLK)週期,二者可以分時複用同一組引線。