展讯/北京移动--笔试题

展讯笔试题目:

1.给出字符串pszBuff, 将其全部转化为大写,a转化为A
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *convert(const char* dest)
{
    int ilen=0;
    char *tmp=(char *)dest;
    char *str;
   
    //strcpy(str,dest);
    while(*dest++) ilen++;
   
    str = (char *)malloc(ilen);

    while(*tmp)
    {
        if ( (*tmp>'a') && (*tmp<'z')) {
            *str = *tmp + 'A' - 'a' ;
        }else{
            *str = *tmp;
        }
        str++;
        tmp++;
    }
   
    *str='\0';
    return str-ilen;
}

int main(int argc, char* argv[])
{
    const char pszBuff[] = "AbCd";
    char *cc;
    cc = convert(pszBuff);
    printf("%s",cc);
    getchar();
    return 0;
}


2. 给出输出结果,假设是CPU32位
int main(int argc, char* argv[])
{
    char *str="1234567890";
    long *pLong= (long *)str;
    char *pChar = str;
    pLong++;
    pChar++;
    printf("%d    %d    %s\n",sizeof(long),sizeof(pLong),pLong);
    printf("%d    %d    %s\n",sizeof(char),sizeof(pChar),pChar);
    printf("%d",sizeof(int));
    getchar();
    return 0;
}
答案:  4    4   567890
       1    4   234567890
       4
                                     

想把 0x12345678 从一台 x86 机器发送到另外一台 x86 机器

1. x86 机器是小端的,所以 0x12345678 在内存中的布局为 78 56 34 12;
2. 网络字节序是大端的,所以 0x12345678 在网络中的传输顺序为 12 34 56 78;可以这样理解,传输的顺序是从内存低地址到内存高地址依次传输,在传输之前先将小端的 78 56 34 12 转换为大端的 12 34 56 78,然后再按照内存低地址到内存高地址的顺序依次传输。
3. 在接收方,依次接收到的是 12 34 56 78,但是它本身是小端的,所以需要先将 78 存储在内存低地址,然后依次存储 56 34 12。

 

Part1  通信
GSM/GPRS/WCDMA区别
GSM的上下行频率

Part2  c语言
c语言中volatile的用处
链表与数组的区别
写出strcpy的c实现代码
求两个字符串的最大公共字符子串


Part3   智力题
一根非均匀绳子可以烧1小时,怎么用它定出15分钟?

两头点燃+中间点燃。一段烧光了,马上到另一段中间点燃。直到最后烧光。

你让工人为你工作7天,给工人的回报是一根金条。

金条平分成相连的7段,你必须在每天结束时给他们一段金条,
如果只许你两次把金条弄断,你如何给你的工人付费?

分成1,2,4三段。每天给一段,有时候要求找零。


Part4   英语
翻译:一段跟移动基站有关的英文技术文章


北京移动:

1,网络192.168.18.0采用255.255.255.240子网掩码划分子网时,那些是有效的主机地址? 192.168.18.33/.112/.119/.126/.175/.208(选择题)

字串3

2,GSM900和DCS1800的上下行频率分别是? 字串1

3,智能网的网络元素组成?

字串4

4,ping指令运行在OSI的哪层? 字串1

5,请写出英文全称:IMSI,HLR,VLR,MSC,TUP,SCCP

字串5

6,基站控制器BSC和基站BTS间的传输方式有哪些? 字串2

 


1. GSM全名为:Global System for Mobile Communications,中文为全球移动通讯系统,中国移动、中国联通各拥有一个GSM网,为世界最大的移动通信网络。GSM系统包括 GSM 900:900MHz、GSM1800:1800MHz 及 GSM-1900:1900MHz等几个频段

GPRS的英文全称为General Packet Radio Service,中文含义为通用分组无线服务,是通信公司的服务,可以利用他上网或一些数据的传输等等。
WCDMA 是一种由3GPP具体制定的,基于GSM MAP核心网,UTRAN(UMTS陆地无线接入网)为无线接口的第三代移动通信系统.
2.gsm900和dcs1900的上下行频率及射频带宽等
http://www.rfhy.com/gb2312/UploadFile/200562794926966.doc

什么是双工间隔?GSM系统、DCS1800的双工间隔是多少?

双工间隔指上下行频率之间的间隔,GSM为45MHz,DCS1800为95MHz。

900MHz

    基本工作频带:          上行:890~915MHz

                    下行:935~960MHz

    扩展工作频带:          上行:880~890MHz

                    下行:925~935MHz

