头文件: my_string.h

#ifndef MY_STRING_H_
#define MY_STRING_H_
#pragma once

#include <iostream>

class MyString {
public:
  MyString();
  MyString(const char* c_str);
  MyString(size_t n, char ch);
  MyString(const MyString& str);
  MyString(const MyString& str, size_t pos, size_t n = NPOS);

  ~MyString();

  size_t len() const { return len_; }
  size_t capacity() const { return capacity_; }
  const char* c_str() const { return buf_; }

  bool IsEmpty() const;
  void Clear();

  size_t Size() const;

  void Resize(size_t n);
  void Resize(size_t n, char ch);
  void Reserve(size_t n = 0);

  const char& At(size_t pos) const;
  char& At(size_t pos);

  MyString& Append(const MyString& my_str);
  MyString& Append(const char* c_str);

  MyString& Assign(const MyString& my_str);
  MyString& Assign(const char* c_str);

  MyString& Insert(size_t pos, const MyString& my_str);
  MyString& Insert(size_t pos, const char* c_str);

  MyString& Erase(size_t pos = 0, size_t n = NPOS);

  int Compare(const MyString& my_str) const;
  int Compare(const char* c_str) const;

  MyString SubStr(size_t pos = 0, size_t n = NPOS) const;

  bool StartWith(const char* c_str) const;
  bool EndWith(const char* c_str) const;

  size_t Find(const char* c_str, size_t pos = 0) const;
  size_t Find(const MyString& my_str, size_t pos = 0) const;

  MyString& Replace(size_t pos, size_t n, const char* c_str);
  MyString& Replace(const char* src_str, const char* target_str);

  friend std::istream& operator>>(std::istream& is, MyString& my_str);
  friend std::ostream& operator<<(std::ostream& os, const MyString& my_str);

  friend MyString operator+(const MyString& left_my_str, const MyString& right_my_str);
  friend MyString operator+(const MyString& left_my_str, const char* right_c_str);
  friend MyString operator+(const char* left_c_str, const MyString& right_my_str);

  friend bool operator==(const MyString& left_my_str, const MyString& right_my_str);
  friend bool operator!=(const MyString& left_my_str, const MyString& right_my_str);

  friend bool operator<(const MyString& left_my_str, const MyString& right_my_str);
  friend bool operator>(const MyString& left_my_str, const MyString& right_my_str);
  friend bool operator>=(const MyString& left_my_str, const MyString& right_my_str);
  friend bool operator<=(const MyString& left_my_str, const MyString& right_my_str);

  MyString& operator=(const MyString& my_str);
  MyString& operator=(const char* c_str);
  MyString& operator=(char ch);

  MyString& operator+=(const MyString& my_str);
  MyString& operator+=(const char* c_str);

  const char& operator[](size_t pos) const;

  char& operator[](size_t pos);

public:
  static const size_t NPOS;

private:
  char* buf_;
  size_t capacity_;
  size_t len_;
};

#endif  // MY_STRING_H_

源文件: my_string.cpp


#include "my_string.h"
#include <cassert>

const size_t kDefaultBufSize = 16;

const size_t MyString::NPOS = -1;

MyString::MyString() {
  capacity_ = kDefaultBufSize;
  buf_ = new char[capacity_ + 1];
  buf_[0] = '\0';
  len_ = 0;
}

MyString::MyString(size_t n, char ch) {
  capacity_ = n + kDefaultBufSize;
  buf_ = new char[capacity_ + 1];
  len_ = n;
  for (size_t i = 0; i < n; ++i) {
    buf_[i] = ch;
  }
  buf_[len_] = '\0';
}

MyString::MyString(const char* c_str) {
  size_t c_str_size = strlen(c_str);
  capacity_ = c_str_size + kDefaultBufSize;
  buf_ = new char[capacity_ + 1];
  strcpy(buf_, c_str);
  len_ = c_str_size;
}

MyString::MyString(const MyString& my_str) {
  buf_ = new char[my_str.capacity_ + 1];
  strcpy(buf_, my_str.buf_);
  capacity_ = my_str.capacity_;
  len_ = my_str.len_;
}

MyString::MyString(const MyString& my_str, size_t pos, size_t n) {
  if (pos > len_) {
    throw std::out_of_range("invalid string position");
  }
  if (pos + n > len_) {
    n = my_str.len_ - pos;
  }
  size_t size = n + kDefaultBufSize;
  buf_ = new char[size + 1];
  len_ = n;
  capacity_ = size;
  for (size_t i = 0; i < n; ++i) {
    buf_[i] = my_str.buf_[pos + i];
  }
  buf_[len_] = '\0';
}

MyString::~MyString() {
  if (buf_ != NULL) {
    delete[] buf_;
    capacity_ = 0;
    len_ = 0;
  }
}

MyString& MyString::operator=(const MyString& my_str) {
  return operator=(my_str.buf_);
}

