第六十六天学习记录:《高质量C/C++编程指南》中附录的考试试卷(含答案)

news/2024/12/29 23:02:39/

该试卷转载自林锐《高质量C/C++编程指南》,先贴下原作者的版权声明。
版权声明:本书的大部分内容取材于作者一年前的书籍手稿(尚未出版),现整理汇编成为上海贝尔网络应用事业部的一个规范化文件,同时作为培训教材。由于C++/C编程是众所周知的技术,没有秘密可言。编程的好经验应该大家共享,我们自己也是这么学来的。作者愿意公开本书的电子文档。版权声明如下:(1)读者可以任意拷贝、修改本书的内容,但不可以篡改作者及所属单位。(2)未经作者许可,不得出版或大量印发本书。(3)如果竞争对手公司的员工得到本书,请勿公开使用,以免发生纠纷。预计到2002年7月,我们将建立切合中国国情的CMMI3级解决方案。届时,包括本书在内的约1000页规范将严格受控。欢迎读者对本书提出批评建议。林锐,2001年7月

附录B:C++/C试题

本试题仅用于考查C++/C程序员的基本编程技能。内容限于C++/C常用语法,不涉及数据结构、算法以及深奥的语法。考试成绩能反映出考生的编程质量以及对C++/C的理解程度,但不能反映考生的智力和软件开发能力。笔试时间90分钟。请考生认真答题,切勿轻视。

一、请填写BOOL,float,指针变量与“零值”比较的if语句。(10分)
提示:这里“零值”可以是0,0.0,FALSE或者“空指针”。例如int变量n与“零值”比较的if语句为:
if(n==0)
if(n!=0)
以此类推。
请写出BOOL flag与“零值”比较的if语句:


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


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


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

char str[]=“Hello”;
char* p=str;
int n=10;
请计算:
sizeof(str)=
sizeof(p)=
sizeof(n)=
void Func(char str[100])
{
请计算sizeof(str)=
}
void* p=malloc(100);
请计算sizeof(p)=

三、简答题(25分)
1、头文件中的ifndef/define/endif干什么用?

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

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

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

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

for(i=0;i<N;i++)
{if(condition)DoSomething();elseDoOtherthing();
}

优点:
缺点:

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");print(str);
}

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

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

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

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

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

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

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

五、编写strcpy函数(10分)已知strcpy函数的原型是charstrcpy(charstrDest,const char*strSrc);其中strDest是目的字符串,strSrc是源字符串。
(1)不调用C++/C的字符串库函数,请编写函数strcpy


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

六、编写类String的构造函数、析构函数和赋值函数(25分)
已知类String的原型为:

classString
{public:String(const char* str=NULL); //普通构造函数String(const String &other);//拷贝构造函数~String(void);//析构函数String & operate = (const String &other);//赋值函数private:char* m_data;//用于保存字符串
};

请编写String的上述4个函数。

附录B:C++/C试题(答案)

本试题仅用于考查C++/C程序员的基本编程技能。内容限于C++/C常用语法,不涉及数据结构、算法以及深奥的语法。考试成绩能反映出考生的编程质量以及对C++/C的理解程度,但不能反映考生的智力和软件开发能力。笔试时间90分钟。请考生认真答题,切勿轻视。

一、请填写BOOL,float,指针变量与“零值”比较的if语句。(10分)
提示:这里“零值”可以是0,0.0,FALSE或者“空指针”。例如int变量n与“零值”比较的if语句为:
if(n==0)
if(n!=0)
以此类推。
请写出BOOL flag与“零值”比较的if语句:

标准答案:
if(flag)
if(!flag)
如下写法均属不良风格,不得分。
if(flag==TRUE)
if(flag==1)
if(flag==FALSE)
if(flag==0)
我的答案:属于不良风格……0分if(flag!=TRUE)if(flag==FALSE)

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

