再見編程小問題

1、int main()前面爲什麼int而不用void,這是爲了系統調用方便

2、變量的生命週期和{}相關

3、大小端模式的問題:我們常用的X86結構是小端模式,而KEIL C51則爲大端模式。很多的ARM,DSP都爲小端模式(這個記反了

4、堆棧搞反了

5、後綴表達式,一般算式轉換成後綴表達式可以先用括號把數包括起來,然後把二者的符號放到最後,然後去掉括號即可。反之,把後綴表達式轉成一般表達式,則需要從後面開始收縮一個符號就加一個括號,直道所有的括號都加載完畢,然後再轉成一般就容易了,前綴的轉換類似

6、內存相關錯誤

7、地址排列問題:(int *)p1-(int *)p2=4倍的(char *)p1-(char *)p2。

Union的使用注意內存公用,以最長的爲準

8、const *p是內容不可改,p可以改

9、static只初始化一次,否則聲明初始化語句不運行

10、sizeof那幾個題目在前面兩篇文章裏面有講訴,見c++內存管理

11、爲麼有了malloc還需要new,malloc只能機械的分配內存,而數據結構除了內部數據意外,還有大量的類對象,這些除了分配內存意外還需要構造和析構,還需要初始化

12、轉義字符

13、爲麼叫單精度浮點數和雙精度浮點數?一個是7位精度的浮點數,有時候這不夠

所以就推出了double float,謂之雙精度型

ps:float的存儲結構:1bit符號位,8bit指數位E(實際指數e=E-127),23bit有效數字M(1=<M<2)
double的存儲結構1bit符號位,11bit指數位E(實際指數e=E-1023),52bit有效數字M(1=<M<2)

14、求整數的絕對值 abs,求雙精度實數的絕對值fabs,頭文件math.h

15、檢查字符串中的[]與()兩個是否匹配的問題,考慮不能先出現右括號,並且嵌套不能交互,如[(})就不行

如果只求一個括號問題,沒必要使用數據結構,單用一個while,然後再加兩邊計數,而且每次右括號不能比左括號多就完了

兩個一起檢查就要考慮嵌套,用單鏈表的頭插法(模擬棧的功能),只要看前面一個是否是相差1或者2(左小括號與左小括號相差1,左中括號與右中括號相差2)就完了

還可以真用堆棧,相關代碼及思想參考網頁:檢查表達式中左右圓括號是否匹配c語言括號匹配檢驗源程序括號匹配思想

16、c語言的輸入函數及其作用

懶得贅述了,就提醒點,scanf遇到空格或者換行符退出,如果要輸入整行的字符串,用gets,其中見網頁:c語言輸入輸出函數

17、c語言賦值函數的真假問題。

賦值是0則爲假,賦值爲其他則爲真,其中a=0,爲假;a=1爲真

18、一個小題目:假設現有一個單向的鏈表,但是隻知道只有一個指向該節點的指針p,並且假設這個節點不是尾節點,試編程實現刪除此節點

方法肯定是先把下一個節點的地址給個p指針,再把下一個節點的數據包括其下一個節點的指針複製到這個上面來,然後把下個節點free,然後把p指向0就算完了

19、關聯數組就是map的典型應用,不像棧隊列這些是線性表

20、程序計數器是不可改變的,不論在哪裏

21各種排序方法及其適用的情況

算法 適用情況
冒泡排序 容易出錯地方(直接交換不用額外空間)
直接插入排序 即只需用到O(1)的額外空間的排序,複雜度o(n*n)
選擇排序  
堆排序  
希爾排序  
快速排序  
歸併排序  

具體每種算法在每種情況下的選擇見下:

(1)若n較小(如n≤50),可採用直接插入或直接選擇排序。  

當記錄規模較小時,直接插入排序較好;否則因爲直接選擇移動的記錄數少於直接插入,應選直接選擇排序爲宜。
(2)若文件初始狀態基本有序(指正序),則應選用直接插入、冒泡或隨機的快速排序爲宜;
(3)若n較大,則應採用時間複雜度爲O(nlgn)的排序方法:快速排序、堆排序或歸併排序。  
快速排序是目前基於比較的內部排序中被認爲是最好的方法,當待排序的關鍵字是隨機分佈時,快速排序的平均時間最短;  
堆排序所需的輔助空間少於快速排序,並且不會出現快速排序可能出現的最壞情況。這兩種排序都是不穩定的。  
若要求排序穩定,則可選用歸併排序。但本章介紹的從單個記錄起進行兩兩歸併的 排序算法並不值得提倡,通常可以將它和直接插入排序結合在一起使用。先利用直接插入排序求得較長的有序子文件,然後再兩兩歸併之。因爲直接插入排序是穩定的,所以改進後的歸併排序仍是穩定的。
(4)在基於比較的排序方法中,每次比較兩個關鍵字的大小之後,僅僅出現兩種可能的轉移,因此可以用一棵二叉樹來描述比較判定過程。  
當文件的n個關鍵字隨機分佈時,任何藉助於"比較"的排序算法,至少需要O(nlgn)的時間。  
箱排序和基數排序只需一步就會引起m種可能的轉移,即把一個記錄裝入m個箱子之一,因此在一般情況下,箱排序和基數排序可能在O(n)時間內完成對n個記錄的排序。但是,箱排序和基數排序只適用於像字符串和整數這類有明顯結構特徵的關鍵字,而當關鍵字的取值範圍屬於某個無窮集合(例如實數型關鍵字)時,無法使用箱排序和基數排序,這時只有藉助於"比較"的方法來排序。  
若n很大,記錄的關鍵字位數較少且可以分解時,採用基數排序較好。雖然桶排序對關鍵字的結構無要求,但它也只有在關鍵字是隨機分佈時才能使平均時間達到線性階,否則爲平方階。同時要注意,箱、桶、基數這三種分配排序均假定了關鍵字若爲數字時,則其值均是非負的,否則將其映射到箱(桶)號時,又要增加相應的時間。
(5)有的語言(如Fortran,Cobol或Basic等)沒有提供指針及遞歸,導致實現歸併、快速(它們用遞歸實現較簡單)和基數(使用了指針)等排序算法變得複雜。此時可考慮用其它排序。
(6)本章給出的排序算法,輸人數據均是存儲在一個向量中。當記錄的規模較大時,爲避免耗費大量的時間去移動記錄,可以用鏈表作爲存儲結構。譬如插入排序、歸併排序、基數排序都易於在鏈表上實現,使之減少記錄的移動次數。但有的排序方法,如快速排序和堆排序,在鏈表上卻難於實現,

以上參考了網頁排序算法彙總總結

19、關於判斷程序是否運行於printf語句的問題

	int x=1,y=1;
	int z=1 || y++ && x++;
	printf("%d %d %d\n",-x++,y,z);
	printf("%d %d %d\n",x=35,y+x,z+y);
	printf("%d %d %d\n",x,y+x,z+y);

運行的結果是

-1 1 1
35 3 2
35 36 2

想說明兩個問題:1、運算符在運算得想要的結果之後就不會往下運算了。2、如果在printf中間出現的運算等等都會按照從右至左的順序運算過來(左邊出現的運算結果不會影響右邊的式子)

20 

a) 一個整型數(An integer)
b) 一個指向整型數的指針(A pointer to an integer)
c) 一個指向指針的的指針,它指向的指針是指向一個整型數(A pointer to a pointer to an integer)
d) 一個有10個整型數的數組(An array of 10 integers)
e) 一個有10個指針的數組,該指針是指向一個整型數的(An array of 10 pointers to integers)
f) 一個指向有10個整型數數組的指針(A pointer to an array of 10 integers)
g) 一個指向函數的指針,該函數有一個整型參數並返回一個整型數(A pointer to a function that takes an integer as an argument and returns an integer)
h) 一個有10個指針的數組,該指針指向一個函數,該函數有一個整型參數並返回一個整型數( An array of ten pointers to functions that take an integer argument and return an

integer )

