《C程式設計專家》:程式設計師面試(附2)

塵虛緣_KY發表於2016-06-19
問題一:確定一個變數是有符號數還是無符號數:
首先signed int型別是有符號的:如果是正數,最高位是0,如果是負數最高位是1,。對於32為的機器來說其表示的範圍為:-2^31到2^31-1。
但是unsigned無符號型別的整數就是所有位參與計數,所以無符號位肯定是一個正數。對於32位的機器來說其表示的範圍為:0到2^32-1。
判斷該變數是否為有無符號的數,還不能用函式來判斷,因為函式對接受的引數或作隱式的轉換。這裡尤其注意一點:int和nusigned int做if比較時,有時會做隱式的型別轉換,得出超過預期的結果。
參考程式碼:
 unsigned int a = 0;
 if(a < a-1) {
      printf("/nunsiged");
 }else{
      printf("/nsigned");
 }
 分析:如果a為有符號數:那麼0<-1不成立,則會列印signed;
 如果a是無符號數:那麼-1會轉換為無符號的整數,是一個非常大的數,則a<a-1,得出unsigned。
 問題二:列印一棵二叉樹的值的時間複雜度:
   這個問題是面試者在申請Intel編譯小組問到的。現在關於時間複雜度的理論,首先需要知道的是大O表示法。O(N)表示當N(通常是需要處理的的物件)增長時,處理時間幾乎是按線性增長的。類似,O(N*N)表示當N增長時,處理時間的增長要快的多,大致是按照N的平方增長。關於複雜度理論,我們其次需要知道的是在一棵二叉樹中,所有的操作時間的複雜度為 O(logN)。所以很多程式設計師不假思索的回答了這個答案。結果:game over,錯誤。
   因為面試官問的與二叉樹的插入,刪除和查詢等操作有所不同,是列印二叉樹的值,所以我們必須逐個訪問,其時間複雜度為O(N)。就和查詢一棵無序二叉樹一樣,也得遍歷整個二叉樹,所以其時間複雜度我O(N),而不是我們平時想象的O(logN)(感覺有點兒坑)。
 問題三:從檔案中隨機提取一個字串
     這是Microsoft喜歡使用的問題之一。主考官要求面試者編寫一些程式碼,實現從一個檔案(檔案的內容是許多字串)中隨機提取一個字串。
    方案一:解決這個問題的經典方法就是讀取檔案,對字串進行計數,並記錄每個字串的偏移位置。然後在1和字元總數之間取一個隨機數,根據選中字串的偏移位置去除該字串。但是很不幸,面試官要求只能按順序遍歷字串一次。
    方案二:最基本的技巧就是:在倖存的字串中挑選,並在過程中不斷更新。從計算的角度看這個方法是非常低效的。
    具體過程是:我們開啟一個檔案,讀取第一個字元,這樣我們就獲得了第一個字元,並有100%的可能性選中它,因為只有一個,也別無選擇,儲存選中的數字;
    接著讀取下一個資料,這樣就有兩個備選資料,我們有50%的機率選擇其中任何一個,儲存;
    接著再讀取下一個字元:這樣該字串和前面的67%的兩個字串加起來就有33%機率被選中;
    這樣不斷的迴圈,最後可以得到一個隨機的字元,並且值遍歷了檔案一遍。

   通過概率的計算,你會發現每個字元被選中的概率是一樣的,並且是隨機的,因為有可能選中的是第一個字元,也可能是最後一個,或者是其中任意一個。這和抽籤的原理是一樣的,想想是不是這樣!

問題四:檔案描述符與檔案指標的區別

   在linux系統中把裝置和普通檔案都看做是檔案,要對檔案操作就必須先開啟檔案,開啟檔案後會得到一個檔案描述符,它是一個很小的正整數,是一個索引值,是一個小整數,其值在(0-255)之間。每個程式PCB(Process Control Block)中儲存著一份檔案描述符表,檔案描述符就是這個表的索引,每個表項都有一個指向已開啟檔案的指標。所以檔案描述符就是開放檔案每個程式表的一個偏移量(如"3"),用於檔案標示。
缺點:系統I/0呼叫有create(),open(),read(),write(),close()等。它們不是ANSI C的一部分,所以移植性差,不能存在於非UNIX環境。但是現在的ANSI C規定所有的編譯器環境都必須支援它們。
   檔案指標:C語言中使用檔案指標做I/O的控制程式碼。檔案指標指向程式使用者區中的一個被稱為FILE結構的資料結構。FILE結構包括一個緩衝區和一個檔案描述符。而檔案描述符是檔案描述符表的一個索引,因此某種意義上說檔案指標就是控制程式碼的控制程式碼,在windows系統中檔案描述符被稱作檔案控制程式碼。所以FILE指標儲存了一個FILE結構的地址。
   FILE結構中含有檔案描述符,那麼可以使用fopen來獲得檔案指標,然後從檔案指標獲取檔案描述符,檔案描述符應該是唯一的,
   而檔案指標卻不是唯一的,但是指向的物件是唯一的。

FILE的結構

struct _iobuf {
        char *_ptr;          //緩衝區當前指標
        int   _cnt;
        char *_base;         //緩衝區基址
        int   _flag;         //檔案讀寫模式
        int   _file;         //檔案描述符
        int   _charbuf;      //緩衝區剩餘自己個數
        int   _bufsiz;       //緩衝區大小
        char *_tmpfname;
        };
C語言檔案指標與檔案描述符之間可以相互轉換:
int fileno( FILE *stream );//fileno()用來取得引數stream指定的檔案流所使用的檔案描述符。
FILE *fdopen(int fd,const char *mode);//建立一個新的FILE結構,並把它與一個確定的檔案描述符相關聯。


相關文章