标准答案示例:
constfloatEPSINON=0.00001;
if((x>=-EPSINON)&&(x<=EPSINON)
不可将浮点变量用“==”或“!=”与数字比较,应该设法转化成“>=”或“<=”此类形式。
我的答案:是错误的写法,0分。if(x==0.0)if(x!=0.0)

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

标准答案:
if(p==NULL)
if(p!=NULL)
我的答案:3分if(p==NULL)if(p!=NULL)

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

char str[]=“Hello”;
char* p=str;
int n=10;
请计算:
sizeof(str)=6 我的答案:正确 2分
sizeof(p)=4 我的答案:正确 2分
sizeof(n)=4 我的答案:正确 2分
void Func(char str[100])
{
请计算sizeof(str)=4        我的答案:sizeof(str)=100 错误 0分 这题太粗心了……
}
void* p=malloc(100);
请计算sizeof(p)=4 我的答案:正确 2分

三、简答题(25分)
1、头文件中的ifndef/define/endif干什么用?
标准答案:
答:防止该头文件被重复引用。
我的答案:
答:总体来说,头文件中的ifndef/define/endif是防止头文件在被重复引用时多次进行调用而加的限制。ifndef就是指该头文件如果被定义,就define定义以下头文件的内容直到endif结束。这样当下一次重复引用该头文件的时候,ifndef到endif之间的内容就不再被执行。

2、#include<filename.h>和#include“filename.h”有什么区别?
标准答案:
答:对于#include<filename.h>,编译器从标准库路径开始搜索filename.h对于#include“filename.h”,编译器从用户的工作路径开始搜索filename.h
我的答案:
答:#include<filename.h>是直接从编译器库的安装路径查找头文件名字,若没有则报错。#include“filename.h”则是先在工程文件目录下查找头文件名字,若没有再从编译器库的安装路径查找头文件名字。

3、const有什么用途?(请至少说明两种)
标准答案:
答:(1)可以定义const常量(2)const可以修饰函数的参数、返回值,甚至函数的定义体。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。
我的答案:
答:一、定义常量,例如const int a;定义后a的值无法被变更。
二、修饰函数的形参,在执行函数时加了const修饰的形参所对应的实参值不会被变更,使得程序更加健壮。
三、修饰指针,常量指针和指针常量。

4、在C++程序中调用被C编译器编译后的函数,为什么要加extern“C”声明?
标准答案:
答:C++语言支持函数重载,C语言不支持函数重载。函数被C++编译后在库中的名字与C语言的不同。假设某个函数的原型为:void foo(intx,inty);该函数被C编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。C++提供了C连接交换指定符号extern“C”来解决名字匹配问题。
我的答案:
答:因为C++编译器无法直接编译.c文件,需要加extern“C”声明后编译器才会将extern“C”声明的内容通过C语言的方式进行编译。

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

for(i=0;i<N;i++)
{if(condition)DoSomething();elseDoOtherthing();
}

标准答案:
优点:程序简洁
缺点:多执行了N-1次逻辑判断,并且打断了循环“流水线”作业,使得编译器不能对循环进行优化处理,降低了效率。
我的答案:
优点:代码量较少
缺点:循环体每进行一次,if,else就会进行一次重复的条件判断,造成资源浪费。
第二个:

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");print(str);
}

请问运行Test函数会有怎样的结果?
标准答案:
答:程序崩溃。因为GetMemory并不能传递动态内存,Test函数中的str一直都是NULL。strcpy(str,“helloworld”);将使程序崩溃。
我的答案:
答:会造成程序崩溃,因为函数GetMemory并没有真正的将str指针的地址传过去,str仍然是空指针,直接对空指针进行操作会造成程序崩溃。

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

请问运行Test函数会有怎样的结果?
标准答案:
答:可能是乱码。因为GetMemory返回的是指向“栈内存”的指针,该指针的地址不是NULL,但其原现的内容已经被清除,新内容不可知。
我的答案:
答:会造成非法访问。函数结束后,p指针所在内存已经被释放,不能再对其指针的内容进行访问。

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

请问运行Test函数会有怎样的结果?
标准答案:
答:(1)能够输出hello(2)内存泄漏
我的答案:
答:会造成内存泄漏,因为malloc之后没有进行free。

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

