西西河

主题:说说我前面提到过的面试题 -- 使用尽量中文

共:💬6 🌺4 新:
全看分页树展 · 主题
家园 说说我前面提到过的面试题

原题如下:

不许用STL,实现一个类 string,封装库函数strcat。这个类可以这么调用:

string s1("abcde"),s2("1234567"),s3;

s3=s1+s2; //now s3 should represent sth like "abcde1234567"

帖子后面给出了我的答案。当然好答案绝对不是唯一的,这里高手众多,希望大家能拨冗指正。

我对答案的评判有这么几个标准:

1. 知道基本的c++概念,类、构造析构、运算符重载,也知道必要的编程惯例,比如c风格的字符串。

2. 具有程序员级别的设计能力和问题解决能力,能根据简要的叙述设计出可行的实现框架。对问题中含糊或没有明确的部分,可以做出尽量合理的假设,并把这些假设体现在文档中。

3. 能够合理分配和释放资源,有RAII的概念。知道delelte[]和delete的区别。

4. 具备exception safe的概念。

5. 实现中避免常见的错误。知道一些避免错误的技巧。

6. 选择让代码的使用者不容易出错的实现方式。

7. 注意到一些易被忽略的实现细节,一个例子就是这道题里的字符串可能是双字节的或多字节的。

前6项都是比较基本和重要的。

我给出的答案里用了重载来实现编译时根据不同的类型调用不同版本的库函数,这个其实不很重要。大家可以忽略。

//myString.h

#ifndef MY_STRING_H

#define MY_STRING_H

#include <string.h>

#if _MSC_VER > 1000

#pragma warning(disable : 4996)

#endif

template<class T> //T could be char, wchar_t, unsigned char, specific to single character, wide character, or multibyte character string

class universal_string{

public:

universal_string();

universal_string(const T* source); //const is expected

virtual ~universal_string(); //virtual so that derived class would be deleted properly

universal_string(const universal_string<T>& source); //mandatory because of "rule of three"

universal_string<T>& operator =(const universal_string<T>& source);

size_t len() const{ //optional for this problem, good habit for a experienced programer though

return length;

}

//helper functions

universal_string<T>& concatenate(const universal_string<T>& source);

private:

size_t length; //we assume the longest string won't exceed an unsigned int.

T* pString;

};

template<class T> //allow expression like "AAA" + string2, in which the first operand is a pointer to char

const universal_string<T> operator + (const universal_string<T>& first, const universal_string<T>& second){ //first const here to make sure the expression won't be misused as lvalue.

universal_string<T> result(first);

return result.concatenate(second);

}

//following helper functions to decide which version function in library to call in compile time.

char * myStrCpy(char *strDestination,const char *strSource ){

return strcpy(strDestination,strSource);

}

wchar_t *myStrCpy( wchar_t *strDestination, const wchar_t *strSource){

return wcscpy(strDestination,strSource);

}

size_t myStrLen(const char* str){

return strlen(str);

}

size_t myStrLen(const wchar_t* str){

return wcslen(str);

}

#ifdef _MBCS

#include <mbstring.h>

unsigned char *myStrCpy(unsigned char *strDestination,const unsigned char *strSource ){

return _mbscpy(strDestination,strSource);

}

size_t myStrLen(const unsigned char* str){

return _mbslen(str);

}

#endif

template<class T>

universal_string<T>::universal_string(const T* source): //assume source is pointing to a valid string. especially, it can not be NULL

length(myStrLen(source)), //even we add codes to check if it is NULL, we still can not prevent it being some other non null but invalid value

pString(new T[length+1]){ //therefore such check does not make much sense.

myStrCpy(pString,source);

}

template<class T>

universal_string<T>::universal_string():

length(0),pString(new T[1]){ //T[1] instead of T to be compatible with destructor

*pString=0;

}

template<class T>

universal_string<T>::~universal_string(){

delete[] pString; //[] is mandatory

}

template<class T>

universal_string<T>::universal_string(const universal_string<T>& source):

length(source.length),

pString(new T[length+1]){

myStrCpy(pString, source.pString);

}

template<class T>

universal_string<T>& universal_string<T>::operator =(const universal_string<T>& source){

//your solution must gurantee that when

//1. source is *this, and/or

//2. exception is thrown inside the function

//it still handles correctly

T* buffer=new T[source.length+1];

myStrCpy(buffer,source.pString);

delete[] pString;

pString=buffer;

length=source.length;

return *this;

}

template<class T>

universal_string<T>& universal_string<T>::concatenate(const universal_string<T>& source){

//your solution must gurantee that when

//1. source is *this, and/or

//2. exception is thrown inside the function

if (source.length>0) {

size_t tmpLen=length+source.length;

T* buffer=new T[tmpLen+1];

if (pString!=NULL) myStrCpy(buffer,pString);

myStrCpy(buffer+length,source.pString); //since we know where to join, we use strcpy in stead of strcat for better performance

delete[] pString;

pString=buffer;

length=tmpLen;

}

return *this;

}

#define string universal_string<wchar_t>

#endif

//main.cpp

#include "myString.h"

int main(int narg,char**varg){

string s1(L"ABCDEFG"),s2(L"1234567"),s3;

s3=s1+s2;

}


本帖一共被 1 帖 引用 (帖内工具实现)
全看分页树展 · 主题


有趣有益,互惠互利;开阔视野,博采众长。
虚拟的网络,真实的人。天南地北客,相逢皆朋友

Copyright © cchere 西西河