C++笔试题(十三)上海聚力传媒技术有限公司成立于2005年5月,是家新冒出来的公司,而他能够冒出来的原因是由于它的电视直播软件PPLIVE()抢占了基于P2P技术的网络视讯服务的先机,超级女生电视节目的火爆成就了PPLIVE软件这款软件,不过现在这个领域的竞争者蜂拥而上,日子并不轻松。如果是我,我会很慎重的考虑这类新兴小公司的,当然我还是很佩服它的,公司的创始人是华中科技大学的校友,有幸见过他的演讲。下面是它2005年度的官方VC笔试题,他称:如有自信2小时能做完的应聘者请将做完答案发mail至campus_hr@synacast.com,我们会马上和你联系的。呵呵,我并不打算把答案发到这个邮箱去。一、问答1、实模式与保护模式。为什么要设计这两种模式?好处在什么地方?分别写出各自寻址的过程。答:1.实模式,又叫实地址模式,CPU完全按照8086的实际寻址方法访问从00000h--FFFFFh(1MB大小)的地址范围的内存,在这种模式下,CPU只能做单任务运行;寻址公式为:物理地址=左移4位的段地址+偏移地址,即:物理地址是由16位的段地址和16位的段内偏移地址组成的。2.保护模式,又叫内存保护模式,寻址采用32位段和偏移量,最大寻址空间4GB,在这种模式下,系统运行于多任务,设计这种模式的原因和好处是:保护模式增加了寻址空间,增加了对多任务的支持,增加了段页式寻址机制的内存管理(分段机制使得段具有访问权限和特权级,各应用程序和操作系统的代码和核心是被保护的,这也是多任务支持的实现关键和保护这个名字的由来)。寻址过程为:物理地址=由段地址查询全局描述符表中给出的段基址+偏移地址,即:物理地址由影像寄存器中的基址加上16位或者32位的偏移组成。2、请阅读以下一段程序,并给出答案。classA{public:A(){doSth();}virtualvoiddoSth(){printf(IamA);}};classB:publicA{public:virtualvoiddoSth(){printf(IamB);}};Bb;执行结果是什么?为什么?答:执行结果是IamA因为b对象构造时调用基类A的构造函数A(),得此结果。3、在STL的应用中map这种key-value的应用很多,如果key的类型是GUID,该如何处理?答:谁知道怎么处理补上吧。4、一个内存变量a=5,有5个线程需要对其进行操作,其中3个对a进行加1操作,2个对a进行减1操作,为了保证能够得到正常结果6,需要使用什么方法?(列出越多越好)答:即要求列出线程同步方法,具体答案可见下面一题。5、描述并比较以下对象:事件,信标,临界区,互斥对象。答:这些对象都是用于线程同步的对象。临界区:一种保证在某一时刻只有一个线程能访问数据的简便办法。它只可以在同一进程内部使用。主要API函数有,产生临界区:InitializeCriticalSection,删除临界区:DeleteCriticalSection,进入临界区:EnterCriticalSection,退出临界区:LeaveCriticalSection。互斥对象:互斥对象跟临界区相似,但它不仅仅能够在同一应用程序不同线程中实现资源的安全共享,而且可以在不同应用程序的线程之间实现对资源的安全共享,当然下面两者也有这个特点。主要API函数有,创建互斥量:CreateMutex,打开一个存在的互斥量:OpenMutex,释放互斥量的使用权:ReleaseMutex,关闭互斥量:CloseHandle。信标:使用信号量(信标)最重要用途是:信号允许多个线程同时使用共享资源,它指出了同时访问共享资源的线程最大数目。它的API函数和使用方法都与互斥对象相似,如创建信号灯:CreateSemaphore,传入的参数可以指定信号灯的初始值。事件:用来通知其他进程/线程某件操作已经完成。API函数有创建,打开事件对象等,特殊点的是可以用函数SetEvent人工设置事件为有无信号状态,因此创建事件对象时可以有两种方式,一种为自动重置,一种为人工重置。只有人工重置方式创建的事件对象才能正确使用函数SetEvent。鉴于本套题考的是VC,有必要说明的是在MFC中对于各种同步对象都提供了相对应的类CCtiticalSection,CMutex,CSemaphore,CEvent,另外为使用等待功能封装了两个类:CSingleLock和CMultiLock。这些类方便了使用这些同步对象。6、cdecl、stdcall、fastcall是什么?哪种可以实现个数不定的入口参数,为什么?答:三者都是函数调用的约定。cdecl:cdeclare(C调用约定)的缩写,是C和C++程序的缺省调用方式,规则是,按从右至左的顺序压参数入栈,由调用者把参数弹出栈,对于传送参数的内存栈是由调用者来维护的,正因为如此,只有这种调用方式可实现个数不定的入口参数(可变参数)。stdcall:是Pascal程序的缺省调用方式,规则是,按从右至左的顺序压参数入栈,被调用的函数在返回前清理传送参数的内存栈。上两者的主要区别是前者由调用者清理栈,后者由被调用的函清理栈。当然函数名的修饰部分也是不同的。fastcall:采用寄存器传递参数,特点就是快了。二、程序设计(以下题目请写出实现代码)1、有一段文本,统计其中的单词数。例如:Asatechnology,HailStormissonewthatitisstillonlyknownbyitscodename.注意:单词间的间隔不一定是一个空格。答:可执行程序代码如下,假设该文本已存入text这个数组里。voidmain(){chartext[1000]={Asatechnology,'HailStorm'issonewthatitisstillonlyknownbyitscodename.};inti=0,count=0;boolflag=false;//前面的字符是否为字母while(text[i]&&i1000){if(flag&&!((text[i]='a'&&text[i]='z')||(text[i]='A'&&text[i]='Z'))){//前面是字母,当前不是字母,表示出现一个单词flag=false;count++;}elseif(!flag&&((text[i]='a'&&text[i]='z')||(text[i]='A'&&text[i]='Z'))){//前面不是字母,当前是字母flag=true;}i++;}if(flag)count++;coutcount;}----------------------------------------------插播广告啦:版权所有:朱科欢迎光临我的网站:,各位转贴别删,劳动成果啊----------------------------------------------2、国际象棋有8×8格,每个格子可放一个棋子。皇后的规则是可以横、竖、斜移动。在一个棋盘放置8个皇后,并使它们互相无法威胁到彼此。答:以下是可执行C代码,采用非递归解法,你如果想了解皇后问题的算法的详细过程可看下面网址:不过下面的代码是以列优先进行试探的,不是上面网址介绍的那样以行优先的,当然本质是一样的。#includeiostream.h#defineQUEEN8//皇后数量intqueen[QUEEN];//下标代表所在列号,值代表所在行号,//如queen[1]=2表示第1列第2行有个皇后boolrow_YN[QUEEN];//棋局的每一行是否有棋,有则为1,无为0;boolpassive_YN[2*QUEEN-1];//斜率为1的斜线方向上是否有棋,共有2*QUEEN-1个斜线boolnegative_YN[2*QUEEN-1];//斜率为负1的斜线方向上是否有棋//用全局变量,因全局数组元素值自动为0intmain(){introw=0;//游标,当前移动的棋子(以列计)boolflag=false;//当前棋子位置是否合法queen[0]=-1;//第0列棋子准备,因一开始移动的就是第0列棋子intcount=0;//一共有多少种解法的计数器;while(row=0)//跳出条件是回溯到无法回溯时{queen[row]++;//row列上的皇后走到下一行试试if(queen[row]=QUEEN)//当前列全部走完{queen[row]=-1;//当前列棋子置于准备状态row--;//回溯到上一列的棋子if(row=0)//回溯时要清理如下行,斜线的标志位{row_YN[queen[row]]=false;passive_YN[queen[row]+row]=false;negative_YN[QUEEN-1+row-queen[row]]=false;}}else{//先判断棋子所在行没有棋子if(row_YN[queen[row]]==false){flag=true;//以下检查当前棋子是否与之前的棋子斜线相交if(passive_YN[queen[row]+row]==true||negative_YN[QUEEN-1+row-queen[row]]==true)flag=false;elseflag=true;if(flag)//flag为真表示位置合法{if(row==QUEEN-1)//列到达最后,即最后一个皇后也找到位置,输出解{count++;//解法的数目加一;cout***第count种解法***endl;for(inti=0;iQUEEN;i++)cout第i列皇后在第queen[i]行endl;}row_YN[queen[row]]=true;//当前行设为有棋子passive_YN[queen[row]+row]=true;//当前行正斜率方向有棋子negative_YN[QUEEN-1+row-queen[row]]=true;//当前行负斜率方向上也有棋子row++;if(row=QUEEN){//找到解后再次回溯找另外的解,这同上面无解回溯是一样的row--;row_YN[queen[row]]=false;passive_YN[queen[row]+row]=false;negative_YN[QUEEN-1+row-queen[row]]=false;//原理同回溯}flag=false;}}}}coutQUEEN皇后问题一共有count种解法endl;return0;}3、输入二个64位的十进制数,计算相乘之后的乘积。答:以下代码为网上别人贴出的,输入任意位数十进制数(包括小数,负数)都可以得出正确结果。思路是:将大数当作字符串进行处理,也就是将大数用10进制字符数组进行表示,然后模拟人们手工进行“竖式计算”的过程编写乘法。#includeiostream.h#defineMAX100intstr_num(charstr[])//计算字符串的长度,等效于strlen(str);{inti=0,num_str=0;while(str[i]!=0){num_str++;i++;}return(num_str);}voidplace(intnum_str,charstr[])//将字符串高低颠倒。{inttemp=0,i=0,j=0;for(i=0,j=num_str-1;ij;i++,j--){temp=str[j];str[j]=str[i];str[i]=temp;}}voidtransition(unsignedinta[],charstr1[])//数字字符转化为数字。{inti=0;while(str1[i]!=0){a[i]=str1[i]-'0';i