请问运行Test函数会有怎样的结果?
标准答案:
答:篡改动态内存区的内容,后果难以预料,非常危险。因为free(str);之后,str成为野指针,if(str!=NULL)语句不起作用。
我的答案:
答:会造成非法访问,free之后,str指针所指的空间已被释放,不能再对其进行访问。而free之后str本身不会变成NULL。

五、编写strcpy函数(10分)已知strcpy函数的原型是charstrcpy(charstrDest,const char*strSrc);其中strDest是目的字符串,strSrc是源字符串。
(1)不调用C++/C的字符串库函数,请编写函数strcpy
标准答案:

char*strcpy(char*strDest,constchar*strSrc);
{assert((strDest!=NULL)&&(strSrc!=NULL));//2分char*address=strDest;//2分while((*strDest++=*strSrc++)!=‘\0’)//2分NULL;returnaddress;//2分}

我的答案:
答:

char* my_strcpy(char*strDest,const char*strSrc)
{assert(strDest&&strSrc);char* p=strDest;while(*strDest++=*strSrc++){;}return p;
}

(2)strcpy能把strSrc的内容复制到strDest,为什么还要char*类型的返回值?
标准答案:
答:为了实现链式表达式。例如intlength=strlen(strcpy(strDest,“helloworld”));
我的答案:
答:函数返回的是源字符串的首地址。这是为了防止strSrc的首地址再后续中还会被其他函数调用。

六、编写类String的构造函数、析构函数和赋值函数(25分)
已知类String的原型为:

classString
{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::~String(void)//3分
{delete [] m_data;//由于m_data是内部数据类型,也可以写成delete m_data;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我的答案:
因为还没开始对C++进行系统性学习,这里做得一塌糊涂……就不贴出来献丑了……

总结

这套题考查的是基本编程能力……但是最后得分很尴尬,如果是“有人情味”大学老师,些许能给个“60分万岁”。但如果稍微严厉一点就肯定不及格。而且其中内存那一块的题还是上C语言视频课时老师讲的原题。
看来路还很长……学无止境……
不过要是没有这2个月的学习,这套题我能拿到的分数估计只有个位数……都不知道我这4年的Qt工作是怎么做下来的……

对于考卷一些内容对ChatAI的提问:
问:const floatEPSINON=0.00001;
答:
这行代码定义了一个名为 EPSINON 的浮点型常量,并将其赋值为 0.00001。常量使用 const 关键字来修饰,以指出它们的值不能被修改。在这个例子中,我们定义了一个用于比较两个浮点数是否相等的精度值,也可以理解为一个允许的误差范围(即在这个误差范围内,可以认为两个浮点数相等)。在很多需要进行浮点数比较的算法中,通常会定义一个这样的常量,以确保比较的正确性和精度。

问:delete [] m_data;和delete m_data;的区别
答:
在 C++ 中,当我们利用 new 操作符动态分配内存以后,就需要利用 delete 操作符来释放这些内存,以免出现内存泄漏。delete 操作符有两种形式,即:

  • delete:用于释放单个对象所占用的内存。
  • delete[]:用于释放数组所占用的内存。

它们的区别在于,delete 释放一个单独的对象所占用的内存,而 delete[] 释放数组中的所有元素所占用的内存,包括数组对象本身。如果你使用 delete 来释放数组内存,则可能会造成内存泄漏,因为它只会释放数组对象本身的内存,而不会释放数组元素的内存,这就会导致内存泄漏。

假设你在动态分配内存时使用了 new[] 操作符,那么就应该使用 delete[] 来释放这段内存,否则会导致内存泄漏和未定义的行为。而在使用 new 来动态分配单个对象的内存时,则需要使用 delete 来释放这段内存。

在具体实现中,delete[] 操作符在释放数组时,会遍历数组的所有元素,并逐个调用元素的析构函数,然后再释放内存。而 delete 操作符只会调用单个对象的析构函数,并释放该对象的内存。因此,在释放动态分配的数组内存时,我们需要使用 delete[] 操作符,而不是 delete 操作符。

最后贴上该书作者写在导读的话:
首先请做附录B的C++/C试题(不要看答案),考查自己的编程质量究竟如何。然后参照答案严格打分。(1)如果你只得了几十分,请不要声张,也不要太难过。编程质量差往往是由于不良习惯造成的,与人的智力、能力没有多大关系,还是有药可救的。成绩越差,可以进步的空间就越大,中国不就是在落后中赶超发达资本主义国家吗?只要你能下决心改掉不良的编程习惯,第二次考试就能及格了。(2)如果你考及格了,表明你的技术基础不错,希望你能虚心学习、不断进步。如果你还没有找到合适的工作单位,不妨到上海贝尔试一试。(3)如果你考出85分以上的好成绩,你有义务和资格为你所在的团队作“C++/C编程”培训。希望你能和我们多多交流、相互促进。半年前我曾经发现一颗好苗子,就把他挖到我们小组来。(4)如果你在没有任何提示的情况下考了满分,希望你能收我做你的徒弟。


http://www.ppmy.cn/news/238290.html

相关文章

关于富斯遥控器5号电池改锂电的问题探究

富斯遥控器原本是4节5号电池串联来给电路供电的&#xff0c;每节5号电池1.5V&#xff0c;一共6V。而这款遥控器十分费电&#xff0c;用不了多久就要买新电池&#xff0c;广大模友为了保护环境和自己的钱包&#xff0c;选择了干电池改锂电池这个方法。 拧下遥控器背板的4颗螺丝…

锂电池生产全过程图解

锂电池大致可分为两类&#xff1a;锂金属电池和锂离子电池。锂离子电池不含有金属态的锂&#xff0c;并且是可以充电的。 我们所熟知的特斯拉电动汽车便是用的18650锂离子电池通过串并联组成的电池板。随着新能源汽车日渐火爆&#xff0c;动力电池行业也变得炙手可热&#xff…

国产芯片加持!可拆卸电池手机杀回来了!

‍ ‍ 想必诺基亚这个品牌大家都很熟悉&#xff0c;毕竟在十年前可是人手一台的手机&#xff0c;就是这几年智能手机发展过于迅速&#xff0c;诺基亚在市场的占比份额明显的变少&#xff0c;甚至很多人都没有听说过这个品牌很久了。但其实&#xff0c;诺基亚也是一直在进行创新…

如何保护Angular应用?这篇文章告诉你答案!

Angular应用现在很火&#xff0c;但它的安全问题尤为突出。因为开发者不仅要保护应用程序&#xff0c;还要保护到服务器连接。本文将告诉您如何保证Angular应用的安全&#xff0c;以及如何避免应用中的潜在漏洞。 PS&#xff1a;给大家推荐一个实用组件~Kendo UI for Angular是…

AS4120原厂单节 2A 开关型锂离子电池充电芯片

概述&#xff1a;泛海微AS4120是一款面向5V供电输出高达2A锂离子电池充电芯片。它是采用1.5MHz固定频率的同步降压型转换器&#xff0c;因此具有高达90%以上的充电效率&#xff0c;自身发热量极小。芯片包括完整的充电终止电路、自动再充电和一个精确度达1%的4.2V/4.35V预设充电…

锂离子电池种类介绍和分类

因为&#xff0c;很多人对锂电池和锂离子电池的不甚理解和头疼于目前国内外的诸多种类&#xff0c;所以&#xff0c;博主接下来主要介绍他们区别和各种分类以及依据。本来准备在写python处理数据的时候再谈&#xff08;或者说是处理电池数据时&#xff09;&#xff0c;但聊聊吧…

强推USB-C统一后,欧盟再出手:手机或重回可拆卸电池时代

出品 | 电脑报&#xff08;ID&#xff1a;CQCPCW&#xff09; 已获得原公众号的授权转载 为提升机身内部空间利用率&#xff0c;从而利于机身轻薄化设计&#xff0c;手机电池早已设计成不可更换&#xff0c;但很会“整活”的欧盟修订了一则新法案&#xff0c;该法案旨在提高电池…