dB、dBm、dBc、dBi的区别:

dB是个比值,不是单位;dBm是功率的单位;dBc常用互调方面,不常用;dBi是增益单位。

通信的时候在逻辑上需要两条链路:一条是出去的,一条是进来的(上行和下行);
上行是指信号从移动台(一般指手机)到基站(2G叫BTS,3G叫NODEB)到BSC
下行是指信号从BSC到基站(2G叫BTS,3G叫NODEB)到移动台(一般指手机)

这两条链路必须要分开,否则通信无法正常进行,由此产生双工模式。双工模式有2种:时分双工(TDD)和频分双工(FDD)
在TDD中,上下行链路靠时隙来区分,频率是一样的,  比如TD-SCDMA
在FDD中,上下行链路靠不同的频率来区分,同时收发,  比如WCDMA(FDD)
为了有效地区分开上下行频率,上行频率与下行频率必须有一定的间隔(保护带)
一般下行频率高于上行频率。

在GSM系统中,上行(接收)的频率为:880-915MHZ;下行(发射)频率为:925-960MHZ;
在我国GSM900的使用频率是:905-915MHZ(上行),950-960MHZ(下行)
移动的:下行(前向)950MHz-954MHz,  上行(反向)905MHz-909MHz共4M带宽,20个频道;
联通CDMA:下行 954MHz~960MHz  上行909MHz~915MHz共6M带宽,29个频道.
频率间隔是200KHZ;
双工间隔是45MHZ

上行:(890~915)MHz,移动台发。
下行:(935~960)MHz,移动台收。
频带宽度:25 MHz。
上,下行频率间隔:45 MHz。
载频间隔:200KHz
频点:25 MHz/200K Hz=125,共124个频点。
通信方式:全双工
DCS1800,上行:1710-1785MHz,下行:1805-1880MHz.
3. volatile关键字有什么用?

恐怕比较一下volatile和synchronized的不同是最容易解释清楚的。volatile是变量修饰符,而synchronized则作用于一段代码或方法;看如下三句get代码:

1.                             int i1; int geti1() {return i1;}

2.                             volatile int i2;  int geti2() {return i2;}

3.                             int i3;synchronized int geti3() {return i3;}

  geti1()得到存储在当前线程中i1的数值。多个线程有多个i1变量拷贝,而且这些i1之间可以互不相同。换句话说,另一个线程可能已经改变了它线程内的i1值,而这个值可以和当前线程中的i1值不相同。事实上,Java有个思想叫“主”内存区域,这里存放了变量目前的“准确值”。每个线程可以有它自己的变量拷贝,而这个变量拷贝值可以和“主”内存区域里存放的不同。因此实际上存在一种可能:“主”内存区域里的i1值是1,线程1里的i1值是2,线程2里的i1值是3——这在线程1和线程2都改变了它们各自的i1值,而且这个改变还没来得及传递给“主”内存区域或其他线程时就会发生。
  而geti2()得到的是“主”内存区域的i2数值。用volatile修饰后的变量不允许有不同于“主”内存区域的变量拷贝。换句话说,一个变量经 volatile修饰后在所有线程中必须是同步的;任何线程中改变了它的值,所有其他线程立即获取到了相同的值。理所当然的,volatile修饰的变量存取时比一般变量消耗的资源要多一点,因为线程有它自己的变量拷贝更为高效。
  既然volatile关键字已经实现了线程间数据同步,又要synchronized干什么呢?呵呵,它们之间有两点不同。首先, synchronized获得并释放监视器——如果两个线程使用了同一个对象锁,监视器能强制保证代码块同时只被一个线程所执行——这是众所周知的事实。但是,synchronized也同步内存:事实上,synchronized在“主”内存区域同步整个线程的内存。因此,执行geti3()方法做了如下几步:
1. 线程请求获得监视this对象的对象锁(假设未被锁,否则线程等待直到锁释放)
2. 线程内存的数据被消除,从“主”内存区域中读入(Java虚拟机能优化此步。。。[后面的不知道怎么表达,汗])
3. 代码块被执行
4. 对于变量的任何改变现在可以安全地写到“主”内存区域中(不过geti3()方法不会改变变量值)
5. 线程释放监视this对象的对象锁
  因此volatile只是在线程内存和“主”内存间同步某个变量的值,而synchronized通过锁定和解锁某个监视器同步所有变量的值。显然synchronized要比volatile消耗更多资源。

  1. 链表和数组的区别

