计算机专业笔试题

原创
2014/09/29 20:41
阅读数 835

1const char*, char const*, char*const的区别问题:

Bjarne在他的The C++ Programming Language里面给出过一个助记的方法: 

把一个声明从右向左读

char * const cp;    // ( * 读成 pointer to )

cp is a const pointer to char

 

const char * p;

p is a pointer to const char;

 

2、char类型为一个字节,取值范围是[-128127]unsigned char [0 ,255]

 

3、n阶阶层的递归算法:--(常考)

int fact(int n)
{
    if(n == 1)
        return 1;
    else
        return n*fact(n-1);
}


4、求数组a[ ]中最大值的递归算法:

int Max(int a[ ], int first, int n)       //first = 0; n为数组长度
{
    int max;
    if(first == n-1)
        return(a[first]);
    max = Max(a, first+1, n);
    if(max < a[first])
        return a[first];
    else
        return max;
}


5、折半查找法(二分法)的递归算法:

int bsearch(int b[], int x, int L, int R)    //在下届为L,上界为R的数组b 中折半查找数据元素x
{
    int mid;
    
    if(L > R)
        return -1;
    mid = (L+R)/2;
    if(x == b[mid])
        return mid;
    else
        if(x < b[mid])
            return bsearch(b, x, L, mid-1);
        else
            return bsearch(b, x, mid+1, R);
}


6、非递归计算如下递归函数的值(斐波拉契):--(常考)

f(1)=1

f(2)=1

f(n)=f(n-1)+f(n-2) n>2

 

解:

int f(int n)
{
    int i,s,s1,s2;
    s1=1;/*s1用于保存f(n-1)的值*/
    s2=1;/*s2用于保存f(n-2)的值*/
    s=1;
    for(i=3;i<=n;i++)
    {
       s=s1+s2;
       s2=s1;
       s1=s;
    }
    return(s);
}


7、交换两个数,不用第三块儿内存:

int a = ……;

int b = ……;

 解:

a = a + b;
b = a - b;
a = a - b;


8、OSI的七层协议:--(常考)

应用层、表示层、回话层、运输层、网络层、数据链路层、物理层

物理层 为数据链路层提供物理连接,在其上串行传送比特流,即所传送数据的单位是比特。此外,该层中还具有确定连接设备的电气特性和物理特性等功能。

数据链路层 负责在网络节点间的线路上通过检测、流量控制和重发等手段,无差错地传送以帧为单位的数据。为做到这一点,在每一帧中必须同时带有同步、地址、差错控制及流量控制等控制信息。

网络层 为了将数据分组从源(源端系统)送到目的地(目标端系统),网络层的任务就是选择合适的路由和交换节点,使源的传输层传下来的分组信息能够正确无误地按照地址找到目的地,并交付给相应的传输层,即完成网络的寻址功能。

传输层 传输层是高低层之间衔接的接口层。数据传输的单位是报文,当报文较长时将它分割成若干分组,然后交给网络层进行传输。传输层是计算机网络协议分层中的最关键一层,该层以上各层将不再管理信息传输问题。

会话层 该层对传输的报文提供同步管理服务。在两个不同系统的互相通信的应用进程之间建立、组织和协调交互。例如,确定是双工还是半双工工作。

表示层 该层的主要任务是把所传送的数据的抽象语法变换为传送语法,即把不同计算机内部的不同表示形式转换成网络通信中的标准表示形式。此外,对传送的数据加密(或解密)、正文压缩(或还原)也是表示层的任务。

应用层 该层直接面向用户,是OSI中的最高层。它的主要任务是为用户提供应用的接口,即提供不同计算机间的文件传送、访问与管理,电子邮件的内容处理,不同计算机通过网络交互访问的虚拟终端功能等。


9、TCP/IP的四层协议:--(常考)

应用层、运输层、网际层IP、网络接口层

网络接口层 这是TCP/IP协议的最低一层,包括有多种逻辑链路控制和媒体访问协议。网络接口层的功能是接收IP数据报并通过特定的网络进行传输,或从网络上接收物理帧,抽取出IP数据报并转交给网际层。

