笔试、面试题

1.堆栈

2.SQL 数据库是面向对象还是面向过程的

3.为什么选软件测试,优势

前端:

1.语义化的理解

2.闭包的理解

(1) for(var i=0;i<=3;i++){
        setTimeout(function(){
            alert(i);
        },0);
    }  //4

(2) var a = 6;
        setTimeout(function(){
            alert(a);
            a = 666;
        },1000);
      a = 66;  //结果 弹出66;(setTimeout(function(){alert(a);a=666;},1000)是1000毫秒后,把function(){alert(a);a=666;}加入到队列,等前面没有其他进程运行的时候再执行;由于setTimeout是异步的,所不会阻塞下面的语句执行;然后执行a=66,等到1000毫秒后且没有其他进程运行的时候执行函数体,所以弹出66(?)


3.JS继承

call()和apply()的区别

4.div嵌套居中

5.http状态码:

    100-199 用于指定客户端应相应的某些动作。
    200-299 用于表示请求成功。
    300-399 用于已经移动的文件并且常被包含在定位头信息中指定新的地址信息。
    400-499 用于指出客户端的错误。400    1、语义有误,当前请求无法被服务器理解。401    当前请求需要用户验证 403    服务器已经理解请求,但是拒绝执行它。
    500-599 用于支持服务器错误。 503 – 服务不可用

6.二分法查找数组某一个元素下标:

function binarySearch(arr, val){
            var low = 0, high = arr.length-1,mid=0;
            while(low<=high){
                mid = Math.floor( (low + high) / 2);
                if(arr[mid] == val){
                    return mid;
                }
                else if(arr[mid] > val){
                    high = mid - 1;
                }
                else{
                    low = mid + 1;
                }
            }
            return -1;
        }


        alert(binarySearch([1,2,5,7,8,9,11],9));



7. P id class style 优先级

8.双向链表排序




笔试:

C/C++

概念:

struct 和 class 

线程 进程 同步方式    :临界区  信号量  事件  互斥量 

char * const p; p为指向字符变量的指针,地址不变,地址内容可变

const char *p;p为指向字符变量的指针,地址可变,地址内容不变

char const *p; 与 const char *p; 等价,只是个人的书写习惯


TCP/IP 五层模型   TCP/IP层次模型共分为五层:应用层HTTP、传输层TCP、网络层IP、数据链路层Data-link、物理层physical。

1)OSI七层模型
 
OSI中的层 功能 TCP/IP协议族
应用层 文件传输,电子邮件,文件服务,虚拟终端 TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet
表示层 数据格式化,代码转换,数据加密 没有协议
会话层 解除或建立与别的接点的联系 没有协议
传输层 提供端对端的接口 TCP,UDP
网络层 为数据包选择路由 IP,ICMP,RIP,OSPF,BGP,IGMP
数据链路层 传输有地址的帧以及错误检测功能 SLIP,CSLIP,PPP,ARP,RARP,MTU
物理层 以二进制数据形式在物理媒体上传输数据 ISO2110,IEEE802,IEEE802.2
 
 


 
 
(2)TCP/IP五层模型的协议
 
应用层
传输层
网络层
数据链路层
物理层
 
物理层:中继器、集线器、还有我们通常说的双绞线也工作在物理层
数据链路层:网桥(现已很少使用)、以太网交换机(二层交换机)、网卡(其实网卡是一半工作在物理层、一半工作在数据链路层)
网络层: 路由器、三层 交换机
传输层:四层交换机、也有工作在四层的路由器
 
 

 

死锁产生条件:产生死锁的原因主要是:
(1) 因为系统资源不足。
(2) 进程运行推进的顺序不合适。
(3) 资源分配不当等。
如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则
就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。
产生死锁的四个必要条件:
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之
一不满足,就不会发生死锁。



1.二叉排序树

2.二维数组

3.排序

4.冒泡排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include 
#define SIZE 8
 
void  bubble_sort( int  a[],  int  n);
 
void  bubble_sort( int  a[],  int  n)
{
     int  i, j, temp;
     for  (j = 0; j < n - 1; j++)
         for  (i = 0; i < n - 1 - j; i++)
         {
             if (a[i] > a[i + 1])
             {
                 temp = a[i];
                 a[i] = a[i + 1];
                 a[i + 1] = temp;
             }
         }
}
 
int  main()
{
     int  number[SIZE] = {95, 45, 15, 78, 84, 51, 24, 12};
     int  i;
     bubble_sort(number, SIZE);
     for  (i = 0; i < SIZE; i++)
     {
         printf ( "%d" , number[i]);
     }
     printf ( "\n" );
}

5.查找

