Fork me on GitHub

求职路姊妹篇 -- 笔试

     求职路持续更新后,我发现还有个东西可以写(哈哈,我就喜欢写东写西)。笔试时的技术问题,有些没回答上来或没回答好的,我可以做一个记录。方便温习。

这次参加的笔试,职位是测试工程师,不过题目好像偏软件工程师。就当把我记得不牢的东西温习温习吧~其实还有个数据库工程师的卷子,不过实在没时间再去做一份了。一共20题,我只记得18道了。

     1.广度优先遍历算法

     分析:这个图的算法,以前还是记得的。但是确实很久没有接触了,前阵子打算再复习的,结果看别的去了。笔试的时候有点点映像,但是它是第二题,我不想在这上面耗费太多的时间,结果试卷完后好多不会。就干脆没做了。

     广度优先搜索遍历类似于树的层次遍历。其中必须设立一个队列来保存访问过的节点,算法描述如下,

     1)从图中选定一个节点V0作为出发点。

     2)访问V0。

     3)将访问过的节点V0入队。

     4)当队列不空时,进入循环:

          节点Vi出队。

          访问与Vi有边相连的且未被访问过的所有节点Vj。

          访问过的节点Vj入队。

      5)当队列为空时,循环结束,说明从V0开始能够到达的所有节点都已被访问过。

      广度优先遍历算法如下(C++):

typedef int dataType;
#include "Queue1.h"

void Graph1::breadthfs(int k)
{
      Queue1 q1(vertCount);   //vertCount 图的节点数
       int i = k;
       cout<<vertex[i]<<"  ";   //char vertex[] 图的节点集合
       vertex[i] = 1;
       q1.enQueue(i);
       while(!q1.isEmpty())
       {
               i = q1.deQueue();
               int j = 0;
               while(j<vertCount)
               {
                      if(i != j && mat[i][j]>0 && mat[i][j]<MaxWeight && visited[j]==0)      //int mat[][] 图的邻接矩阵
                     {
                            cout<<vertex[j]<<" ";
                            visited[j] = 1;  //int visited[] 访问标记数组
                            q1.enQueue(j);
                     } 
                     else
                            j++;
               }
       }
}

顺便复习下深度优先遍历算法:深度优先搜索遍历类似于树的先根遍历。其递归算法描述如下,

  从图中选定的一个节点v0出发。

  访问v0.

  查找与v0有边相连且未被访问过的另一个节点vj。

  若有vj,从vj出发继续进行深度优先搜索遍历。

  若找不到vj,说明v0开始能够到达的所有节点都已经被访问过,遍历结束。

深度优先遍历算法如下(C++):

void Graph1::depthfs(int k)
{
   int i=k,j=0;
   cout<<vertex[i]<<" ";
   visited[i]=1;
   while(j<vertCount)
   {
        if(i!=j && mat[i][j]>0 && mat[i][j]<MaxWeight && visited[j]==0)
        {
                 depthfs(j);   //递归
        }
        else
                   j++;
   }
}

 

2.画出在windows下进行socket通信的简单模型

分析:当时我只记得socket是服务器和客户端的通信机制,那还是大一看孙鑫老师的MFC时记的笔记,当时还做了个简单的通信工具,现在不知道有多少年没碰了,印象最深的是有三次“握手”。结果画了个错误的模型图。

我想应该就是下面这个图,如果不对,请指出。

 

3.用纯C写输入一字符串,并逆转输出。

分析:去年暑假的时候,买了本计算机等级考试的书,里面就是纯C的,我利用项目的空闲时间做完了这本书。但是当时认为我学的是C#,就没有很关注C的语法,值看题目的对错去了。想用char指针的方法,但是也忘光了。我的方法差不多是下面这个样子,用了一个字符数组的方法,通过for循环倒着输出来了。肯定是杯具~

