写一个 string
类,目标:输出 Hello World。
程序
String.h
#pragma once
#define _TVJ_STRING_
#include <Windows.h>
#include <iostream>
namespace tvj
{
template<typename ValueType>
class Heap_Vector
{
public:
Heap_Vector(int n);
Heap_Vector();
~Heap_Vector();
// similar to the function of push_back in vector
void push_back(const ValueType& value);
void pop_back();
ValueType& operator [](const int& index);
ValueType operator [](const int& index) const;
const int size() const;
ValueType* into_array();
private:
ValueType* vec;
int capacity;
int content_number;
void expand();
};
class string
{
friend std::istream& operator>>(std::istream& in, tvj::string& str);
friend std::ostream& operator<<(std::ostream& in, const tvj::string& str);
friend tvj::string toupper(tvj::string s);
friend tvj::string tolower(tvj::string s);
public:
string(const char* init_string);
string(const char& init_char);
string(const int& n, const char& init_char);
string(const string& init_string);
//string(const int& init_int);
//string(const double& init_double);
//string clear();
int size() const;
int length() const;
//string left(int n);
//string right(int n);
//string substr(int n1, int n2);
string append(const string& str);
string operator+(const string& str);
string operator+(const char* str);
string operator+(const char& str);
void operator+=(const string& str);
char& operator[](const int& n);
char operator[](const int& n) const;
string& operator=(const string& init_string);
private:
int Length = 0;
Heap_Vector<char> char_vector;
};
std::istream& operator>>(std::istream& in, string& str);
std::ostream& operator<<(std::ostream& in, const string& str);
char toupper(char);
string toupper(string&);
char tolower(char);
string tolower(string&);
//string strcat(string&, const string&);
//string strcpy(string&, const string&);
//std::istream& getline(std::istream&, const string&);
}
String.cpp
#include "String.h"
tvj::string::string(const char* init_string) : Length(0)
{
if (init_string != nullptr)
{
for (int i = 0; init_string[i] != '\0'; i++)
{
char_vector.push_back(init_string[i]);
}
Length = char_vector.size();
char_vector.push_back('\0');
}
}
tvj::string::string(const char& init_char) : Length(1)
{
if (init_char == EOF)
{
Length = 0;
}
else if (init_char == '\0')
{
this->char_vector.push_back('\0');
Length = 0;
}
else
{
this->char_vector.push_back(init_char);
this->char_vector.push_back('\0');
Length = 1;
}
}
tvj::string::string(const int& n, const char& init_char)
{
if (init_char == EOF)
{
this->Length = 0;
}
else
{
if (n < 0)
{
MessageBox(NULL, L"Number can not be negative", L"Error", MB_ICONERROR);
}
else
{
for (int i = 0; i != n; i++)
{
this->char_vector.push_back(init_char);
this->Length = n;
}
if (init_char != '\0')
{
this->char_vector.push_back(init_char);
}
this->Length = char_vector.size();
this->char_vector.push_back('\0');
}
}
}
tvj::string::string(const string& init_string)
{
for (int i = 0; i != init_string.length() && init_string[i] != '\0'; i++)
{
this->char_vector.push_back(init_string[i]);
}
this->Length = init_string.length();
this->char_vector.push_back('\0');
}
int tvj::string::size() const
{
return (this->char_vector.size() == 0) ? 0 : (1 + this->Length);
}
int tvj::string::length() const
{
return this->Length;
}
//tvj::string::string(const int& init_int)
//{
//
//}
//
//tvj::string::string(const double& init_double)
//{
//
//}
//tvj::string tvj::string::clear()
//{
//
//}
//tvj::string tvj::string::left(int n)
//{
//
//}
//
//tvj::string tvj::string::right(int n)
//{
//
//}
//
//tvj::string tvj::string::substr(int n1, int n2)
//{
//
//}
tvj::string tvj::string::append(const string& str)
{
if (this->char_vector.size() != 0)
{
this->char_vector.pop_back();
for (int i = 0; i != str.length() && str[i] != '\0'; i++)
{
this->char_vector.push_back(str[i]);
this->Length++;
}
this->char_vector.push_back('\0');
}
else
{
*this = str;
}
return *this;
}
tvj::string tvj::string::operator+(const string& str)
{
return this->append(str);
}
tvj::string tvj::string::operator+(const char* str)
{
string init(str);
return this->append(init);
}
tvj::string tvj::string::operator+(const char& str)
{
string init(str);
return this->append(init);
}
void tvj::string::operator+=(const string& str)
{
*this = *this + str;
}
char& tvj::string::operator[](const int& n)
{
return this->char_vector[n];
}
char tvj::string::operator[](const int& n) const
{
return this->char_vector[n];
}
tvj::string& tvj::string::operator=(const string& init_string)
{
string temp_str(init_string);
return temp_str;
}
std::istream& tvj::operator>>(std::istream& in, tvj::string& str)
{
tvj::Heap_Vector<char> temp_vector;
char temp_ch;
while (in >> temp_ch && (temp_ch != EOF && temp_ch != ' ' && temp_ch != '\t' && temp_ch != '\r' && temp_ch != '\n'))
{
temp_vector.push_back(temp_ch);
}
str = temp_vector.into_array();
return in;
}
std::ostream& tvj::operator<<(std::ostream& out, const tvj::string& str)
{
for (int i = 0; i != str.size(); i++)
{
out << str.char_vector[i];
}
return out;
}
char tvj::toupper(char c)
{
if ('a' < c && c < 'z')
{
c += 'A' - 'a';
}
return c;
}
tvj::string tvj::toupper(tvj::string s)
{
for (int i = 0; i != s.size(); i++)
{
s.char_vector[i] = toupper(s.char_vector[i]);
}
return s;
}
char tvj::tolower(char c)
{
if ('A' < c && c < 'Z')
{
c -= 'A' - 'a';
}
return c;
}
tvj::string tvj::tolower(tvj::string s)
{
for (int i = 0; i != s.length(); i++)
{
(s.char_vector)[i] = tolower(s.char_vector[i]);
}
return s;
}
//tvj::string strcat(tvj::string&, const tvj::string&)
//{
//
//}
//
//tvj::string strcpy(tvj::string&, const tvj::string&)
//{
//
//}
//
//std::istream& getline(std::istream&, const tvj::string&)
//{
//
//}
template<typename ValueType>
tvj::Heap_Vector<ValueType>::Heap_Vector(int n) :capacity(n), content_number(0), vec(new ValueType[n]) {}
template<typename ValueType>
tvj::Heap_Vector<ValueType>::Heap_Vector() : capacity(8), content_number(0), vec(new ValueType[8]) {}
template<typename ValueType>
tvj::Heap_Vector<ValueType>::~Heap_Vector() // destructor
{
delete[] vec; // free the dynamic array
}
// similar to the function of push_back in vector
template<typename ValueType>
void tvj::Heap_Vector<ValueType>::push_back(const ValueType& value)
{
if (content_number == capacity)
{
expand();
}
vec[content_number++] = value;
}
template<typename ValueType>
void tvj::Heap_Vector<ValueType>::pop_back()
{
content_number--;
}
template<typename ValueType>
ValueType& tvj::Heap_Vector<ValueType>::operator[](const int& index)
{
if (index >= this->size())
{
MessageBox(NULL, L"Subscript out of range.", L"Runtime Error", MB_ICONERROR);
return vec[0];
}
else
{
return vec[index];
}
}
template<typename ValueType>
ValueType tvj::Heap_Vector<ValueType>::operator[](const int& index) const
{
if (index >= this->size())
{
MessageBox(NULL, L"Subscript out of range.", L"Runtime Error", MB_ICONERROR);
return vec[0];
}
else
{
return vec[index];
}
}
template<typename ValueType>
const int tvj::Heap_Vector<ValueType>::size() const
{
return content_number;
}
template<typename ValueType>
ValueType* tvj::Heap_Vector<ValueType>::into_array()
{
return this->vec;
}
template<typename ValueType>
void tvj::Heap_Vector<ValueType>::expand()
{
// 1. ask for new space for the array
ValueType* new_vec = new ValueType[2 * capacity];
// 2. copy the values over
for (int i = 0; i != content_number; i++)
new_vec[i] = vec[i];
// 3. delete the old array
delete[] vec;
// 4. point vec to new array
vec = new_vec;
// 5. update capacity (twice the capacity)
capacity *= 2;
}
Main.cpp
#include <iostream>
#include "String.h"
using std::cin;
using std::cout;
using std::endl;
using tvj::string;
int main(int argc, char** argv)
{
string str1("He");
str1 += "llo";
string str2 = " ";
str2.append("Warl");
string str = str1 + str2;
str += 'd';
str[7] = 'o';
cout << str << endl;
return 0;
}
输出示例
分析
- 这是一个极简版的
string
类,以后会不断改进提升。 - 其中的
HeapVector
是用堆内存的自编简化vector
,长度到了之后会自动翻倍。另外的应用在我的博客 【SEU程序设计课笔记】 12 - 2020/11/19 - Write C++ programs - 排序。
ALL RIGHTS RESERVED © 2020 Teddy van Jerry
欢迎转载,转载请注明出处。