字符串类String8

本文介绍了一个仿Android String8工具类的设计与实现,包括构造函数、字符串操作方法及格式化输出等功能。通过示例展示了如何使用该类进行字符串拼接、格式化输出等常见操作。

仿Android 工具类String8写的

/*************************************************************************
    > File Name: string8.h
    > Author: hsz
    > Mail:
    > Created Time: 2021年04月11日 星期日 12时24分52秒
 ************************************************************************/

#ifndef __STRING8_H__
#define __STRING8_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <stdarg.h>
#include <stdint.h>
#include <ctype.h>

namespace Alias {

#define MAXSIZE (1024 * 8)

class String8 {
public:
                        String8();
                        String8(const String8& other);
                        String8(const char* other);
                        String8(const char* other, const size_t numChars);
                        String8(const std::string& other);

                        ~String8();

    const char*         c_str() const;
    std::string         toStdString() const;           // String8 -> std::string

    bool                isEmpty() const;
    size_t              length() const;
    void                clear();

    int                 append(const String8& other);
    int                 append(const char* other);
    int                 append(const char* other, size_t numChars);
	// this只能用于非静态成员函数,所以第一个参数就是fmt
    static String8      format(const char* fmt, ...) __attribute__((format(printf, 1, 2)));
    // 类成员函数第一个参数是隐藏的this指针   
    int                 appendFormat(const char* fmt, ...) __attribute__((format (printf, 2, 3)));  

    String8&            operator=(const String8& other);
    String8&            operator=(const char* other);

    String8&            operator+=(const String8& other);
    String8             operator+(const String8& other) const;

    String8&            operator+=(const char* other);
    String8             operator+(const char* other) const;

    int                 compare(const String8& other) const;
    int                 compare(const char* other) const;
    // if == return 0;
    int                 StrCaseCmp(const String8& other) const;
    int                 StrCaseCmp(const char* other) const;

    bool                operator<(const String8& other) const;
    bool                operator<=(const String8& other) const;
    bool                operator==(const String8& other) const;
    bool                operator!=(const String8& other) const;
    bool                operator>=(const String8& other) const;
    bool                operator>(const String8& other) const;

    bool                operator<(const char* other) const;
    bool                operator<=(const char* other) const;
    bool                operator==(const char* other) const;
    bool                operator!=(const char* other) const;
    bool                operator>=(const char* other) const;
    bool                operator>(const char* other) const;

    // return the index of the first byte of other in this at or after
    // start, or -1 if not found
    size_t              find(const char* other, size_t start = 0) const;

    // return true if this string contains the specified substring
    bool                contains(const char* other) const;
    bool                removeAll(const char* other);

    void                toLower();
    void                toLower(size_t start, size_t numChars);
    void                toUpper();
    void                toUpper(size_t start, size_t numChars);

private:
    char*               getBuffer(size_t numChars = 0);
    void                release();
    static String8      formatV(const char* fmt, va_list args);
    int                 appendFormatV(const char* fmt, va_list args);
    void                setTo(const String8& other);
    int                 setTo(const char* other);
    int                 setTo(const char* other, size_t numChars);

private:
    char *mString = nullptr;
};

} // namespace Alias
#endif // __STRING8_H__
/*************************************************************************
    > File Name: string8.cpp
    > Author: hsz
    > Mail:
    > Created Time: 2021年04月11日 星期日 12时25分02秒
 ************************************************************************/
/*************************************************************************
    > File Name: string8.cpp
    > Author: hsz
    > Mail:
    > Created Time: 2021年04月11日 星期日 12时25分02秒
 ************************************************************************/

#include "string8.h"