#include <stdio.h>
#include <string.h>
void main(void)
{	
char str[100];	
int len, i;	
while(gets(str) != NULL) /* Ctrl+Z结束循环 */	
{		
len = strlen(str);		
for(i = len-1; i >= 0; --i)
     putchar(str[i]);
putchar('\n');	
}
}

网上有个理想的方法,但我不知道是不是最高效的,还有一些其他的就不列举了:

#include<stdio.h>
#include<string.h>
void func(char *s)
{
char *p1, *p2;
char c;
p1 = s;
p2 = s + strlen(s) - 1;
while(p1 < p2)
{
c = *p1;
*p1 = *p2;
*p2 = c;
p1++;
p2--;
}
}
void main()
{
char s[] = "sdlkfjslkdfja";
func(s);
printf("%s\n", s);
}

 

4.接口和类的异同。

分析:本来刚看完The C# Programming Language这本书,这道题应该可以答得很好才对。结果也不尽理想,相异的地方还是写出一些。相同感觉太多了啊!

异:
不能直接实例化接口。  //ok
接口不包含方法的实现。 //ok
接口、类和结构可从多个接口继承。但是C# 只支持单继承:类只能从一个基类继承实现。 //no
类定义可在不同的源文件之间进行拆分。//no
同:
接口、类和结构可从多个接口继承。//ok
接口类似于抽象基类:继承接口的任何非抽象类型都必须实现接口的所有成员。 //no
接口可以包含事件、索引器、方法和属性。//no
一个类可以实现多个接口。//no

 

5.用C/C++写一个深度为xxx,宽度为xx的环形缓冲区。

分析:xxx是有具体数字的,我忘记了。但是这个题目直接无语。

/*ringbuf .c*/
#include<stdio.h>
#include<ctype.h>
#define NMAX 8
int iput = 0; /* 环形缓冲区的当前放人位置 */
int iget = 0; /* 缓冲区的当前取出位置 */
int n    = 0; /* 环形缓冲区中的元素总数量 */
double buffer[NMAX];
/* 环形缓冲区的地址编号计算函数,,如果到达唤醒缓冲区的尾部,将绕回到头部。 ** 环形缓冲区的有效地址编号为:0到(NMAX-1) */
int addring (int i){    return ((i+1) == NMAX )? 0 : i+1;}
/* 从环形缓冲区中取一个元素 */
double get(void)
{   
 int pos;   
 if (n>0){      
  pos = iget;    
  iget = addring(iget);   
  n--;       
  return buffer[pos];    
  }    else {  
      printf("Buffer is emptyn");     
   return 0.0;    
  }
}
/* 向环形缓冲区中放人一个元素*/
void put(double z)
{    
if (n<NMAX)
{       
 buffer[iput]=z;     
 iput = addring(iput);  
 n++;    
}   
else  
printf("Buffer is fulln");
}

int main(void)
{   
  char opera[5];  
  double z;    
  do     
  {        
    printf("Please input p|g|e:");  
    scanf("%s", &opera);    
    switch(tolower(opera[0]))  
    {            
      case 'p': /* put */        
         printf("Please input a float number:");     
         scanf("%lf", &z);          
         put(z);              
         break;        
      case 'g': /* get */        
        z = get();               
        printf("%8.2f from Buffern", z);   
        break;        
      case 'e':              
        printf("Endn");       
        break;             
      default:              
        printf("%s - Operation command error! n", opera);   
     }/* end switch */    
    }while(opera[0] != 'e');   
  return 0;
}

也不知道这个对不对,应该没这么长的程序,可能就是这两句吧:

double buffer[NMAX];
/* 环形缓冲区的地址编号计算函数,,如果到达唤醒缓冲区的尾部,将绕回到头部。 ** 环形缓冲区的有效地址编号为:0到(NMAX-1) */
int addring (int i){    return ((i+1) == NMAX )? 0 : i+1;}

 

6.线程和进程的区别,然后讲讲同步和互斥。

