C++字符串与C语言中的字符串处理函数

C++字符串与C语言中的字符串处理函数

一.C++中的字符串类

下面是简单的一种实现:

#ifndef STRING_H_INCLUDED
#define STRING_H_INCLUDED

class String
{
public:
    String (const char* cstr = 0);
    String (const String&);
    String& operator = (const String&);
    ~String();
    char* get_c_str() const  { return m_data; }

private:
    char* m_data;
};

#include <cstring>

inline
String::String (const char* cstr)
{
    if (cstr) {
        m_data = new char[strlen(cstr) + 1];
        strcpy (m_data, cstr);
    }
    else {
        m_data = new char[1];
        *m_data = '\0';
    }
}

inline
String::String (const String& str)
{
    m_data = new char[strlen(str.m_data) + 1];
    strcpy (m_data, str.m_data);
}

inline String&
String::operator = (const String& str)
{
    if(this == &str)
        return *this;
    delete [] m_data;
    m_data = new char[strlen(str.m_data) + 1];
    strcpy (m_data, str.m_data);
    return *this;
}

inline
String::~String()
{
    delete [] m_data;
}

#include <iostream>
using namespace std;
ostream& operator << (ostream& os, const String& str)
{
    os << str.get_c_str();
    return os;
}

#endif // STRING_H_INCLUDED

特别注意:string类是由一系列字符组成,但是必须以\0结尾**
依次来分析这个类的实现:
- 成员变量就是一个char*
- 构造函数,传入const char*,如果传入的是空指针,特别注意开辟一个新的内存来放置\0;如果非空,先用new开辟一块内存,内存大小要等于strlen()+1,1也是用来放置\0的,最后使用strcpy()进行拷贝,下一节我们也探讨了这个函数的实现。
- 拷贝构造函数:和构造函数类似。
- 拷贝赋值运算符:要注意证同测试,先释放原先的内存,再声明一块内存,最后使用strcpy()进行拷贝。
- 析构函数:比较显然。
- 为了保持一致,重载了运算符<<

二.C语言中的常见字符串处理函数以及内存拷贝函数

首先头文件必须包含以下

#include <assert.h> //for assert
#include <cstddef>  //for size_t

1. 计算字符串的长度:

这个函数比较简单,只要遇到\0退出即可

//计算字符串的长度:strlen
std::size_t myStrlen(const char* str){
    assert(str != NULL);
    std::size_t length = 0;
    while(*str++ != '\0')
        ++length;
    return length;
}

2. 字符串的拷贝:

拷贝源(第二个参数)是const char*,注意拷贝目的地(第一个参数)需要使用临时变量保存一下,最后只需要循环执行(*dest++ = *src++) != '\0'即。

//实现字符串的拷贝:strcpy
char* myStrcpy(char* dest, const char* src){
    //dest: 指向要写入的字符数组的指针
    //src: 指向复制来源的空终止字节字符串的指针
    //若dest数组不够大则行为未定义;若字符串重叠则行为未定义。
    assert(dest != NULL && src != NULL);
    char *temp = dest;
    while((*dest++ = *src++) != '\0');
    return temp;
}

Strncpy则将src前count个字符拷贝给dest,如果Count大于src的长度(strlen),则剩余部分补\0

char* myStrncpy(char* dest, const char* src, std::size_t count){
    assert(dest != NULL && src != NULL);
    char *temp = dest;
    int offset = 0;
    if(myStrlen(src) < count){
        offset = count - myStrlen(src);
        count = myStrlen(src);
    }
    while(count--)
        *dest++ = *src++;
    while(offset--)
        *dest++ = '\0';
    return temp;
}

3.字符串的拼接:

先跑到dest的末尾\0,再依次拷贝src。

//实现字符串的拼接:strcat
char *myStrcat( char *dest, const char *src ){
    //dest 指向要后附到的空终止字节字符串的指针
    //src 指向作为复制来源的空终止字节字符串的指针
    //若字符串重叠则行为未定义。
    assert(dest != NULL && src != NULL);
    char* temp = dest;
    while(*dest)
        ++dest;
    while(*dest++ = *src++);
    return temp;
}

myStrncat:将则将src前count个字符拼接到dest后面,方法类似,注意最后要补\0

char *myStrncat( char *dest, const char *src, std::size_t count ){
    assert(dest != NULL && src != NULL);
    char* temp = dest;
    while(*dest)
        ++dest;
    while(count-- && (*dest++ = *src++));
    *dest = '\0';
    return temp;
}

4.字符串的比较:

注意返回值:*lhs - *rhs,最后一个不相同的字符的ASCII之差。

//实现字符串的比较:strcmp
int myStrcmp(const char* lhs, const char* rhs){
    //lhs, rhs 指向待比较的空终止字节字符串的指针
    assert(lhs != NULL && rhs != NULL);
    while(*lhs == *rhs){
        if(*lhs == '\0')
            return 0;
        ++lhs;
        ++rhs;
    }
    return *lhs - *rhs;
}

5.memset()函数:

//将dest前面count个字符置为字符c.返回dest的值.
void *myMemset(void *dest, int c, size_t count) {
    assert(dest != NULL);
    void *s = dest;
    while (count--) {
        *(char *)s = (char) c;
        s = (char *)s + 1;
    }
    return dest;
}

6.memcpy()函数:

注意,如果src和dest重叠的情况,则会出错

//从src复制count字节的字符到dest. 与memmove功能一样, 只是不能处理src和dest出现重叠.返回dest的值
void *myMemcpy(void *dest, const void *src, size_t count) {
    assert(dest != NULL && src != NULL);
    void *s = dest;
    while (count--) {
        *(char *)s = *(char *)src;
        s = (char *)s + 1;
        src = (const char *)src + 1;
    }
    return dest;
}

7.memmove()函数:

可以正确处理src和dest重叠的情况

//从src复制count字节的字符到dest. 如果src和dest出现重叠, 函数会自动处理.返回dest的值.
void *myMemmove(void *dest, const void *src, size_t count) {
    assert(dest != NULL && src != NULL);
    void *s = dest;
    if (s <= src || (char *)s >= (char *)src + count) {
        //未重叠的部分,和memcpy一样的行为
        while (count--) {
            *(char *)s = *(char *)src;
            s = (char *)s + 1;
            src = (const char *)src + 1;
        }
    }
    else {
        //内存出现重叠之后,从后往前copy;
        s = (char *)s + count - 1;
        src = (char *)src + count - 1;
        while (count--) {
            *(char *)s = *(char *)src;
            s = (char *)s - 1;
            src = (char *)src - 1;
        }
    }
    return dest;
}

猜你喜欢

转载自blog.csdn.net/qq_25467397/article/details/80891084