20170212C++编程试题讲解

来源:互联网 发布:burpsuite安装linux 编辑:程序博客网 时间:2024/06/08 20:11

C++编程测试题

一、请填写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 语句:if(x == 0.0)  错误的

if((x<0.00001)&&(x>-0.00001))//这里不出现魔数更好。

const float EPSINON = 0.00001

If(x<EPSINON && x>-EPSINON )

请写出 char *p “零值”比较的 if 语句:if(p == nullptr)//正确

if(p == NULL)//C风格

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

char str[] = “Hello” ;

char *p = str ;

int n = 10;

请计算

sizeof (str ) =6  6个字节,单位为byte

sizeof ( p ) =4

sizeof ( n ) =4

 

void Func ( char str[100])

{

请计算

sizeof( str ) =100;  传参的时候会产生退化,降级成一个指针,大小为4

}

 

void *p = malloc( 100 );

请计算

sizeof ( p ) =4;

三、简答题(25 分)

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

答:目的是防止头文件二次编译,意思分别为:如果未宏定义、宏定义、结束。  

防止头文件被重复包含。

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

答:用尖括号包含头文件,编译器默认会先到vs软件目录下去找文件,用引号包含会默认先到工程目录去找头文件。  

<>会在系统标准库文件里面搜索,后者””会优先在工程目录里面搜索,未找到还是会去标准库路径搜索。。

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

答:1:传递引用参数的时候防止函数里面修改数据,2:为const属性的类对象提供const方法调用,不然无法获取对象的一些数据,3:变量常量化,可用来定义一些不变的数,比如π。  

1:定义一个常量

2:修饰成员函数

3:修饰返回值,修饰参数//防止被更改,增加程序的健壮性。

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

// 第一个

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

{

if (condition)

DoSomething();

else

DoOtherthing();

}

答:优点:只有一个for循环,代码量少。缺点:每次循环都要执行判断语句和DoSomething();,效率低,cpu计算量较大。  

可读性更高,但判断次数多

// 第二个

if (condition)

{

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

DoSomething();

}

else

{

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

DoOtherthing();

}

答:优点:书写代码量稍大一点,但是先执行的判断,后面每次循环做的都是有用功,在循环次数大的情况下效率会高一些。  

可读性差点,但是效率会高些

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

void GetMemory(char *p)

{

p = (char *)malloc(100);

}

void Test(void)

{

char *str = NULL;

GetMemory(str);

strcpy(str, "hello world");

printf(str);

}

请问运行Test 函数会有什么样的结果?

答:打印出hello world  

strcpy的时候会崩溃,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  

传递的就是str,与第一个不同。但是会内存泄漏。

void Test(void)

{

char *str = (char *) malloc(100);

strcpy(str, “hello”);

free(str);

if(str != NULL)

{

strcpy(str, “world”);

printf(str);

}

请问运行Test 函数会有什么样的结果?

答:运行出错。  

str为野指针,同样是未定义的行为,但还是指向了一段空间,运行不会崩溃,因为指向的内存区域还是可用的(存在于堆上)。free后代表这块内存不再使用了,不再拥有这块内存的管理权限,但其他指针malloc的时候可能会用上这块空间。是一个非常危险的行为。但运行结果“可能”还是会打印出world。

 

五、编写strcpy 函数(10 分)

已知strcpy 函数的原型是

char *strcpy(char *strDest, const char *strSrc);

其中strDest 是目的字符串,strSrc 是源字符串。

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

char *strcpy(char *strDest, const char *strSrc)

{

char *strDestMem  =  strDest;

Char *strDestMem1 = strDest;

Char *strSrcMem = strSrc;

While(*strSrcMem != \0)

{

*strDestMem = *strSrcMem;

++strDestMem;

++strSrcMem;

}

*strDestMem = \0;

return strDestMem1;

}  

可以先判断是否为空。标准库没有判断,所以有空指针异常。

while((*strDest++ = *strSrc++) != \0);

(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::String(const char *str)

{

m_data = new char[strlen(str)+sizeof(char)];

memset(m_data,0,strlen(str)+sizeof(char));

strcpy(m_data,str);

}

 

String::String(const String &other)

{

m_data = new char[strlen(other.m_data)+sizeof(char)];

memset(m_data,0,strlen(other.m_data)+sizeof(char));

strcpy(m_data,other.m_data);

}

 

String::~String(void)

{

delete[]m_data;

}

 

String::String&operator=(const String &other)

{

if(this == &other)

return *this;

if(strlen(m_data)<strlen(other.m_data))

{

delete[]m_data;

m_data = new char[strlen(other.m_data)+sizeof(char)];

}

memset(m_data,0,strlen(other.m_data)+sizeof(char));

strcpy(m_data,other.m_data);

}  

operator=一定要检查自赋值!!!

在最外层加上if(this == &other){return *this;}

1 0