分析:线程和进程的区别还是记得的。但是我想回答也不全面,至于同步和互斥。知道有这个概念,并且我博客上不还有个弄错了的进程同步的例子么。

请参看:http://www.cnblogs.com/kulong995/archive/2008/10/10/1307952.html#1443479

呵呵。可惜,秃头老师的Mutex犹在耳边,而我依然只有模糊的概念而已。

这位仁兄跟我差不多:http://www.ezloo.com/2007/10/thread_process_program.html

我也只是知道线程是进程的一部分,进程是程序的一部分。更具体的区别见下面:

1、线程是进程的一部分,所以线程有的时候被称为是轻权进程或者轻量级进程。
2、一个没有线程的进程是可以被看作单线程的,如果一个进程内拥有多个进程,进程的执行过程不是一条线(线程)的,而是多条线(线程)共同完成的。
3、系统在运行的时候会为每个进程分配不同的内存区域,但是不会为线程分配内存(线程所使用的资源是它所属的进程的资源),线程组只能共享资源。那就是说,出了CPU之外(线程在运行的时候要占用CPU资源),计算机内部的软硬件资源的分配与线程无关,线程只能共享它所属进程的资源。
4、与进程的控制表PCB相似,线程也有自己的控制表TCB,但是TCB中所保存的线程状态比PCB表中少多了。
5、进程是系统所有资源分配时候的一个基本单位,拥有一个完整的虚拟空间地址,并不依赖线程而独立存在。

 

7.在一张表内(具体表大概就是工资,部分,人员,薪水之类的)用一条sql语句选择出除了hr_depart部门的平均薪水,并对人员字符排序。

PS:这道题应该记错了,可能是对低于部门平均薪水的人排序。

分析:当时以为只是简单的select where orderby的。结果发现不对劲。自从发现了Sql server可以利用视图自动生成sql语句后,我就懒了。最后一次写sql语句貌似也是半年前了(这半年我干嘛去了?)。而且平常老是问人,要不就是搜索。很少自己静下心来构造T-Sql。结果我的语句肯定写错了,但还是硬着头皮写了一点。不能让人误会我完全不会Sql啊!

这道题我自己待会去数据库上建个表试一试,总感觉怪怪的。

 

8.选择(num int(32))中最小的数,但不能用min和max。

分析:当时看到觉得不知道,后来想了个笨办法。选择按从小到大排序后的第一个结果。select top 1 from num orderby num desc.

没找到更合适的答案,这里有个园友碰到个更BT的,同时查最大值和最小值:http://www.cnblogs.com/wszhe/archive/2007/07/20/824815.html

也有可能是我记错题了,就是要查最大和最小值。

 

9.final,finally,finallize的区别

分析:说实话,我只见过finally。所以这道题又没答。好吧,我发现这是java题。

final--如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重载。

finally—在异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)。 finalize —方法名。Java 技术允许使用finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。一旦垃圾回收器准备好释放对象占用的空间,将首先调用其finalize()方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。垃圾回收只与内存有关,只所以会用finalize()方法,是由于在分配内存时采用了类似C语言的做法,这种情况主要发生在使用“本地方法”的情况下,本地方法采用的是非java代码方式,本地方法目前只支持C和C++,在非java代码中也许会调用到C的malloc()函数系列来分配存储空间,而且除非调用了free()函数,否则存储空间将得不到释放。

更具体的研究请参看:http://blog.csdn.net/yakihappy/archive/2009/03/11/3979759.aspx
插播广告:) google让我们的生活更美好~\(^o^)/~其实我应该给自己一板砖,我应该用必应的。

 

