面试 1

转载 2006年06月09日 17:18:00

关于C++的面试方面,林锐博土的<<高质量C++/C编程指南>>里附带的一些试题被大量引证来测试应试人员的基础。很不幸,我也被做了一份,回来后,和林锐的标准答案一对,觉得,他的答案还是有些不足之处,下面我就说说那两个题,也许凭记忆能回忆起面试中的一些趣事。

已知strcpy函数的原型是

char *strcpy(char *strDest, const char *strSrc);

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

不调用C++/C的字符串库函数,请编写函数 strcpy

林锐的标准答案如下:

char *strcpy(char *strDest, const char *strSrc);

{

         assert((strDest!=NULL) && (strSrc !=NULL));   // 2分

         char *address = strDest;                     // 2分

         while( (*strDest++ = * strSrc++) != ‘/0’ )      // 2分

           NULL ;

         return address ;                            // 2分

}

我在写时,写出下面这样子的:

char *strcpy_x(char *strDest, const char *strSrc)

{

    if((strDest==NULL) || (strSrc ==NULL))

       return NULL;       // 2分

    if(strDest==strSrc)//add by xie

       return strDest;  

    char *address = strDest;                                     // 2分

    while( (*strDest++ = * strSrc++) != ''/0'' )              // 2分

       ;

   return address ;                                          // 2分

}

我当时这样写的理由如下:

a. 没必要为一个strcpy函数中的参数有NULL就断言大错涌出,返回NULL值也是一个好见识

b. 为了防止写出strcpy(strDest,strSrc)(而strDest是等于strSrc,又很不凑巧strDest是大字串,这些代码又运行一种比较计时的环境下,所以判断是否相同应该是必须的。更重要的一点:林锐的这篇文章影响了好多公司招人,这样一写,我给别人留下的印象是不同的,你认为呢?:)

2. 相信大部人都看过甚至做过下面这个题:

已知类String的原型为:

    class String

    {

      public:

        String(const char *str = NULL);  // 普通构造函数

        String(const String &other);        // 拷贝构造函数

        ~ String(void);                        // 析构函数

        String & operate =(const String &other);    // 赋值函数

      private:

        char      *m_data;                // 用于保存字符串

    };

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

在我给出我找碴的理由先,我先给出林锐的标准答案及指出一点不足处:

// String的析构函数

       String::~String(void)               // 3分

{

    delete [] m_data;                        

// 由于m_data是内部数据类型,也可以写成 delete m_data;

       }

       // String的普通构造函数            

       String::String(const char *str)      // 6分

{

    if(str==NULL)                         

    {

        m_data = new char[1];    // 若能加 NULL 判断则更好(你都白痴的,还判断null干鸟啊)

        *m_data = ‘/0’;                     

    }                                         

    else

    {

        int length = strlen(str);          

        m_data = new char[length+1];  // 若能加 NULL 判断则更好     

        strcpy(m_data, str);               

    }

}  

// 拷贝构造函数

    String::String(const String &other)   // 3分

    {  

    int length = strlen(other.m_data); 

    m_data = new char[length+1];      // 若能加 NULL 判断则更好   

    strcpy(m_data, other.m_data);        

}

// 赋值函数

    String & String::operate =(const String &other)    // 13分

    {  

      // (1) 检查自赋值                     // 4分

        if(this == &other)

           return *this;

// (2) 释放原有的内存资源            // 3分

        delete [] m_data;

       // (3)分配新的内存资源,并复制内容 // 3分

    int length = strlen(other.m_data); 

    m_data = new char[length+1];         // 若能加 NULL 判断则更好

        strcpy(m_data, other.m_data);

       // (4)返回本对象的引用            // 3分

        return *this;

}  

我记得我去年初买了<<inside C++ object modules>>时,里面也以String为例作了一个介绍,不过书到用时找不到,因为我已送给好学后进了。而电子版的,我当时在网上看了,但好像没当下来。我依稀记得里面的拷贝构造函数也要判断if(this == &other)的,不过我认为要是已实现了operator==函数的话,if(*this == other)会更好一些,因为例如象String的两个对象,内容一样,一个给另一个赋值时,用if(*this == other)的判断的话,就可避免下一些操作了。黑夜给了我黑色的眼,我睁一只眼闭一只眼都可以看出上面的标准答案里关于拷贝构造函数中没有这样的判断,对了,上文中的operator被误写成operate了,那些公司里的试题也是这样子的,让我看的时候愣了下。