答案是:
a) int a; // An integer
b) int *a; // A pointer to an integer
c) int **a; // A pointer to a pointer to an integer
d) int a[10]; // An array of 10 integers
e) int *a[10]; // An array of 10 pointers to integers
f) int (*a)[10]; // A pointer to an array of 10 integers
g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer
h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer

21、char str[] 和 char *str 的區別

(1)各自取常數了之後分配的地址不同,數組分配的是棧區,如果在函數內部用完就回收,而指針指向的應該是全局區,只有程序完成纔會回收

(2)各自取常量,數組的內容可以改,指針的內容不可改

(3)sizeof得到的也不同,數組是數組有多少成員,指針永遠都是4,但是作爲函數參數,數組名退化成指針,都一樣,全是4

22、!與&這些符號的特殊性

比如z=5,!Z=0;&&是單位運算,非零與零相區分

23、枚舉類型的默認參數

默認從有值的地方開始增加1,全沒有值的時候從0開始

比如enum  Months{JAN=1,FEB,MAR,APR,MAY=3,JUN,JUL,AUG,SEP,OCT,NOV,DEC}; 其中FEB=2 MAR=3 而JUN卻要從4重新開始算,反正是後面比前面多1
printf("%d",(MAR & AUG) ^ !JUN); 

24、x *= x + 1; 等價於x=x*(x+1)即等號右邊的式子相當於用括號括起來的,因爲運算符的優先級