网际网层(IP层)  该层包括以下协议:IP(网际协议)、ICMPInternet Control Message Protocol,因特网控制报文协议)、ARPAddress Resolution Protocol,地址解析协议)、RARPReverse Address Resolution Protocol,反向地址解析协议)。该层负责相同或不同网络中计算机之间的通信,主要处理数据报和路由。在IP层中,ARP协议用于将IP地址转换成物理地址,RARP协议用于将物理地址转换成IP地址,ICMP协议用于报告差错和传送控制信息。IP协议在TCP/IP协议组中处于核心地位。

传输层  该层提供TCP(传输控制协议)和UDPUser Datagram Protocol,用户数据报协议)两个协议,它们都建立在IP协议的基础上,其中TCP提供可靠的面向连接服务,UDP提供简单的无连接服务。传输层提供端到端,即应用程序之间的通信,主要功能是数据格式化、数据确认和丢失重传等。

应用层  TCP/IP协议的应用层相当于OSI模型的会话层、表示层和应用层,它向用户提供一组常用的应用层协议,其中包括:TelnetSMTPDNS等。此外,在应用层中还包含有用户应用程序,它们均是建立在TCP/IP协议组之上的专用程序。

(五层协议:应用层、运输层、网络层、数据链路层、物理层)


10、IP协议 是支持网间互连的数据报协议,它与TCP协议(传输控制协议)一起构成了TCP/IP协议族的核心。

       与IP协议配套使用的还有三个协议:地址解析协议ARP、网际控制报文协议ICMP、网际组管理协议IGMP。

       IP地址的划分:

数据帧:首部(SOH:01)+ IP数据报 + 尾部(EOT:04)


11、面向对象的三大特征是封装性、继承性和多态性:

(1)封装性:将客观事物抽象成类,每个类对自身的数据和方法实行 protection(private,  protected,

public)。

(2)继承性:广义的继承有三种实现形式:实现继承(使用基类的属性和方法而无需额外编码的能力)、可

视继承(子窗体使用父窗体的外观和实现代码)、接口继承(仅使用属性和方法,实现滞后到子类实现)。

(3)多态性:是将父类对象设置成为和一个或更多它的子对象相等的技术。用子类对象给父类对象赋值

之后,父类对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。


12、简述指针常量与常量指针区别:

    指针常量是指定义了一个指针,这个指针的值只能在定义时初始化,其他地方不能改变。常量指针是指定义了一个指针,这个指针指向一个只读的对象,不能通过常量指针来改变这个对象的值。指针常量强调的是指针的不可改变性,而常量指针强调的是指针对其所指对象的不可改变性。


13、数组名和指针的区别:--(常考)

#include <iostream.h>
#include <string.h>
void main(void)
{
    char str[13]="Hello world!"; 
    char *pStr="Hello world!";
    
    cout<<sizeof(str)<<endl;
    cout<<sizeof(pStr)<<endl;
    cout<<strlen(str)<<endl;
    cout<<strlen(pStr)<<endl;
}

打印结果:
13
4
12
12


14、谈谈你对面向对象的认识。

    面向对象可以理解成对待每一个问题,都是首先要确定这个问题由几个部分组成,而每一个部分其

实就是一个对象。然后再分别设计这些对象,最后得到整个程序。传统的程序设计多是基于功能的思想

来进行考虑和设计的,而面向对象的程序设计则是基于对象的角度来考虑问题。这样做能够使得程序更

加的简洁清晰。


15、重载 (overload)和重写(overried, 有的书也叫做“覆盖”) 的区别?

从定义上来说:

重载: 是指允许存在多个同名函数, 而这些函数的参数表不同 (或许参数个数不

同,或许参数类型不同,或许两者都不同)。

重写:是指子类重新定义复类虚函数的方法。


16、局部变量能否和全局变量重名? 

答:能,局部会屏蔽全局。要用全局变量,需要使用"::"


17、TCP/UDP有何优缺点?