链表的特性是在中间任意位置添加删除元素的都非常的快,不需要移动其它的元素。
链表顾名思义,要把各个元素链接起来才算撒。
通常链表每一个元素都要保存一个指向下一个元素的指针(单链表)。
双链表的化每个元素即要保存到下一个元素的指针,还要保存一个上一个元素的指针。
循环链表则把最后一个元素中保存下一个元素指针指向第一个元素。
数组是一组具有相同类型和名称的变量的集合。这些变量称为数组的元素,每个数组元素都有一个编号,这个编号叫做下标,我们可以通过下标来区别这些元素。数组元素的个数有时也称之为数组的长度
5. 写出strcpy的c实现代码

不使用库函数实现strcpy。这是一个很简单的题目,但它却可以考察如下的几点:

1)编程风格;

2)出错处理;

3)算法复杂度分析(用于提高性能)。

这是摘自林锐的《高质量C++/C编程指南》中的内容。

也有人总结成了下面的几点,说的也很有道理:

1)注意编程风格。比如,使用dstsrc这样增强可读性的名字。

2)使用断言来检验输入参数的有效性。

3)使用const来约束src,表明src对应的内容不能被修改。

4)返回dst,以便实现链式表达式这样的机制。
char   *strcpy(char   *strDest,   const   char   *strSrc);
{
        //使用断言来检验输入参数的有效性。

assert((strDest!=NULL)   &&   (strSrc !=NULL));
        char   *address   =   strDest;
        while(   (*strDest++   =   *   strSrc++)   !=   ‘\0’   )
              NULL   ;  
        return   address   ;
}
6。求两个字符串的最大公共字符子串,如"abccade","dgcadde"的最大子串为"cad"
int GetCommon(char *s1, char *s2, char **r1, char **r2)
{
    int len1 = strlen(s1);
    int len2 = strlen(s2);
    int maxlen = 0;

    for(int i = 0; i < len1; i++)
    {
        for(int j = 0; j < len2; j++)
        {
            if(s1 == s2[j])
            {
        int as = i, bs = j, count = 1;
        while((as + 1 < len1 )&& (bs + 1 < len2) && (s1[++as] ==s2[++bs]))
                    count++;

                if(count > maxlen)
                {
                    maxlen = count;
                    *r1 = s1 + i;
                    *r2 = s2 + j;
                }
            }
        }
}

 

 

 

关于内存的4个经典题目GetMomery
void GetMemory(char *p)
{
    p = (char *)malloc(100);
}

void Test(void) 
{
    char *str = NULL;
    GetMemory(str); 
    strcpy(str, "hello world");
    printf(str);
}
请问运行Test函数会有什么样的结果?
答:程序崩溃。
因为GetMemory并不能传递动态内存,
Test函数中的 str一直都是 NULL。
strcpy(str, "hello world");将使程序崩溃。
说的简单一些,就是传入的就是一个空指针,p确实分配空间了,
但是生成的空间首地址没有返回给str


2:
char *GetMemory(void)

    char p[] = "hello world";
    return p;
}
void Test(void)
{
    char *str = NULL;
    str = GetMemory(); 
    printf(str);
}
请问运行Test函数会有什么样的结果?
答:可能是乱码。
因为GetMemory返回的是指向"栈内存"的指针,该指针的地址不是 NULL,但其原现的内容已经被清除,新内容不可知。
说的简单一些,就是函数的局部变量释放了。

3:
void GetMemory2(char **p, int num)
{
    *p = (char *)malloc(num);
}
void Test(void)
{
    char *str = NULL;
    GetMemory(&str, 100);
    strcpy(str, "hello"); 
    printf(str); 
}
请问运行Test函数会有什么样的结果?
答:
(1)能够输出hello
(2)内存泄漏
说的简单一些,就是没有释放malloc的空间

4:
void Test(void)
{
    char *str = (char *) malloc(100);
    strcpy(str, "hello");
    free(str); 
    if(str != NULL)
{
            strcpy(str, "world"); 
            printf(str);
}
}
请问运行Test函数会有什么样的结果?
答:篡改动态内存区的内容,后果难以预料,非常危险。
因为free(str);之后,str成为野指针,
if(str != NULL)语句不起作用。
说的简单一些,就是只收回内存,没有用str=NULL收回指针

posted on 2013-10-23 15:33  -赶鸭子上架-  阅读(617)  评论(0编辑  收藏  举报