大家可能会认为拷贝构造函数是构造函数,怎么会传进去它自己呢?肯定是别的对象了。很搞笑的是:String ss(ss),没错,String ss(ss=”xieyingjun”)也是对的写法(对了,我没就这个C++语意查看C++标准,要是根据C++98的标准,我的说法扯淡,也请付之一笑)。文后我附上本篇文章的测试代码。您也可以在C++Builder中先打上这两行,看看结果:AnsiString ss(ss=”xieyingjun”);ShowMessage(ss); 不过,很不幸,类似的代码用STL中的String或VC中的CString来实现,运行结果好象并非是一帆风顺。

#include <iostream>

char *strcpy_x(char *strDest, const char *strSrc)

{

    if((strDest==NULL) || (strSrc ==NULL))

       return NULL;       // 2分

    if(strDest==strSrc)//add by xie

       return strDest;  

    char *address = strDest;                                     // 2分

    while( (*strDest++ = * strSrc++) != ''/0'' )              // 2分

        ;

   return address ;                                          // 2分

}

class String

       {

         friend std::ostream& operator <<(std::ostream& os, const String& arg);       //add by xie

         public:

              String(const char *str = NULL);  // 普通构造函数

              String(const String &other);           // 拷贝构造函数

              ~ String(void);                              // 析构函数

              String & operator =(const String &other); // 赋值函数

        private:

              char         *m_data;                            // 用于保存字符串

       };

// String的析构函数

String::~String(void)               // 3分

{

       delete [] m_data;

       m_data=0; //add by xie                       

// 由于m_data是内部数据类型,也可以写成 delete m_data;

//note by xie:有次去华为,华为批题,写成delete m_data;不给分,一个人的见识就是这样得来的,:P 

}

       // String的普通构造函数            

String::String(const char *str)      // 6分

{

       if(str==NULL)                         

       {

              m_data = new char[1];    // 若能加 NULL 判断则更好

              *m_data = ''/0'';                     

       }                                           

       else

       {

              int length = strlen(str);          

              m_data = new char[length+1];  // 若能加 NULL 判断则更好     

              strcpy(m_data, str);               

       }

}    

// 拷贝构造函数

       String::String(const String &other)   // 3分

       {    

        if(this==&other)

           return; //add by xie

       int length = strlen(other.m_data);    

       m_data = new char[length+1];      // 若能加 NULL 判断则更好   

       strcpy(m_data, other.m_data);        

}

// 赋值函数

       String & String::operator =(const String &other)    // 13分

       {    

              // (1) 检查自赋值                     // 4分

              if(this == &other)

                     return *this;

// (2) 释放原有的内存资源            // 3分

              delete [] m_data;

              // (3)分配新的内存资源,并复制内容 // 3分

       int length = strlen(other.m_data);    

       m_data = new char[length+1];         // 若能加 NULL 判断则更好

              strcpy(m_data, other.m_data);

// (4)返回本对象的引用            // 3分

              return *this;

}    

std::ostream& operator <<(std::ostream& os, const String& arg) //add by xie

{

  os<<arg.m_data;

  return os;  

}

int main()

{

  const char s1[]="hello world!";

  char s2[100];

  char s3[100];

  strcpy_x(s3, strcpy_x(s2,s1));

  std::cout<<"s3:"<<s3<<std::endl;

  std::cout<<"s2:"<<s2<<std::endl;

  String ss(ss=s1);

  std::cout<<"ss:"<<ss<<std::endl;

 /*此处会报一个内存不能read的错,具体原因引起,还要看C++标准关于这处的语意定义,再作修改,不过要是有人写出大量的不当类似实现代码也会造成内存泄露的。 */

  return 0;

}


黑马程序员 (7k面试)银行取票系统学习笔记

---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ---------------------   通过对银行取票系统的分析,需要至...

Java 笔试 面试

数据库调优,服务器调优
  • lzx0122
  • lzx0122
  • 2015年03月25日 22:27
  • 341

Linux 信号,僵尸进程,(面试)

1,信号有那些是不能被屏蔽的???() 2,僵尸进程是什嘛样子的,产生子进程的时候给其分配空间了之后,在变成僵尸进程之后,对这块空间是如何处理   的,是将其全部释放掉???还是保留部分空间给(子进程...

3.1.3 Memcached的安装(1)

《高性能Linux服务器构建实战:运维监控、性能调优与集群应用》第3章Memcached应用实战,本章主要介绍Memcached的特征、运行原理和使用经验。Memcached是一套分布式内存对象缓存系...

sql 学习(1)

  • 2008年06月10日 08:55
  • 172KB
  • 下载

《精通Hadoop》:第 1 章 Hadoop 2.X

第 1 章 Hadoop 2.X “没有什么是不能通过搜索引擎或互联网找到的。” ——埃里克·施密特,谷歌执行主席 在大规模、高并行和分布式计算处理这个行业中,Hadoop实...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:面试 1
举报原因:
原因补充:

(最多只允许输入30个字)