TCP 服务提供了数据流传输、可靠性、有效流控制、全双工操作和多路复用技术等。 与 TCP 不同, UDP 并不提供对 IP 协议的可靠机制、流控制以及错误恢复功能等。由于 UDP 比较简单, UDP 头包含很少的字节,比 TCP 负载消耗少。 

TCP: 提供稳定的传输服务,有流量控制,缺点是包头大,冗余性不好 

UDP: 不提供稳定的服务,包头小,开销小


18、CPU调度算法:

(1)先到先服务FCFS

(2)最短作业/进程优先 SJF/SPF

 SJ(P)F算法从就绪队列中选出估计运行时间最短的作业(进程),为之分配处理机,如果运行时间相同,按FCFS调度。

(3)优先级调度

(4)轮转法调度 RR;

(5)多级队列调度。


19、PV操作:


20、死锁: 指多个进程因竞争共享资源而造成的一种僵局, 若无外力作用, 这些进程都将永远不能再向前推进。

       银行家算法是最有代表性的死锁避免策略:


21、将字符型转换成整型

int Atoi(const char *str){  
    int i=0,result=0,sign=1;  
    if(str==NULL){ //判断是否为空  
        return 0;  
    }  
    while (isspace(str[i])) //跳过开头的空格字符  
           i++;  
    if (str[i]=='+'||str[i]=='-'){//如果除去空格后第一个出现的字符是"-","+"则跳过并标识sign  
        sign=(str[i]=='-')?-1:1; //如果字符是"-" 则sign为-1  
        i++;  
    }  
    while(isdigit(str[i])){  //循环直到遇到非数字结束循环  
        result=result*10+str[i]-'0';//将数字字符转换成整形数字  
        i++;  
    }  
    result=result * sign; //数字加上符号  
    return result;  
}


22、strcpy()函数--(常考)

char* strcpy(char *strDest,const char*strSrc)    //第二个参数的const要写上  
{  
    if((NULL==strDest)||(NULL==strSrc))//先判断参数是否为空  
        return NULL;//当然这里可以抛出异常或者直接用断言,以便在众多应聘者中突出自己^^  
    char  *strTemp = strDest;      //用strTemp指向strDest开始地址
    while((*strTemp++ = *strSrc++) != '\0');  
    return strDest;  
}

 


23、逗号表达式的要领:

(1) 逗号表达式的运算过程为:从左往右逐个计算表达式。

(2) 逗号表达式作为一个整体,它的值为最后一个表达式(也即表达式n)的值。

(3) 逗号运算符的优先级别在所有运算符中最低。

例:

int i=(j=4,k=8,l=16,m=32); 
printf(“ %d” , i);     //输出是多少,答:32



24、解释堆和栈的区别:

栈区(stack)--由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
堆区(heap) --一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。


25、论述含参数的宏与函数的优缺点:

(1).函数调用时,先求出实参表达式的值,然后带入形参。而使用带参的宏只是进行简单的字符替换。

(2).函数调用是在程序运行时处理的,分配临时的内存单元;而宏展开则是在编译时进行的,在展开时并不分配内存单元,不进行值的传递处理,也没有“返回值”的概念。

(3).对函数中的实参和形参都要定义类型,二者的类型要求一致,如不一致,应进行类型转换;而宏不存在类型问题,宏名无类型,它的参数也无类型,只是一个符号代表,展开时带入指定的字符即可。宏定义时,字符串可以是任何类型的数据。

(4).调用函数只可得到一个返回值,而用宏可以设法得到几个结果。

(5).使用宏次数多时,宏展开后源程序长,因为每展开一次都使程序增长,而函数调用不使源程序变长。

(6).宏替换不占运行时间,只占编译时间;而函数调用则占运行时间(分配单元、保留现场、值传递、返回)。

一般来说,用宏来代表简短的表达式比较合适。


26、Windows 程序的入口是哪里?写出 Windows 消息机制的流程

Windows程序的入口是WinMain()函数。 

