高质量C++编程_C++/C试题

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

请写出 BOOLflag 与“零值”比较的if语句:

if (flag)
{ }

if (!flag)
{ }
请写出 float x 与“零值”比较的 if 语句:

const float EPSINON = 0.00001;
if (x >= -EPSINON && x <=EPSINON)
{ }

if (!(x >= -EPSINON && x <=EPSINON))
{ }

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

if (p == NULL)
{ }

if (p != NULL)
{ }

二、以下为Windows NT下的32C++程序,请计算sizeof 的值


说明:数组当参数时,该数组会退化成指针,即char strp[] 变成了 char* str。

三、简答题

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

答:防止头文件被重复引用

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

答:告诉编译器取哪里查找头文件

对于

#include <filename.h>,编译器从标准库路径搜索

filename.h

对于

#include “filename.h”,编译器从用户的工作路径

搜索

filename.h

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

答:

被const修饰的东西会受到强制的保护,可以防止意外的改动,提高程序的健壮性。

(1)可以定义const常量

(2)const可以修饰函数的参数、返回值、函数体。

4、在C++ 程序中调用被 C 编译器编译后的函数,为什么要加 extern “C”声明?

答:解决函数名字的匹配问题

在C++语言支持函数重载,C语言不支持函数重载。C++编译器对函数进行编译后,生成的名字和C编译器对函数编译后,生成的名字不同。

假设函数原型:void foo(int x,int y);

C++编译器编译后,该函数在库中的名字为 _foo_int_int。

C编译器编译后,该函数在库中的名字为 _foo。

为了解决这些被

 C 编译器编译后的函数的名字问题,C++就提供了C连接交换指定符号 ”extern C“ 。

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


四、有关内存的思考题

程序一

void GetMemory(char *p)
{
	p = (char *)malloc(100);
}
void Test(void)
{
	char *str = NULL;
	GetMemory(str);
	strcpy(str, "hello world");
	printf(str);
}

问题:

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

答:程序直接崩溃

(1)内存泄露:p指针申请的空间没有被释放

(2)程序崩溃:函数GetMemory的参数时值传递,没不能把p申请的空间传到Test函数中,使得str一直为NULL。在执行函数strcpy时,相当于把内容写到一个空指针中,导致系统崩溃。

程序二

char *GetMemory(void)
{
	char p[] = "hello world";
	return p;
}
void Test(void)
{
	char *str = NULL;
	str = GetMemory();
	printf(str);
}

问题:

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

答:输出为乱码

原因:p指向的空间是一个栈内存,当函数GetMemory结束时,p指向的空间被释放了,因此str在接受函数GetMemory的值后,str的值仍是p指向的这块地址,但是这块地址已经被系统收回,其值可能发生改变,所以输出其值时,会输出乱码。

程序三

char *GetMemory(void)
{
	char* p = "hello world";
	return p;
}
void Test(void)
{
	char *str = NULL;
	str = GetMemory();
	printf(str);
}

问题:

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

答:输出为 hello world

原因:p指向的空间是在全局内存区申请的内存,只有当整个程序结束时,才被os回收。当函数GetMemory结束时,p指向的空间没有被释放,因此str在接受函数GetMemory的值后,str的值仍是p指向的这块地址,输出str的值时,就直接输出hello world。

程序四

void GetMemory(char **p, int num)
{
	*p = (char *)malloc(num);
}
void Test(void)
{
	char *str = NULL;
	GetMemory(&str, 100);
	strcpy(str, "hello");
	printf(str);
}

问题:

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

答:

(1)输出为 hello world

(2)内存泄露:内存没有释放。

程序五

void Test(void)
{
	char *str = (char *) malloc(100);
	strcpy(str, “hello”);
	free(str);
	if(str != NULL)
	{
		strcpy(str, “world”);
		printf(str);
	}
}

问题:

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

答:篡改动态内存区的内容,后果难以预料,非常危险。

在free完str后,str就变成了野指针,执行strcpy后,会改变属于该程序的内存的值,而可能引起未知的错误。

五、编写strcpy函数

已知strcpy 函数的原型是

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

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

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

char *Strcpy(char* strDest, const char* strSrc)
{
	assert(strDest != NULL && strSrc != NULL);

	char* pCur = strDest;
	while (*strSrc)
	{
		*pCur = *strSrc;
		pCur++;
		strSrc++;
	}
	return strDest;
}
2 strcpy  能把 strSrc  的内容复制到 strDest ,为什么还要 char *  类型的返回值?

答:为了实现链式表达。

cout<<Strcpy(str1,str)<<endl;

六,编写类String 的构造函数,析构函数和赋值函数

class String
{
public:
	String(const char* str = NULL);
	String(const String& other);
	~String();
	String& operate=(const String& other);
private:
	char* m_data;
};

String::String(const char* str)
{
	if (str != NULL)
	{
		int nLen = strlen(m_data);
		m_data = new char[nLen + 1];
		strcpy(m_data,str);
	}
	else
	{
		m_data = new char[1]; //没有实际值的字符串加了字符串结束符
		*m_data = '\0';
	}
}

String::String(const String &other)
{
	int nLen = strlen(other.m_data);
	m_data = new char[nLen + 1];
	strcpy(m_data,other.m_data);
}

String::~String()
{
	delete[] m_data;
	m_data = NULL;
}

String& String::operate=(const String& other)
{
	//检测自赋值
	if (this == &other)
	{
		return *this;
	}
	//释放原有内存
	delete m_data;
	
	//申请新内存,并复制内容
	int nLen = strlen(other.m_data);
	m_data = new char[nLen + 1];
	strcpy(m_data,other.m_data);

	//返回本对象的引用
	return *this;
}
说明:

(1)字符串没有实际值时,使用了字符串结束符填充。

(2)在使用旧String对象对新String对象进行复制时,由于旧String对象的m_data一定是不为空的,则不必写if语句判断为空了。

(3)由于使用new申请空间时,也可以加上if语句,判断申请空间是否成功。

(4)写赋值函数时,需要根据四步走书写。

  • 7
    点赞
  • 67
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值