笔试面试总结

《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 常量赋值时,必须同时初始化

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