筆試面試總結

《c/ C++常見問題剖析》

 

 strcpy 的函數編寫,主要考查對基本功的掌握:

    (1)字符串以’\0’結尾;    (2)對數組越界把握的敏感度; (3)庫函數 strcpy 的工作方式

 

 

對內存操作的考查主要集中在:

    (1)指針的理解; (2)變量的生存期及作用範圍; (3)良好的動態內存申請和釋放習慣。

 

 

數組名的本質如下: (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。

 

 程序員對宏定義的使用要非常小心,特別要注意兩個問題: (1)謹慎地將宏定義中的“參數”和整個宏用用括弧括起來。(2)防止宏的副作用。宏定義#define min(a,b) ((a) <= (b) ? (a) : (b))對 min(*p++, b)的作用結果是:

    ((*p++) <= (b) ? (*p++) : (*p++)) 這個表達式會產生副作用,指針 p 會作三次++自增操作。

 

 

 

爲什麼標準頭文件都有類似以下的結構?

    #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++  的函數了。

 

 

編寫一個函數,作用是把一個 char 組成的字符串循環右移 n 個。比如原來是“abcdefghi”如 果 n=2,移位後應該是“hiabcdefgh” 函數頭是這樣的: //pstr 是指向以'\0'結尾的字符串的指針 //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 ) ) = '\0'; 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 試題

 

 

編寫類 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]; // 得分點:對空字符串自動申請存放結束標誌'\0'的空 //加分點:對 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; }


    //拷貝構造函數 // 得分點:輸入參數爲 const 型
 string::string(const string &other) {

int length = strlen(other.m_data);

 m_data = new char[length+1];

strcpy(m_data, other.m_data); }
    //加分點:對 m_data 加 null 判斷


    //賦值函數

string & string::operate =(const string &other) // 得分點:輸入參數爲 const 型

{

 if(this == &other)

return *this;

delete [] m_data; //得分點:釋放原有的內存資源 //加分點:對 m_data 加 null 判斷 //得分點:檢查自賦值
 int length = strlen( other.m_data );

m_data = new char[length+1];

strcpy( m_data, other.m_data );

return *this; //得分點:返回本對象的引用

}

 

剖析: 能夠準確無誤地編寫出 string 類的構造函數、拷貝構造函數、賦值函數和析構函數的面試者至少已經 具備了 c++基本功的 60%以上!     在這個類中包括了指針類成員變量 m_data,當類中包括指針類成員變量時,一定要重載其拷貝構造函 數、賦值函數和析構函數(內存分配釋放等問題),這既是對 c++程序員的基本要求,也是《effective c++》中特別強調的條款。 仔細學習這個類,特別注意加註釋的得分點和加分點的意義,這樣就具備了 60%以上的 c++基本功!

 

 

 

 

請說出 static 和 const 關鍵字儘可能多的作用 解答: 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 關鍵字的部分功能。

 

 const 常量賦值時,必須同時初始化

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