华为C++面试题

C/C++面试题 专栏收录该内容
7 篇文章 0 订阅
 

suningin华为招聘--前人经验(1)

 

这篇文章是写给2007届的毕业生的,我想我这些日子的经历应该能给2007届的师弟和师妹们将来的校园招聘提供点帮助。

一、准备阶段:

在华为面试之前,我把《软件设计师教程》大概的复习了一遍,时间实在太紧迫了,有些概念我也只是很粗糙地掠过去。10号下午还到图书馆借了一本《程序员面试攻略》,11号下午就差不多把那本书大概地啃完。

二、笔试:

11号,收到短信通知当晚7:00在E栋笔试(只要是注册了电子简历的同学都有资格),考试种类分两种:硬件和软件,共四类题:填空,选择,改错,程序设计。基本上都是一些C/C++语言题,数据结构的树的前序、中序及后序排列,计算机网络里的IP报文中的TTL(Time to live),数据库的操作等等;程序题有两道,一道题是关于数据结构的,另外有一道是“字符串A插入字符串B中”。虽然都基础,但题量太大,考试时间太短。大家都在喊没信心。

三、面试:

第二天就有人接到通知去面试了,我们班一位同学去了,他很牛B,从第一轮到第四轮一

直很顺利。我是第三天才和我们寝室另外的一位同学才接到面试通知的(不过我听说我们这一批接到通知的笔试分数普遍都很高),当然在前三天的等待时间里,我心情很郁闷,我还以为我没有慧通的面试资格了,所以一直在玩,希望有时真的是期而不遇,遇而不期阿。(其实笔试这一轮刷的人不多,大家以后没必要像我这样子提前就爆弃了)

我下午4:00准时到凯莱大酒店,一进去就感觉一股热气,大厅里也许是因为太热或者太紧张的缘故,每个人的脸都很红,很红。大概等了半个小时,我的心也跳得好厉害,我就到门口舒缓下情绪,很快一位帅哥就领我去第一轮面试了,他问我会什么,**,这问题该怎么答阿,然后我说我是电子科学与技术专业的,计算机基本上是靠自学的,大概他体会到自学的不易,他给我出了5道编程题,虽然很多,但基本上都不很难。(我一同专业的哥们虽然只有一道题,但却是用C语言编桌球的运动轨迹,妈啊,对于C语言的图像功能我都没接触到过阿),我的题目是:

1、1到100之间的所有素数之和;

2、队列的实现;

3、选首领(有一群人围在一圈,从第一个人开始数1、2、3,数到3者退出,用循环链表实现)

4、字符串匹配问题(int countABC(* s) 输入任何一串字符串,计算机其中有连续ABC子字符串的个数 )

5、用数组存储超大数的问题。

6、询问我操作系统的进程和线程的区别

幸好这些题目在笔试前我就都已经见过了,虽然第四个题目,面试老师说我执行效率不高,但可以过得去了。哈哈,他直接通知我去进行第二轮面试了。

第二轮是资格面试,没多大问题,就聊聊家乡,聊聊自己的情况,这一关只要说话有分寸,一般都可以通过。第二轮面试完,就快到了晚饭的时间了,晚饭当然是慧通免费提供的,晚饭一过后,我就被一被称作是部长的面试官叫了进去,这一关一进去他直接拿了我《软件设计书》提问我:

1、ping命令使用的是哪种报文?

2、OSI分哪几个层,IP是在哪个层?

3、哈希表的问题

4、为什么要采取二叉树这种数据结构?(折半查找)

5、两台计算机中的进程怎么互相通信,我说通过IP呗,他说除了IP呢?我卡住了,他说你听说过五元组吗?我只好老老实实的回答说不知道,然后他在那里给我解释一通,但我还是没搞明白,回来翻潘爱民老师的《计算机网络书》

也没有。这一轮虽然第5个问题我有点卡壳,但老师说我毕竟是自学,还表扬了我,说我已经很不错了。面试完已经好晚了,华为的MM通知我第二天继续去进行第四轮的面试。

第二天,我按时到了考试地点,这一天,明显感觉气氛没有第一天的好,垂头丧气的好多。很快就通知我去面试了,这一轮面试的老师明显态度比前几轮差多了,问的问题都有点让我透不过气来,但终于挺了过去,最后他直接点到桌子上

的一个题目:

void main()

{

char *p;

*p=-130;

printf("%d",*p);

}

正确的答案是126,原因:-130在计算机里面存储形式是11111111-01111110(取反码的形式),因为C里面的CHAR是8位的,所以,最高位1去掉,剩下01111110。

四、些许体会

  面试,就是面试,不是学习,考试。你现在会多少东西固然重要,但更重要的是你得

让面试官知道,所以面试时把你的知识表达出来是最重要的。切记!面试表达是关键,你

可以先把自己熟悉的整理一下,不至于面试的时候磕磕碰碰的。面试,好比下棋。把握局

面,掌握主动权是关键。一旦你把面试官成功引入你的领地,让他把注意力关注在你熟悉

的领域,无暇自顾,那就尽情发挥吧,已经成功了一大半。所以从面试官拿到你的简历起

,就主动出击,别给他机会.另外,在大肆开学初,一定要把各位的专业课翻出来看看,考软件的特别要多多看看基础的C语言,想找到好工作一定要从骨子里面重视起来。

1、1到100之间的所有素数之和;

int i = 1;

int j = 0;

bool change= 1;

int sum = 0;

for (i=1; i<100; i++)

{     for (j=2; j<i; j++)

        {   if(i%j= =0)

            {    change = 0;   

                 break;  跳出J循环,I+1继续判断

             }

         }

       if(change= =1)

     sum +=i;

    change = 1;

}

printf("%d\n",sum);

2、队列的实现;(用数组或者链表,定义好输入和输出即可)

3、选首领(有一群人围在一圈,从第一个人开始数1、2、3,数到3者退出,用循环链表实现)

n个人围成一圈,从第一个人开始依次从1到m循环报数,当报到m的时候此人出圈,直到圈 中只剩一人为止.求最后一个人的原始编号。  

     int  yuesefu(int  n, int  m)  

     {      int     i,r=0;  

            for     (i=2;i<=n;i++)     r=(r+m)%i;  

            return     r+1;  

     }  

//上面看不懂,程心建注释

4、字符串匹配问题(int countABC(* s) 输入任何一串字符串,计算机其中有连续ABC子字符 串的个数 )

int countABC(* s)

{

    int i = 0;

    int j = 0;

    int num = 0;

    scanf("%s",s);

    int len = strlen(s);

    for (i=0; i<len-3; i++)

    {

     j = strcmp(s+i,"ABC");

     if(j= =0)

      num++;

    }

}

5、用数组存储超大数的问题。

这是数组得一个应用,思想是我们定义一个数组,让每一个元素得值都是从后到前以十    进制得方式存贮得,如过到了9下一位就要让前一个元素进位为1,9变为0同时。

下面这个例子是要求一个40位的 n!的值

int data[40];//存储40位书的整数数组

int digit;//数据位数变量

int i,j,r,k;

int n;//用户输入值

for(i=1; i<40+1; i++)

    data[i]=0;

data[0]=data[1]=1;

digit=1;

printf("enter a number :");

scanf("%d",&n);

for(i=1; i<n+1; i++)

{

    for(j=1; j<digit+1; j++)

     data[j]*=i;

    for(j=1; j<digit+1; j++)

    {

     if(data[j]>10)

     {

      for(r=1; r<digit+1; r++)

      {

       if(data[digit]>10)//大于10时候位数加1

        digit++;

       data[r+1]+=data[r]/10;//进位增加

       data[r]=data[r]%10;//去掉进位后得值

      }

     }

    }

    printf("%d! = ",i);

    for(k =digit; k>0; k--)

     printf("%d",data[k]);

    printf("\n");

}

6、询问我操作系统的进程和线程的区别

进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元 实现系统对应用的并发性。进程和线程的区别,简而言之:一个程序至少有一个进程,一个进程至少有一个线程. 线程的划分尺度小于进程,使得多线程程序的并发性高。 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大 地提高了程序的运行效率。

1、ping命令使用的是哪种报文?

PING命令使用ICMP的哪种code类型:Echo reply(回显请求报文)

2、OSI分哪几个层,IP是在哪个层?

osi:物理层、链路层、网络层、传输层、会话层、管理层、应用层。

tcp/ip:机网络层、互联层、传输层、应用层。ip是在互联层

3、哈希表的问题

主要用于快速查找检索方面

4、为什么要采取二叉树这种数据结构?

    他折半查找,可以减少查找比较次数

5、五元组

二元组的定义:<K,R>

三元组的定义:<D,F,A>

五元组的定义:<V,O,G,M,S>

V是值的集合,O是操作的集合,G是构成名字的文法,M是存储的集合,S是从G能构成的名字 几个到M的映射.

iP报文中的五元组(即源IP地址,源端口号,目的IP地址,目的端口,协议)。

半相关

综上所述,网络中用一个三元组可以在全局唯一标志一个进程:

(协议,本地地址,本地端口号)

这样一个三元组,叫做一个半相关(half-association),它指定连接的每半部分。

全相关

一个完整的网间进程通信需要由两个进程组成,并且只能使用同一种高层协议。也就是 说,不可能通信的一端用TCP协议,而另一端用UDP协议。因此一个完整的网间通信需要 一个五元组来标识:

(协议,本地地址,本地端口号,远地地址,远地端口号)

这样一个五元组,叫做一个相关(association),即两个协议相同的半相关才能组合 成一个合适的相关,或完全指定组成一连接。

 

suningin详解华为面试试题(1)

 

  1.怎么判断 float a 是 0?

(if (a>-1e-6)&&a<1e-6) 判断= =0

if(x < -0.000001 && x > 0.000001)判断!=0