namespace Alias {

char *String8::getBuffer(size_t numChars)
{
    char *ret = nullptr;
    if (numChars <= 0) {
        ret = (char *)malloc(1);
        if (ret) {
            *ret = '\0';
        }
        return ret;
    } else if (numChars > 0) {
        ret = (char *)malloc(numChars + 1);
        if (ret) {
            memset(ret, 0, numChars + 1);
        }
        return ret;
    }
}

void String8::release()
{
    if (mString == nullptr) {
        return;
    }
    free(mString);
    mString = nullptr;
}

String8::String8()
{
    mString = getBuffer();
}

String8::String8(const String8& other)
{
    if (other.length() == 0) {
        mString = getBuffer();
        return;
    }
    mString = getBuffer(other.length());
    memcpy(mString, other.mString, other.length());
}

String8::String8(const char* other)
{
    if (other == nullptr) {
        mString = getBuffer();
        return;
    }
    size_t length = strlen(other);
    mString = getBuffer(length);
    memcpy(mString, other, length);
}

String8::String8(const char* other, const size_t numChars)
{
    if (other == nullptr) {
        mString = getBuffer();
        return;
    }
    size_t length = strlen(other);
    if (length > numChars) {
        length = numChars;
    }
    mString = getBuffer(length);
    memcpy(mString, other, length);
}

String8::String8(const std::string& other)
{
    size_t length = other.length();
    mString = getBuffer(length);
    memcpy(mString, other.c_str(), length);
}

String8::~String8()
{
    release();
}
size_t String8::find(const char* other, size_t start) const
{
    const char *tmp = strstr(mString + start, other);
    return tmp ? tmp - mString : -1;
}

const char* String8::c_str() const
{
    return mString;
}

std::string String8::toStdString() const
{
    return std::string(mString);
}

bool String8::isEmpty() const
{
    return length() == 0;
}

size_t String8::length() const
{
    return strlen(mString);
}

void String8::clear()
{
    memset(mString, 0, strlen(mString));
}

int String8::append(const String8& other)
{
    return append(other.mString, other.length());
}

int String8::append(const char* other)
{
    return append(other, strlen(other));
}

int String8::append(const char* other, size_t numChars)
{
    if (other == nullptr) {
        return -1;
    }
    size_t size = strlen(other);
    if (size > numChars) {
        size = numChars;
    }
    if (size == 0) {
        return 0;
    }

    size_t totalSize = size + length();
    char *buf = getBuffer(totalSize);
    if (buf) {
        memcpy(buf, mString, length());
        memcpy(buf + length(), other, size);
        this->release();
        mString = buf;
        return size;
    }
    return 0;
}

String8& String8::operator=(const String8& other)
{
    setTo(other);
    return *this;
}
String8& String8::operator=(const char* other)
{
    setTo(other);
    return *this;
}

String8& String8::operator+=(const String8& other)
{
    this->append(other);
    return *this;
}
String8 String8::operator+(const String8& other) const
{
    String8 tmp(*this);
    tmp += other;
    return tmp;
}
String8& String8::operator+=(const char* other)
{
    this->append(other);
    return *this;
}
String8  String8::operator+(const char* other) const
{
    String8 tmp(*this);
    tmp += other;
    return tmp;
}

int String8::compare(const String8& other) const
{
    return strcmp(mString, other.mString);
}

int String8::compare(const char* other) const
{
    return strcmp(mString, other);
}

int String8::StrCaseCmp(const String8& other) const
{
    return strcasecmp(mString, other.mString);
}

int String8::StrCaseCmp(const char* other) const
{
    return strcasecmp(mString, other);
}

bool String8::operator<(const String8& other) const
{
    return strcmp(mString, other.mString) < 0;
}
bool String8::operator<=(const String8& other) const
{
    return strcmp(mString, other.mString) <= 0;
}
bool String8::operator==(const String8& other) const
{
    return strcmp(mString, other.mString) == 0;
}
bool String8::operator!=(const String8& other) const
{
    return strcmp(mString, other.mString) != 0;
}
bool String8::operator>=(const String8& other) const
{
    return strcmp(mString, other.mString) >= 0;
}
bool String8::operator>(const String8& other) const
{
    return strcmp(mString, other.mString) > 0;
}

bool String8::operator<(const char* other) const
{
    return strcmp(mString, other) < 0;
}
bool String8::operator<=(const char* other) const
{
    return strcmp(mString, other) <= 0;
}
bool String8::operator==(const char* other) const
{
    return strcmp(mString, other) == 0;
}
bool String8::operator!=(const char* other) const
{
    return strcmp(mString, other) != 0;
}
bool String8::operator>=(const char* other) const
{
    return strcmp(mString, other) >= 0;
}
bool String8::operator>(const char* other) const
{
    return strcmp(mString, other) > 0;
}

void String8::setTo(const String8& other)
{
    setTo(other.mString, other.length());
}

int String8::setTo(const char* other)
{
    return setTo(other, strlen(other));
}

int String8::setTo(const char* other, size_t numChars)
{
    if (other == nullptr) {
        return -1;
    }
    numChars = numChars > strlen(other) ? strlen(other) : numChars;

    if (strlen(mString) >= numChars) {
        memset(mString, 0, strlen(mString));
        memcpy(mString, other, numChars);
    } else { // if (strlen(mString) < other.length()) 
        release();
        mString = getBuffer(numChars);
        memcpy(mString, other, numChars);
    }
}

bool String8::contains(const char* other) const
{
    return nullptr != strstr(mString, other);
}

bool String8::removeAll(const char* other)
{
    size_t start = 0;
    if (other && ((start = find(other)) >= 0)) {
        size_t end = strlen(other) + start;
        if (end >= length()) {
            mString[start] = '\0';
            return true;
        } else {
            size_t bufferSize = length() - (end - start);
            char *newString = getBuffer(bufferSize);
            if (newString == nullptr) {
                return false;
            }
            memcpy(newString, mString, start);
            memcpy(newString + start, mString + end, length() - end);
            free(mString);
            mString = newString;
            return true;
        }
    }
    return false;
}

void String8::toLower()
{
    toLower(0, length());
}

void String8::toLower(size_t start, size_t numChars)
{
    size_t size = length();
    if (size > start) {
        for (size_t i = start; i < numChars && i < size; ++i) { // i < size -> anti overflow
            mString[i] = static_cast<char>(tolower(mString[i]));
        }
    }
}

void String8::toUpper()
{
    toUpper(0, length());
}

void String8::toUpper(size_t start, size_t numChars)
{
    size_t size = length();
    if (size > start) {
        for (size_t i = start; i < numChars && i < size; ++i) { // i < size -> anti overflow
            mString[i] = static_cast<char>(toupper(mString[i]));
        }
    }
}

String8 String8::format(const char* fmt, ...)
{
    va_list args;
    va_start(args, fmt);

    String8 result(formatV(fmt, args));

    va_end(args);
    return result;
}

String8 String8::formatV(const char* fmt, va_list args)
{
    String8 result;
    result.appendFormatV(fmt, args);
    return result;
}

int String8::appendFormat(const char* fmt, ...)
{
    va_list args;
    va_start(args, fmt);

    int numChars = appendFormatV(fmt, args);

    va_end(args);
    return numChars;
}

int String8::appendFormatV(const char* fmt, va_list args)
{
    int n;
    va_list tmp_args;
    va_copy(tmp_args, args);
    n = vsnprintf(nullptr, 0, fmt, tmp_args);
    va_end(tmp_args);

    if (n < 0) {
        return n;
    }

    if (n > 0) {
        size_t oldLength = length();
        if ((size_t)n > MAXSIZE - 1 ||
            oldLength > MAXSIZE - (size_t)n - 1) {
            return -1;
        }

        char *buf = (char *)malloc(oldLength + n);
        if (buf == nullptr) {
            return -1;
        }
        memcpy(buf, mString, oldLength);
        release();
        vsnprintf(buf + oldLength, n + 1, fmt, args);
        mString = buf;
    }
    return n;
}
} // namespace Alias