MyString& MyString::operator=(const char* c_str) {
  size_t size = strlen(c_str);
  if (size <= capacity_) {
    strcpy(buf_, c_str);
    len_ = size;
  } else {
    char* temp = buf_;
    size += kDefaultBufSize;
    buf_ = new char[size + 1];
    strcpy(buf_, c_str);
    capacity_ = size;
    len_ = size - kDefaultBufSize;
    delete[] temp;
  }
  return *this;
}

MyString& MyString::operator=(char ch) {
    buf_[0] = ch;
    buf_[1] = '\0';
    len_ = 1;
  return *this;
}

MyString& MyString::operator+=(const MyString& my_str) {
  return Append(my_str);
}

MyString& MyString::operator+=(const char* c_str) {
  return Append(c_str);
}

const char& MyString::operator[](size_t pos) const {
  assert(pos < len_);
  return buf_[pos];
}

char& MyString::operator[](size_t pos) {
  assert(pos < len_);
  return buf_[pos];
}

std::ostream& operator<<(std::ostream& os, const MyString& my_str) {
  os << my_str.buf_;
  return os;
}

std::istream& operator>>(std::istream& is, MyString& my_str) {
  const size_t kMaxTempSize = 10000;
  char* temp = new char[kMaxTempSize];
  is >> temp;
  size_t size = strlen(temp);
  if (size <= my_str.capacity_) {
    strcpy(my_str.buf_, temp);
    my_str.len_ = size;
  } else {
    char* temp2 = my_str.buf_;
    size += kDefaultBufSize;
    my_str.buf_ = new char[size + 1];
    strcpy(my_str.buf_, temp);
    my_str.capacity_ = size;
    my_str.len_ = size - kDefaultBufSize;
    delete[] temp2;
  }
  delete[] temp;
  return is;
}

MyString operator+(const MyString& left_my_str, const MyString& right_my_str) {
  return MyString(left_my_str).Append(right_my_str);
}

MyString operator+(const MyString& left_my_str, const char* right_c_str) {
  return MyString(left_my_str).Append(right_c_str);
}

MyString operator+(const char* left_c_str, const MyString& right_my_str) {
  return MyString(left_c_str).Append(right_my_str);
}

bool operator==(const MyString& left_my_str, const MyString& right_my_str) {
  return strcmp(left_my_str.buf_, right_my_str.buf_) == 0;
}

bool operator!=(const MyString& left_my_str, const MyString& right_my_str) {
  return strcmp(left_my_str.buf_, right_my_str.buf_) != 0;
}

bool operator<(const MyString& left_my_str, const MyString& right_my_str) {
  return strcmp(left_my_str.buf_, right_my_str.buf_) == -1;
}

bool operator>(const MyString& left_my_str, const MyString& right_my_str) {
  return strcmp(left_my_str.buf_, right_my_str.buf_) == 1;
}

bool operator>=(const MyString& left_my_str, const MyString& right_my_str) {
  return strcmp(left_my_str.buf_, right_my_str.buf_) >= 0;
}

bool operator<=(const MyString& left_my_str, const MyString& right_my_str) {
  return strcmp(left_my_str.buf_, right_my_str.buf_) <= 0;
}

bool MyString::IsEmpty() const{
  return len_ == 0;
}

void MyString::Clear() {
  buf_[0] = '\0';
  len_ = 0;
}

size_t MyString::Size() const{
  return len_;
}

void MyString::Resize(size_t n) {
  if (n <= len_) {
    buf_[n] = '\0';
    len_ = n;
  } else {
    if (n <= capacity_) {
      for (size_t i = len_; i < n; i++) {
        buf_[i] = ' ';
      }
      buf_[n] = '\0';
      len_ = n;
    } else {
      size_t size = n + kDefaultBufSize;
      char* temp = buf_;
      buf_ = new char[size + 1];
      strcpy(buf_, temp);
      for (size_t i = len_; i < n; i++) {
        buf_[i] = ' ';
      }
      delete[] temp;
      buf_[n] = '\0';
      len_ = n;
      capacity_ = size;
    }
  }
}

void MyString::Resize(size_t n, char ch) {
  if (n > len_) {
    if (n <= capacity_) {
      for (size_t i = len_; i < n; i++) {
        buf_[i] = ch;
      }
      buf_[n] = '\0';
      len_ = n;
    } else {
      size_t size = n + kDefaultBufSize;
      char* temp = buf_;
      buf_ = new char[size + 1];
      strcpy(buf_, temp);
      for (size_t i = len_; i < n; i++) {
        buf_[i] = ch;
      }
      buf_[n] = '\0';
      len_ = n;
      capacity_ = size;
      delete[] temp;
    }
  }
}

void MyString::Reserve(size_t n) {
  if (n > capacity_) {
    size_t size = n + kDefaultBufSize;
    char* temp = buf_;
    buf_ = new char[size + 1];
    strcpy(buf_, temp);
    capacity_ = size;
    delete[] temp;
  } else {
    if (n > len_) {
      char* temp = buf_;
      buf_ = new char[n];
      strcpy(buf_, temp);
      capacity_ = n;
      delete[] temp;
    }
  }
}

const char& MyString::At(size_t pos) const {
  if (pos < len_) {
    return buf_[pos];
  } else {
    throw std::out_of_range("invalid string position");
  }
}