1e-6=1*(10的-6次方
    2.有 double a[100],问 sizeof(a),sizeof(a[2])有什么不同?

sizeof(a)=800    sizeof(a[2])=8

这里要注意如果数组名作为函数的形参后,它就是一个普通的指针了这时sizeof (a)=4指针占4位(后面有)
double 8位

32位系统中,字符型占1字节,整型占4字节,短整型占2字节,浮点型占4字节,双精度占8字节。
    3.const 型数据在内存中如何存储?

(静态存储区中)

 

  共有四轮面试:

  问题一:两笔记本电脑连起来后拼不通,你觉得可能有哪些问题?

  问题二:我们在南京,和深圳的网络是通的,但和北京的网络不通, 你以怎样的顺序检查问题?

  问题三:解释什么叫"透明"?什么叫"网格"?

  问题四:交换和路由的区别?VLAN的特点?

  问题五:画一个积分电路和一个微分电路。

  问题六:知道现在的路由器是第几代了吗?

 

问题一:两笔记本电脑连起来后ping不通,你觉得可能有哪些问题可能的原因大体有以下几个:

1、网线不通;

2、某台笔记本上的tcp/ip协议安装的不完整;

3、ip地址配置有问题(不在一个网段上);

4、某台笔记本上有防火墙,把icmp端口给屏蔽了(端口号:139)。

         这个题的我是从osi模型上入手,从物理层往上一层层排除。

问题二:我们在南京,和深圳的网络是通的,但和北京的网络不通,你以怎样的顺序检查问题?

我设想的顺序是按照由近及远的顺序进行测试,如果是有vpn的话,只要确定两端和本 地网络提供支持的公司之间的网络是连通的,其他的就交个那个公司来做了,如果是自 己维护的基于ddn一类的点对点网络,那么找到路由表,从最近的路由器开始ping吧。

问题三:解释什么叫“透明”?什么叫“网格”?

关于透明,我的理解就是一种开放的通信,意味着应用程序可以与网络上它所知道地址的其它任何应用程序连接并会话,而在这个网络上的所有中间设备不会干扰应用程序之间的信息交换。

 

关于网格,就是把网络上所有的计算机进行整合使其成一台超级计算 机,实现计算能力、存储容量、数据和信息资源等全方位的共享。 网格作为一种能带来巨大处理、存储能力和其他IT资源的新型网络,可以应付临时之用。网格计算通过共享网络将不同地点的大量计算机相联,从而形成虚拟的超级计算机,将各处计算机的多余处理器能力合在一起,可为研究和其他数据集中应用提供巨大的处理能力。有了网格计算,那些没有能力购买价值数百万美元的超级计算机的机构,也能利用其巨大的计算能力。

问题四:交换和路由的区别?VLAN的特点?

交换技术和路由技术的最大区别在于他们寻址的方式以及报文的转发方式上,交换技术是发生在2层也就是数据链路层上,是直接利用mac地址建立会话;路由技术发生在网络层,需要通过ip地址建立路由表,然后进行数据通信。在报文的转发方式上,交换技术 是使用先收再转,路由技术是采用边收边转。

vlan(虚拟局域网)的主要特点就是安全,信息只到达应该到达的地点。因此,防止了大部分基于网络监听的入侵手段。通过虚拟网设置的访问控制,使在虚拟网外的网络节点不能直接访问虚拟网内节点。

问题五:画一个积分电路和一个微分电路。

这个题目这里不好给出图片,呵呵,我还不会弄图片,大家可以查看电子书就好了,相信电子通信的朋友都知道的。

 问题六:知道现在的路由器是第几代了吗?

第几代是华为公司提出的概念

第三代是基于分布式处理系统,软件转发,如华为的NE16E/08E/05,CISCO 7200/7500。

第四代是基于分布式处理系统,ASIC硬件转发,如CISCO 12000

第五代是基于分布式处理系统,NP硬件转发,如华为的NE80。

第六代是基于集群系统,啥转发的不知道,例子也不知道。

 

还有一种回答,大家也参考一下:

从体系结构上看,路由器可以分为

第一代单总线单CPU结构路由器

第二代单总线主从CPU结构路由器

第三代单总线对称式多CPU结构路由器

第四代多总线多CPU结构路由器

第五代共享内存式结构路由器

第六代交叉开关体系结构路由器和基于机群系统的路由器等多类。  

 

 

suningin详解华为面试试题(2)(本科生)华为面试题

1:OSI七层网络结构:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。

    TCP/IP五层结构:物理层、数据链路层、互联层、传输层、应用层。

                     四层  :主机-网络层、互联层、传输层、应用层。

2:TCP/IP是一个协议集,对英特网中主机的寻址方式,主机的命名机制,信息的传输规则,以及各种服务功能作了约定.

IP协议是英特网中的交通规则,连入英特网中的每台计算机及处于十字路口的路由器都必须熟知和遵守该交通规则。IP运行于互联层。屏蔽各个物理网络的细节和差异。

   TCP:传输控制协议,运行于传输层。利用IP层提供的服务,提供端到端的可靠的(TCP)服务.

   UDP:用户数据报协议,运行于传输层。利用IP层提供的服务,提供端到端的不可靠的(UDP)服务。

 

3:一般意义上说交换机是工作在数据链路层。但随着科技的发展,现在有了三层交换机,三层交换机已经扩展到了网络层。也就是说:它等于“数据链路层 + 部分网络层”。交换机中传的是。通过存储转发来实现的。

路由器是工作在网络层。路由器中传的是IP数据报。主要是选址和路由。

交换机属于OSI第二层即数据链路层设备。它根据MAC地址寻址,通过站表选择路由,站表的建立和维护由交换机自动进行。

路由器属于OSI第三层即网络层设备,它根据IP地址进行寻址,通过路由表路由协议产生。

交换机最大的好处是快速,路由器最大的好处是控制能力强

 

4.比较“C++的类”和“C的struct”的区别没什么意思,他们的区别太大了,至少C的struct不能有成员函数。

比较“C++的类”和“C++的struct”还有点意思。主要体现在:

(1)class的默认成员访问权限是private,而struct是public;

(2)从class的的默认继承是private继承,从struct的默认继承是public继承。(Union是protected继承)。

 

5.置于“~”是析构函数;析构函数因使用"~"符号(逻辑非运算符),表示它为逆构造函数,加上类名称来定义;析构函数也是特殊的类成员函数,它没有返回类型,没有参数,不能随意调用,也没有重载,只有在类对象的生命期结束的时候,由系统自动调用。 有适放内存空间的做用!

虚函数是C++多态的一种表现

例如:子类继承了父类的一个函数(方法),而我们把父类的指针指向子类,则必须把父类的该函数(方法)设为virtual(虚函数)。

使用虚函数,我们可以灵活的进行动态绑定,当然是以一定的开销为代价。

如果父类的函数(方法)根本没有必要或者无法实现,完全要依赖子类去实现的话,可以把此函数(方法)设为virtual 函数名=0 ;我们把这样的函数(方法)称为纯虚函数。如果一个类包含了纯虚函数,称此类为抽象类

 

6.全局变量是整个程序都可访问的变量,谁都可以访问,生存期在整个程序从运行到结束(在程序结束时所占内存释放),而局部变量存在于模块(子程序,函数)中,只有所在模块可以访问,其他模块不可直接访问,模块结束(函数调用完毕),局部变量就消失,所占据的内存释放。

操作系统和编译器,可能是通过内存分配的位置来知道的,全局变量分配在全局数据段并且在程序开始运行的时候被加载。局部变量则分配在堆栈里面 。

 

8.8086的机器字长是16位,8086使用40个引脚的16个做地址/数据复用引腿来传输数据,一次读写过程由一个基本总线周期完成,它由4个时钟(CLK)周期组成,按时间顺序定义为T1、T2、T3、T4。在T1期间8086发出访问目的地的地址信号和地址锁存选通信号ALE;T2期间发出读写命令信号RD、WR及其它相关信号;T3期间完成数据的访问;T4结束该总线周期。可见,地址与数据信号不会同时出现在一个时钟(CLK)周期,二者可以分时复用同一组引线。

 

suningin详解华为笔试题(1)

suningin解答的华为笔试题

 

1.写出判断ABCD四个表达式的是否正确, 若正确, 写出经过表达式中 a的值(3分)

int a = 4;

(A) a += (a++); (B) a += (++a) ; (C) (a++) += a; (D) (++a) += (a++);

a = ?

答:C错误,左侧不是一个有效变量,不能赋值,可改为(++a) += a;改后答案依次为9,10,10,11

a++是先运算完了 A再加1;++a是先加1在运算,二者好像都不能单独作为左值

2.某32位系统下, C++程序,请计算sizeof 的值(5分).

char str[] = “www.ibegroup.com”

char *p = str ;

int n = 10;

请计算

sizeof (str ) = ?(1)

sizeof ( p ) = ?(2)

sizeof ( n ) = ?(3)

void Foo ( char str[100]){

请计算 sizeof( str ) = ?(4)

void *p = malloc( 100 );

请计算  sizeof ( p ) = ?(5)

答:(1)17 (2)4 (3) 4 (4)4 (5)4

字符串结束标志符为\0,一般不写,系统默认占1位,32位系统中,字符型占1字节,整型占4字节,短整型占2字节,浮点型占4字节,双精度占8字节,指针占4位;这里要注意如果数组名作为函数的形参后,它就是一个普通的指针了这时sizeof(a)=4,

3. 回答下面的问题. (4分)

(1).头文件中的 ifndef/define/endif 干什么用?预处理

答:防止头文件被重复引用

(2). #include 《filename.h》和 #include “filename.h” 有什么区别?

答:前者用来包含开发环境提供的库头文件,后者用来包含自己编写的头文件。查找的

(3).在C++ 程序中调用被C 编译器编译后的函数,为什么要加 extern “C”声明?

答:函数和变量被C++编译后在符号库中的名字与C语言的不同,被extern "C"修饰的变量和函数是按照C语言方式编译和连接的。由于编译后的名字不同,C++程序不能直接调用C 函数。C++提供了一个C 连接交换指定符号extern“C”来解决这个问题。

(4). switch()中不允许的数据类型是?

答:实型

4. 回答下面的问题(6分)

(1).Void GetMemory(char **p, int num)

{ *p = (char *)malloc(num);}

void Test(void)

{   char *str = NULL;

       GetMemory(&str, 100);

       strcpy(str, "hello");由后面的串复制得前面的串

       printf(str);

}

请问运行Test 函数会有什么样的结果?

答:输出“hello”

(2). void Test(void)

{

       char *str = (char *) malloc(100);

       strcpy(str, “hello”);

       free(str); free掉的只是内存,并非指针本身,指针要在赋值为空在真正不存在

       if(str != NULL)

         { strcpy(str, “world”);

           printf(str);

         }

}

请问运行Test 函数会有什么样的结果?

答:输出“world”

正确,str经过Free后必须手工赋值为NULL,内存已经释放了,str现在是一个野指针,所以,要养成释放后,指针赋零的习惯,使用前变量初始化;free是释放申请的内存空间,释放了之后该变量的值是一个随机值,因而需要自己赋NULL;就象某个人死了,但是没有去派出所去注销户口, 结果你去查,发现他还"活着"~~~~~~~~~`于是你想给他打电话,就见鬼了啊--------程序死了

(3). char *GetMemory(void)

{  char p[] = "hello world";

      return p;

}

void Test(void)

{  char *str = NULL;

     str = GetMemory();

     printf(str);

}

请问运行Test 函数会有什么样的结果?

答:无效的指针,输出不确定

char p[] = "hello world";
return p;的p[]数组为函数内的局部自动变量,在函数返回后,内存已经被释放。这是许多程序员常犯的错误,其根源在于不理解变量的生存期。

void GetMemory( char *p )
{
 p = (char *) malloc( 100 );
}
void Test( void )
{
 char *str = NULL;
 GetMemory( str );
 strcpy( str, "hello world" );
 printf( str );
}

请问运行Test 函数会有什么样的结果?

程心建注释//不能通过编译,编译报错是某些内存区的内容不确定。

传入中GetMemory( char *p )函数的形参为字符串指针,在函数内部修改形参并不能真正的改变传入形参的值,执行完char *str = NULL;GetMemory( str );后的str仍然为NULL;

再看看下面的一段程序有什么错误

swap( int* p1,int* p2 )
{
 int *p;
 *p = *p1;
 *p1 = *p2;
 *p2 = *p;
}

在swap函数中,p是一个“野”指针,有可能指向系统区,导致程序运行的崩溃。在VC++中DEBUG运行时提示错误“Access Violation”。该程序应该改为:

swap( int* p1,int* p2 )
{
 int p;
 p = *p1;
 *p1 = *p2;
 *p2 = p;
}

5.编写strcat函数(6分)

已知strcat函数的原型是char *strcat (char *strDest, const char *strSrc);

其中strDest 是目的字符串,strSrc 是源字符串。

(1)不调用C++/C 的字符串库函数,请编写函数 strcat

答:

VC源码:

char * __cdecl strcat (char * dst, const char * src)

{

      char * cp = dst;

      while( *cp )

      cp++; /* find end of dst */

      while( *cp++ = *src++ ) ; /* Copy src to end of dst */

      return( dst ); /* return dst */

}

(2)strcat能把strSrc 的内容连接到strDest,为什么还要char * 类型的返回值?

答:方便赋值给其他变量

 

6.MFC中CString是类型安全类么?

答:不是,其它数据类型转换到CString可以使用CString的成员函数Format来转换

 

7.C++中为什么用模板类。

答:(1)可用来创建动态增长和减小的数据结构

(2)它是类型无关的,因此具有很高的可复用性。

(3)它在编译时而不是运行时检查数据类型,保证了类型安全

(4)它是平台无关的,可移植性

(5)可用于基本数据类型

 

8.CSingleLock是干什么的。

答:同步多个线程对一个数据类的同时访问

 

9.NEWTEXTMETRIC 是什么。Newtextmetric

答:物理字体结构,用来设置字体的高宽大小

 

10.程序什么时候应该使用线程,什么时候单线程效率高。

答:1.耗时的操作使用线程,提高应用程序响应

    2.并行操作时使用线程,如C/S架构的服务器端并发线程响应用户的请求。

    3.多CPU系统中,使用线程提高CPU利用率

    4.改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序会利于理解和修改。

其他情况都使用单线程。

 

11.Windows是内核级线程么。

答:见下一题

 

12.Linux有内核级线程么。

答:线程通常被定义为一个进程中代码的不同执行路线。从实现方式上划分,线程有两种类型:“用户级线程”和“内核级线程”。 用户线程指不需要内核支持而在用户程序中实现的线程,其不依赖于操作系统核心,应用进程利用线程库提供创建、同步、调度和管理线程的函数来控制用户线程。这种线程甚至在象 DOS 这样的操作系统中也可实现,但线程的调度需要用户程序完成,这有些类似 Windows 3.x 的协作式多任务。另外一种则需要内核的参与,由内核完成线程的调度。其依赖于操作系统核心,由内核的内部需求进行创建和撤销,这两种模型各有其好处和缺点。用户线程不需要额外的内核开支,并且用户态线程的实现方式可以被定制或修改以适应特殊应用的要求,但是当一个线程因 I/O 而处于等待状态时,整个进程就会被调度程序切换为等待状态,其他线程得不到运行的机会;而内核线程则没有各个限制,有利于发挥多处理器的并发优势,但却占用了更多的系统开支。

Windows NT和OS/2支持内核线程。Linux 支持内核级的多线程

 

13.C++中什么数据分配在栈或堆中,New分配数据是在近堆还是远堆中?

答:栈: 存放局部变量,函数调用参数,函数返回值,函数返回地址。由系统管理

    堆: 程序运行时动态申请,new 和malloc申请的内存就在堆上

 

14.使用线程是如何防止出现大的波峰。

答:意思是如何防止同时产生大量的线程,方法是使用线程池,线程池具有可以同时提高调度效率和限制资源使用的好处,线程池中的线程达到最大数时,其他线程就会排队等候。

 

15函数模板与类模板有什么区别?

答:函数模板的实例化是由编译程序在处理函数调用时自动完成的,而类模板的实例化必须由程序员在程序中显式地指定。

 

16一般数据库若出现日志满了,会出现什么情况,是否还能使用?

答:只能执行查询等读操作,不能执行更改,备份等写操作,原因是任何写操作都要记录日志。也就是说基本上处于不能使用的状态。

 

17 SQL Server是否支持行级锁,有什么好处?

答:支持,设立封锁机制主要是为了对并发操作进行控制,对干扰进行封锁,保证数据的一致性和准确性,行级封锁确保在用户取得被更新的行到该行进行更新这段时间内不被其它用户所修改。因而行级锁即可保证数据的一致性又能提高数据操作的迸发性。

 

19 关于内存对齐的问题以及sizeof()的输出

答:编译器自动对齐的原因:为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;然而,对齐的内存访问仅需要一次访问。

 

20 int i=10, j=10, k=3; k*=i+j; k最后的值是?

答:60,此题考察优先级,实际写成: k*=(i+j);,赋值运算符优先级最低

 

21.对数据库的一张表进行操作,同时要对另一张表进行操作,如何实现?

答:将操作多个表的操作放入到事务中进行处理

22.TCP/IP 建立连接的过程?(3-way shake)

答:在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。

  第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;

  第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。

 

23.ICMP是什么协议,处于哪一层?

答:Internet控制报文协议,处于网络层(IP层)

 

24.触发器怎么工作的?

答:触发器主要是通过事件进行触发而被执行的,当对某一表进行诸如UPDATE、 INSERT、 DELETE 这些操作时,数据库就会自动执行触发器所定义的SQL 语句,从而确保对数据的处理必须符合由这些SQL 语句所定义的规则。

25.winsock建立连接的主要实现步骤?

答:服务器端:socker()建立套接字,绑定(bind)并监听(listen),用accept()等待客户端连接。

客户端:socker()建立套接字,连接(connect)服务器,连接上后使用send()和recv(),在套接字上写读数据,直至数据交换完毕,closesocket()关闭套接字。

服务器端:accept()发现有客户端连接,建立一个新的套接字,自身重新开始等待连接。该新产生的套接字使用send()和recv()写读数据,直至数据交换完毕,closesocket()关闭套接字。

26.动态连接库的两种方式?

答:调用一个DLL中的函数有两种方法:

1.载入时动态链接(load-time dynamic linking),模块非常明确调用某个导出函数,使得他们就像本地函数一样。这需要链接时链接那些函数所在DLL的导入库,导入库向系统提供了载入DLL时所需的信息及DLL函数定位。

2.运行时动态链接(run-time dynamic linking),运行时可以通过LoadLibrary或LoadLibraryEx函数载入DLL。DLL载入后,模块可以通过调用GetProcAddress获取DLL函数的出口地址,然后就可以通过返回的函数指针调用DLL函数了。如此即可避免导入库文件了。

27.IP组播有那些好处?

答:Internet上产生的许多新的应用,特别是高带宽的多媒体应用,带来了带宽的急剧消耗和网络拥挤问题。组播是一种允许一个或多个发送者(组播源)发送单一的数据包到多个接收者(一次的,同时的)的网络技术。组播可以大大的节省网络带宽,因为无论有多少个目标地址,在整个网络的任何一条链路上只传送单一的数据包。所以说组播技术的核心就是针对如何节约网络资源的前提下保证服务质量。

1、填空选择

1.1   二分法的时间复杂度.(答:log(N))

1.2   堆栈的工作方式. (答:先进后出表FILO(first in last out )队列为先进先出FIFO)

1.3   循环链表的概念(答:链表的最后一个节点指向第一个节点)

1.4   图的遍历方式. (答:深度优先搜索和广度优先搜索)

1.10  80x86的加减操作最后对标志位的影响 (溢出标志位)

1.12 private, protected, public类型的区别

2、 下列两个编程题任选其一,如果都答去分最低的。(40分)

2.1 对于非负整数0,1,2,....,如果该整数左右对称,我们称该数为回文数,如11, 121, 1331 等,请编一段C程序,查找0到N内所有满足(m, m*m, m*m*m)同时都是回文数的m.

#include "stdio.h"

#include "stdlib.h"

int panduan(int numputin)//判断是不是对称数

{ int digit[10];//用于存放每个输入数字的每位位数

  int temp = numputin;

for(int digitstop=0; digitstop<10; digitstop++)//初始化

{   digit[digitstop] = 0;}

digitstop=0;

while(temp)//取出每位的数值

{   digit[digitstop] = temp%10;

   digitstop++;

   temp = temp/10 ;}

for(int i=0; i<digitstop/2; i++)//比较看看是不是对称

{

   if(digit[i]!=digit[digitstop-i-1])

      {    numputin = 0;

           break;

       }

}

return numputin;

}

 

int main(int argc, char* argv[])

{

int numtop ;

int cishu = 0;//第一输入数字相乘次数 如m,m*m,m*m*m

printf("putin top number more than 10: ");

scanf("%d",&numtop);

int *num = (int*)malloc(sizeof(int)*numtop);//开辟一段空间用于存储要寻找的数组

int temp = 0;

for(int i=10; i<numtop; i++)//个位数字我们这里不考虑

{

   num[i] = i;

   num[i] = panduan(num[i]);//做判断如果是不变,如果不是清零

   cishu = 0;

   temp = num[i];

   while(num[i]!=0&&cishu<2)//cishu<2题目是要相乘两次m,m*m,m*m*m

   {

    temp *= num[i];

    temp = panduan(temp);

    if(temp!=0)

    cishu++;

    else break;

   }

   if(cishu==2)//输出结果

   printf("\n%d is right\n",num[i]);

   else

printf("no num!");

}

free(num);

return 0;

}

2.2 对于非负整数0,1,2,....n-1,随机放入一个大小为n的一维数组中,请用时间复杂度为O(n)的算法,把他们调整为0,1,2,3,....n-1的顺序,辅助空间为O(1),只允许用交换操作,一次只能交换两个元素位置。

int main()

{

   int a[]   = {10,6,9,5,2,8,4,7,1,3};

   int len = sizeof(a) / sizeof(int);

   int temp;

   for(int i = 0; i < len; )

     {

temp = a[a[i] - 1];

a[a[i] - 1] = a[i];

a[i] = temp;

if ( a[i] == i + 1)

        i++;

     }

     for (int j = 0; j < len; j++)

       cout<<a[j]<<",";

    return 0;

}

suningin详解华为笔试题(3)

一、判断题(对的写T,错的写F并说明原因,每小题4分,共20分)

1、有数组定义int a[2][2]={{1},{2,3}};则a[0][1]的值为0。(答:正确 )

2、int (*ptr) (),则ptr是一维数组的名字。(答:错误   int (*ptr) ();定义一个指向函数的指针变量)

3、指针在任何情况下都可进行>,<,>=,<=,==运算。(答:错误 )

4、switch(c) 语句中c可以是int ,long,char ,float ,unsigned int 类型。(答:错,不能用实型)

二、填空题(共30分)

1、在windows下,写出运行结果,每空2分,共10分。

char str[ ]= "Hello";

char *p=str;

int n=10;

sizeof(str)=(  ? );

sizeof(p)=(  ? );

sizeof(n)=(  ? );

void func(char str[100]){  。。。};

sizeof(str)=(  ? );

答案:6,4,4,4,

3、设int arr[]={6,7,8,9,10};

     int *ptr=arr;指针指向数组的第一个元素

     *(ptr++)+=123; ptr++并不是元素加1,而是指针加1,相当于往后挪一个

printf("%d,%d",*ptr,*(++ptr));

结果是什么?(  ?  )10分

答案:8,8。这道题目的意义不大,因为在不同的编译器里printf的参数的方向是不一样的,在vc6.0下是从有到左,这里先*(++ptr) 后*pt,于是结果为8,8

C中printf计算参数时是从右往左压栈的

二、编程题(第一小题20,第二小题30分)

1、不使用库函数,编写函数int strcmp(char  *source, char *dest),若相等则返回0,不等返回-1;

答案:一、

int strcmp(char * source, char * dest)

{

assert((source!=NULL)&&(dest!=NULL));

int i,j;

for(i=0; source[i]= =dest[i]; i++)

{

     if(source[i]= ='\0' && dest[i]= ='\0')

       return 0;

     else

       return -1;

}

}

答案:二、

int strcmp(char * source, char * dest)

{

     while ( (*source != '\0') && (*source = = *dest))

     {

source++;

dest++;

     }

     return ( (*source) - (*dest) ) ? -1 : 0;

}

2、写一函数int fun(char *p)判断一字符串是否为回文,是返回1,不是返回0,出错返回-1

答案:一、

int fun(char *p)

{

if(p==NULL)

    return -1;

else

{

      int length = 0;

      int i = 0;

      int judge = 1;

      length = strlen(p);

      for(i=0; i<length/2; i++)

       {

         if(p[i]!=p[length-1-i])

         judge = 0;

         break;

       }

     if(judge == 0)

       return 0;

   else

       return 1;

}

}

答案:二、

int fun(char *p)

{

    int len = strlen(p) - 1;

    char *q = p + len;

    if (!p)

      return -1;

while (p < q)

{

      if ((*p++) != (*q--))

         return 0;

     }

return 1;

}

选择题

1.在OSI 7 层模型中,网络层的功能有( )

A.确保数据的传送正确无误   B.确定数据包如何转发与路由C.在信道上传送比特流     D.纠错与流控

2.FDDI 使用的是___局域网技术。( )A.以太网; B.快速以太网;  C.令牌环;   D.令牌总线。3.下面那种LAN 是应用CSMA/CD协议的 ()A.令牌环 B.FDDI    C.ETHERNET     D.NOVELL

4.TCP 和UDP 协议的相似之处是 ( )A.面向连接的协议     B.面向非连接的协议     C.传输层协议     D.以上均不对

5.应用程序PING 发出的是___报文.( )A.TCP 请求报文。  B.TCP 应答报文。  C.ICMP 请求报文。  D.ICMP 应答报文。

6.以下说法错误的是(多) ( )A.中继器是工作在物理层的设备     B.集线器和以太网交换机工作在数据连路层C.路由器是工作在网络层的设备      D.桥能隔离网络层广播

7.当桥接收的分组的目的MAC地址在桥的映射表中没有对应的表项时,采取的策略是( )A.丢掉该分组    B.将该分组分片     C.向其他端口广播该分组     D.以上答案均不对8.LAN Switch 在网络层次模型中的地位( )A.物理层  B.链路层  C.网络层   D.以上都不是

9.小于___的TCP/UDP端口号已保留与现有服务一一对应,此数字以上的端口号可自由分配。( )A.199       B.100      C.1024       D.2048

10.当一台主机从一个网络移到另一个网络时,以下说法正确的是 ( )A.必须改变它的IP 地址和MAC 地址   B.必须改变它的IP 地址,但不需改动MAC 地址  C.必须改变它的MAC 地址,但不需改动IP 地址    D.MAC 地址.IP 地址都不需改动

找错

void test1()

{

     char string[10];

     char* str1="0123456789";

     strcpy(string, str1);

}

答:表面上并且编译都不会错误。但如果string数组原意表示的是字符串的话,那这个赋值就没有达到意图。最好定义为char string[11],这样最后一个元素可以存储字符串结尾符'\0';

void test2()

{

   char string[10], str1[10];

   for(int i=0; i<10;i++)

   {

     str1[i] ='a';

   }

   strcpy(string, str1);

}

答:strcpy使用错误,strcpy只有遇到字符串末尾的'\0'才会结束,而str1并没有结尾标志,导致strcpy函数越界访问,不妨让str1[9]='\0',这样就正常了。

void test3(char* str1)

{

     char string[10];

     if(strlen(str1)<=10)

{

     strcpy(string, str1);

}

}

答:这又会出现第一道改错题的错误了。strlen(str1)算出来的值是不包含结尾符'\0'的,如果str1刚好为10个字符+1结尾符,string就得不到结尾符了。可将strlen(str1)<=10改为strlen(str1)<10。

2. 找错

#define MAX_SRM 256

DSN get_SRM_no( )

{

     static int SRM_no;

     int i;

     for(i=0;I(i)<MAX_SRM;i++,SRM_no++)

   {

     SRM_no %= MAX_SRM;

     if(MY_SRM.state= =IDLE)

     {

       break;

     }

   }

   if(i>=MAX_SRM)

     return (NULL_SRM);

   else

     return SRM_no;

}

答:我不知道这段代码的具体功能,但明显有两个错误

1,SRM_no没有赋初值

2,由于static的声明,使该函数成为不可重入(即不可预测结果)函数,因为SRM_no变量放在程序的全局存储区中,每次调用的时候还可以保持原来的赋值。这里应该去掉static声明。

3. 写出程序运行结果

int sum(int a)

{

    auto int c=0; 全局变量

     static int b=3;静态变量

     c+=1;

     b+=2;

   return(a+b+c);

}

void main()

{

     int i;

     int a=2;

     for(i=0;i<5;i++)

     {

       printf("%d,", sum(a));

     }

}

答:8,10,12,14,16(貌似是错的!!!!)

该题比较简单。只要注意b声明为static静态全局变量,其值在下次调用时是可以保持住原来的赋值的就可以。

 

4. int func(int a)

{

     int b;

     switch(a)

     {

         case 1: b=30;

         case 2: b=20;

         case 3: b=16;

         default: b=0;

      }

    return b;

}

问题:则func(1)=?

答:func(1)=0,因为没有break语句,switch中会一直计算到b=0。这是提醒我们不要忘了break。呵呵。

5:  int a[3];

   a[0]=0; a[1]=1; a[2]=2;

   int *p, *q;

   p=a;

   q=&a[2];

问题:则a[q-p]=?

答:a[q-p]=a[2]=2;这题是要告诉我们指针的运算特点

 

6. 定义 int **a[3][4], 则变量占有的内存空间为:_____

答:此处定义的是指向指针的指针数组,对于32位系统,指针占内存空间4字节,因此总空间为3×4×4=48。

 

7.编写一个函数,要求输入年月日时分秒,输出该年月日时分秒的下一秒。如输入2004年12月31日23时59分59秒,则输出2005年1月1日0时0分0秒。

答:/*输入年月日时分秒,输出年月日时分秒的下一秒,输出仍然在原内存空间*/

void NextMinute(int *nYear,int *nMonth,int *nDate,int *nHour,int *nMinute,int *nSecond)

{

   int nDays;

   (*nSecond)++;   // 秒加1

   if(*nSecond>=60)   // 秒满60,做出特殊处理,下面时,日,月等类同

   {

     *nSecond=0;

     (*nMinute)++;

     if(*nMinute>=60)

     {

       *nMinute=0;

       (*nHour)++;

       if(*nHour>=24)

       {

         *nHour=0;

         (*nDate)++;

         switch(*nMonth)

         {

           case 1:

           case 3:

           case 5:

           case 7:

           case 8:

           case 10:

           case 12:

             nDays=31;

           break;

           case 2:// 判断闰年

             if(*nYear%400==0||*nYear%100!=0&&*nYear%4==0)

             {

             nDays=29;

             }

             else

             {

             nDays=28;

             }

           break;

           default:

             nDays=30;

           break;

         }

         if(*nDate>nDays)

         {

           *nDate=1;

           (*nMonth)++;

           if(*nMonth>12)

           {

           *nMonth=1;

           (*nYear)++;

           }

         }

       }

     }

   }

}

/*示例可运行代码*/

void main()

{

   int nYear=2004,nMonth=12,nDate=31,nHour=59,nMinute=59,nSecond=59;

   NextMinute(&nYear,&nMonth,&nDate,&nHour,&nMinute,&nSecond);

   printf("The result:%d-%d-%d %d:%d:%d",nYear,nMonth,nDate,nHour,nMinute,nSecond);

} //cxj注释,编写代码的人C语言很强

已知:无序数组,折半查找,各元素值唯一。

函数原型是:Binary_Seach(int array[], int iValue, int iCount)

array是数组,在里面用折半查找的方法找等于iValue的值,找到返回1,否则0,iCount是元素个数,如何做呢?

 

把插入排序和折半查找一起做:

 

int Binary_Seach(int array[], int iValue, int iCount)

{

int i,low,high,tmp,m,j;

for(i=2;i<=iCount;++i)

{

    tmp=array[i];

    low=1; high=i-1;

while(low<=high)

{

       m=(low+high)/2;

       if(array[m]==iValue)

return 1;

       if(tmp>=array[m])

{ low=m+1;}

else

{ high=m-1;}

 }

for(j=i-1;j>=high+1;--j)

array[j+1]=array[j];

    array[high+1]=tmp;

}

return 0;

}

//cxj注释,没有看懂,能看懂折半查找。

写一个程序, 要求功能:求出用1,2,5这三个数不同个数组合的和为100的组合个数。

如:100个1是一个组合,5个1加19个5是一个组合。。。。 请用C++语言写。

答案:最容易想到的算法是:

     设x是1的个数,y是2的个数,z是5的个数,number是组合数

     注意到0<=x<=100,0<=y<=50,0<=z=20,所以可以编程为:

     number=0;

     for (x=0; x<=100; x++)

         for (y=0; y<=50; y++)

             for (z=0; z<=20; z++)

                 if ((x+2*y+5*z)==100)

                     number++;

     cout<<number<<endl;

 

     上面这个程序一共要循环100*50*20次,效率实在是太低了

     事实上,这个题目是一道明显的数学问题,而不是单纯的编程问题。我的解法如下:

     因为x+2y+5z=100

     所以x+2y=100-5z,且z<=20 x<=100 y<=50

     所以(x+2y)<=100,且(x+5z)是偶数

     对z作循环,求x的可能值如下:

      z=0, x=100, 98, 96, ... 0

      z=1, x=95, 93, ..., 1

      z=2, x=90, 88, ..., 0

      z=3, x=85, 83, ..., 1

      z=4, x=80, 78, ..., 0

      ......

      z=19, x=5, 3, 1

      z=20, x=0

 

     因此,组合总数为100以内的偶数+95以内的奇数+90以内的偶数+...+5以内的奇数+1,

即为:

(51+48)+(46+43)+(41+38)+(36+33)+(31+28)+(26+23)+(21+18)+(16+13)+(11+8)+(6+3)+1

 

     某个偶数m以内的偶数个数(包括0)可以表示为m/2+1=(m+2)/2

     某个奇数m以内的奇数个数也可以表示为(m+2)/2

 

     所以,求总的组合次数可以编程为:

     number=0;

     for (int m=0;m<=100;m+=5)

     {

         number+=(m+2)/2;

     }

     cout<<number<<endl;

     这个程序,只需要循环21次, 两个变量,就可以得到答案,比上面的那个程序高效了许多倍----只是因为作了一些简单的数学分析

这再一次证明了:计算机程序=数据结构+算法,而且算法是程序的灵魂,对任何工程问题,当用软件来实现时,必须选取满足当前的资源限制,用户需求限制,开发时间限制等种种限制条件下的最优算法。而绝不能一拿到手,就立刻用最容易想到的算法编出一个程序了事——这不是一个专业的研发人员的行为。

 那么,那种最容易想到的算法就完全没有用吗?不,这种算法正好可以用来验证新算法的正确性,在调试阶段,这非常有用。在很多大公司,例如微软,都采用了这种方法:在调试阶段,对一些重要的需要好的算法来实现的程序,而这种好的算法又比较复杂时,同时用容易想到的算法来验证这段程序,如果两种算法得出的结果不一致(而最容易想到的算法保证是正确的),那么说明优化的算法出了问题,需要修改。

     可以举例表示为:

     #ifdef DEBUG

         int simple();

     #end if

         int optimize();

     ......

     in a function:

     {

         result=optimize();

         ASSERT(result==simple());

     }

     这样,在调试阶段,如果简单算法和优化算法的结果不一致,就会打出断言。同时,在程

序的发布版本,却不会包含笨重的simple()函数。——任何大型工程软件都需要预先设计良

好的调试手段,而这里提到的就是一种有用的方法。

一个学生的信息是:姓名,学号,性别,年龄等信息,用一个链表,把这些学生信息连在一起, 给出一个age, 在些链表中删除学生年龄等于age的学生信息。

#include "stdio.h"

#include "conio.h"   % Console Input/Output(控制台输入输出)

struct stu{

     char name[20];

     char sex;

     int no;

     int age;

     struct stu * next;

}*linklist;

struct stu *creatlist(int n)

{

     int i;

     //h为头结点,p为前一结点,s为当前结点

     struct stu *h,*p,*s;

     h = (struct stu *)malloc(sizeof(struct stu));

     h->next = NULL;

     p=h;

     for(i=0;i<n;i++)

     {  

         s = (struct stu *)malloc(sizeof(struct stu));

         p->next = s;

         printf("Please input the information of the student: name sex no age \n");

         scanf("%s %c %d %d",s->name,&s->sex,&s->no,&s->age);

         s->next = NULL;

         p = s;

     }

     printf("Create successful!");

     return(h);

}

void deletelist(struct stu *s,int a)

{

struct stu *p;

while(s->age!=a)

{

   p = s;

   s = s->next;

}

if(s==NULL)

   printf("The record is not exist.");

else

{

   p->next = s->next;

   printf("Delete successful!");

}

}

void display(struct stu *s)

{

s = s->next;

     while(s!=NULL)

     {

         printf("%s %c %d %d\n",s->name,s->sex,s->no,s->age);

         s = s->next;

     }

}

int main()

{

     struct stu *s;

int n,age;

printf("Please input the length of seqlist:\n");

scanf("%d",&n);

     s = creatlist(n);

     display(s);

printf("Please input the age:\n");

scanf("%d",&age);

deletelist(s,age);

display(s);

     return 0;

}

2、实现一个函数,把一个字符串中的字符从小写转为大写。

#include "stdio.h"

#include "conio.h"

void uppers(char *s,char *us)

{

     for(;*s!='\0';s++,us++)

     {

         if(*s>='a'&&*s<='z')

             *us = *s-32;

         else

             *us = *s;

     }

     *us = '\0';

}

int main()

{

     char *s,*us;

     char ss[20];

     printf("Please input a string:\n");

     scanf("%s",ss);

     s = ss;

     uppers(s,us);

     printf("The result is:\n%s\n",us);

     getch();

}

 

随机输入一个数,判断它是不是对称数(回文数)(如3,121,12321,45254)。不能用字符串库函数  

 

/***************************************************************

1.

函数名称:Symmetry

功能: 判断一个数时候为回文数(121,35653)

输入: 长整型的数

输出: 若为回文数返回值为1 esle 0

******************************************************************/

unsigned char Symmetry (long n)

{

   long i,temp;

   i=n; temp=0;

   while(i) //不用出现长度问题,将数按高低位掉换

   {

     temp=temp*10+i%10;

     i/=10;

   }

   return(temp==n);

}

方法一

/* ---------------------------------------------------------------------------

功能:

判断字符串是否为回文数字

实现:

先将字符串转换为正整数,再将正整数逆序组合为新的正整数,两数相同则为回文数字

输入:

char *s:待判断的字符串

输出:

返回:

0:正确;1:待判断的字符串为空;2:待判断的字符串不为数字;

3:字符串不为回文数字;4:待判断的字符串溢出

---------------------------------------------------------------------------- */

unsigned IsSymmetry(char *s)

{

char *p = s;

long nNumber = 0;

long n = 0;

long nTemp = 0;

 

/*判断输入是否为空*/

if (*s == \'\\0\')

return 1;

 

/*将字符串转换为正整数*/

while (*p != \'\\0\')

{

/*判断字符是否为数字*/

if (*p<\'0\' || *p>\'9\')

return 2;

 

/*判断正整数是否溢出*/

if ((*p-\'0\') > (4294967295-(nNumber*10)))

return 4;

 

nNumber = (*p-\'0\') + (nNumber * 10);

 

p++;

}

 

/*将数字逆序组合,直接抄楼上高手的代码,莫怪,呵呵*/

n = nNumber;

while(n)

{

/*判断正整数是否溢出*/

if ((n%10) > (4294967295-(nTemp*10)))

return 3;

 

nTemp = nTemp*10 + n%10;

n /= 10;

}

 

/*比较逆序数和原序数是否相等*/

if (nNumber != nTemp)

return 3;

 

return 0;

}

 

方法二

/* ---------------------------------------------------------------------------

功能:

判断字符串是否为回文数字

实现:

先得到字符串的长度,再依次比较字符串的对应位字符是否相同

输入:

char *s:待判断的字符串

输出:

返回:

0:正确;1:待判断的字符串为空;2:待判断的字符串不为数字;

3:字符串不为回文数字

---------------------------------------------------------------------------- */

unsigned IsSymmetry_2(char *s)

{

char *p = s;

int nLen = 0;

int i = 0;

 

/*判断输入是否为空*/

if (*s == \'\\0\')

return 1;

 

/*得到字符串长度*/

while (*p != \'\\0\')

{

/*判断字符是否为数字*/

if (*p<\'0\' || *p>\'9\')

return 2;

 

nLen++;

p++;

}

 

/*长度不为奇数,不为回文数字*/

if (nLen%2 == 0)

return 4;

 

/*长度为1,即为回文数字*/

if (nLen == 1)

return 0;

 

/*依次比较对应字符是否相同*/

p = s;

i = nLen/2 - 1;

while (i)

{

if (*(p+i) != *(p+nLen-i-1))

return 3;

i--;

}

return 0;

}

 

求2~2000的所有素数.有足够的内存,要求尽量快

答案:

int findvalue[2000]={2};

static int find=1;

bool adjust(int value)

{

assert(value>=2);

if(value==2) return true;

for(int i=0;i<=find;i++)

{

if(value%findvalue[i]==0)

return false;

}

findvalue[find++];

return true;

}

suningin华为招聘--前人经验(3)

发了一篇华为面试归来,然后有好多人问我相关的情况,大家找工作的心情都是一样的,所以我干脆把自己的经历说详细一点,希望能对要面试的同学有点帮助。

我面试的时间比较早,去了以后先是填表,跟简历上的内容差不多,只是更详细了一些,等填完以后有一个漂亮的姐姐领着你去面试官那,我们当时面试的时候是所有面试官都在大厅里,一个人面试一个同学,第三轮的面试官就是北研所的总监和另外一个,想来也应该是个小头目,他们两个在里间的小房间里。然后给我面试的哥哥先看我的简历,然后问偶做过

的项目,因为偶简历上是四个,所以问偶哪一个时间最长,偶答网络,然后再问偶最感兴趣的课程,偶打离散数学,然后是最擅长的语言,偶曰c/c++,然后他记到纸上准备就这些问题提问了。

然后先让我讲我的项目,把项目情况跟他说了说,第一遍说没听太明白,就又拿纸和笔给他画了草图,讲的更细一些,然后就问我项目中编程量怎么样,用什么来编,偶都一一作答。

接着是网络,问偶七层协议,数据链路层的作用,简要介绍一下以太网,这些偶还是很熟的,所以倒也能答的很流利。再然后c语言,先让偶回答public,protect,private的区别,偶答了,然后让偶写一段c的程序,偶也完成的还可以。最后偶可就不行了,看偶的成绩还不错,就问偶高等数学里面的中值定理,偶从大一上完就再也没看过,虽说也对其有印象,

但答不出来,提示以后也没回答正确,接着问偶离散数学里面的摩尔定律,偶还可以被动作答,但电路设计里面的什么低通滤波器偶实在一点印象都没有,当时有点狼狈的说,接着就基本没什么技术问题了,接着就基本是闲聊,具体什么偶现在都不记得了,呵呵,不好意思的说。再接下来的第二轮,第三轮就基本没有什么太难为你的技术问题了,第二轮就是问了问偶对自己的发展目标是什么,偶想不想继续深造,平时项目解决过程中如何和别人沟通,还有就是偶认为自己最满意的一件事情,接着问偶的英语情况,然后第二轮就结束,让偶等第三轮第三轮基本就是个相互之间进行交流,你可以问他你想了解什么问题,他问偶对华为的看法,还有就是对天大的看法,还有工作想去哪,基本就没有别的了,总体感觉还可以,没有要故意难为你的意思,基本都不用做什么准备的,偶觉得。三轮下来,就让偶等通知了,后天就出来结果。所以总体还是比较简单的说。

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

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

局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。对于有些编译器而言,在同一个函数内可以定义多个同名的局部变量,比如在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内

2、如何引用一个已经定义过的全局变量?

答案:extern。

可以用引用头文件的方式,也可以用extern关键字,如果用引用头文件方式来引用某个在头文件中声明的全局变理,假定你将那个变写错了,那么在编译期间会报错,如果你用extern方式引用时,假定你犯了同样的错误,那么在编译期间不会报错,而在连接期间报错

3、全局变量可不可以定义在可被多个.C文件包含的头文件中?为什么?

答:可以,在不同的C文件中以static形式来声明同名全局变量。可以在不同的C文件中声明同名的全局变量,前提是其中只能有一个C文件中对此变量赋初值,此时连接不会出错。

4、语句for( ;1 ;)有什么问题?它是什么意思?

答案:和while(1)相同。

5、do……while和while……do有什么区别?

答案:前一个循环一遍再判断,后一个判断以后再循环。

6、请写出下列代码的输出内容

#include<stdio.h>

main()

{

int a,b,c,d;

a=10;

b=a++;

c=++a;

d=10*a++;

printf("b,c,d:%d,%d,%d",b,c,d);

return 0;

}

答案:10,12,120

 

a=10;

b=a++;//a=11 b=10

c=++a;//a=12 c=12

d=10*a++;//a=13 d=120

 

高级题

1、static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?

答案:

全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。

 

而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用, 因此可以避免在其它源文件中引起错误。从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域, 限制了它的使用范围。

 

static函数与普通函数作用域不同。仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件

 

static全局变量与普通的全局变量有什么区别:static全局变量只初使化一次,防止在其他文件单元中被引用;

static局部变量和普通局部变量有什么区别:static局部变量只被初始化一次,下一次依据上一次结果值;

static函数与普通函数有什么区别:static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝

 

2、程序的局部变量存在于()中,全局变量存在于()中,动态申请数据存在于( )中。

答案:栈;静态区;堆

 

3、设有以下说明和定义:

typedef union {long i; int k[5]; char c;} DATE;

struct data { int cat; DATE cow; double dog;} too;

DATE max;

则语句 printf("%d",sizeof(too)+sizeof(max));的执行结果是:______

答案:DATE是一个union, 变量公用空间. 里面最大的变量类型是int[5], 占用20个字节. 所以它的大小是20。

data是一个struct, 每个变量分开占用空间. 依次为int4 + DATE20 + double8 = 32.

所以结果是 20 + 32 = 52.

当然...在某些16位编辑器下, int可能是2字节,那么结果是 int2 + DATE10 + double8 = 20

 

4、队列和栈有什么区别

答案:队列先进先出,栈后进先出

 

5、已知一个单向链表的头,请写出删除其某一个结点的算法,要求,先找到此结点,然后删除。

答案:slnodetype *Delete(slnodetype *Head,int key){}中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;

}

void delete(Node* p)

{

   if(Head = Node)

   while(p)

}

7、请找出下面代码中的所以错误

说明:以下代码是把一个字符串倒序,如“abcd”倒序后变为“dcba”

 

1、#include"string.h"

2、main()

3、{

4、 char*src="hello,world";

5、 char* dest=NULL;

6、 int len=strlen(src);

7、 dest=(char*)malloc(len);

8、 char* d=dest;

9、 char* s=src[len];

10、 while(len--!=0)

11、 d++=s--;

12、 printf("%s",dest);

13、 return 0;

14、}

答案:还要加上#include <stdio.h>

 

int main(){

char* src = "hello,world";

int len = strlen(src);

char* dest = (char*)malloc((len+1)*sizeof(char));   //要为\0分配一个空间

char* d = dest;

char* s = &src[len-1]; //指向最后一个字符

while( len-- != 0 )

*d++=*s--;

*d = 0; //尾部要加\0

printf("%s\n",dest);

free(dest);// 使用完,应当释放空间,以免造成内存汇泄露

return 0;

suningin详解华为笔试题(6)

看看下面这个题目和结果我们可以从中看到=号赋值的顺序参考,“suningin详解笔试面试题(5)-++a和a++专题” 中+号的运算。

 

int main(int argc, char* argv[])

{

int ia,ib,ic;

(ia=5,ib=4,ic=3,ic)=(ia=16,ib=17,ic=18,ic);

// 注意:=(赋值运算符)是右结合的,即先计算=号的右边,再计算左边

// 因此,上面一句执行完后, ia==5, ib==4, ic==3

printf("%d,%d,%d\n",ia,ib,ic); //输出为5,4,3

//=(赋值运算符)是右结合的,即先计算=号的右边,再计算左边

//++在后面要在表达式结束的时候才执行加1,记要看到;才执行

//++在前面则要马上执行

int arr[]={0,1,2,3,4,5,6,7,8,9,10,11,12};

int *ptr=arr;

*(ptr++)=*(ptr++)+16; //实际 a[0]=a[0]+16=16;--分号后ptr为a[2]

*(++ptr)=*(++ptr)+16; //实际 a[4]=a[3]+16=19;--分号后ptr为a[4]

*(++ptr)=*(ptr++)+16; //实际 a[5]=a[4]+16=35;--分号后ptr为a[6]

*(ptr++)=*(++ptr)+16; //实际 a[7]=a[7]+16=23;--分号后ptr为a[8]

*(ptr++)=*(ptr++)+16; //实际 a[8]=a[8]+16=24;--分号后ptr为a[10]

printf("%d,%d,%d\n",*ptr++,*(++ptr),*(++ptr));// 输出顺序为从右到左见下面的解释

return 0;

}

================================

// 下面的语句执行完后的结果在语句后面的注解中

         *(ptr++)=*(ptr++)+16; // ptr == (arr+) 2, arr[1] == 16

         *(++ptr)=*(++ptr)+16; // ptr == 4, arr[4] = 19

         *(++ptr)=*(ptr++)+16; // ptr == 6, arr[6] = 35

         *(ptr++)=*(++ptr)+16; // ptr == 8, arr[7] = 23

         *(ptr++)=*(ptr++)+16; // ptr == 10, arr[9] = 24

         //根据C的函数参数进栈顺序,是从右到左

         // 那么据此原则,下面首先计算最右边的:ptr == 11, %d == 11

         // 然后计算中间的: ptr == 12, %d == 12

         // 最后计算最左边的:ptr == 12, %d == 12,分号后ptr为13

         printf("%d,%d,%d",*ptr++,*(++ptr),*(++ptr));

         // 输出结果是12,12,11

suningin详解华为笔试题(7)

指出程序中的错误:

void main()

{

     char *p;

     p = "ss";

     for (; *p != 0; p++)

         *p = 0;

}

答案:

char *p="ss"既不在栈(函数结束时由函数收回)里,也不在堆(因为是手动建立,所以要手动收回)里,而是在静态存储区(字符串" "都是存放在静态存储区中的)。

而char p[]="ss"相当于定义一个数组并赋值,是在栈里;

p = "ss",p指向"ss"的首地址,但是"ss"在静态存储区,所以*p不能修改,即*p=0会出现编译错误。

 

从变量的作用域(即从空间)角度来分,可以分为全局变量和局部变量。

从另一个角度,从变量值存在的作时间(即生存期)角度来分,可以分为静态存储方式和动态存储方式。

 

1.程序区存放程序的代码;

2.静态存储区存放全局变量和静态的局部变量;

3.动态存储区存放函数的局部变量,函数的形参变量,函数调用时的现场保护和返回地址;

存放在静态存储区中的变量的生存周期是程序的整个执行过程;

存放在动态存储区中的变量的生存周期是函数的执行期间。

在c语言中将变量和函数的属性划分为两个:数据类型和数据的存储类别。

存储类别是指数据在内存中的存储方式,共有四种存储类别:自动的(auto),静态的(static),寄存器的(register),外部的(extern),分别放在静态存储区和动态存储区.

 

(一)数组与指针

C++/C程序中,指针和数组在不少地方可以相互替换着用,让人产生一种错觉,以为两者是等价的。

数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变。

指针可以随时指向任意类型的内存块,它的特征是"可变",所以我们常用指针来操作动态内存。指针远比数组灵活,但也更危险。

下面以字符串为例比较指针与数组的特性。示例中,字符数组a的容量是6个字符,其内容为hello\0。a的内容可以改变,如a[0]= ‘X'。指针p指向常量字符串"world"(位于静态存储区,内容为world\0),常量字符串的内容是不可以被修改的。从语法上看,编译器并不觉得语句p[0]= ‘X'有什么不妥,但是该语句企图修改常量字符串的内容而导致运行错误

char a[] = "hello";

a[0] = ‘X';

cout << a << endl;

char *p = "world"; // 注意p指向常量字符串

p[0] = ‘X'; // 编译器不能发现该错误

cout << p << endl;

 

(二)解决方法

#include

void copy(char *from,char *to)

{

to=(char *)malloc(sizeof(char));//自己分配动态内存地址

 

for(;*from!=\0;from++,to++)

*to=*from;

*to=\0;

}

注意:如果函数的参数是一个指针,不要指望用该指针去申请动态内存。

必须自己动手区分配!

suningin详解华为面试试题(5).

 

-1,2,7,28,——,126请问28和126中间那个数是什么?为什么?

答案:第一题的答案应该是4^3-1=63

规律是n^3-1(当n为偶数0,2,4)

      n^3+1(当n为奇数1,3,5)

 

2.用两个栈实现一个队列的功能?要求给出算法和思路!

答案:设2个栈为A,B, 一开始均为空.

 

入队:

将新元素push入栈A;

 

出队:

(1)判断栈B是否为空;

(2)如果不为空,则将栈A中所有元素依次pop出并push到栈B;

(3)将栈B的栈顶元素pop出;

 

这样实现的队列入队和出队的平摊复杂度都还是O(1), 比上面的几种方法要好。

 

3.在c语言库函数中将一个字符转换成整型的函数是atol( )吗,这个函数的原型是什么?

答案:函数名: atol

功 能: 把字符串转换成长整型数

用 法: long atol(const char *nptr);

程序例:

#include <stdlib.h>

#include <stdio.h>

int main(void)

{

long l;

char *str = "98765432";

l = atol(lstr);

printf("string = %s integer = %ld\n", str, l);

return(0);

}

 

4。对于一个频繁使用的短小函数,在C语言中应用什么实现,在C++中应用什么实现?

答案:c用宏定义,c++用inline

 

5。直接链接两个信令点的一组链路称作什么?

答案:PPP点到点连接

 

6。软件测试都有那些种类?

答案:黑盒:针对系统功能的测试     白盒:测试函数功能,各函数接口

 

7。确定模块的功能和模块的接口是在软件设计的那个队段完成的?

答案:概要设计阶段

 

8。enum string

     {

     x1,

     x2,

     x3=10,

     x4,

     x5,

     }x;

    问x;

答案:取值在0。1。10。11。12中的一个

 

10。unsigned char *p1;

     unsigned long *p2;

     p1=(unsigned char *)0x801000;

     p2=(unsigned long *)0x810000;

     请问p1+5= ? ;

          p2+5= ? ;

 

答案:801005;810014。不要忘记了这个是16进制的数字,p2要加20变为16进制就是14

 

选择题:

   1.Ethternet链接到Internet用到以下那个协议?

   A.HDLC;B.ARP;C.UDP;D.TCP;E.ID

   2.属于网络层协议的是:

   A.TCP;B.IP;C.ICMP;D.X.25

   3.Windows消息调度机制是:

   A.指令队列;B.指令堆栈;C.消息队列;D.消息堆栈;

答案:b,a,c

 

四.找错题:

   1.请问下面程序有什么错误?

    int a[60][250][1000],i,j,k;

    for(k=0;k<=1000;k++)

     for(j=0;j<250;j++)

      for(i=0;i<60;i++)

       a[i][j][k]=0;

答案:把循环语句内外换一下

 

2。以下是求一个数的平方的程序,请找出错误:

     #define SQUARE(a)   ((a)*(a))

     int a=5;

     int b;

     b=SQUARE(a++);

答案:这个没有问题,s(a++),就是((a++)×(a++))唯一要注意的就是计算后a=7了

 

3。typedef unsigned char BYTE

      int examply_fun(BYTE gt_len; BYTE *gt_code)

       { 

       BYTE *gt_buf;

       gt_buf=(BYTE *)MALLOC(Max_GT_Length);

       ......

       if(gt_len>Max_GT_Length)

         {

         return GT_Length_ERROR; 

         }

         .......

       }

答案:要释放内存

1.IP Phone的原理是什么?

答案:IPV6

2.TCP/IP通信建立的过程怎样,端口有什么作用

答案:三次握手,确定是哪个应用程序使用该协议

 

慧通:

1。什么是预编译,何时需要预编译:

答案:1、总是使用不经常改动的大型代码体。

2、程序由多个模块组成,所有模块都使用一组标准的包含文件和相同的编译选项。在这种情况下,可以将所有包含文件预编译为一个预编译头。

 

2。 char * const p

    char const * p

    const char *p

上述三个有什么区别?

答案:

char * const p; //常量指针,p的值不可以修改

char const * p;//指向常量的指针,指向的常量值不可以改

const char *p; //和char const *p

 

3。char str1[] = "abc";

char str2[] = "abc";

 

const char str3[] = "abc";

const char str4[] = "abc";

 

const char *str5 = "abc";

const char *str6 = "abc";

 

char *str7 = "abc";

char *str8 = "abc";

 

cout << ( str1 == str2 ) << endl;

cout << ( str3 == str4 ) << endl;

cout << ( str5 == str6 ) << endl;

cout << ( str7 == str8 ) << endl;

结果是:0 0 1 1

str1,str2,str3,str4是数组变量,它们有各自的内存空间;

而str5,str6,str7,str8是指针,它们指向相同的常量区域。

 

4。 以下代码中的两个sizeof用法有问题吗?[C易]

void UpperCase( char str[] ) // 将 str 中的小写字母转换成大写字母

{

     for( size_t i=0; i<sizeof(str)/sizeof(str[0]); ++i )

         if( 'a'<=str[i] && str[i]<='z' )

             str[i] -= ('a'-'A' );

}

char str[] = "aBcDe";

cout << "str字符长度为: " << sizeof(str)/sizeof(str[0]) << endl;

UpperCase( str );

cout << str << endl;

答案:函数内的sizeof有问题。根据语法,sizeof如用于数组,只能测出静态数组的大小,无法检测动态分配的或外部数组大小。函数外的str是一个静态定义的数组,因此其大小为6,因为还有'\0',函数内的str实际只是一个指向字符串的指针,没有任何额外的与数组相关的信息,因此sizeof作用于上只将其当指针看,一个指针为4个字节,因此返回4。

 

5。一个32位的机器,该机器的指针是多少位

答案:指针是多少位只要看地址总线的位数就行了。80386以后的机子都是32的数据总线。所以指针的位数就是4个字节了。

 

6。main()

{

   int a[5]={1,2,3,4,5};

   int *ptr=(int *)(&a+1);

   printf("%d,%d",*(a+1),*(ptr-1));

}

答案:2。5

*(a+1)就是a[1],*(ptr-1)就是a[4],执行结果是2,5

&a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int)

int *ptr=(int *)(&a+1);

则ptr实际是&(a[5]),也就是a+5

原因如下:

&a是数组指针,其类型为 int (*)[5];

而指针加1要根据指针类型加上一定的值,

不同类型的指针+1之后增加的大小不同

a是长度为5的int数组指针,所以要加 5*sizeof(int)

所以ptr实际是a[5]

但是prt与(&a+1)类型是不一样的(这点很重要)

所以prt-1只会减去sizeof(int*)

a,&a的地址是一样的,但意思不一样,a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5].

 

7。请问以下代码有什么问题:

int  main()

{

char a;

char *str=&a;

strcpy(str,"hello");

printf(str);

return 0;

}

答案:没有为str分配内存空间,将会发生异常

问题出在将一个字符串复制进一个字符变量指针所指地址。虽然可以正确输出结果,但因为越界进行内在读写而导致程序崩溃。

 

8。char* s="AAA";

printf("%s",s);

s[0]='B';

printf("%s",s);

有什么错?

答案:"AAA"是字符串常量。s是指针,指向这个字符串常量,所以声明s的时候就有问题。

cosnt char* s="AAA";

然后又因为是常量,所以对是s[0]的赋值操作是不合法的。

 

9。写一个“标准”宏,这个宏输入两个参数并返回较小的一个。

答案:.#define Min(X, Y) ((X)>(Y)?(Y):(X))   //结尾没有‘;’

 

10。嵌入式系统中经常要用到无限循环,你怎么用C编写死循环。

答案:while(1){}或者for(;;)

 

11。关键字static的作用是什么?

答案:定义静态变量

 

12。关键字const有什么含意?

答案:表示常量不可以修改的变量。

13。关键字volatile有什么含意?并举出三个不同的例子?

答案:提示编译器对象的值可能在编译器未监测到的情况下改变。

 

14。int (*s[10])(int) 表示的是什么啊?

答案:int (*s[10])(int) 函数指针数组,每个指针指向一个int func(int param)的函数。

 

15。有以下表达式:

int a=248; b=4;int const c=21;const int *d=&a;

int *const e=&b;int const *f const =&a;

请问下列表达式哪些会被编译器禁止?为什么?

答案:*c=32;d=&b;*d=43;e=34;e=&a;f=0x321f;

*c 这是个什么东东,禁止

*d 说了是const, 禁止

e = &a 说了是const 禁止

const *f const =&a; 禁止

 

16交换两个变量的值,不使用第三个变量。即a=3,b=5,交换之后a=5,b=3;

答案:有两种解法, 一种用算术算法, 一种用^(异或)

a = a + b;

b = a - b;

a = a - b;

or

a = a^b;// 只能对int,char..

b = a^b;

a = a^b;

or

a ^= b ^= a;

17.c和c++中的struct有什么不同?

答案:c和c++中struct的主要区别是c中的struct不可以含有成员函数,而c++中的struct可以。c++中struct和class的主要区别在于默认的存取权限不同,struct默认为public,而class默认为private

18.#include <stdio.h>

   #include <stdlib.h>

   void getmemory(char *p)

   {

     p=(char *) malloc(100);

     strcpy(p,"hello world");

   }

   int main( )

   {

     char *str=NULL;

     getmemory(str);

     printf("%s/n",str);

     free(str);

     return 0;

    }

答案:程序崩溃,getmemory中的malloc 不能返回动态内存, free()对str操作很危险

 

19.char szstr[10];

   strcpy(szstr,"0123456789");

   产生什么结果?为什么?

 

答案:长度不一样,会造成非法的OS  注:结尾字符“\0”没有空间

 

20.列举几种进程的同步机制,并比较其优缺点

答案:原子操作

信号量机制

      自旋锁

      管程,会合,分布式系统

 

21.进程之间通信的途径

答案:共享存储系统

消息传递系统

管道:以文件系统为基础

 

22.进程死锁的原因

答案:资源竞争及进程推进顺序非法

 

23.死锁的4个必要条件

答案:互斥、请求保持、不可剥夺、环路

 

24.死锁的处理?

答案:鸵鸟策略、预防策略、避免策略、检测与解除死锁

 

25. 操作系统中进程调度策略有哪几种?

答案:FCFS(先来先服务),优先级,时间片轮转,多级反馈

 

26.类的静态成员和非静态成员有何区别?

答案:类的静态成员每个类只有一个,非静态成员每个对象一个

 

27.纯虚函数如何定义?使用时应注意什么?

答案:virtual void f()=0;

是接口,子类必须要实现

 

28.数组和链表的区别

答案:数组:数据顺序存储,固定大小

表:数据可以随机存储,大小可动态改变

 

29.ISO的七层模型是什么?tcp/udp是属于哪一层?tcp/udp有何优缺点?

答案:应用层,表示层,会话层,传输层,网络层,链路层,物理层

tcp /udp属于传输层

tcp服务提供了数据流传输、可靠性、有效流控制、全双工操作和多路复用技术等。

与tcp不同,UDP并不提供对IP协议的可靠机制、流控制以及错误恢复功能等。由于UDP 比较简单, UDP 头包含很少的字节,比tcp负载消耗少。

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

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

 

30:(void *)ptr 和 (*(void**))ptr的结果是否相同?其中ptr为同一个指针

答案:.(void *)ptr 和 (*(void**))ptr值是相同的

 

31:int main()

    {

     int x=3;

     printf("%d",x);

     return 1;

    }

问函数既然不会被其它函数调用,为什么要返回1?

答案:main中,c标准认为0表示成功,非0表示错误。具体的值是某中具体出错信息

 

32,要对绝对地址0x100000赋值,我们可以用(unsigned int*)0x100000 = 1234;

那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做?

答案:*((void (*)( ))0x100000 ) ( );

首先要将0x100000强制转换成函数指针,即:(void (*)())0x100000

然后再调用它:

*((void (*)())0x100000)();

用typedef可以看得更直观些:

typedef void(*)() voidFuncPtr;

*((voidFuncPtr)0x100000)();

 

33,已知一个数组table,用一个宏定义,求出数据的元素个数

答案:#define NTBL

#define NTBL (sizeof(table)/sizeof(table[0]))

 

34。线程与进程的区别和联系? 线程是否具有相同的堆栈? dll是否有独立的堆栈?

答案:进程是死的,只是一些资源的集合,真正的程序执行都是线程来完成的,程序启动的时候操作系统就帮你创建了一个主线程。

 

每个线程有自己的堆栈。

DLL中有没有独立的堆栈,这个问题不好回答,或者说这个问题本身是否有问题。因为DLL中的代码是被某些线程所执行,只有线程拥有堆栈,如果DLL中的代码是EXE中的线程所调用,那么这个时候是不是说这个DLL没有自己独立的堆栈?如果DLL中的代码是由DLL自己创建的线程所执行,那么是不是说DLL有独立的堆栈?

 

以上讲的是堆栈,如果对于堆来说,每个DLL有自己的堆,所以如果是从DLL中动态分配的内存,最好是从DLL中删除,如果你从DLL中分配内存,然后在EXE中,或者另外一个DLL中删除,很有可能导致程序崩溃

 

35。unsigned short A = 10;

printf("~A = %u\n", ~A);

 

char c=128;

printf("c=%d\n",c);

输出多少?并分析过程

答案:第一题,~A =0xfffffff5,int值 为-11,但输出的是uint。所以输出4294967285

第二题,c=0x10,输出的是int,最高位为1,是负数,所以它的值就是0x00的补码就是128,所以输出-128。

这两道题都是在考察二进制向int或uint转换时的最高位处理。

suningin详解华为面试试题(7)

 

华为全套完整试题

7.有一个16位的整数,每4位为一个数,写函数求他们的和。

解释:

整数1101010110110111

和   1101+0101+1011+0111

感觉应该不难,当时对题理解的不是很清楚,所以写了一个函数,也不知道对不对。

疑问:

     既然是16位的整数,1101010110110111是2进制的,那么函数参数怎么定义呢,请大虾指教。

答案:用十进制做参数,计算时按二进制考虑。

/* n就是16位的数,函数返回它的四个部分之和 */

char SumOfQuaters(unsigned short n)

{

     char c = 0;

     int i = 4;

     do

     {

         c += n & 15;

         n = n >> 4;

     } while (--i);

     return c;

}

 

8.有1,2,....一直到n的无序数组,求排序算法,并且要求时间复杂度为O(n),空间复杂度O(1),使用交换,而且一次只能交换两个数.(华为)

#include<iostream.h>

int main()

{

     int a[]   = {10,6,9,5,2,8,4,7,1,3};

     int len = sizeof(a) / sizeof(int);

     int temp;

     for(int i = 0; i < len; )

     {

temp = a[a[i] - 1];

a[a[i] - 1] = a[i];

a[i] = temp;

if ( a[i] == i + 1)

 i++;

         for (int j = 0; j < len; j++)

            cout<<a[j]<<",";

 

     return 0;

}

 

(慧通)

1 写出程序把一个链表中的接点顺序倒排

typedef struct linknode

{

int data;

struct linknode *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;

return head;

}

2 写出程序删除链表中的所有接点

void del_all(node *head)

{

node *p;

while(head!=NULL)

{

p=head->next;

free(head);

head=p;

}

cout<<"释放空间成功!"<<endl;

}

3两个字符串,s,t;把t字符串插入到s字符串中,s字符串有足够的空间存放t字符串

void insert(char *s, char *t, int i)

{

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的。则地址相同。如果编译器没有优化,那么就是两个不同的地址,则不同

评论 2 您还未登录,请先 登录 后发表或查看评论
1. 虚函数是可以[New一个对象的时候要根据虚函数的函数体来填虚表;而内联函数没有函数体,只是在预编译阶段展开]内联的,这样就可以减少函数调用的开销,提高效率(错误) 2. 一个类里可以同时存在[同一个类里无论什么函数都不能函数名和参数完全一样]参数和函数名都相同的虚函数与静态函数(错误) 3. 父类的析构函数是非虚的,但是子类的析构函数是虚的,delete子类指针(指向该子类对象)[特殊情况,参见题5],会调用父类的析构函数(正确)//任何情况下删除子类都会调用到父类的析构函数 4.对于下面的类CA,sizeof(CA) = _B_: A. 4 B. 8 C. 12 D. 16 class CA { public: CA(); virtual ~CA(); //因为有虚函数,所以会有4个字节的虚表指针 private: int m_iTime; //成员变量4个字节 public: int GetTime(); int SetTime(int iTime); }; 5.下面这段程序,打印结果是_A_: A. 1 B. 2 C. 3 D. 以上都不对 int g_iCount = 0; class CParent { public: CParent() {} ~CParent() {g_iCount += 1;} }; class CSon : public CParent { public: CSon() {} ~CSon() {g_iCount += 2;} }; main() { CParent* p = new CSon(); delete p[由于p被声明成父类指针,并且父类和子类的析构函数都非虚,因此delete操作只能根据p指针声明的类型来调用父类的析构函数]; std::cout << g_iCount << std::endl; } 6.请问下面这段程序的输出结果是_A_: A. 2,1, B. 2,2, C. 1,1, D. 1,2, class CParent { public: CParent() {} virtual ~CParent() {} public: virtual void Print() { std::cout << "1,"; }; }; class CSon : public CParent { public: CSon() {}; virtual ~CSon() {}; public: void Print() { std::cout << "2,"; }; }; void Test1(CParent& oParent[这里是引用了一个外部对象,该对象的虚表不会发生变化]) {oParent.Print();} void Test2(CParent oParent[这里会在栈空间内重新构造一个CParent类的对象,如果传入实参的类型与CParent不同则虚表会发生变化]) {oParent.Print();} main() { CSon * p = new CSon(); Test1(*p); //这里只是一个引用 Test2(*p); //这里会在栈空间重新构造Cparent类对象 delete p; } 7.请问下面这段程序的输出结果是_D_: A. 2,1, B. 2,2, C. 1,1, D. 1,2, class CParent { public: CParent() {} virtual ~CParent() {} public: void Print(){ std::cout << "1," ; }; }; class CSon : public CParent { public: CSon() {} virtual ~CSon() {} public: void Print(){ std::cout <Print(); pSon->Print();[由于父类和子类的Print函数都非虚,所以根据指针类型决定调用关系] } 8.请问下面这段程序的输出结果是_C_: A. 2,1, B. 2,2, C. 1,2, D. 1,1, class CParent { public: CParent() {Print();} virtual ~CParent() {} public: virtual void Print(){ std::cout << "1,"; } }; class CSon : public CParent { public: CSon() {Print();} virtual ~CSon() {} public: void Print(){ std::cout << "2,"; } }; main() { CParent * pParent = new CSon()[类的构造过程遵循压栈原则,构造过程中虚表尚未建立成功,是静态调用虚函数]; delete pParent; } 9.请问下面这段程序的输出结果是_D_: A. 2,2, B. 2, C. 输出结果不确定 D. 以上都不对 class CParent { public: CParent() {Print();[构造子类对象时调用到父类的构造函数,但父类的Print函数是纯虚的,没有实现,所以这里的调用不成功,编译会出错]} virtual ~CParent() {} public: virtual void Print() = 0; }; class CSon : public CParent { public: CSon() {Print();} virtual ~CSon() {} public: void Print() { std::cout << "2,"; }; }; main() { CParent * pParent = new CSon(); delete pParent; } 10.请仔细阅读以下程序: class Base { public: virtual bool operator == (int iValue) { std::cout << "I am Base class !" << std::endl; return true; } virtual ~Base(){} }; class Derive: public Base { public: virtual bool operator == (int iValue) { std::cout << "I am Derive class !" << std::endl; return true; } virtual ~Derive(){} }; int main() { Derive derive; Base* pBase = &derive; Derive* pDerive = &derive; *pBase == 0; *pDerive == 0;[重载操作符声明为virtual使操作符产生多态性] return 0; } 程序的输出结果是_B_: A、I am Base class ! I am base class ! B、I am Derive class ! I am Derive class ! C、I am base class ! I am Derive class ! D、I am Derive class ! I am Base class !
©️2022 CSDN 皮肤主题:技术黑板 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值