1. 程式人生 > >面試中常見的字串庫函式程式設計

面試中常見的字串庫函式程式設計

下面對一些常見的關於字元的庫函式進行實現,這些也是通常面試中所問的一些問題,需要注意的是有些看起來很簡單,但是一定要考慮一些邊界條件,否則很容易出錯.

strcpy實現

char* strcpy(char* dst,const char* src){
    if(dst== nullptr||src== nullptr)  //注意邊界條件
        return nullptr;
    char* pdst =dst;
    const char* psrc = src;
    while(*psrc!='\0') {    //這裡不能寫成psrc!='\0'
        *pdst++ = *psrc++;
    }
    *pdst = '\0'
; //注意結尾 return dst; }

strncpy實現

char* strncpy(char* dst,const char* src,size_t count) {
    if(dst== nullptr||src== nullptr||count<=0)
        return dst;
    char* pdst =dst;
    const char* psrc = src;
    while(count--&&*psrc!='\0') {
        *pdst++ = *psrc++;
    }
    *pdst = '\0'
; //注意 return dst; }

上述的兩個關於拷貝的函式都有問題–其沒有考慮到記憶體的重疊的問題,因此會有下面一個函式作為代替.

memmove實現

void* memmove(void *dst,const void *src,size_t n) {
    //判斷合法性
    if (dst == NULL || src == NULL)
        return NULL;
    char* pdst = (char*)dst;      //強制轉換成char*
    const char* psrc=(const char*)src;
    //防止記憶體重疊的處理
if (pdst<psrc) { for (size_t i = 0;i<n;i++) *(pdst++)=*(psrc++); } else { //從後往前 pdst += n-1; psrc += n-1; for (size_t i = 0;i<n;i++) *(pdst--)=*(psrc--); } *pdst='\0'; return dst; }

strlen實現

最常見的庫函數了,下面是一種實現的方式

size_t mystrlen(const char* src) {
    if(src== nullptr) return 0;
    size_t count=0;
    while(*src!='\0') {
        src++;
        count++;
    }
    return count;
}

memset實現

這個函式是非常容易出錯的,因為它是以位元組為單位進行初始化的,因此如果對與int等別的型別進行初始化的時候要非常小心.

//其函式的形式就是標準的庫函式形式
void* mymemset(void* src,int ch,size_t n){   //注意函式的形式
    if(src== nullptr)
        return src;
    char* psrc = (char*)src;
    while(n--){
        *psrc++ = static_cast<char>(ch);
    }
    return src;
}

測試

下面對上述的函式進行測試,看出其不同的地方:

#include <iostream>
using namespace std;
char* strcpy(char* dst,const char* src){
    if(dst== nullptr||src== nullptr)
        return nullptr;
    char* pdst =dst;
    const char* psrc = src;
    while(*psrc!='\0') {
        *pdst++ = *psrc++;
    }
    *pdst = '\0';
    return dst;

}
char* strncpy(char* dst,const char* src,size_t count) {
    if(dst== nullptr||src== nullptr||count<=0)
        return dst;
    char* pdst =dst;
    const char* psrc = src;
    while(count--&&*psrc!='\0') {
        *pdst++ = *psrc++;
    }
    *pdst = '\0';
    return dst;

}
void* memmove(void *dst,const void *src,size_t n) {
    //判斷合法性
    if (dst == NULL || src == NULL)
        return NULL;
    char* pdst = (char*)dst;
    const char* psrc=(const char*)src;
    //防止記憶體重疊的處理
    if (pdst<psrc) {
        for (size_t i = 0;i<n;i++)
            *(pdst++)=*(psrc++);
    }
    else {
        pdst += n-1;
        psrc += n-1;
        for (size_t i = 0;i<n;i++)
            *(pdst--)=*(psrc--);
    }
    *pdst='\0';
    return dst;
}
size_t mystrlen(const char* src) {
    if(src== nullptr) return 0;
    size_t count=0;
    while(*src!='\0') {
        src++;
        count++;
    }
    return count;
}
void* mymemset(void* src,int ch,size_t n){
    if(src== nullptr)
        return src;
    char* psrc = (char*)src;
    while(n--){
        *psrc++ = static_cast<char>(ch);
    }
    return src;
}
int main() {
    //兩種情況會不同...有記憶體的重疊
    char c1[]="hello,world";
    char c2[]="hello,world";
    memmove(c2+6,c2+5,5);
    strncpy(c1+6,c1+5,5);
    cout<<c1<<endl;
    cout<<c2<<endl;
    ////////////////////////
    char t[]="12345";
    cout<<mystrlen(t)<<endl;    //5
    cout<<sizeof(t)<<endl;      //6 , have '\0'
    char* t1 ="12345";
    cout<<sizeof(t1)<<endl;     //8 ,pointer,64 machine
    cout<<mystrlen(t1)<<endl;   //5
    ///////////////////////注意memeset函式的用法
    char buf[10];
    mymemset(buf,'1',sizeof(buf));
    for(int i=0;i<sizeof(buf);i++)
        cout<<buf[i]<<" ";
    cout<<endl;
    int buf1[10];
    mymemset(buf1,1,sizeof(buf1));
    cout<<sizeof(buf1)<<endl;
    for(int i=0;i<sizeof(buf1)/sizeof(int);i++)
        cout<<buf1[i]<<" ";
    cout<<endl;

    return 0;
}

…………to be continue