25、給幾個程序相關的英文 strip去除,@S代表 char *

26、while(*s)意思就是字符串輸出完就結束循環

27、c中的>>還有什麼數組的第幾位問題a[2][2][0]是第201位要注意好。

28、嵌入式c中如果按位清0就是 a&(~n),如果是除了某位之外都取反那就是a^(~n)(由於1^1=0,0^1=1,)

29解釋一下位域

比如後面跟:數字,數字代表佔用幾個字節,參見網頁位域全解析

30怎麼比較兩個浮點數的大小。

兩個想減,其差在一定的範圍內

31寫一個類似於printf的函數,可以接受任意多個參數

採用微軟的stdarg庫,參加網頁寫一個類似printf的帶有不定參數的函數

#include <stdio.h>
#include <stdarg.h>        //要包含這個頭文件
void variable(int i, ...)
{
    int j = 0;
      va_list arg_ptr;    //第1步,定義這個指向參數列表的變量
      va_start(arg_ptr, i);//第2步,把上面這個變量初始化.即讓它指向參數列表

    while( j != -1 )
      {
        //第3步,獲取arg_ptr指向的當前參數.這個參數的類型由va_arg的第2個參數指定
          j = va_arg(arg_ptr, int);
          printf("%d ",j );
      }
      va_end(arg_ptr);    //第4步,做一些清理工作
}
main()
{
      variable(3, 3, 4, 5, 6, -1);
}

32有兩個單鏈表,用什麼方法可以快速的知道他們有沒有相同的部分

分別遍歷兩個表,求出差,然後從差的位置開始比較,找出的相同的

33有關殭屍進程的問題

 .解釋一下殭屍進程、殭屍進程怎麼回收 :一個進程結束了,但是父進程沒有wait該進程就成爲了殭屍進程

   在linux系統上怎麼列出所有的殭屍進程ps aux

具體解決方法參加網頁linux殭屍進程及其解決方法

34fork函數和wait函數的作用

一個是創建子線程和,一個是回收,具體見網頁linux的fork和wait函數詳解

35使用memcp函數的時候,有什麼要注意的

空間夠不夠,具體參見strcpy和memcp的注意事項



未完待續。。。

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章