char& MyString::At(size_t pos) {
  if (pos < len_) {
    return buf_[pos];
  } else {
    throw std::out_of_range("invalid string position");
  }
}

MyString& MyString::Append(const MyString& my_str) {
  return Append(my_str.buf_);
}

MyString& MyString::Append(const char* c_str) {
  size_t size = len_ + strlen(c_str);
  if (size <= capacity_) {
    strcat(buf_, c_str);
    len_ = size;
  } else {
    char* temp = buf_;
    buf_ = new char[size + kDefaultBufSize + 1];
    strcpy(buf_, temp);
    strcat(buf_, c_str);
    capacity_ = size + kDefaultBufSize;
    len_ = size;
    delete[] temp;
  }
  return *this;
}

MyString& MyString::Assign(const MyString& my_str) {
  return operator=(my_str);
}

MyString& MyString::Assign(const char* c_str) {
  return operator=(c_str);
}

MyString& MyString::Insert(size_t pos, const MyString& my_str) {
  return Insert(pos, my_str.buf_);
}

MyString& MyString::Insert(size_t pos, const char* c_str) {
  if (pos > len_) {
    throw std::out_of_range("invalid string position");
  }
  size_t c_str_size = strlen(c_str);
  size_t size = c_str_size + len_;
  if (size <= capacity_) {
    for (size_t i = size - 1; i >= pos + c_str_size; --i) {
      buf_[i] = buf_[i - c_str_size];
    }
    for (size_t i = 0; i < c_str_size; ++i) {
      buf_[i + pos] = c_str[i];
    }
    buf_[size] = '\0';
    len_ = size;
  } else {
    char* temp = buf_;
    buf_ = new char[size + kDefaultBufSize + 1];
    for (size_t i = 0; i < pos; ++i) {
      buf_[i] = temp[i];
    }
    for (size_t i = pos; i < pos + c_str_size; ++i) {
      buf_[i] = c_str[i - pos];
    }
    for (size_t i = pos + c_str_size; i < size; ++i) {
      buf_[i] = temp[i - c_str_size];
    }
    buf_[size] = '\0';
    len_ = size;
    capacity_ = size + kDefaultBufSize;
    delete[] temp;
  }
  return *this;
}

MyString& MyString::Erase(size_t pos, size_t n) {
  if (pos > len_) {
    throw std::out_of_range("invalid string position");
  }
  if (pos + n > len_) {
    buf_[pos] = '\0';
  } else {
    for (size_t i = 0; i < len_ - pos - n; ++i) {
      buf_[pos + i] = buf_[pos + i + n];
    }
    buf_[len_ - n] = '\0';
    len_ = len_ - n;
  }
  return *this;
}

int MyString::Compare(const char* c_str) const {
  return strcmp(buf_, c_str);
}

int MyString::Compare(const MyString& my_str) const {
  return Compare(my_str.buf_);
}

MyString MyString::SubStr(size_t pos, size_t n) const {
  return MyString(*this, pos, n);
}

bool MyString::StartWith(const char* c_str) const {
  if (c_str == NULL) {
    return false;
  }
  return strncmp(c_str, buf_, strlen(c_str)) == 0;
}

bool MyString::EndWith(const char* c_str) const {
  if (c_str == NULL) {
    return false;
  }
  size_t end_size = strlen(c_str);
  if (len_ < end_size) {
    return false;
  }
  return strcmp(buf_ + len_ - end_size, c_str) == 0;
}

size_t MyString::Find(const char* c_str, size_t pos) const {
  if (pos > len_) {
    return NPOS;
  }
  size_t sub_str_size = strlen(c_str);
  for (size_t i = pos; sub_str_size + i <= len_; ++i) {
    if (strncmp(buf_ + i, c_str, sub_str_size) == 0) {
      return i;
    }
  }
  return NPOS;
}
size_t MyString::Find(const MyString& my_str, size_t pos) const {
  return Find(my_str.buf_, pos);
}

MyString& MyString::Replace(size_t pos, size_t n, const char* dst_str) {
  if (pos > len_) {
    throw std::out_of_range("invalid string position");
  }
  if (pos + n > len_) {
    n = len_ - pos;
  }
  size_t dst_str_size = strlen(dst_str);
  size_t size = dst_str_size + len_ - n;
  if (size > capacity_) {
    char* temp = buf_;
    buf_ = new char[size + kDefaultBufSize + 1];
    strcpy(buf_, temp);
    delete[] temp;
    capacity_ = size;
  }
  char* temp = new char[len_ - n + 1];
  strcpy(temp, buf_ + pos + n);
  strcpy(buf_ + pos, dst_str);
  strcpy(buf_ + pos + dst_str_size, temp);
  len_ = len_ + dst_str_size - n;
  delete[] temp;
  return *this;

}

MyString& MyString::Replace(const char* src_str, const char* dst_str) {
  size_t pos = Find(src_str);
  if (pos == NPOS) {
    return *this;
  }
  size_t n = strlen(src_str);
  return Replace(pos, n, dst_str);
}