Windows应用程序消息处理机制: 
A. 操作系统接收应用程序的窗口消息,将消息投递到该应用程序的消息队列中 
B. 应用程序在消息循环中调用GetMessage函数从消息队列中取出一条一条的消息,取出消息后,应用程序可以对消息进行一些预处理。 
C. 应用程序调用DispatchMessage,将消息回传给操作系统。 
D. 系统利用WNDCLASS结构体的lpfnWndProc成员保存的窗口过程函数的指针调用窗口过程,对消息进行处理


27、实现双向链表删除一个节点P,在节点P后插入一个节点,写出这两个函数

{        //删除
    p->pre->next=p->next;
    p->next->pre=p->pre;
    delete p;
}

{        //插入
    new->next=p->next;
    new->pre=p;
    p->next->pre=new;
    p->next=new;
}


28、进程:

进程是执行中的程序(进程是程序的一次执行过程);

进程是动态概念,有生命周期;

它是操作系统进行资源分配和调度的基本单位;

线程:


29、向服务器发送请求有几中方式?有什么区别?

答:get,post。get一般为链接方式,post一般为按钮方式。


30、(1)判断单链表是否有环:使用两个指针。一个每次前进1,另一个每次前进2,且都从链表第一个元素开始。显然,如果有环,两个指针必然会相遇。

//判断单链表是否有环  
bool IsCircle( Node *pHead )  
{  
    //空指针 或 只有一个元素且next为空时,必无环  
    if( pHead == NULL || pHead->next == NULL ) return false;  
      
    Node *pSlow = pHead;  
    Node *pFast = pHead;  
  
    while( ( pFast != NULL ) && ( pFast->next != NULL )  )  
    {  
        //分别按步长1、2前进  
        pSlow = pSlow->next;  
        pFast = pFast->next->next;  
  
        if( pSlow == pFast ) break;  
    }  
    if( ( pFast == NULL ) || ( pFast->next == NULL ) )   
        return false;  
    else   
        return true;  
}

(2)求环的长度:记下第一次的相遇点,这个指针再次从相遇点出发,直到第二次相遇。此时,步长为1的指针所走的步数恰好就是环的长度。

int GetLen( Node *pHead )  
{  
    if( pHead == NULL || pHead->next == NULL ) return false;  
      
    Node *pSlow = pHead;  
    Node *pFast = pHead;  
  
    //求相遇点  
    while( ( pFast != NULL ) && ( pFast->next != NULL )  )  
    {  
        pSlow = pSlow->next;  
        pFast = pFast->next->next;  
  
        if( pSlow == pFast ) break;  
    }  
  
    //计算长度  
    int cnt = 0;  
    while( ( pFast != NULL ) && ( pFast->next != NULL )  )  
    {  
        pSlow = pSlow->next;  
        pFast = pFast->next->next;  
        cnt++;  
  
        //再次相遇时,累计的步数就是环的长度  
        if( pSlow == pFast ) break;  
    }  
    return cnt;  
}

(3)求环的链接点:记下第一次的相遇点,使一个指针指向这个相遇点,另一个指针指向链表第一个元素。然后,两个指针同步前进,且步长都为1。当两个指针相遇时所指的点就是环的连接点。

//求环的入口点  
Node* GetEntrance( Node* pHead )  
{  
    if( pHead == NULL || pHead->next == NULL ) return false;  
      
    Node *pSlow = pHead;  
    Node *pFast = pHead;  
  
    //求相遇点  
    while( ( pFast != NULL ) && ( pFast->next != NULL )  )  
    {  
        pSlow = pSlow->next;  
        pFast = pFast->next->next;  
  
        if( pSlow == pFast ) break;  
    }  
  
    pSlow = pHead;  
    while( pSlow != pFast )  
    {  
        //同步前进  
        pSlow = pSlow->next;  
        pFast = pFast->next;  
    }  
    return pSlow;  
}


31、产生死锁的原因主要是:
(1) 因为系统资源不足。
(2) 进程运行推进的顺序不合适。
(3) 资源分配不当等。


如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。


产生死锁的四个必要条件:

(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

展开阅读全文
打赏
0
11 收藏
分享
加载中
更多评论
打赏
0 评论
11 收藏
0
分享
返回顶部
顶部