Parent directory Makefile mystring.cpp mystring.h test1.cpp test2.cpp test3.cpp test4.cpp
Download
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; }