测试(未测试全)

#include <iostream>
#include <stdio.h>
#include "string8.h"

int main()
{
    Alias::String8 str1;
    str1 = "123456789";
    str1.append("abcde", 3);
    std::cout << str1.c_str() << "\n";
    str1.appendFormat(" %p", str1.c_str());
    std::cout << "ptr = " << str1.c_str() << "\n";

    str1.clear();
    str1.appendFormat("[%d.%d.%d.%d]", 192, 168, 124, 7);
    std::cout << str1.c_str() << "\n";

    Alias::String8 str2 = str1;
    str2.appendFormat(" %p", str2.c_str());
    std::cout << "str2: "<< str2.c_str() << "\n";
    std::cout << str2.find("168.124.7") << "\n";
    std::cout << str2.contains("168.124.7") << "\n";
    std::cout << str2.compare(str1) << "\n";
    str2 = "ABcdEF";
    str2.toLower();
    std::cout << "toLower str2: "<< str2.c_str() << "\n";

    Alias::String8 str3(str1);
    std::cout << "str3: "<< str3.c_str() << "\n";
    std::cout << (str3 == str2) << "\n";
    str3 = "AbcdEF";
    std::cout << str3.StrCaseCmp(str2) << "\n";
    str3.toLower();
    std::cout << "toLower str3: "<< str3.c_str() << "\n";
    std::cout << "str3 == str2 -> " << (str3 == str2) << "\n";

    str3.removeAll("abcdef");
    str3 += str2;
    std::cout << "str3: "<< str3.c_str() << "\n";
    Alias::String8 str4 = str1 + str2 + str3;
    std::cout << str4.toStdString() << std::endl;

	Alias::String8 str5 = Alias::String8::format("%s", str4.c_str());
    std::cout << str5.toStdString() << std::endl;
    return 0;
}

运行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值