[C++基础]实现自己的String

string

Posted by JinFei on March 9, 2020

assert是宏,而不是函数。它的原型定义在头文件 assert.h 中:

void assert( int expression );

宏 assert 经常用于在函数开始处检验传入参数的合法性,可以将其看作是异常处理的一种高级形式。assert 的作用是先计算表达式expression,然后判断:

  • 如果表达式值为假,那么它先向stderr打印错误信息,然后通过调用 abort 来终止程序运行。
  • 如果表达式值为真,继续运行后面的程序。

类型CMyString,请为该类型添加赋值运算符函数。

// 数据成员有char* m_data[]
CMyString& CMyString::operate = (const CMyString& str){ //参数设置为引用,防止从形参到实参调用复制构造函数。
    if(this == &str){      // 要判断传入参数和*this是否是同一个实例。
        return *this;   
    }
    delete[] m_data;      // 释放自己本身的内存,防止程序发生内存泄漏。
    m_data = NULL;
    m_data = new char[strlen(str.m_data) + 1];
    strcpy(m_data, str.m_data);
    return *this;       // 只有返回一个引用(*this),才可以被连续赋值。
}

字符串长度 strlen

int strlen(const char* str){
    assert(str != NULL);
    int cnt = 0;
    char* t = str;
    while(*t  != '\0'){
        t++;
        cnt++;
    }
    return cnt;
}

字符串复制 strcpy

// 为了实现链式表达式. // int length = strlen( strcpy( strDest, “hello world”) );

char* strcpy(char* dest, const char* src){
    assert(dest != NULL && src != NULL)
    char* res = dest;
    /*
    while((*dest++ = *src++) != '\0'){   // 最后拷贝的应该包含 '\0'
        ;
    }
    */
    // 也可以改为
    int i;
    for(i = 0; src[i] != '\0'; i++){
        dest[i] = src[i];
    }
    dest[i] = '\0'; // 最后加一个‘\0’ 结尾标识符
    return res;
}

字符串拼接 strcat

char* strcat(char* desc, const char* src){
    assert(desc != NULL && src != NULL);
    char* res = desc;   // 一般返回新的地址
    while(*desc != '\0'){
        desc++;  
    }
    while((*desc++ = *src++) != ‘\0’){
        ;
    }
    return res;
}

字符串比较 strcmp

int strcmp(const char* str1, const char* str2){
    assert(str1 != NULL && str2 != NULL);
    while(*str1 != NULL && *str1 == *str2){
        str1++;
        str2++;
    }
    return (int)((unsigned char)*str1 - (unsigned char)*str2);
}

返回字符串s中第一次出现c的位置 strchr

// 返回首次出现c的位置的指针,如果s中不存在c则返回NULL。
char* strchr(const char* str, const char c){
    assert(str != NULL)
    char* t = str;
    while(*t != '\0' && *t != c){
        t++;
    }
    if(*t != '\0'){
        return (char*)t;    // 需要强转
    }
    return NULL;
}

设置内存位置v开始的n个元素值为c memset

内存拷贝,注意覆盖情况 memcopy

void* memcpy(void* dsc, const void* src, int length){
    assert(dsc != nullptr && src != nullptr);   // 如果为假的话 断言报错
    char* d;
    const char* s;
    if((char*)src + length < (char*)dsc || dsc < src){
        d = (char*)dsc;
        s = (char*)src;
        while(length > 0){
            *d = *s;
            d++;
            s++;
            length--;
        }
    }else{
        d = (char*)dsc + length - 1;
        s = (char*)src + length - 1;
        while(length){
            *d = *s;
            d--;
            s--;
            length--;
        }
    }
    return dsc;
}