Parent directory
Makefile
mystring.cpp
mystring.h
test1.cpp
test2.cpp
test3.cpp
test4.cpp
CC = g++
CXX = g++
CFLAGS = -g -Wall
CXXFLAGS = -g -Wall -std=c++14
executables = test1 test2 test3 test4
objects = mystring.o test1.o test2.o test3.o test4.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"
using namespace std;
void f2() {
MyString s("abc");
int x = s[-1];
cout << x << endl;
}
void f1() {
f2();
}
int main() {
MyString s1;
MyString s2("hello");
MyString s3(s2);
s1 = s2;
cout << s1 << "," << s2 << "," << s3 << endl;
try {
f1();
}
catch (const out_of_range& e) {
cout << e.what() << endl;
}
return 0;
}
#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;
return 0;
}
#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;
return 0;
}
// test4.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;
}