if(addr[i]==narry[sum-kk])cout<return0;}1、找错
Voidtest1(){
charstring[10];
char*str1=\"01234567\";
strcpy(string,str1);//溢出,应该包括一个存放'\\0'的字符string[11]}
Voidtest2(){
charstring[10],str1[10];for(I=0;I<10;I++){
str1[i]='a';}
strcpy(string,str1);//I,i没有声明。}
Voidtest3(char*str1){
charstring[10];
if(strlen(str1)<=10)//改成<10,字符溢出,将strlen改为sizeof也可以{
strcpy(string,str1);}}
2.
voidg(int**);intmain(){
intline[10],i;
int*p=line;//p是地址的地址for(i=0;i<10;i++){
*p=i;
g(&p);//数组对应的值加1}
for(i=0;i<10;i++)printf(\"%d\\n\return0;}
voidg(int**p){
(**p)++;
(*p)++;//无效}
输出:123456710
3.写出程序运行结果intsum(inta){
autointc=0;staticintb=3;c+=1;b+=2;
return(a+b+c);}
voidmain(){intI;inta=2;
for(I=0;I<5;I++)
{
printf(\"%d,\sum(a));}}
//static会保存上次结果,记住这一点,剩下的自己写输出:8,10,12,14,16,
4.
intfunc(inta){
intb;switch(a){
case1:30;case2:20;case3:16;default:0}
returnb;}
则func(1)=?
//b定义后就没有赋值。
5:
inta[3];
a[0]=0;a[1]=1;a[2]=2;int*p,*q;p=a;
q=&a[2];
则a[q-p]=a[2]
解释:指针一次移动一个int但计数为1
今天早上的面试题9道,比较难,向牛人请教,国内的一牛公司,坐落在北京北四环某大厦:
1、线形表a、b为两个有序升序的线形表,编写一程序,使两个有序线形表合并成一个有序升序线形表h;
答案在请化大学严锐敏《数据结构第二版》第二章例题,数据结构当中,这个叫做:两路归并排序
Linklist*unio(Linklist*p,Linklist*q){linklist*R,*pa,*qa,*ra;pa=p;qa=q;
R=ra=p;
while(pa->next!=NULL&&qa->next!=NULL){if(pa->data>qa->data){ra->next=qa;qa=qa->next;}else{
ra->next=pa;pa=pa->next;}}
if(pa->next!=NULL)ra->next=pa;
if(qa->next!=NULL)ra->next==qa;returnR;}
2、运用四色定理,为N个局域举行配色,颜色为1、2、3、4四种,另有数组adj[][N],如adj[i][j]=1则表示i区域与j区域相邻,数组color[N],如color[i]=1,表示i区域的颜色为1号颜色。四色填充
3、用递归算法判断数组a[N]是否为一个递增数组。
递归的方法,记录当前最大的,并且判断当前的是否比这个还大,大则继续,否则返回false结束:
boolfun(inta[],intn){
if(n==1)returntrue;if(n==2)
returna[n-1]>=a[n-2];
returnfun(a,n-1)&&(a[n-1]>=a[n-2]);}
4、编写算法,从10亿个浮点数当中,选出其中最大的10000个。用外部排序,在《数据结构》书上有
《计算方法导论》在找到第n大的数的算法上加工5、编写一unix程序,防止僵尸进程的出现.
Top
回复人:free131(白日?做梦!)()信誉:1002006-4-1710:17:34得
分:0
?
同学的4道面试题,应聘的职位是搜索引擎工程师,后两道超级难,(希望大家多给一些算发)
1.给两个数组和他们的大小,还有一动态开辟的内存,求交集,把交集放到动态内存dongtai,并且返回交集个数
longjiaoji(long*a[],longb[],long*alength,longblength,long*dongtai[])
2.单连表的建立,把'a'--'z'26个字母插入到连表中,并且倒叙,还要打印!方法1:
typedefstructval{intdate_1;structval*next;}*p;
voidmain(void){charc;
for(c=122;c>=97;c--){p.date=c;p=p->next;}
p.next=NULL;}}
方法2:
node*p=NULL;node*q=NULL;
node*head=(node*)malloc(sizeof(node));head->data='';head->next=NULL;
node*first=(node*)malloc(sizeof(node));
first->data='a';first->next=NULL;head->next=first;p=first;
intlongth='z'-'b';inti=0;
while(i<=longth)
{
node*temp=(node*)malloc(sizeof(node));
temp->data='b'+i;temp->next=NULL;q=temp;head->next=temp;temp->next=p;p=q;i++;}
print(head);
3.可怕的题目终于来了
象搜索的输入信息是一个字符串,统计300万输入信息中的最热门的前十条,我们每次输入的一个字符串为不超过255byte,内存使用只有1G,请描述思想,写出算发(c语言),空间和时间复杂度,
4.国内的一些帖吧,如baidu,有几十万个主题,假设每一个主题都有上亿的跟帖子,怎么样设计这个系统速度最好,请描述思想,写出算发(c语言),空间和时间复杂度,
#includestring.hmain(void)
{char*src=\"hello,world\";char*dest=NULL;
dest=(char*)malloc(strlen(src));intlen=strlen(str);char*d=dest;char*s=src[len];while(len--!=0)d++=s--;
printf(\"%s\}
找出错误!!
#include\"string.h\"#include\"stdio.h\"#include\"malloc.h\"main(void){
char*src=\"hello,world\";char*dest=NULL;
dest=(char*)malloc(sizeof(char)*(strlen(src)+1));intlen=strlen(src);char*d=dest;
char*s=src+len-1;while(len--!=0)
*d++=*s--;*d='\\0';
printf(\"%s\}
1.简述一个Linux驱动程序的主要流程与功能。
2.请列举一个软件中时间换空间或者空间换时间的例子。voidswap(inta,intb){
intc;c=a;a=b;b=a;}
--->空优
voidswap(inta,intb){
a=a+b;b=a-b;a=a-b;}
6.请问一下程序将输出什么结果?char*RetMenory(void){
charp[]=“hellowworld”;returnp;}
voidTest(void){
char*str=NULL;str=RetMemory();printf(str);}
RetMenory执行完毕,p资源被回收,指向未知地址。返回地址,str的内容应是不可预测的,打印的应该是str的地址
写一个函数,它的原形是intcontinumax(char*outputstr,char*intputstr)功能:
在字符串中找出连续最长的数字串,并把这个串的长度返回,并把这个最长数字串付给其中一个函数参数outputstr所指内存。例如:\"abcd12345ed125ss1234567\"的首地址传给intputstr后,函数将返回
9,outputstr所指的值为1234567
intcontinumax(char*outputstr,char*inputstr){
char*in=inputstr,*out=outputstr,*temp,*final;
intcount=0,maxlen=0;
while(*in!='\\0'){
if(*in>47&&*in<58){
for(temp=in;*in>47&&*in<58;in++)count++;}elsein++;
if(maxlenmaxlen=count;count=0;final=temp;}}for(inti=0;i*out=*final;out++;final++;}*out='\\0';returnmaxlen;}
不用库函数,用C语言实现将一整型数字转化为字符串方法1:
intgetlen(char*s){intn;
for(n=0;*s!='\\0';s++)n++;returnn;}
voidreverse(chars[]){
intc,i,j;
for(i=0,j=getlen(s)-1;i}}voiditoa(intn,chars[]){
inti,sign;
if((sign=n)<0)n=-n;i=0;
do{/*以反序生成数字*/
s[i++]=n%10+'0';/*getnextnumber*/}while((n/=10)>0);/*deletethenumber*/if(sign<0)s[i++]='-';
s[i]='\\0';reverse(s);}
方法2:
#includeusingnamespacestd;voiditochar(intnum);voiditochar(intnum){inti=0;intj;
charstra[10];charstrb[10];while(num){
stra[i++]=num%10+48;num=num/10;}
stra[i]='\\0';
for(j=0;jstrb[j]=stra[i-j-1];}
strb[j]='\\0';
cout<intmain(){intnum;cin>>num;itochar(num);return0;}
前几天面试,有一题想不明白,请教大家!typedefstruct{
inta:2;intb:2;intc:1;}test;testt;t.a=1;t.b=3;t.c=1;
printf(\"%d\printf(\"%d\printf(\"%d\谢谢!
t.a为01,输出就是1t.b为11,输出就是-1t.c为1,输出也是-1
3个都是有符号数int嘛。这是位扩展问题01111
编译器进行符号扩展
求组合数:求n个数(1....n)中k个数的组合....如:combination(5,3)
要求输出:3,2,1,532,531,521,432,431,421,321,#includeintpop(int*);intpush(int);voidcombination(int,int);intstack[3]={0};top=-1;
intmain(){
intn,m;
printf(\"Inputtwonumbers:\\n\");
while((2!=scanf(\"%d%*c%d\){
fflush(stdin);
printf(\"Inputerror!Again:\\n\");}
combination(n,m);printf(\"\\n\");}
voidcombination(intm,intn){
inttemp=m;push(temp);while(1){
if(1==temp){
if(pop(&temp)&&stack[0]==n)//当栈底元素弹出&&为可能取的最小值,循环退出break;}
elseif(push(--temp)){
printf(\"%d%d%d\pop(&temp);}}}
intpush(inti){
stack[++top]=i;if(top<2)return0;else
return1;}
intpop(int*i){
*i=stack[top--];if(top>=0)return0;else
return1;}
1、用指针的方法,将字符串“ABCD1234efgh”前后对调显示#include#include#includeintmain(){charstr[]=\"ABCD1234efgh\";intlength=strlen(str);char*p1=str;
char*p2=str+length-1;while(p1charc=*p1;*p1=*p2;*p2=c;++p1;--p2;}printf(\"strnowis%s\\n\system(\"pause\");return0;}
2、有一分数序列:1/2,1/4,1/6,1/8……,用函数调用的方法,求此数列前20项的和
#includedoublegetValue(){doubleresult=0;inti=2;
while(i<42){
result+=1.0/i;//一定要使用1.0做除数,不能用1,否则结果将自动转化成整数,即0.000000i+=2;}
returnresult;}
intmain(){
printf(\"resultis%f\\n\getValue());system(\"pause\");return0;}
Top
回复人:free131(白日?做梦!)()信誉:1002006-4-1710:18:33得分:0
?
有一个数组a[1000]存放0--1000;要求每隔二个数删掉一个数,到末尾时循环至开头继续进行,求最后一个被删掉的数的原始下标位置。以7个数为例:
{0,1,2,3,4,5,6,7}0-->1-->2(删除)-->3-->4-->5(删除)-->6-->7-->0(删除),如此循环直到最后一个数被删除。方法1:数组
#includeusingnamespacestd;#definenull1000intmain(){
intarr[1000];
for(inti=0;i<1000;++i)arr[i]=i;intj=0;
intcount=0;
while(count<999){
while(arr[j%1000]==null)j=(++j)%1000;j=(++j)%1000;
while(arr[j%1000]==null)j=(++j)%1000;j=(++j)%1000;
while(arr[j%1000]==null)j=(++j)%1000;arr[j]=null;++count;}
while(arr[j]==null)j=(++j)%1000;
cout<#includeusingnamespacestd;#definenull0structnode{intdata;node*next;};
intmain(){
node*head=newnode;head->data=0;head->next=null;node*p=head;
for(inti=1;i<1000;i++){
node*tmp=newnode;tmp->data=i;tmp->next=null;head->next=tmp;head=head->next;}
head->next=p;while(p!=p->next){
p->next->next=p->next->next->next;p=p->next->next;}
cout<data;return0;}
方法3:通用算法#include#defineMAXLINE1000//元素个数/*
MAXLINE元素个数a[]元素数组R[]指针场suffix下标
index返回最后的下标序号
values返回最后的下标对应的值start从第几个开始K间隔*/
intfind_n(inta[],intR[],intK,int&index,int&values,ints=0){intsuffix;
intfront_node,current_node;suffix=0;if(s==0){
current_node=0;
front_node=MAXLINE-1;}
else{
current_node=s;front_node=s-1;}
while(R[front_node]!=front_node){printf(\"%d\\n\R[front_node]=R[current_node];if(K==1){
current_node=R[front_node];continue;}
for(inti=0;ifront_node=R[front_node];}current_node=R[front_node];}
index=front_node;values=a[front_node];return0;}
intmain(void){
inta[MAXLINE],R[MAXLINE],suffix,index,values,start,i,K;suffix=index=values=start=0;K=2;
for(i=0;iR[i-1]=0;find_n(a,R,K,index,values,2);
printf(\"thevalueis%d,%d\\n\return0;}
试题:
voidtest2(){
charstring[10],str1[10];inti;
for(i=0;i<10;i++){
str1[i]='a';}
strcpy(string,str1);}
解答:对试题2,如果面试者指出字符数组str1不能在数组内结束可以给3分;如果面试者指出strcpy(string,str1)调用使得从str1内存起复制到string内存起所复制的字节数具有不确定性可以给7分,在此基础上指出库函数strcpy工作方式的给10分;
str1不能在数组内结束:因为str1的存储为:{a,a,a,a,a,a,a,a,a,a},没有'\\0'(字符串结束符),所以不能结束
strcpy(char*s1,char*s2)他的工作原理是,扫描s2指向的内存,逐个字符付到s1所指向的内存,直到碰到'\\0',因为str1结尾没有'\\0',所以具有不确定性,不知道他后面还会付什么东东。正确应如下voidtest2(){
charstring[10],str1[10];inti;
for(i=0;i<9;i++){
str1[i]='a'+i;//把abcdefghi赋值给字符数组}
str[i]='\\0';//加上结束符
strcpy(string,str1);}
第二个code题是实现strcmp
intStrCmp(constchar*str1,constchar*str2)做是做对了,没有抄搞,比较乱
intStrCmp(constchar*str1,constchar*str2){
assert(str1&&srt2);
while(*str1&&*str2&&*str1==*str2){str1++,str2++;}
if(*str1&&*str2)return(*str1-*str2);
elseif(*str1&&*str2==0)return1;
elseif(*str1==0&&*str2)return-1;else
return0;}
intStrCmp(constchar*str1,constchar*str2){
//省略判断空指针(自己保证)
while(*str1&&*str1++==*str2++);return*str1-*str2;}
第三个code题是实现子串定位
intFindSubStr(constchar*MainStr,constchar*SubStr)做是做对了,没有抄搞,比较乱
intMyStrstr(constchar*MainStr,constchar*SubStr){
constchar*p;constchar*q;
constchar*u=MainStr;
//assert((MainStr!=NULL)&&(SubStr!=NULL));//用断言对输入进行判断
while(*MainStr)//内部进行递增{
p=MainStr;q=SubStr;
while(*q&&*p&&*p++==*q++);
if(!*q){
returnMainStr-u+1;//MainStr指向当前起始位,u指向}
MainStr++;}
return-1;}
分析:
intarr[]={6,7,8,9,10};int*ptr=arr;*(ptr++)+=123;
printf(“%d%d”,*ptr,*(++ptr));输出:88
过程:对于*(ptr++)+=123;先做加法6+123,然后++,指针指向7;对于printf(“%d%d”,*ptr,*(++ptr));从后往前执行,指针先++,指向8,然后输出8,紧接着再输出8
华为全套完整试题高级题
6、已知一个单向链表的头,请写出删除其某一个结点的算法,要求,先找到此结点,然后删除。slnodetype*Delete(slnodetype*Head,intkey){}中if(Head->number==key){
Head=Pointer->next;free(Pointer);break;}
Back=Pointer;
Pointer=Pointer->next;if(Pointer->number==key){
Back->next=Pointer->next;free(Pointer);break;}
voiddelete(Node*p){
if(Head=Node)while(p)}
有一个16位的整数,每4位为一个数,写函数求他们的和。解释:
整数1101010110110111和1101+0101+1011+0111
感觉应该不难,当时对题理解的不是很清楚,所以写了一个函数,也不知道对不对。疑问:
既然是16位的整数,1101010110110111是2进制的,那么函数参数怎么定义呢,请大虾指教。
答案:用十进制做参数,计算时按二进制考虑。
/*n就是16位的数,函数返回它的四个部分之和*/charSumOfQuaters(unsignedshortn){
charc=0;inti=4;do{
c+=n&15;n=n>>4;}while(--i);returnc;}
有1,2,....一直到n的无序数组,求排序算法,并且要求时间复杂度为O(n),空间复杂度O(1),使用交换,而且一次只能交换两个数.(华为)#includeint{intintintmain()
a[]={10,6,9,5,2,8,4,7,1,3};len=sizeof(a)/sizeof(int);temp;
for(inti=0;itemp=a[a[i]-1];a[a[i]-1]=a[i];a[i]=temp;if(a[i]==i+1)i++;}
for(intj=0;j(慧通)1写出程序把一个链表中的接点顺序倒排typedefstructlinknode{
intdata;
structlinknode*next;}node;
//将一个链表逆置
node*reverse(node*head){
node*p,*q,*r;p=head;q=p->next;while(q!=NULL){
r=q->next;q->next=p;p=q;q=r;}
head->next=NULL;head=p;
returnhead;}
2写出程序删除链表中的所有接点voiddel_all(node*head){
node*p;
while(head!=NULL){
p=head->next;free(head);head=p;}
cout<<\"释放空间成功!\"<}3两个字符串,s,t;把t字符串插入到s字符串中,s字符串有足够的空间存放t字符串
voidinsert(char*s,char*t,inti){
char*q=t;char*p=s;
if(q==NULL)return;while(*p!='\\0'){
p++;}
while(*q!=0){
*p=*q;p++;q++;}
*p='\\0';}
分析下面的代码:char*a=\"hello\";char*b=\"hello\";if(a==b)
printf(\"YES\");else
printf(\"NO\");
这个简单的面试题目,我选输出no(对比的应该是指针地址吧),可在VC是YES在C是NO
lz的呢,是一个常量字符串。位于静态存储区,它在程序生命期内恒定不变。如果编译器优化的话,会有可能a和b同时指向同一个hello的。则地址相同。如果编译器没有优化,那么就是两个不同的地址,则不同
写一个函数,功能:完成内存之间的拷贝memcpysourcecode:
270void*memcpy(void*dst,constvoid*src,unsignedintlen)271{
272registerchar*d;273registerchar*s;27
275if(len==0)276returndst;
277
278if(is_overlap(dst,src,len,len))
279complain3(\"memcpy\dst,src,len);280
281if(dst>src){
282d=(char*)dst+len-1;283s=(char*)src+len-1;284while(len>=4){285*d--=*s--;286*d--=*s--;287*d--=*s--;288*d--=*s--;2len-=4;290}
291while(len--){292*d--=*s--;293}
294}elseif(dst=4){298*d++=*s++;299*d++=*s++;300*d++=*s++;301*d++=*s++;302len-=4;303}304while(len--){305*d++=*s++;306}307}
308returndst;309}
公司考试这种题目主要考你编写的代码是否考虑到各种情况,是否安全(不会溢出)
各种情况包括:
1、参数是指针,检查指针是否有效
2、检查复制的源目标和目的地是否为同一个,若为同一个,则直接跳出3、读写权限检查
4、安全检查,是否会溢出
memcpy拷贝一块内存,内存的大小你告诉它strcpy是字符串拷贝,遇到'\\0'结束
/*memcpy───拷贝不重叠的内存块*/
voidmemcpy(void*pvTo,void*pvFrom,size_tsize){
void*pbTo=(byte*)pvTo;
void*pbFrom=(byte*)pvFrom;
ASSERT(pvTo!=NULL&&pvFrom!=NULL);//检查输入指针的有效性
ASSERT(pbTo>=pbFrom+size||pbFrom>=pbTo+size);//检查两个指针指向的内存是否重叠while(size-->0)
*pbTo++==*pbFrom++;return(pvTo);}
华为面试题:怎么判断链表中是否有环?boolCircleInList(Link*pHead){
if(pHead==NULL||pHead->next==NULL)//无节点或只有一个节点并且无自环return(false);
if(pHead->next==pHead)//自环return(true);
Link*pTemp1=pHead;//step1
Link*pTemp=pHead->next;//step2
while(pTemp!=pTemp1&&pTemp!=NULL&&pTemp->next!=NULL){
pTemp1=pTemp1->next;
pTemp=pTemp->next->next;}
if(pTemp==pTemp1)return(true);return(false);}
两个字符串,s,t;把t字符串插入到s字符串中,s字符串有足够的空间存放t字符串
voidinsert(char*s,char*t,inti){
memcpy(&s[strlen(t)+i],&s[i],strlen(s)-i);memcpy(&s[i],t,strlen(t));s[strlen(s)+strlen(t)]='\\0';}
1。编写一个C函数,该函数在一个字符串中找到可能的最长的子字符串,且该字符串是由同一字符组成的。
char*search(char*cpSource,charch){
char*cpTemp=NULL,*cpDest=NULL;intiTemp,iCount=0;while(*cpSource){
if(*cpSource==ch){
iTemp=0;
cpTemp=cpSource;while(*cpSource==ch)++iTemp,++cpSource;if(iTemp>iCount)
iCount=iTemp,cpDest=cpTemp;if(!*cpSource)break;}
++cpSource;}
returncpDest;}
2。请编写一个C函数,该函数在给定的内存区域搜索给定的字符,并返回该字符所在位置索引值。
intsearch(char*cpSource,intn,charch){inti;
for(i=0;i一个单向链表,不知道头节点,一个指针指向其中的一个节点,问如何删除这个指针指向的节点?将这个指针指向的next节点值copy到本节点,将next指向next->next,并随后删除原next指向的节点。
#includevoidfoo(intm,intn){printf(\"m=%d,n=%d\\n\m,n);}
intmain(){
intb=3;
foo(b+=3,++b);printf(\"b=%d\\n\b);return0;}
输出:m=7,n=4,b=7(VC6.0)
这种方式和编译器中得函数调用关系相关即先后入栈顺序。不过不同编译器得处理不同。也是因为C标准中对这种方式说明为未定义,所以各个编译器厂商都有自己得理解,所以最后产生得结果完全不同。
因为这样,所以遇见这种函数,我们首先要考虑我们得编译器会如何处理这样得函数,其次看函数得调用方式,不同得调用方式,可能产生不同得结果。最后是看编译器优化。
2.写一函数,实现删除字符串str1中含有的字符串str2.
第二个就是利用一个KMP匹配算法找到str2然后删除(用链表实现的话,便捷于数组)
/*雅虎笔试题(字符串操作)
给定字符串A和B,输出A和B中的最大公共子串。比如A=\"aocdfe\"B=\"pmcdfa\"则输出\"cdf\"*/
//Author:azhen#include#include#includechar*commanstring(charshortstring[],charlongstring[]){
inti,j;
char*substring=malloc(256);
if(strstr(longstring,shortstring)!=NULL)//如果……,那么返回shortstring
returnshortstring;
for(i=strlen(shortstring)-1;i>0;i--)//否则,开始循环计算{
for(j=0;j<=strlen(shortstring)-i;j++){memcpy(substring,&shortstring[j],i);
substring[i]='\\0';
if(strstr(longstring,substring)!=NULL)returnsubstring;}}
returnNULL;}
main(){
char*str1=malloc(256);char*str2=malloc(256);char*comman=NULL;gets(str1);gets(str2);
if(strlen(str1)>strlen(str2))//将短的字符串放前面comman=commanstring(str2,str1);else
comman=commanstring(str1,str2);
printf(\"thelongestcommanstringis:%s\\n\comman);}
11.写一个函数比较两个字符串str1和str2的大小,若相等返回0,若str1大于
str2返回1,若str1小于str2返回-1
intstrcmp(constchar*src,constchar*dst){
intret=0;
while(!(ret=*(unsignedchar*)src-*(unsignedchar*)dst)&&*dst){
++src;++dst;}
if(ret<0)ret=-1;
elseif(ret>0)ret=1;
return(ret);
}
3,求1000!的未尾有几个0(用素数相乘的方法来做,如72=2*2*2*3*3);求出1->1000里,能被5整除的数的个数n1,能被25整除的数的个数n2,能被125整除的数的个数n3,能被625整除的数的个数n4.
1000!末尾的零的个数=n1+n2+n3+n4;#include#defineNUM1000intfind5(intnum){intret=0;
while(num%5==0){num/=5;ret++;}
returnret;}
intmain(){intresult=0;inti;
for(i=5;i<=NUM;i+=5){
result+=find5(i);}
printf(\"thetotalzeronumberis%d\\n\return0;}
1.有双向循环链表结点定义为:structnode{intdata;
structnode*front,*next;};
有两个双向循环链表A,B,知道其头指针为:pHeadA,pHeadB,请写一函数将两链表中data值相同的结点删除
BOOLDeteleNode(Node*pHeader,DataTypeValue){
if(pHeader==NULL)return;BOOLbRet=FALSE;
Node*pNode=pHead;while(pNode!=NULL){
if(pNode->data==Value){
if(pNode->front==NULL){
pHeader=pNode->next;pHeader->front=NULL;}else{
if(pNode->next!=NULL){
pNode->next->front=pNode->front;}
pNode->front->next=pNode->next;}
Node*pNextNode=pNode->next;deletepNode;
pNode=pNextNode;
bRet=TRUE;
//不要break或return,删除所有}else{
pNode=pNode->next;}}
returnbRet;}
voidDE(Node*pHeadA,Node*pHeadB){
if(pHeadA==NULL||pHeadB==NULL){
return;}
Node*pNode=pHeadA;while(pNode!=NULL)
{
if(DeteleNode(pHeadB,pNode->data)){
if(pNode->front==NULL){
pHeadA=pNode->next;pHeadA->front=NULL;}else{
pNode->front->next=pNode->next;if(pNode->next!=NULL){
pNode->next->front=pNode->front;}}
Node*pNextNode=pNode->next;deletepNode;
pNode=pNextNode;}else{
pNode=pNode->next;}}}
2.编程实现:找出两个字符串中最大公共子字符串,如\"abccade\的最大子串为\"cad\"
intGetCommon(char*s1,char*s2,char**r1,char**r2){
intlen1=strlen(s1);intlen2=strlen(s2);intmaxlen=0;
for(inti=0;ifor(intj=0;jif(s1[i]==s2[j]){intas=i,bs=j,count=1;
while(as+1if(count>maxlen){maxlen=count;*r1=s1+i;*r2=s2+j;}}}}
3.编程实现:把十进制数(long型)分别以二进制和十六进制形式输出,不能使用printf系列库函数char*test3(longnum){
char*buffer=(char*)malloc(11);buffer[0]='0';buffer[1]='x';buffer[10]='\\0';
char*temp=buffer+2;for(inti=0;i<8;i++){
temp[i]=(char)(num<<4*i>>28);
temp[i]=temp[i]>=0?temp[i]:temp[i]+16;
temp[i]=temp[i]<10?temp[i]+48:temp[i]+55;}
returnbuffer;}
输入N,打印N*N矩阵比如N=3,打印:1234765
N=4,打印:12341213145111615610987解答:
1#defineN15
ints[N][N];voidmain(){
intk=0,i=0,j=0;inta=1;
for(;k<(N+1)/2;k++){
while(jk-1)s[i][j--]=a++;i--;j++;while(i>k)s[i--][j]=a++;i++;j++;}for(i=0;ifor(j=0;j2defineMAX_N100intmatrix[MAX_N][MAX_N];
/*
*(x,y):第一个元素的坐标*start:第一个元素的值*n:矩阵的大小*/
voidSetMatrix(intx,inty,intstart,intn){inti,j;
if(n<=0)//递归结束条件return;
if(n==1){//矩阵大小为1时matrix[x][y]=start;return;}
for(i=x;ifor(j=y;jx;i--)//底部matrix[y+n-1][i]=start++;for(j=y+n-1;j>y;j--)//左部matrix[j][x]=start++;
SetMatrix(x+1,y+1,start,n-2);//递归}
voidmain(){inti,j;intn;
scanf(\"%d\&n);
SetMatrix(0,0,1,n);//打印螺旋矩阵
for(i=0;iprintf(\"%4d\matrix[i][j]);printf(\"\\n\");}}斐波拉契数列递归实现的方法如下:intFunct(intn){
if(n==0)return1;if(n==1)return1;
retrurnFunct(n-1)+Funct(n-2);}
请问,如何不使用递归,来实现上述函数?请教各位高手!
解答:intFunct(intn)//n为非负整数{
inta=0;intb=1;intc;
if(n==0)c=1;
elseif(n==1)c=1;
elsefor(inti=2;i<=n;i++)//应该n从2开始算起{
c=a+b;a=b;b=c;
}
returnc;}
解答:
现在大多数系统都是将低字位放在前面,而结构体中位域的申明一般是先声明高位。
100的二进制是001100100低位在前高位在后001----s3100----s2100----s1
所以结果应该是1
如果先申明的在低位则:001----s1100----s2100----s3结果是4
1、原题跟little-endian,big-endian没有关系
2、原题跟位域的存储空间分配有关,到底是从低字节分配还是从高字节分配,从DevC++和VC7.1上看,都是从低字节开始分配,并且连续分配,中间不空,不像谭的书那样会留空位
3、原题跟编译器有关,编译器在未用堆栈空间的默认值分配上有所不同,DevC++未用空间分配为
01110111b,VC7.1下为11001100b,所以在DevC++下的结果为5,在VC7.1下为1。
注:PC一般采用little-endian,即高高低低,但在网络传输上,一般采用big-endian,即高低低高,华为是做网络的,所以可能考虑big-endian模式,这样输出结果可能为4
判断一个字符串是不是回文
intIsReverseStr(char*aStr){
inti,j;
intfound=1;if(aStr==NULL)return-1;
j=strlen(aStr);for(i=0;iif(*(aStr+i)!=*(aStr+j-i-1)){found=0;
break;}
returnfound;}
Josephu问题为:设编号为1,2,…n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。
数组实现:
#include#includeintJosephu(intn,intm){intflag,i,j=0;
int*arr=(int*)malloc(n*sizeof(int));for(i=0;ifor(i=1;iflag=0;while(flagif(j==n)j=0;if(arr[j])++flag;++j;}arr[j-1]=0;
printf(\"第%4d个出局的人是:%4d号\\n\i,j);}
free(arr);returnj;}
intmain(){
intn,m;
scanf(\"%d%d\&n,&m);
printf(\"最后胜利的是%d号!\\n\Josephu(n,m));system(\"pause\");return0;}
链表实现:
#include#includetypedefstructNode{intindex;
structNode*next;}JosephuNode;
intJosephu(intn,intm){
inti,j;
JosephuNode*head,*tail;
head=tail=(JosephuNode*)malloc(sizeof(JosephuNode));for(i=1;itail->index=i;tail->next=(JosephuNode*)malloc(sizeof(JosephuNode));tail=tail->next;}
tail->index=i;tail->next=head;
for(i=1;tail!=head;++i){
for(j=1;jtail=head;head=head->next;}
tail->next=head->next;
printf(\"第%4d个出局的人是:%4d号\\n\i,head->index);free(head);
head=tail->next;}
i=head->index;free(head);returni;}
intmain(){
intn,m;
scanf(\"%d%d\&n,&m);
printf(\"最后胜利的是%d号!\\n\Josephu(n,m));system(\"pause\");return0;
}
已知strcpy函数的原型是:
char*strcpy(char*strDest,constchar*strSrc);1.不调用库函数,实现strcpy函数。2.解释为什么要返回char*。解说:
1.strcpy的实现代码
char*strcpy(char*strDest,constchar*strSrc){
if((strDest==NULL)||(strSrc==NULL))file://[/1]throw\"Invalidargument(s)\";//[2]
char*strDestCopy=strDest;file://[/3]
while((*strDest++=*strSrc++)!='\\0');file://[/4]returnstrDestCopy;}
错误的做法:[1]
(A)不检查指针的有效性,说明答题者不注重代码的健壮性。
(B)检查指针的有效性时使用((!strDest)||(!strSrc))或(!(strDest&&strSrc)),说明答题者对C语言中类型的隐式转换没有深刻认识。在本例中char*转换为bool即是类型隐式转换,这种功能虽然灵活,但更多的是导致出错概率增大和维护成本升高。所以C++专门增加了bool、true、false三个关键字以提供更安全的条件表达式。
(C)检查指针的有效性时使用((strDest==0)||(strSrc==0)),说明答题者不知道使用常量的好处。直接使用字面常量(如本例中的0)会减少程序的可维护性。0虽然简单,但程序中可能出现很多处对指针的检查,万一出现笔误,编译器不能发现,生成的程序内含逻辑错误,很难排除。而使用NULL代替0,如果出现拼写错误,编译器就会检查出来。[2]
(A)returnnewstring(\"Invalidargument(s)\");,说明答题者根本不知道返回值的用途,并且他对内存泄漏也没有警惕心。从函数中返回函数体内分配的内存是十分危险的做法,他把释放内存的义务抛给不知情的调用者,绝大多数情况下,调用者不会释放内存,这导致内存泄漏。
(B)return0;,说明答题者没有掌握异常机制。调用者有可能忘记检查返回值,调用者还可能无法检查返回值(见后面的链式表达式)。妄想让返回值肩负返回正确值和异常值的双重功能,其结果往往是两种功能都失效。应该以抛出异常来代替返回值,这样可以减轻调用者的负担、使错误不会被忽略、增强程序的可维护性。[3]
(A)忘记保存原始的strDest值,说明答题者逻辑思维不严密。[4]
(A)循环写成while(*strDest++=*strSrc++);,同[1](B)。
(B)循环写成while(*strSrc!='\\0')*strDest++=*strSrc++;,说明答
题者对边界条件的检查不力。循环体结束后,strDest字符串的末尾没有正确地加上'\\0'。
预处理器(Preprocessor)
1.用预处理指令#define声明一个常数,用以表明1年中有多少秒(忽略闰年问题)
#defineSECONDS_PER_YEAR(60*60*24*365)UL我在这想看到几件事情:
1).#define语法的基本知识(例如:不能以分号结束,括号的使用,等等)2).懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。
3).意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。
4).如果你在你的表达式中用到UL(表示无符号长整型),那么你有了一个好的起点。记住,第一印象很重要。
2.写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。
#defineMIN(A,B)((A)<=(B)(A):(B))这个测试是为下面的目的而设的:
1).标识#define在宏中应用的基本知识。这是很重要的,因为直到嵌入(inline)操作符变为标准C的一部分,宏是方便产生嵌入代码的唯一方法,对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。2).三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产生比if-then-else更优化的代码,了解这个用法是很重要的。3).懂得在宏中小心地把参数用括号括起来
4).我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什么事?
least=MIN(*p++,b);
3.预处理器标识#error的目的是什么?
如果你不知道答案,请看参考文献1。这问题对区分一个正常的伙计和一个书呆子是很有用的。只有书呆子才会读C语言课本的附录去找出象这种问题的答案。当然如果你不是在找一个书呆子,那么应试者最好希望自己不要知道答案。
死循环(Infiniteloops)
4.嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢?
这个问题用几个解决方案。我首选的方案是:while(1){}
一些程序员更喜欢如下方案:for(;;){}
这个实现方式让我为难,因为这个语法没有确切表达到底怎么回事。如果一个应试者给出这个作为方案,我将用这个作为一个机会去探究他们这样做的
基本原理。如果他们的基本答案是:“我被教着这样做,但从没有想到过为什么。”这会给我留下一个坏印象。第三个方案是用gotoLoop:...
gotoLoop;
应试者如给出上面的方案,这说明或者他是一个汇编语言程序员(这也许是好事)或者他是一个想进入新领域的BASIC/FORTRAN程序员。数据声明(Datadeclarations)
5.用变量a给出下面的定义a)一个整型数(Aninteger)
b)一个指向整型数的指针(Apointertoaninteger)
c)一个指向指针的的指针,它指向的指针是指向一个整型数(Apointertoapointertoaninteger)
d)一个有10个整型数的数组(Anarrayof10integers)
e)一个有10个指针的数组,该指针是指向一个整型数的(Anarrayof10pointerstointegers)
f)一个指向有10个整型数数组的指针(Apointertoanarrayof10integers)g)一个指向函数的指针,该函数有一个整型参数并返回一个整型数(Apointertoafunctionthattakesanintegerasanargumentandreturnsaninteger)h)一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数(Anarrayoftenpointerstofunctionsthattakeanintegerargumentandreturnaninteger)答案是:
a)inta;//Aninteger
b)int*a;//Apointertoaninteger
c)int**a;//Apointertoapointertoanintegerd)inta[10];//Anarrayof10integers
e)int*a[10];//Anarrayof10pointerstointegersf)int(*a)[10];//Apointertoanarrayof10integers
g)int(*a)(int);//Apointertoafunctionathattakesanintegerargumentandreturnsaninteger
h)int(*a[10])(int);//Anarrayof10pointerstofunctionsthattakeanintegerargumentandreturnaninteger
人们经常声称这里有几个问题是那种要翻一下书才能回答的问题,我同意这种说法。当我写这篇文章时,为了确定语法的正确性,我的确查了一下书。
但是当我被面试的时候,我期望被问到这个问题(或者相近的问题)。因为在被面试的这段时间里,我确定我知道这个问题的答案。应试者如果不知道
所有的答案(或至少大部分答案),那么也就没有为这次面试做准备,如果该面试者没有为这次面试做准备,那么他又能为什么出准备呢?
Static
6.关键字static的作用是什么?
这个简单的问题很少有人能回答完全。在C语言中,关键字static有三个明显的作用:
1).在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。
2).在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。3).在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被在声明它的模块的本地范围内使用。
大多数应试者能正确回答第一部分,一部分能正确回答第二部分,同是很少的人能懂得第三部分。这是一个应试者的严重的缺点,因为他显然不懂得本地化数据和代码范围的好处和重要性。
Const
7.关键字const是什么含意?
我只要一听到被面试者说:“const意味着常数”,我就知道我正在和一个业余者打交道。去年DanSaks已经在他的文章里完全概括了const的所有用法,因此ESP(译者:EmbeddedSystemsProgramming)的每一位读者应该非常熟悉const能做什么和不能做什么.如果你从没有读到那篇文章,只要能说出const意味着“只读”就可以了。尽管这个答案不是完全的答案,但我接受它作为一个正确的答案。(如果你想知道更详细的答案,仔细读一下Saks的文章吧。)如果应试
者能正确回答这个问题,我将问他一个附加的问题:下面的声明都是什么意思?constinta;intconsta;constint*a;int*consta;
intconst*aconst;
前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。如果应试者能正确回答这些问题,那么他就给我留下了一个好印象。顺带提一句,也许你可能会问,即使不用关键字const,也还是能很容易写出功能正确的程序,那么我为什么还要如此看重关键字const呢?我也如下的几下理由:
1).关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清理的。)
2).通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。
3).合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。Volatile
8.关键字volatile有什么含意并给出三个不同的例子。
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:
1).并行设备的硬件寄存器(如:状态寄存器)
2).一个中断服务子程序中会访问到的非自动变量(Non-automaticvariables)3).多线程应用中被几个任务共享的变量回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所用这些都要求volatile变量。不懂得volatile内容将会带来灾难。假设被面试者正确地回答了这是问题(嗯,怀疑这否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。1).一个参数既可以是const还可以是volatile吗?解释为什么。2).一个指针可以是volatile吗?解释为什么。3).下面的函数有什么错误:
intsquare(volatileint*ptr){
return*ptr**ptr;}
下面是答案:
1).是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。2).是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。
3).这段代码的有个恶作剧。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:intsquare(volatileint*ptr){
inta,b;a=*ptr;b=*ptr;returna*b;}
由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:longsquare(volatileint*ptr){
inta;a=*ptr;returna*a;}
位操作(Bitmanipulation)
9.嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量a,写两段代码,第一个设置a的bit3,第二个清除a的bit3。在以上两个操作中,要保持其它位不变。
对这个问题有三种基本的反应
1).不知道如何下手。该被面者从没做过任何嵌入式系统的工作。
2).用bitfields。Bitfields是被扔到C语言死角的东西,它保证你的代码在不同编译器之间是不可移植的,同时也保证了的你的代码是不可重用的。我最近不幸看到Infineon为其较复杂的通信芯片写的驱动程序,它用到了bitfields因此完全对我无用,因为我的编译器用其它的方式来实现bitfields的。从道德讲:永远不要让一个非嵌入式的家伙粘实际硬件的边。
3).用#defines和bitmasks操作。这是一个有极高可移植性的方法,是应该被用到的方法。最佳的解决方案如下:#defineBIT3(0x1<<3)staticinta;
voidset_bit3(void){
a|=BIT3;}
voidclear_bit3(void){
a&=~BIT3;}
一些人喜欢为设置和清除值而定义一个掩码同时定义一些说明常数,这也是可以接受的。我希望看到几个要点:说明常数、|=和&=~操作。
访问固定的内存位置(Accessingfixedmemorylocations)
10.嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。
这一问题测试你是否知道为了访问一绝对地址把一个整型数强制转换(typecast)为一指针是合法的。这一问题的实现方式随着个人风格不同而不同。典型的类似代码如下:int*ptr;
ptr=(int*)0x67a9;*ptr=0xaa55;
一个较晦涩的方法是:
*(int*const)(0x67a9)=0xaa55;
即使你的品味更接近第二种方案,但我建议你在面试时使用第一种方案。
中断(Interrupts)
11.中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准C支持中断。具代表事实是,产生了一个新的关键字__interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。
__interruptdoublecompute_area(doubleradius){
doublearea=PI*radius*radius;printf(\"Area=%f\area);returnarea;}
这个函数有太多的错误了,以至让人不知从何说起了:
1).ISR不能返回一个值。如果你不懂这个,那么你不会被雇用的。
2).ISR不能传递参数。如果你没有看到这一点,你被雇用的机会等同第一项。3).在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需要让额处的寄存器入栈,有些处理器/编译器就是不允许在ISR中做浮点运算。此外,ISR应该是短而有效率的,在ISR中做浮点运算是不明智的。4).与第三点一脉相承,printf()经常有重入和性能上的问题。如果你丢掉了第三和第四点,我不会太为难你的。不用说,如果你能得到后两点,那么你的被雇用前景越来越光明了。
代码例子(Codeexamples)
12.下面的代码输出是什么,为什么?
voidfoo(void){
unsignedinta=6;intb=-20;
(a+b>6)puts(\">6\"):puts(\"<=6\");}
这个问题测试你是否懂得C语言中的整数自动转换原则,我发现有些开发者懂得极少这些东西。不管如何,这无符号整型问题的答案是输出是“>6”。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。如果你答错了这个问题,你也就到了得不到这份工作的边缘。
13.评价下面的代码片断:
unsignedintzero=0;
unsignedintcompzero=0xFFFF;/*1'scomplementofzero*/
对于一个int型不是16位的处理器为说,上面的代码是不正确的。应编写如下:
unsignedintcompzero=~0;
这一问题真正能揭露出应试者是否懂得处理器字长的重要性。在我的经验里,好的嵌入式程序员非常准确地明白硬件的细节和它的局限,然而PC机程序往往把硬件作为一个无法避免的烦恼。到了这个阶段,应试者或者完全垂头丧气了或者信心满满志在必得。如果显然应试者不是很好,那么这个测试就在这里结束了。但如果显然应试者做得不错,那么我就扔出下面的追加问题,这些问题是比较难的,我想仅仅非常优秀的应试者能做得不错。提出这些问题,我希望更多看到应试者应付问题的方法,而不是答案。不管如何,你就当是这个娱乐吧…
动态内存分配(Dynamicmemoryallocation)
14.尽管不像非嵌入式计算机那么常见,嵌入式系统还是有从堆(heap)中动态分配内存的过程的。那么嵌入式系统中,动态分配内存可能发生的问题是什么?
这里,我期望应试者能提到内存碎片,碎片收集的问题,变量的持行时间等等。这个主题已经在ESP杂志中被广泛地讨论过了(主要是P.J.Plauger,他的解释远远超过我这里能提到的任何解释),所有回过头看一下这些杂志吧!让应试者进入一种虚假的安全感觉后,我拿出这么一个小节目:下面的代码片段的输出是什么,为什么?
char*ptr;
if((ptr=(char*)malloc(0))==NULL)puts(\"Gotanullpointer\");else
puts(\"Gotavalidpointer\");
这是一个有趣的问题。最近在我的一个同事不经意把0值传给了函数malloc,得到了一个合法的指针之后,我才想到这个问题。这就是上面的代码,该代码的输出是“Gotavalidpointer”。我用这个来开始讨论这样的一问题,看看被面试者是否想到库例程这样做是正确。得到正确的答案固然重要,但解决问题的方法和你做决定的基本原理更重要些。
Typedef
15.Typedef在C语言中频繁用以声明一个已经存在的数据类型的同义字。也可以用预处理器做类似的事。例如,思考一下下面的例子:#definedPSstructs*typedefstructs*tPS;
以上两种情况的意图都是要定义dPS和tPS作为一个指向结构s指针。哪种方法更好呢?(如果有的话)为什么?这是一个非常微妙的问题,任何人答对这个问题(正当的原因)是应当被恭喜的。答案是:typedef更好。思考下面的例子:dPSp1,p2;tPSp3,p4;
第一个扩展为
structs*p1,p2;
上面的代码定义p1为一个指向结构的指,p2为一个实际的结构,这也许不是你想要的。第二个例子正确地定义了p3和p4两个指针。
晦涩的语法
16.C语言同意一些令人震惊的结构,下面的结构是合法的吗,如果是它做些什么?
inta=5,b=7,c;c=a+++b;
这个问题将做为这个测验的一个愉快的结尾。不管你相不相信,上面的例子是完全合乎语法的。问题是编译器如何处理它?水平不高的编译作者实际上会争论这个问题,根据最处理原则,编译器应当能处理尽可能所有合法的用法。因此,上面的代码被处理成:c=a+++b;
因此,这段代码持行后a=6,b=7,c=12。
如果你知道答案,或猜出正确答案,做得好。如果你不知道答案,我也不把这个当作问题。我发现这个问题的最大好处是:这是一个关于代码编写风格,代码的可读性,代码的可修改性的好的话题
C++
1.以下三条输出语句分别输出什么?[C易]charstr1[]=\"abc\";charstr2[]=\"abc\";
constcharstr3[]=\"abc\";constcharstr4[]=\"abc\";constchar*str5=\"abc\";constchar*str6=\"abc\";
cout<cout<2.非C++内建型别A和B,在哪几种情况下B能隐式转化为A?[C++中等]答:a.classB:publicA{……}//B公有继承自A,可以是间接继承的b.classB{operatorA();}//B实现了隐式转化为A的转化
c.classA{A(constB&);}//A实现了non-explicit的参数为B(可以有其他带默认值的参数)构造函数
d.A&operator=(constA&);//赋值操作,虽不是正宗的隐式类型转换,但也可以勉强算一个
3.以下代码中的两个sizeof用法有问题吗?[C易]
voidUpperCase(charstr[])//将str中的小写字母转换成大写字母{
for(size_ti=0;icharstr[]=\"aBcDe\";cout<<\"str字符长度为:\"<4.以下代码有什么问题?[C难]voidchar2Hex(charc)//将字符以16进制表示{
charch=c/0x10+'0';if(ch>'9')ch+=('A'-'9'-1);charcl=c%0x10+'0';if(cl>'9')cl+=('A'-'9'-1);cout<charstr[]=\"Ilove中国\";for(size_ti=0;i5.以下代码有什么问题?[C++易]structTest{Test(int){}Test(){}voidfun(){}};
voidmain(void){
Testa(1);a.fun();Testb();b.fun();}
6.以下代码有什么问题?[C++易]cout<<(true?1:\"1\")<7.以下代码能够编译通过吗,为什么?[C++易]unsignedintconstsize1=2;charstr1[size1];unsignedinttemp=0;cin>>temp;
unsignedintconstsize2=temp;charstr2[size2];
8.以下代码中的输出语句输出0吗,为什么?[C++易]structCLS{
intm_i;
CLS(inti):m_i(i){}CLS(){
CLS(0);}};
CLSobj;
cout<9.C++中的空类,默认产生哪些类成员函数?[C++易]答:classEmpty{
public:
Empty();//缺省构造函数
Empty(constEmpty&);//拷贝构造函数~Empty();//析构函数
Empty&operator=(constEmpty&);//赋值运算符Empty*operator&();//取址运算符
constEmpty*operator&()const;//取址运算符const};
10.以下两条输出语句分别输出什么?[C++难]
floata=1.0f;
cout<<(int)a<cout<cout<<(int)b<cout<array.push_back(1);array.push_back(2);array.push_back(3);for(vector::size_typei=array.size()-1;i>=0;--i)//反向遍历array数组{
cout<12.以下代码有什么问题?[STL易]typedefvectorIntArray;IntArrayarray;array.push_back(1);array.push_back(2);array.push_back(2);array.push_back(3);
//删除array数组中所有的2
for(IntArray::iteratoritor=array.begin();itor!=array.end();++itor){
if(2==*itor)array.erase(itor);}
13.写一个函数,完成内存之间的拷贝。[考虑问题是否全面]答:
void*mymemcpy(void*dest,constvoid*src,size_tcount){
char*pdest=static_cast(dest);constchar*psrc=static_cast(src);if(pdest>psrc&&pdestfor(size_ti=count-1;i!=-1;--i)pdest[i]=psrc[i];}else{
for(size_ti=0;ireturndest;}intmain(void){
charstr[]=\"01234567\";mymemcpy(str+1,str+0,9);cout<本试题仅用于考查C++/C程序员的基本编程技能。内容限于C++/C常用语法,不涉及数据结构、算法以及深奥的语法。考试成绩能反映出考生的编程质量以及对C++/C的理解程度,但不能反映考生的智力和软件开发能力。笔试时间90分钟。请考生认真答题,切勿轻视。一、请填写BOOL,float,指针变量与“零值”比较的if语句。(10分)提示:这里“零值”可以是0,0.0,FALSE或者“空指针”。例如int变量n与“零值”比较的if语句为:if(n==0)if(n!=0)以此类推。
请写出BOOLflag与“零值”比较的if语句:
请写出floatx与“零值”比较的if语句:
请写出char*p与“零值”比较的if语句:
二、以下为WindowsNT下的32位C++程序,请计算sizeof的值(10分)
charstr[]=“Hello”;char*p=str;intn=10;请计算sizeof(str)=
sizeof(p)=
sizeof(n)=
voidFunc(charstr[100]){请计算sizeof(str)=}
void*p=malloc(100);请计算sizeof(p)=
三、简答题(25分)
1、头文件中的ifndef/define/endif干什么用?
2、#include和#include“filename.h”有什么区别?
3、const有什么用途?(请至少说明两种)
4、在C++程序中调用被C编译器编译后的函数,为什么要加extern“C”声明?
5、请简述以下两个for循环的优缺点
//第一个for(i=0;i{
if(condition)DoSomething();else
DoOtherthing();}
//第二个if(condition){for(i=0;iDoSomething();}else{for(i=0;iDoOtherthing();}优点:
缺点:
优点:
缺点:
四、有关内存的思考题(20分)
voidGetMemory(char*p){
p=(char*)malloc(100);}
voidTest(void){
char*str=NULL;GetMemory(str);strcpy(str,\"helloworld\");printf(str);}
请问运行Test函数会有什么样的结果?答:
char*GetMemory(void){
charp[]=\"helloworld\";returnp;}
voidTest(void){
char*str=NULL;str=GetMemory();printf(str);}
请问运行Test函数会有什么样的结果?答:
VoidGetMemory2(char**p,intnum){
*p=(char*)malloc(num);}
voidTest(void){
char*str=NULL;GetMemory(&str,100);strcpy(str,\"hello\");printf(str);}
请问运行Test函数会有什么样的结果?答:
voidTest(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,constchar*strSrc);
其中strDest是目的字符串,strSrc是源字符串。
(1)不调用C++/C的字符串库函数,请编写函数strcpy
(2)strcpy能把strSrc的内容复制到strDest,为什么还要char*类型的返回值?
六、编写类String的构造函数、析构函数和赋值函数(25分)已知类String的原型为:classString{public:
String(constchar*str=NULL);//普通构造函数String(constString&other);//拷贝构造函数~String(void);//析构函数
String&operate=(constString&other);//赋值函数private:
char*m_data;//用于保存字符串};
请编写String的上述4个函数。
附录C:C++/C试题的答案与评分标准
一、请填写BOOL,float,指针变量与“零值”比较的if语句。(10分)
请写出BOOLflag与“零值”比较的if语句。(3分)标准答案:if(flag)
if(!flag)
如下写法均属不良风格,不得分。