(1)折半查找

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
intBinSearch(SeqList*R,intn,KeyTypeK)
{
//在有序表R[0..n-1]中进行二分查找,成功时返回结点的位置,失败时返回-1
intlow=0,high=n-1,mid; //置当前查找区间上、下界的初值
while (low<=high)
{
if (R[low].key==K)
returnlow;
if (R[high].key==k)
returnhigh;
//当前查找区间R[low..high]非空
mid=low+((high-low)/2);
//使用(low+high)/2会有整数溢出的问题
//(问题会出现在当low+high的结果大于表达式结果类型所能表示的最大值时,
//这样,产生溢出后再/2是不会产生正确结果的,而low+((high-low)/2)不存在这个问题
if (R[mid].key==K)
returnmid; //查找成功返回
if (R[mid].key
low=mid+1; //继续在R[mid+1..high]中查找
 
 
else
high=mid-1; //继续在R[low..mid-1]中查找
 
}
if (low>high)
return -1; //当low>high时表示所查找区间内没有结果,查找失败
} //BinSeareh
 
------------上面代码复杂难懂-----------------
intbsearchWithoutRecursion(intarray[],intlow,inthigh,inttarget)
{
while (low<=high)
{
intmid=(low+high)/2;
if (array[mid]>target)
high=mid-1;
elseif(array[mid]
low=mid+1;
else //findthetarget
returnmid;
}
//thearraydoesnotcontainthetarget
return -1;
}
----------------------------------------
递归实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
intbinary_search(constintarr[],intlow,inthigh,intkey)
{
intmid=low+(high-low)/2;
if (low>high)
return -1;
else {
if (arr[mid]==key)
returnmid;
elseif(arr[mid]>key)
returnbinary_search(arr,low,mid-1,key);
else
returnbinary_search(arr,mid+1,high,key);
}
}

6.C语言编写 1到10 的整数相加

#include

using namespace std;

#include

#include

void main()

{

  int i=0;

  for(int j=1;j<=10;j++)

  {

    i+=j;

  }

  cout<<"1+2+...+10="<

  system("pause");

}

7.

void main()  
{  
        int a = 1;
int b = a++;

                                      

cout<

void main()  
{  
        int a = 1;
int c = ++a;

cout<

8.1到n求和

(1)void main()
{
   int n; 
   printf("请输入一个整数:\n");
   scanf("%d",&n); 
   printf("运算结果:%d",(n+1)*n/2);
  system("pause");
}



(2)

int sum(int n)
{
   int result = 0;


   if(n == 1)
   {
       result = 1;
   }
   else if(n > 1)
   {
       result = sum(n-1) + n;
   }
   return result;
}


void main()
{
 int n; 
printf("请输入一个整数:\n");
    scanf("%d",&n); 
    int result = sum(n);
cout<     system("pause");
}

(3)指针+递归

 
  

void Add(int *n,int *ret){if (*n<1){return;}else{*ret+=*n;*n=*n-1;Add(n,ret);}}void main(){int n;int ret=0;printf("请输入一个整数:\n");scanf("%d",&n);Add(&n,&ret);printf("运算结果:%d\n",ret);    system("pause");}

9. GDI 绘图的类和函数

10.C/S架构  服务器访问人数不能超过1万人,如果很多用户同时访问一个服务器会导致速度变慢,服务器是 PC SERVER(具体题目记不太清楚了)

1、修改连接池。
2、进行压力测试。
3、给需要查询最多的数据库字段创建索引。
4、再就是关于硬件、内存、网速的配置了。
5、设置并发数量。

仔细的分析后台代码,找出瓶颈所在,并通过优化算法等改进性能

PC Server是使用普通的PC做服务器小型机就是我们真正的高端配置的服务器性能,兼容性差别很大

11.求最大子序列和

#include

using namespace std;

int* MaxSum(int arr[],int count){    //start_tmp和max_tmp是临时存储开始位置和    //最大和的变量    

int Start,End,Max,result[3],start_tmp,max_tmp;  

  int i;   

Start=End=start_tmp=0;   

Max=max_tmp=arr[0];   

for(i=1;i

  {       

if(max_tmp>=0)        

    max_tmp+=arr[i];     

  else       {          

  max_tmp=arr[i];            

start_tmp=i;      

  }       

if(Max

  {            

Max=max_tmp;         

  Start=start_tmp;      

      End=i;       

}   

}   

result[0]=Max;    //“+1”是把数组的0号元素当成第一个来数    //这样比较直观  

  result[1]=Start+1;  

  result[2]=End+1;    

return result;

}//测试

void main(){    

int arr[7]={0,6,-1,1,-6,7,-5};  

int *result=MaxSum(arr,7);    

cout<system("pause");}

最大字段和 n个整数(含负数)

 
int  max_sum( int  s[],  int  n) {
     int  max = 0;
     int  sum = 0;
     for  ( int  i = 0; i < n; i++) {
         if (sum + s[i] > 0)
             sum = sum + s[i];
         else
             sum = 0;
         if (sum > max)
              max = sum;
      }
      return  max;
 
int  main() {
     int  a[12]={27,6,-50,21,-3,14,16,-8,42,33,-21,9};
     cout << max_sum(a,12) << endl;
     cin.get();
}

13.二叉树

层次遍历

void level(BTNode *p)

{

int front,rear;

BTNode *que[maxsize];

front =rear = 0;

BTNode *q;

if(p!=NULL)

{

rear = (rear + 1) % maxsize;

que[rear]=p;

while(front!=rear)

{

front = (front+1)%maxsize;

q = que[front];

visit(q);

if(q->lchild!=null)

{

rear = (rear + 1)%maxsize;

que[rear]=q->lchild;

}

if(q->rchild!=null)

{

  rear=(rear+1)%maxsize;

que[rear] = q->rchild;

}

}

}

}

struct BiNode {  
    char data;  
    struct BiNode *lchild, *rchild;  
}BiNode;  
struct BiNode *T; 
struct BiNode *CreateBiTree(struct BiNode *T) {       //创建
    char data;  
    scanf("%c", &data);  
    if((data=='#')||(data=='\n')) {  
        T = NULL;  
    } else {  
        T = (struct BiNode *)malloc(sizeof(struct BiNode));  
       if(T==NULL) {  
            printf("memory error");  
        }  
        T->data = data;  
        T->lchild = CreateBiTree(T->lchild);  
        T->rchild = CreateBiTree(T->rchild);  
    }  
    return T;  
}  
  
void PreOrderTraverse(struct BiNode *T) {     //先序遍历
    if(T==NULL) {  
        return;  
    } else {  
        printf("%c ", T->data);  
        PreOrderTraverse(T->lchild);  
        PreOrderTraverse(T->rchild);  
    }  
}  
 int height(struct BiNode *T)                  //求高度
 {  int lh,rh,h=0;
      if(T==NULL)
      h=0;
      else
    {lh=height(T->lchild);
    rh=height(T->rchild);
    h=(lh>rh ? lh:rh)+1;}
    return h;  
    
       } 
  
int main() { int mul; 
        T = NULL;  
   T = CreateBiTree(T);  
   printf("先序遍历: \n");  
   PreOrderTraverse(T);  
   printf("\n");  
  printf("%d",height(T));

   getch();
   return 0;  
}


14. #include<>和#include " " 的区别

< >引用的是编译器的类库路径里面的头文件
" "引用的是你程序目录的相对路径中的头文件

假如你编译器定义的自带头文件引用在C:\Keil\c51\INC\下面
则#include引用的就是C:\Keil\c51\INC\stdio.h这个头文件
不管你的项目在什么目录里,C:\Keil\c51\INC\stdio.h这个路径就定下来了
一般是引用自带的一些头文件:stdio.h、conio.h、string.h、stdlib.h等等之类的。。

假如你的项目目录是在D:\Projects\tmp\
则#include "my.h" 引用的就是D:\Projects\tmp\my.h这个头文件
一般是用来引用自己写的一些头文件
如果使用" ",它是会先在你项目的当前目录查找是否有对应头文件
如果没有,它还是会在对应的引用目录里面查找对应的头文件
意思就是,使用#include "stdio.h"如果你项目目录里面,没有stdio.h这个头文件,它还是会定位到C:\Keil\c51\INC\stdio.h这个头文件的
15.将数字型字符串转换成整数

#include
using namespace std;




long fun ( char *p)
{


int i, len, t;
long x=0;
len=strlen(p);


   if(p[0]=='-')

t=-1; len--; p++; 
}
else 
t=1;


while(*p)
x=10*x+(*p-48),p++;


return x*t;
}
void main()
{     
char s[6];
long n;
printf("Enter a string:\n") ;
gets(s);
n = fun(s);
printf("%ld\n",n);
system("pause");
}

16.数组和链表的区别

  • 数组是将元素在内存中连续存放,由于每个元素占用内存相同,可以通过下标迅速访问数组中任何元素。但是如果要在数组中增加一个元素,需要移动大量元素,在内存中空出一个元素的空间,然后将要增加的元素放在其中。同样的道理,如果想删除一个元素,同样需要移动大量元素去填掉被移动的元素。如果应用需要快速访问数据,很少或不插入和删除元素,就应该用数组。
  • 链表恰好相反,链表中的元素在内存中不是顺序存储的,而是通过存在元素中的指针联系到一起。比如:上一个元素有个指针指到下一个元素,以此类推,直到最后一个元素。如果要访问链表中一个元素,需要从第一个元素开始,一直找到需要的元素位置。但是增加和删除一个元素对于链表数据结构就非常简单了,只要修改元素中的指针就可以了。如果应用需要经常插入和删除元素你就需要用链表数据结构了。

   *C++语言中可以用数组处理一组数据类型相同的数据,但不允许动态定义数组的大小,即在使用数组之前必须确定数组的大小。而在实际应用中,用户使用数组之前有时无法准确确定数组的大小,只能将数组定义成足够大小,这样数组中有些空间可能不被使用,从而造成内存空间的浪费。链表是一种常见的数据组织形式,它采用动态分配内存的形式实现。需要时可以用new分配内存空间,不需要时用delete将已分配的空间释放,不会造成内存空间的浪费。
  (1) 从逻辑结构角度来看
     a, 数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费。
     b,链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。(数组中插入、删除数据项时,需要移动其它数据项)
  (2)从内存存储角度来看
     a,(静态)数组从栈中分配空间, 对于程序员方便快速,但自由度小。
     b, 链表从堆中分配空间, 自由度大但申请管理比较麻烦.

17.浅复制和深复制

C++中,浅复制和深复制对于完全的值类型没有区别。
如果类或结构体的实例中含有指向不同属于一个对象的其它对象的指针时,那么浅复制和深复制的行为就有差异。浅复制仅复制对象本身(其中包括是指针的成员),这样不同被复制对象的成员中的对应非空指针会指向同一对象,被成员指针引用的对象成为共享的,无法直接通过指针成员安全地删除(因为若直接删除,另外对象中的指针就会无效,而访问无效指针是危险的;除非这些指针有引用计数或者其它手段确保被指对象的所有权);而深复制在浅复制的基础上,连同指针指向的对象也一起复制,代价比较高,但是相对容易管理。
Java/C#用引用类型代替指针类型,在语言的特定上下文中有特定的操作模式和约定。具体可以见LS两位提供的链接。

深拷贝和浅拷贝

(1)什么时候用到拷贝函数?

  a.一个对象以值传递的方式传入函数体; 
  b.一个对象以值传递的方式从函数返回;
  c. 一个对象需要通过另外一个对象进行初始化。

如果在类中没有显式地声明一个拷贝构造函数,那么,编译器将会自动生成一个默认的拷贝构造函数,该构造函数完成对象之间的位拷贝。位拷贝又称浅拷贝

 

(2)是否应该自定义拷贝函数?

 

 

(3)什么叫深拷贝?什么是浅拷贝?两者异同?

自定义拷贝构造函数是一种良好的编程风格,它可以阻止编译器形成默认的拷贝构造函数,提高源码效率。

 

 

深如果一个类拥有资源,当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝。

 

(4)深拷贝好还是浅拷贝好?

如果实行位拷贝,也就是把对象里的值完全复制给另一个对象,如A=B。这时,如果B中有一个成员变量指针已经申请了内存,那A中的那个成员变量也指向同一块内存。这就出现了问题:当B把内存释放了(如:析构),这时A内的指针就是野指针了,出现运行错误。



18. new delete malloc free

相同点:都可用于申请动态内存和释放内存

不同点
(1)操作对象有所不同
malloc与free是C++/C 语言的标准库函数,new/delete 是C++的运算符。对于非内部数据类的对象而言,光用maloc/free 无法满足动态对象的要求。对象在创建的同时要自动执行构造函数, 对象消亡之前要自动执行析构函数。由于malloc/free 是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加malloc/free。

(2)用法上也有所不同
函数malloc 的原型如下:
void * malloc(size_t size);
用malloc 申请一块长度为length 的整数类型的内存,程序如下:
int *p = (int *) malloc(sizeof(int) * length);
我们应当把注意力集中在两个要素上:“类型转换”和“sizeof”。
1、malloc 返回值的类型是void *,所以在调用malloc 时要显式地进行类型转换,将void * 转换成所需要的指针类型。
2、 malloc 函数本身并不识别要申请的内存是什么类型,它只关心内存的总字节数。
函数free 的原型如下:
void free( void * memblock );
为什么free 函数不象malloc 函数那样复杂呢?这是因为指针p 的类型以及它所指的内存的容量事先都是知道的,语句free(p)能正确地释放内存。如果p 是NULL 指针,那么free
对p 无论操作多少次都不会出问题。如果p 不是NULL 指针,那么free 对p连续操作两次就会导致程序运行错误。

19. 不调用c++/c字符串库函数,编写函数strcmp/strcpy

#include
using namespace std;




#include


// 将字符串s中的内容拷贝到d中,包括字符串结束符'\0'
char *strcpy(char *d, const char *s)
{
    char *p = d;
    while (1)
    {
        *p = *s;
        if (*p == '\0') break;
        
        p++;
        s++;
    }
    
    return p;
}


// 按ascii码比较字符串a和b的内容大小,a > b返回正整数,a < b返回负整数,a == b返回0
int strcmp(const char *a, const char *b)
{
    while(*a != '\0' && *a == *b)
    {
        a++;
        b++;
    }
    
    return (int)(*a - *b);
}


// 测试这两个自定义函数
int main()
{
    char s[20];
    char *p = "abc";
    char *q = "ab";
    
    strcpy(s, p);
    
    printf("%s\n", s);
    printf("%d\n", strcmp(p, q));
    system("pause");
    return  0;

}



20.单链表创建 插入节点 删除节点 单链表反转


  1. #include   
  2. #include   
  3. #include   
  4. typedef struct student  
  5. {  
  6.     int num;  
  7.     char name[16];  
  8.     struct student *next;  
  9. }node;  
  10. node *creat()//创建链表  
  11. {  
  12.     int x;  
  13.     int cycle = 1;  
  14.     char stu_name[16];  
  15.     node *head,*p,*s;  
  16.     head =(node*)malloc(sizeof(node));  
  17.     p = head;  
  18.     while(cycle)  
  19.     {  
  20.         printf("please input the student number:");  
  21.         scanf("%d",&x);  
  22.         if(x != 0)  
  23.         {  
  24.             printf("please input the student name:");  
  25.             scanf("%s",stu_name);  
  26.         //  printf("STU_NAME:%s/n", stu_name);  
  27.             s = (node *)malloc(sizeof(node));  
  28.                         if(NULL == s)  
  29.                         {  
  30.                         exit(1);  
  31.                         }  
  32.             s->num = x;  
  33.             memcpy(s->name, stu_name, 16);  
  34.             p->next = s;  
  35.             p = s;   
  36.         }  
  37.         else  
  38.             cycle = 0;  
  39.     }  
  40.     head = head->next;  
  41.     p->next = NULL;  
  42.     return head;  
  43. }  
  44. int length(node *head)//链表测长  
  45. {  
  46.     int n = 0;  
  47.     node *p;  
  48.     p = head;  
  49.     while(p != NULL)  
  50.     {  
  51.         n++;  
  52.                 p = p->next;  
  53.                   
  54.     }  
  55.     return (n);  
  56. }  
  57. node *insert(node *head, int num, int length)//链表插入,NUM表示在第几个位置插入  
  58. {  
  59.     int n=num;  
  60.     int i = 1;  
  61.     node *p0,*p1,*p2;  
  62.     p1 = head;  
  63.     p0 = (node *)malloc(sizeof(node));  
  64.     printf("please input the student number:");  
  65.     scanf("%d", &p0->num);  
  66.     printf("please input the student name:");  
  67.     scanf("%s", &p0->name);  
  68.     if(n == 1)//插入表头  
  69.     {  
  70.         p0->next = p1;  
  71.         head = p0;  
  72.         return (head);  
  73.     }  
  74.     while(i < n-1)//找到要插入的前置节点  
  75.     {  
  76.         p1 = p1->next;  
  77.         i++;  
  78.     }  
  79.     p2 = p1->next;  
  80.     p1->next = p0;  
  81.     p0->next = p2;  
  82.     if(n == length+1)//插入表尾  
  83.     {  
  84.         p1->next = p0;  
  85.         p0->next = NULL;  
  86.     }  
  87.     return (head);  
  88. }  
  89. node *delete(node *head, int location, int length)//删除链表节点  
  90. {  
  91.     int n = location;  
  92.     int i = 1;  
  93.     node *p1,*p2;  
  94.     p1 = head;  
  95.     if(n == 1)  
  96.     {  
  97.         head = p1->next;  
  98.         free(p1);  
  99.         return (head);  
  100.     }  
  101.     while(i < n-1)//找到要删除的节点的前置节点  
  102.     {  
  103.         p1 = p1->next;  
  104.         i++;  
  105.     }  
  106.     if(n < length)  
  107.     {  
  108.         p2 = p1->next;  
  109.         p1->next = p2->next;  
  110.         free(p2);  
  111.     }  
  112.     if(n == length)  
  113.     {  
  114.         p2 = p1->next;  
  115.         p1->next = NULL;  
  116.         free(p2);  
  117.     }  
  118.     return (head);  
  119. }  
  120. void print(node *head)  
  121. {  
  122.     while(head != NULL)  
  123.     {  
  124.         printf("students:%d/n", head->num);  
  125.                 printf("student name: %s/n", head->name);  
  126.         head = head->next;  
  127.                   
  128.     }  
  129. }  
  130. node *invert(node *head)//链表逆置  
  131. {  
  132. node *p1,*p2,*p3;  
  133. p1 = head;  
  134. p2 = p1->next;  
  135. while(p2)  
  136. {  
  137. p3 = p2->next;  
  138. p2->next = p1;  
  139. p1=p2;  
  140. p2=p3;  
  141. }  
  142. head->next = NULL;  
  143. head = p1;  
  144. return (head);  
  145. }  
  146. int main(int argc, char **argv)  
  147. {  
  148.     int len,insert_num,del_num;  
  149.     node *stu_node;  
  150.     stu_node = creat();  
  151.     print(stu_node);  
  152.     len = length(stu_node);  
  153.     printf("there are %d node/n", len);  
  154.     printf("what dou you want to do?/n[a]打印链表 [b]逆置链表 [c]删除节点 [d]插入节点: ");  
  155. char ch,c;  
  156. c = getchar();//用于清除缓冲区中的/n字符  
  157. scanf("%c",&ch);  
  158.     switch (ch)  
  159.     {  
  160.         case 'a': print(stu_node);  
  161.               break;  
  162.         case 'b': stu_node = invert(stu_node);  
  163.               print(stu_node);  
  164.               break;  
  165.         case 'c':   
  166.               printf("which node dou you want to detele?:");  
  167.               scanf("%d", &del_num);  
  168.               stu_node = delete(stu_node, del_num, len);  
  169.               print(stu_node);  
  170.               break;  
  171.         case 'd':  
  172.               printf("which location dou you want to insert:");  
  173.               scanf("%d",&insert_num);  
  174.               stu_node = insert(stu_node , insert_num, len);  
  175.               print(stu_node);  
  176.               break;  
  177.     }  
  178.     return 0;  
  179. }  
 

反转单链表。假设单链表的数据结构定义如下:

  

typedef  struct  LNode
{
     int      data;
     struct  LNode    *next;
}LNode, *LinkedList;

  并且这个单链表有一个头指针list指向第一个结点,最后一个结点指向NULL,很容易理解。

  最容易想到的第一种方法就是重新建立一个单链表newList,每次将list中的第一个结点放到newList后面。注释比较详细,所以就不具体说了,直接看代码吧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
LinkedList ReverseSinglyLinkedList(LinkedList list)
{
     LinkedList  newList;     //新链表的头结点
     LNode       *tmp;        //指向list的第一个结点,也就是要摘除的结点
 
     //
     //参数为空或者内存分配失败则返回NULL
     //
     if  (list == NULL || (newList = (LinkedList) malloc ( sizeof (LNode))) == NULL)
     {
         return  NULL;
     }
 
     //
     //初始化newList
     //
     newList->data = list->data;
     newList->next = NULL;
 
     //
     //依次将list的第一个结点放到newList的第一个结点位置
     //
     while  (list->next != NULL)
     {
         tmp = newList->next;          //保存newList中的后续结点
         newList->next = list->next;        //将list的第一个结点放到newList中
         list->next = list->next->next;      //从list中摘除这个结点
         newList->next->next = tmp;         //恢复newList中后续结点的指针
     }
 
     //
     //原头结点应该释放掉,并返回新头结点的指针
     //
     free (list);
     return  newList;
}

  第二种方法是每次都将原第一个结点之后的那个结点放在list后面,下图是原始的单链表。

  为了反转这个单链表,我们先让头结点的next域指向结点2,再让结点1的next域指向结点3,最后将结点2的next域指向结点1,就完成了第一次交换,顺序就变成了Header-结点2-结点1-结点3-结点4-NULL,然后进行相同的交换将结点3移动到结点2的前面,然后再将结点4移动到结点3的前面就完成了反转,思路有了,就该写代码了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
LinkedList ReverseSinglyLinkedList(LinkedList list)
{
     LNode   *tmp = NULL;
     LNode   *p = NULL;
 
     if  (list == NULL)
     {
         return  NULL;
     }
     tmp = list->next;
     while  (tmp->next != NULL)
     {
         p = tmp->next;
         tmp->next = p->next;
         p->next = list->next;
         list->next = p;
     }
     return  list;
}
21.C++调用被C编译后的函数为什么要加 extern c ?

C++语言支持函数重载,C 语言不支持函数重载。函数被C++编译后在库中的名字
与C 语言的不同。假设某个函数的原型为: void foo(int x, int y);
该函数被C 编译器编译后在库中的名字为_foo , 而C++ 编译器则会产生像
_foo_int_int 之类的名字。
C++提供了C 连接交换指定符号extern“C”来解决名字匹配问题。

 

如果C++程序要调用已经被编译后的C函数,该怎么办? 假设某个C函数的声明如下: void foo(int x, int y); 该函数被C编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字用来支持函数重载和类型安全连接。由于编译后的名字不同,C++程序不能直接调用C函数。C++提供了一个C连接交换指定符号extern“C”来解决这个问题。例如: extern “C” { void foo(int x, int y); … // 其它函数 } 或者写成 extern “C” { #include “myheader.h” … // 其它C头文件 } 这就告诉C++编译译器,函数foo是个C连接,应该到库中找名字_foo而不是找_foo_int_int。C++编译器开发商已经对C标准库的头文件作了extern“C”处理,所以我们可以用#include 直接引用这些头文件。

22.输入两个正整数,求其最大公倍数和公约数


  1. # include   
  2.   
  3. int  main(void)  
  4. {  
  5.     int x, y, num1, num2, temp;  
  6.       
  7.     printf("请输入两个正整数:\n");  
  8.     scanf("%d %d", &num1, &num2);  
  9. if(num1 < num2)  
  10.     {  
  11.         temp = num1;  
  12.         num1 = num2;  
  13.         num2 = temp;  
  14.     }  
  15.     x = num1;  
  16.     y = num2;  
  17.     while(y != 0)  
  18.     {  
  19.         temp = x%y;  
  20.         x = y;  
  21.         y = temp;  
  22.     }  
  23. printf("它们的最大公约数为:%d\n", x);  
  24.     printf("它们的最小公倍数为:%d\n", num1*num2/x);  
  25.       
  26.     return 0;  
  27. }  

23.设计程序按从大到小依次输出函数f(a+b)=2*a*a+b*b的最小的100个函数值


24.

从扑克牌中随机抽5张牌,判断是不是一个顺子

点击打开链接



第一php网提供的教程–从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。






/*
* 算法要求:
* 从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。
* 2-10为数字本身,A为1,J为11,Q为12,K为13,而大小王可以看成任意数字。
*
* 算法分析:符合顺子的扑克牌,5张扑克牌的数字之间只能相差1,花色一样是同花顺。大小王可以作为任意数字,如果抽到了一个王,那么可以填补
* 一个空位,如:1 [] 3 4 5,2用王代替;如果抽中了2个王,则可以填补2个空位,如:1 [] [] 4 5。这里重要的是要判断在什么情行下
* 使用王来填补空位时,正好满足顺子的要求。我们首先来看,如何判断5个数为顺序的。我们使用for循环,从第一个数开始遍历,每循环一次当前数+1,
* 然后判断+1后的结果是否存在于扑克牌的值中,如果存在说明下一个数与前面的数构成顺序,那么使用continue关键字,从第二个数开始循环,仍然是+1,
* 然后比较;这样的比较进行4次,每得到一个顺序序列,计数器自增,如果最后计数器的值等于4,那么说明这个数列是顺子。
*
* 现在,我们来考虑一个王的情形。我们知道一个王可以填补一个空位,如果这个空位两边都有数,那么这两个数的差不能超过2,如:1 [] 4 5 6
* ,这样即使有王也无法满足顺子的要求。这里我们比较的时候跟5个数字不同,首先我们对当前数字+1,如果存在继续循环;如果不存在,则+2,+2
* 后如果存在,继续循环;不存在,也继续循环。如1 [] 3 4 5,1+1=2不存在,1+2=3,存在。这样,到最后如果使用王后符合顺子的要求,计数器
* 应该等于3。
*
* 2个王的情形跟上面差不多,只不过还增加了一个+3的情况,如:1 [] [] 4 5。最近计数器的值应该等于2。
*
* 如果一个王都没有,就更简单了,只要其余的4个数构成顺子,那么就一定是顺子。
*
* 花色的判断简单,使用array_unique函数去掉重复值,如果最后数组个数为1,是同花顺;不是,就是普通顺子。
*/
session_start();
//定义扑克牌
$poker=array(‘黑桃_1′,’黑桃_2′,’黑桃_3′,’黑桃_4′,’黑桃_5′,’黑桃_6′,’黑桃_7′,’黑桃_8′,’黑桃_9′,’黑桃_10′,’黑桃_11′,’黑桃_12′,’黑桃_13′,
‘红桃_1′,’红桃_2′,’红桃_3′,’红桃_4′,’红桃_5′,’红桃_6′,’红桃_7′,’红桃_8′,’红桃_9′,’红桃_10′,’红桃_11′,’红桃_12′,’红桃_13′,
‘梅花_1′,’梅花_2′,’梅花_3′,’梅花_4′,’梅花_5′,’梅花_6′,’梅花_7′,’梅花_8′,’梅花_9′,’梅花_10′,’梅花_11′,’梅花_12′,’梅花_13′,
‘方块_1′,’方块_2′,’方块_3′,’方块_4′,’方块_5′,’方块_6′,’方块_7′,’方块_8′,’方块_9′,’方块_10′,’方块_11′,’方块_12′,’方块_13′,
‘sking’,’bking’);
shuffle($poker);//洗牌
$fp=array_rand($poker,5);//抽五张牌
foreach($fp as $value)
{
$p_arr[]=$poker[$value];
}
//打印抽取的牌
echo ‘你抽取的是:
'; 
   
print_r($p_arr);
echo ‘
';

$p_color=array();//定义数组存储花色
$p_value=array();//定义数组扑克牌的值
foreach ($p_arr as $value)//遍历扑克牌
{
if($value==’sking’)//如果抽中了小王
{
$p_color[]=’any';//花色可以任意
$p_value[]=’14′;//值可以任意,定义为14,方便排序
}
else if($value==’bking’)//如果抽中了大王
{
$p_color[]=’any';//花色可以任意
$p_value[]=’15′;//值可以任意,定义为14,方便排序
}
else//如果没有抽中任何王
{
$arr=explode(‘_’,$value);//分隔花色和值
$p_color[]=$arr[0];//存储花色
$p_value[]=$arr[1];//存储值
}
}
array_unique($p_color);//判断有几种花色
$clen=count($p_color);
sort($p_value);//对扑克牌进行排序
$len=count($p_value);//计算扑克牌的数量,实际上就是5
$twostep=false;
$threestep=false;
//如果只抽中一个王
if((in_array(’14’,$p_value)&&!in_array(’15’,$p_value))||(in_array(’15’,$p_value)&&!in_array(’14’,$p_value)))
{
$len–;
for($i=0;$i
{
if(in_array($p_value[$i]+1,$p_value))//执行+1比较
{
$cons++;
continue;
}
else if(!$twostep&&in_array($p_value[$i]+2,$p_value))//执行+2比较
{
$cons++;
$twostep=true;
continue;
}
else
{
continue;
}
}
if($cons==3&&$clen==1)
{
echo ‘同花顺';
}
else if($cons==3&&$clen==2)
{
echo ‘是顺子,但是非同花顺';
}
else
{
echo ‘不是顺子';
$_SESSION[‘unlucky’]++;
}
}
else if(in_array(’14’,$p_value)&&in_array(’15’,$p_value))//如果抽中2个王
{
$len=$len-2;
for($i=0;$i
{
if(in_array($p_value[$i]+1,$p_value))//执行+1比较
{
$cons++;
continue;
}
else if(!$threestep&&in_array($p_value[$i]+2,$p_value))//执行+2比较
{
$cons++;
continue;
}
else if(!$threestep&&in_array($p_value[$i]+3,$p_value))//执行+3比较
{
$cons++;
$threestep=true;
continue;
}
else
{
continue;
}
}
if($cons==2&&$clen==1)
{
echo ‘同花顺';
}
else if($cons==2&&$clen==2)
{
echo ‘是顺子,但是非同花顺';
}
else
{
echo ‘不是顺子';
$_SESSION[‘unlucky’]++;
}
}
//如果没抽中任何王
else if(!in_array(’14’,$p_value)&&!in_array(’15’,$p_value))
{
for($i=0;$i
{
if(in_array($p_value[$i]+1,$p_value))//执行+1比较
{
$cons++;
continue;
}
}
if($cons==4&&$clen==1)
{
echo ‘同花顺';
}
else if($cons==4&&$clen==2)
{
echo ‘是顺子,但是非同花顺';
}
else
{
echo ‘不是顺子';
$_SESSION[‘unlucky’]++;
}
}
?>




点击打开链接

题目:一幅扑克牌,任意抽取5张,判断是5张牌是否是顺子。“顺子”指的是五张牌的紧紧相连的五张牌,如A,2,3,4,5或者8,9,10,J,Q,其中,大小王可以代表任意你想代表的牌。设计一个程序判断随机抽取的5张牌是否是顺子。
 
思路:将扑克牌A,2,3,...,K,分别以数字1,2,3,...,13表示,大、小王用20表示。定义数组int a[5],将5张扑克牌对应的数字存入数组,对数组进行升序排序,查看元素是否按照公差为1递增。分大、小王存在与否的情况讨论。具体实现如下:
 
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include  
using namespace std; 
   
void sort( int a[], int n) //升序排序 
     int temp = 0; 
     for ( int i=0;i
         for ( int j=i+1;j
        
             if (a[i]>a[j]) 
            
                 temp = a[i]; 
                 a[i] = a[j]; 
                 a[j] = temp; 
            
        
   
bool IsShunZi( int a[], int n) 
     sort(a,n); //升序排列 
     int num = 0; //大小王的个数(一幅牌中,可以为0,1,2) 
     for ( int i=0;i
         if (a[i]==20) 
                 num++; 
   
     //牌出现重复的情况 
     for ( int i=0;i
         for ( int j=i+1;j
             if (a[i]==a[j]) 
                 return false
       
     switch (num) 
    
     case 0: if (a[4]-a[0]==4) 
                return true
            else 
                return false
            break
     case 1: if (a[3]-a[0]<=4) 
                return true
            else 
                return false
            break
     case 2: if (a[2]-a[0]<=4) 
                return true
            else  
                return false
            break
     default : return false ; break
    
int  main( ) 
     int a[5] = {2,3,20,6,20}; //扑克牌对应的数组 
     bool bt = IsShunZi(a,5); //函数调用 
   
     if (bt) 
        
             cout<< "顺子!" <
        
     else 
        
             cout<< "不是顺子!" <
        
   
     system ( "pause" ); 
       
     return 0; 

 

已知类String的原型为: 
C++代码   收藏代码
  1. class String  
  2. {  
  3. public:  
  4.      String(const char *str = NULL);// 普通构造函数  
  5.      String(const String &other);    // 拷贝构造函数  
  6.      ~ String(void);    // 析构函数  
  7.      String & operate =(const String &other);// 赋值函数  
  8. private:  
  9.      char *m_data;// 用于保存字符串  
  10. };   

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

C++代码   收藏代码
  1. //普通构造函数  
  2. String::String(const char *str)  
  3. {  
  4.         if(str==NULL)  
  5.         {  
  6.                 m_data = new char[1]; // 得分点:对空字符串自动申请存放结束标志'\0'的//加分点:对m_data加NULL 判断  
  7.                 *m_data = '\0';  
  8.         }      
  9.         else  
  10.         {  
  11.          int length = strlen(str);  
  12.          m_data = new char[length+1]; // 若能加 NULL 判断则更好  
  13.          strcpy(m_data, str);  
  14.         }  
  15. }   
  16. // String的析构函数  
  17. String::~String(void)  
  18. {  
  19.         delete [] m_data; // 或delete m_data;  
  20. }  
  21. //拷贝构造函数  
  22. String::String(const String &other)    // 得分点:输入参数为const型  
  23. {       
  24.         int length = strlen(other.m_data);  
  25.         m_data = new char[length+1];     //加分点:对m_data加NULL 判断  
  26.         strcpy(m_data, other.m_data);      
  27. }   
  28. //赋值函数  
  29. String & String::operate =(const String &other) // 得分点:输入参数为const  
  30.   
  31. 型  
  32. {       
  33.         if(this == &other)                    //得分点:检查自赋值  
  34.                 return *this;     
  35.         delete [] m_data;                //得分点:释放原有的内存资源  
  36.         int length = strlen( other.m_data );        
  37.         m_data = new char[length+1];  //加分点:对m_data加NULL 判断  
  38.         strcpy( m_data, other.m_data );     
  39.         return *this;             //得分点:返回本对象的引用    
  40.   
  41. }  



测试:

1.白盒测试 黑盒测试 概念 区别 黑盒测试的类型

白盒测试方法按照程序内部的结构测试程序,检验程序中的每条通路是否都能按预定要求正确工作,而不顾它的功能。

白盒测试的主要方法有逻辑覆盖、基本路径测试等

逻辑覆盖包括:
1、语句覆盖

2、判断覆盖

3、条件覆盖

4、判断/条件覆盖

5、条件组合覆盖

6、路径覆盖


黑盒测试并不涉及程序的内部结构和内容特性,主要根据规格说明,只依靠被测试程序的输入和输出之间关系或程序的功能来设计测试用例。

黑盒测试主要包括边界值分析法、等价类划分法、因果图法、决策表法等。


2.软件的生命周期:
软件生命周期又称为软件生存周期或系统开发生命周期,是软件的产生直到报废的生命周期,周期内有问题定义、可行性分析、总体描述、系统设计、编码、调试和测试、验收与运行、维护升级到废弃等阶段,这种按时间分程的思想方法是软件工程中的一种思想原则,即按部就班、逐步推进,每个阶段都要有定义、工作、审查、形成文档以供交流或备查,以提高软件的质量。但随着新的面向对象的设计方法和技术的成熟,软件生命周期设计方法的指导意义正在逐步减少。 生命周期的每一个周期都有确定的任务,并产生一定规格的文档(资料),提交给下一个周期作为继续工作的依据。按照软件的生命周期,软件的开发不再只单单强调“编码”,而是概括了软件开发的全过程。软件工程要求每一周期工作的开始只能必须是建立在前一个周期结果“正确”前提上的延续;因此,每一周期都是按“活动 ── 结果 ── 审核 ── 再活动 ── 直至结果正确”循环往复进展的。

3.软件验收测试
实施验收测试的常用策略有三种,它们分别是:
· 正式验收
· 非正式验收或 Alpha 测试
· Beta 测试
4.压力测试 负载测试 区别
负载测试和压力测试的区别:负载测试在于确定最终满足系统指标的前提下,系统所能承受的最大负载测试,压力测试的目标则在确定什么条件下系统性能处于失效状态。
负载测试:在一定的工作负荷下,给系统造成的负荷及系统响应的时间。 
压力测试:在一定的负荷条件下,长时间连续运行系统给系统性能造成的影响。
5.系统测试有哪些
主要进行功能测试(含可使用性测试)、性能测试、安全测试和回归测试。
功能测试:
检查被测系统的修改和增加功能是否正常实现;
检查控制流程图和模块关系图、模块内部关系图;
识别特殊情况,如出错处理流程,错误提示是否合理;
检查用户界面是否符合窗口程序的标准,界面操作是否简便直观。
性能测试:
系统运行占用的资源,完成某一步骤需要的时间;
系统能承受的压力;
压力完成后数据库连接数立即恢复正常值
安全性测试:
根据需求说明检查系统是否达到安全性要求,如同一用户登陆不同机器,同时操作对数据的破坏;
写到配置文件或数据库的密码是否经过加密;回归测试:
验证Bug是否修正;
Bug修正后是否影响其他功能的正常运行。

前端:

1.({fpp:true}).foo

2.判断A、B、C不相等

3.创建person的一个实例

 4.

function A()
   {
       this.do = function(){return 'foo';}
   }
   A.prototype = function()
   {
       this.do = function(){return 'bar';}


   }
    var x = new A().do();
    var printName = function()
    {
        alert('matt');
        printName = function()
        {
            alert('James');
        }
    }
    var copy = printName;
    printName();
    copy();

matt matt

5.比较输入的两个Json的内容是否完全相同

6.区分单双字节来截取字符

  function substr(str, len)
    {
        if( ! str || ! len)
        {
            return '';
        }
        // 预期计数:中文2字节,英文1字节
        var a = 0;
        // 循环计数
        var i = 0;
        // 临时字串
        var temp = '';
        for (i = 0; i < str.length; i ++ )
        {
            if (str.charCodeAt(i) > 255)
            {
                // 按照预期计数增加2
                a += 2;
            }
            else
            {
                a ++ ;
            }
            // 如果增加计数后长度大于限定长度,就直接返回临时字符串
            if(a > len)
            {
                return temp;


            }
            // 将当前内容加到临时字符串
            temp += str.charAt(i);
        }
        // 如果全部是单字节字符,就直接返回源字符串
        return str;
    }


    var str = "你a好Tom";


   var len = 3;


    


    document.write("" + substr(str, len) + "

");






你可能感兴趣的:(面试题,笔试题,总结)