10.面向对象技术的特点。
分析:我觉得这个题如果答不上来可以去撞死了。好吧,我去找块豆腐来撞吧~由于越来越没信心。我居然就这么答了:继承,多态,封装,隐藏。天天用面向对象的C#来写程序,居然忘了它的特点了,那是看园子里涛哥的《你必须知道的.NET》,奉若珍宝。你不知道?out了吧~http://www.cnblogs.com/anytao/ 等我回忆下。。。好像是1年半前。哎,很多东西也随着时间一起给流逝了。
面向对象的三个基本特征是:封装、继承、多态。请见:http://www.svn8.com/uml/OOAD/uml200907127306.html
百度百科有多个抽象。请见:http://baike.baidu.com/view/1520586.htm?func=retitle

 

11.解释什么是中断重X。(通过谷歌的帮助下,可重断中断)。

PS:可能又记错题了,是不是函数的重入呢。刚好看到这个概念。
分析:又不知道,又没答。
好吧,我连搜都搜不到,请知道的园友告知一声吧。

所谓的函数是可重入的(也可以说是可预测的),即:只要输入数据相同就应产生相同的输出。

12.String s = new String("abc");一共分配了几次内存。
分析:前几天园子里不是有位朋友面试时碰到这个问题么,当时我还想,是两次吧(不要有“吧”)!结果自己写的时候又犹豫了,但是我还是写的两次。

后来回家后,我请教了Gray,他的回答如下:”栈空间分配了2次,堆不一定,会有intern的吧,而且我也不知道编译器会不会在这一句上作优化,就像会把""优化成String.Empty“ 具体的分配: ”栈空间第一次分配一个指针指到"abc",第二次分配出来给new string("abc")啊 第二次的栈指针有个名字叫s,应该是这样了 “

涛哥的书上应该有,但是我现在没书。

 

13.static 函数 和 static 变量各自的特点。

分析:当时我怎么想的呢,我觉得这问的应该是C或C++里面的吧。但是又不熟悉。就只好写了自己熟悉的C#里面的情况。

关于C里面的这个不错:http://hi.baidu.com/gtfcugb/blog/item/57b836dd6e11f5e976c638f1.html

 

14.&和&&的区别。

分析:这个前两天看到了,&不是短路运算 ,而&&是短路运算符。

这个应该没有问题吧?

 

15.adp.net中常用的对象。

分析:这个我只回答出了Connection和Command对象。

Connection          打开数据库连接

Command         执行数据库命令

DataAdapter     连接数据,执行数据库命令,填充DataSet

DataSet         数据在内存中的缓存,数据结构

DataReader          只读向前的读取数据库

更详细的可以参看:http://www.phome.net/document/net/200504/net111246243813950.html

 

    还记得的3题是其他内容的,滤波器什么的,更加不懂。就不在这里记录了。

    通过这次笔试,让我明白自己最近半年所关注的内容全是赶着时髦的技术,像Linq,WPF,而自己又没有能力好好的掌握。作为一个学生,书本上的知识快忘光光了,却还在想着需求分析怎么写,概要设计怎么写,详细设计怎么写,该怎么做项目。其实我早应该出去找地方实习了,而不是一味的自己瞎干。眼看大学就快要毕业了,曾经以为自己不迷茫了,结果发现自己还是云里雾里的在学习,原来是越来越迷茫了。也不知道自己的精力该放在哪里了。

     很久没有发过园子里的首页了,记得第一次来博客园稀里糊涂的发到首页被骂个半死,就再也不敢乱发了。这次借着这个机会,一方面希望可以给即将毕业,正在面试求职的战友们一点点帮助,顺便大家可以一起来交流面试求职的心得。另一方面,想请园子里的前辈们,能开导下我这个即将步入社会的年轻人。该怎么样才能在这个行业干得愉快。发现自己怀着很好的心情开始写这篇随笔,到后来却心情沉重。

PS:如果大伙觉得这样放笔试题有问题,我会马上撤销这篇随笔。希望没有问题:)呵呵~如果有跟我一样困惑的朋友,欢迎加群:30918609 一起来讨论。

posted @ 2010-03-05 18:47  idoku  阅读(552)  评论(0编辑  收藏  举报