 Parent directory
Parent directory
 Makefile
Makefile
 mystring.cpp
mystring.cpp
 mystring.h
mystring.h
 test1.cpp
test1.cpp
 test2.cpp
test2.cpp
 test3.cpp
test3.cpp
 test4.cpp
test4.cpp
 test5.cpp
test5.cpp
CC  = g++
CXX = g++
CFLAGS   = -g -Wall
CXXFLAGS = -g -Wall -std=c++14
executables = test1 test2 test3 test4 test5
objects = mystring.o test1.o test2.o test3.o test4.o test5.o
.PHONY: default
default: $(executables)
$(executables): mystring.o
$(objects): mystring.h
.PHONY: clean
clean:
	rm -f *~ a.out core $(objects) $(executables)
.PHONY: all
all: clean default#include <cstring>
#include <cstdio>
#include "mystring.h"
// default constructor
MyString::MyString()
{
    data = new char[1];
    data[0] = '\0';
    len = 0;
}
// constructor
MyString::MyString(const char *p)
{
    if (p) {
        len = strlen(p);
        data = new char[len+1];
        strcpy(data, p);
    } else {
        data = new char[1];
        data[0] = '\0';
        len = 0;
    }
}
// destructor
MyString::~MyString()
{
    delete[] data;
}
// copy constructor
MyString::MyString(const MyString& s)
{
    len = s.len;
    data = new char[len+1];
    strcpy(data, s.data);
}
// copy assignment
MyString& MyString::operator=(const MyString& rhs)
{
    if (this == &rhs) {
        return *this;
    }
    // first, deallocate memory that 'this' used to hold
    delete[] data;
    // now copy from rhs
    len = rhs.len;
    data = new char[len+1];
    strcpy(data, rhs.data);
    return *this;
}
// operator+
MyString operator+(const MyString& s1, const MyString& s2)
{
    MyString temp;
    delete[] temp.data;
    temp.len = s1.len + s2.len;
    temp.data = new char[temp.len+1];
    strcpy(temp.data, s1.data);
    strcat(temp.data, s2.data);
    return temp;
}
// put-to operator
std::ostream& operator<<(std::ostream& os, const MyString& s)
{
    os << s.data;
    return os;
}
// get-from operator
std::istream& operator>>(std::istream& is, MyString& s)
{
    // this is kinda cheating, but this is just to illustrate how this
    // function can work.
    std::string temp;
    is >> temp;
    delete[] s.data;
    s.len = strlen(temp.c_str());
    s.data = new char[s.len+1];
    strcpy(s.data, temp.c_str());
    return is;
}
// operator[] - in real life this function should be declared inline
char& MyString::operator[](int i)
{
    if (i < 0 || i >= len) {
        throw std::out_of_range{"MyString::op[]"};
    }
    return data[i];
}
// operator[] const - in real life this should be inline
const char& MyString::operator[](int i) const
{
    // illustration of casting away constness
    return ((MyString&)*this)[i];
    // The C-style casting above works, but the proper way
    // to cast away constness in C++ is to do the following:
    //
    // return const_cast<MyString&>(*this)[i];
}#ifndef __MYSTRING_H__
#define __MYSTRING_H__
#include <iostream>
class MyString {
public:
    // default constructor
    MyString();
    // constructor
    MyString(const char* p);
    // destructor
    ~MyString();
    // copy constructor
    MyString(const MyString& s);
    // copy assignment
    MyString& operator=(const MyString& s);
    // returns the length of the string
    int length() const { return len; }
    // operator+
    friend MyString operator+(const MyString& s1, const MyString& s2);
    // put-to operator
    friend std::ostream& operator<<(std::ostream& os, const MyString& s);
    // get-from operator
    friend std::istream& operator>>(std::istream& is, MyString& s);
    // operator[]
    char& operator[](int i);
    // operator[] const
    const char& operator[](int i) const;
private:
    char* data;
    int len;
};
#endif#include "mystring.h"
int main() {
    using namespace std;
    MyString s1;
    MyString s2("hello");
    MyString s3(s2);
    s1 = s2;
    cout << s1 << "," << s2 << "," << s3 << endl;
}#include "mystring.h"
int main() {
    using namespace std;
    MyString s1("hello ");
    MyString s2("world!");
    MyString s3;
    s3 = s1 + s2;
    cout << s3 << endl;
    cout << s1 + s2 << endl;
    cout << s1 + "world!" << endl;
    cout << "hello " + s2 << endl;
    // this is an error
    // cout << "hello " + "world!" << endl;
}#include "mystring.h"
int main() {
    using namespace std;
    cout << "Enter a string: ";
    MyString s;
    cin >> s;
    for (int i = 0; i < s.length(); ++i) {
        if ('a' <= s[i] && s[i] <= 'z') {
            s[i] = s[i] - ('a' - 'A');
        }
    }
    cout << "Here is how to say it louder: " << s << endl;
}#include "mystring.h"
void f2() {
    MyString s("abc");
    int x = s[-1];
    std::cout << x << std::endl;
}
void f1() {
    MyString s("xyx");
    f2();
    std::cout << s << std::endl;
}
int main() {
    using namespace std;
    try {
        f1();
    }
    catch (const out_of_range& e) {
        cout << e.what() << endl;
    }
    cout << "That's all folks!" << endl;
}// test5.cpp
#include "mystring.h"
static MyString add(MyString a, MyString b)
{
    MyString t{" and "};
    return a + t + b;
}
int main()
{
    using namespace std;
    MyString x{"one"};
    MyString y{"two"};
    MyString z = add(x, y);
    cout << z << endl;
    return 0;
}