PoEdu培训 C++班 第十六课 易错试题考试
文章类别: 培训笔记 0 评论

PoEdu培训 C++班 第十六课 易错试题考试

文章类别: 培训笔记 0 评论

易错试题考试

一、请填写BOOL , float, 指针变量 与“零值”比较的 if 语句。(10 分)

提示:这里“零值”可以是0, 0.0 , FALSE 或者“空指针”。
例如 int 变量 n 与“零值”比较的 if 语句为:
if ( n == 0 )
if ( n != 0 )
以此类推。

请写出 BOOL flag 与“零值”比较的 if 语句

// 标准写法
if (flag == FALSE)
if (flag != FALSE)
// 老鸟写法
if (flag)
if (!flag)

请写出 float x 与“零值”比较的 if 语句

// 最优写法
const float EPSINON = 0.00001f;
if (x > -EPSINON && x < EPSINON);

请写出 char *p 与“零值”比较的 if 语句

if (p == nullptr)  // nullptr表示指针的0
// 或者
if (p == NULL)
// 老鸟写法
if (p)
if (!p)

二、以下为Windows NT 下的32 位C++程序,请计算sizeof 的值(10 分)

char str[] = “Hello”;
char *p = str ;
int n = 10;
请计算
sizeof ( str )
sizeof ( p )
sizeof ( n )

sizeof(str) = 6byte // sizeof数组名, 计算数组大小, 字符5+'\0' == 6
sizeof(p) = 4byte   // 指针, 32位程序中占4byte
sizeof(n) = 4byte   // int, 32位程序中占4byte

void Func ( char str[100])
{
请计算 sizeof( str )
}

sizeof(str) = 4byte;`// 因为数组在参数传递的时候, 数组会进行降级, 变成指针.

void *p = malloc( 100 );
请计算sizeof ( p )

sizeof(p) = 4byte;  // malloc返回的是指针

三、简答题(25 分)

1、头文件中的 ifndef/define/endif 干什么用?

预处理指令, 在预处理阶段进行处理的指令.
一般用来防止重复包含头文件.

2、#include <filename.h> 和 #include “filename.h” 有什么区别?

#include<> 是从系统标准库路径开始搜索头文件.
#include"" 是首先从工作目录开始搜索, 没找到在去标准库目录中搜索头文件.

3、const 有什么用途?(请至少说明两种)

1) const 与变量结合, 定义一个常量
    如 const int x = 0; 表示 变量 x 是一个常量.
2) 修饰成员函数, 放到成员函数末尾, 表示成员函数不修改类成员的值.
3) 修饰返回值
4) 修饰参数, 防止被修改, 增加程序健壮性

4、请简述以下两个for 循环的优缺点

前提: condition不会被改变.
// 第一个
for (i=0; i < N; i++)
{

**if (condition)**   
    **DoSomething();**   
**else**   
    **DoOtherthing();**   

}

// 第二个
if (condition)
{

**for (i=0; i < N; i++)**   
    **DoSomething();**   

}
else
{

**for (i=0; i < N; i++)**   
    **DoOtherthing();**   

}

第一个优点: 可读性更高, 逻辑清晰
第一个缺点: 多执行了 N-1 次判断, 效率相对较低.
第二个优点: 执行效率相对较高
第二个缺点: 可读性略差, 逻辑不太清晰.

四、有关内存的思考题(20 分)

void GetMemory(char * p)
{
p = (char * )malloc(100);
}
void Test(void)
{
char * str = NULL;
GetMemory(str);
strcpy(str, "hello world");
printf(str);
}
请问运行Test 函数会有什么样的结果?

空指针异常, 程序会崩溃
因为参数的传递是进行值的拷贝, p 是 str 的一个拷贝, 所以 str==NULL

char * GetMemory(void)
{
char p[] = "hello world";
return p;
}
void Test(void)
{
char * str = NULL;
str = GetMemory();
printf(str);
}
请问运行Test 函数会有什么样的结果?

由于返回了局部变量, 产生了未定义的行为, 不知道结果.

Void GetMemory2(char p, int num)**
{
( p) = (char )malloc(num);
}
void Test(void)
{
char * str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
}
请问运行Test 函数会有什么样的结果?

输出 hello
没有free, 造成内存泄露

void Test(void)
{
char str = (char ) malloc(100);
strcpy(str, “hello”);
free(str);
if(str != NULL)
{
strcpy(str, “world”);
printf(str);
}
请问运行Test 函数会有什么样的结果?

返回了已删除的内存, 产生未定义行为, 结果未知.

五、编写strcpy 函数(10 分)

已知strcpy 函数的原型是 char strcpy(char strDest, const char * strSrc);
其中strDest 是目的字符串,strSrc 是源字符串。

(1) 不调用C++/C 的字符串库函数,请编写函数 strcpy

// 加分/装X答案
char *strcpy(char *strDest, const char *strSrc)
{
    while((*strDest++ = *strSrc++) != ‘\0’);
    return strDest;
}

(2)strcpy 能把strSrc 的内容复制到strDest,为什么还要char * 类型的返回值?

方便进行连续调用.

六、编写类String 的构造函数、析构函数和赋值函数(25 分)

已知类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 的上述4 个函数。

// String.cpp

// 本函数声明在String.h的private:访问限定符中.
// 本处不在写出声明
bool SetMemberValue(char* str)
{
    bool bRet = false;
    
    do
    {
        size_t iLen = strlen(str);
        m_data = new char[iLen + sizeof(char)];
        memset(m_data, 0x00, (iLen + 1) * sizeof(char));
        if (iLen > 0)
            strcpy(m_data, str);
        bRet = true;
    } while (false);
    
    return bRet;
}

String(const char* str)
{
    SetMemberValue (str);
}

String(const String &other)
{
    SetMemberValue (other.m_data);
}

~ String(void)
{
    // m_data必定有值
    delete[] m_data;
}

String & operate =(const String &other)
{
    if (this != *other) // 考点, 必须要考虑自复制
    {
        // m_data必定有值
        delete[] m_data;
        SetMemberValue(other.m_data);
    }
    return *this;
}

如有错误,请提出指正!谢谢.

回复