12-2
Implement the c_str, data, and copy functions.
12-3
Define the relational operators for Str. In doing so, you will want to know that the header defines a function called strcmp, which compares two character pointers. The function returns a negative integer if the null-terminated character array denoted by the first pointer is less than the second, zero if the two strings are equal, or a positive value if the first string is greater than the second.
12-4
Define the equality and inequality operators for Str.
12-5
Implement concatenation for Str so as not to rely on conversions from const char*.
12-6
Give Str an operation that will let us implicitly use a Str object as a condition. The test should fail if the Str is empty, and should succeed otherwise.
12-7
The standard string class provides random-access iterators to manipulate the string’s characters. Add iterators and the iterator operations begin and end to your Str class.
12-8
Add the getline function to the Str class.
12-9
Use class ostream_iterator to reimplement the Str output operator. Why didn’t we ask you to reimplement the input operator using class istream_iterator?
12-10
Having seen in §12.1/212 how Str defined a constructor that takes a pair of iterators, we can imagine that such a constructor would be useful in class Vec. Add this constructor to Vec, and reimplement Str to use the Vec constructor instead of calling copy.
12-12
Define the insert function that takes two iterators for the Vec and Str classes.
12-13
Provide an assign function that could be used to assign the values in an array to a Vec.
//"Vec.h"
#ifndef Vec_H
#define Vec_H
#include <memory>
#include <cstddef>
#include <algorithm>
template <class T>
class Vec
{
public:
typedef T* iterator;
typedef const T* const_iterator;
typedef T& reference;
typedef const T& const_reference;
typedef size_t size_type;
typedef T value_type;
Vec()
{
create();
}
explicit Vec(size_type n, const T& t = T())
{
create(n, t);
}
Vec(const Vec& v)
{
create(v.begin(), v.end());
}
template <class In> Vec(In b, In e)
{
create();
std::copy(b, e, std::back_inserter(*this));
}
Vec& operator=(const Vec&);
~Vec()
{
uncreate();
}
T& operator[](size_type i)
{
return data[i];
}
const T& operator[](size_type i) const
{
return data[i];
}
void push_back(const T& t)
{
if (avail == limit)
grow();
unchecked_append(t);
}
template <class In> void insert(iterator iter, In b, In e)
{
size_type new_size = (limit - data) + (e - b);
iterator new_data = alloc.allocate(new_size);
iterator temp1 = std::uninitialized_copy(data, iter, new_data);
iterator temp2 = std::uninitialized_copy(b, e, temp1);
iterator new_avail = std::uninitialized_copy(iter, avail, temp2);
uncreate();
data = new_data;
avail = new_avail;
limit = data + new_size;
}
template <class In> void assign(In array[])
{
In *array_end = array;
while (*array_end) array_end++;
size_type new_size = array_end - array;
iterator new_data = alloc.allocate(new_size);
iterator new_avail = std::uninitialized_copy(array, array_end, new_data);
uncreate();
data = new_data;
avail = new_avail;
limit = data + new_size;
}
size_type size() const
{
return avail - data;
}
iterator begin()
{
return data;
}
const_iterator begin() const
{
return data;
}
iterator end()
{
return avail;
}
const_iterator end() const
{
return avail;
}
void clear()
{
uncreate();
}
iterator erase(iterator it)
{
for (iterator i = it; i != avail; ++i)
{
alloc.destroy(i);
if ((i + 1) != avail) alloc.construct(i, *(i + 1));
}
--avail;
return it;
}
bool empty() const { return data == avail; }
private:
iterator data;
iterator avail;
iterator limit;
std::allocator<T> alloc;
void create();
void create(size_type, const T&);
void create(const_iterator, const_iterator);
void uncreate();
void grow();
void unchecked_append(const T&);
};
template <class T>
Vec<T>& Vec<T>::operator=(const Vec& rhs)
{
if (&rhs != this)
{
uncreate();
create(rhs.begin(), rhs.end());
}
return *this;
}
template <class T>
void Vec<T>::create()
{
data = avail = limit = 0;
}
template <class T>
void Vec<T>::create(size_type n, const T& val)
{
data = alloc.allocate(n);
limit = avail = data + n;
std::uninitialized_fill(data, limit, val);
}
template <class T>
void Vec<T>::create(const_iterator i, const_iterator j)
{
data = alloc.allocate(j - i);
limit = avail = std::uninitialized_copy(i, j, data);
}
template <class T>
void Vec<T>::uncreate()
{
if (data)
{
iterator it = avail;
while (it != data)
alloc.destroy(--it);
alloc.deallocate(data, limit - data);
}
data = limit = avail = 0;
}
template <class T>
void Vec<T>::grow()
{
size_type new_size = std::max(2 * (limit - data), ptrdiff_t(1));
iterator new_data = alloc.allocate(new_size);
iterator new_avail = std::uninitialized_copy(data, avail, new_data);
uncreate();
data = new_data;
avail = new_avail;
limit = data + new_size;
}
template <class T>
void Vec<T>::unchecked_append(const T& val)
{
alloc.construct(avail++, val);
}
#endif // Vec_H
//"Str.h"
#ifndef Str_H
#define Str_H
#include <iostream>
#include <iterator>
#include "Vec.h"
#include <string.h>
#include <iterator>
class Str
{
friend std::istream& operator>> (std::istream&, Str&);
friend Str operator+ (const Str&, const char*);
friend Str operator+ (const char*, const Str&);
public:
typedef Vec<char>::size_type size_type;
typedef char* iterator;
typedef const char* const_iterator;
Str(){ }
Str(size_type n, char c) : data(n, c) { }
Str(const char* cp) { std::copy(cp, cp + std::strlen(cp), std::back_inserter(data)); }
template <class In> Str(In b, In e) { std::copy(b, e, std::back_inserter(data)); }
size_type size() const { return data.size(); }
iterator begin() { return data.begin(); }
const_iterator begin() const { return data.begin(); }
iterator end(){ return data.end(); }
const_iterator end() const { return data.end(); }
Str& operator+= (const Str& s);
char& operator[](size_type i) { return data[i]; }
const char& operator[](size_type i) const { return data[i]; }
operator void*()
{
return data.empty() ? 0 : (void*)1;
}
std::istream& getline(std::istream& is)
{
data.clear();
char c;
while (is.get(c) && isspace(c));
if (is)
{
do
{
data.push_back(c);
} while (is.get(c) && c != '\n');
if (is)
is.unget();
}
return is;
}
template <class In> void insert(iterator iter, In b, In e) { data.insert(iter, b, e); }
private:
Vec<char> data;
};
std::istream& operator>> (std::istream& is, Str& s)
{
s.data.clear();
char c;
while (is.get(c) && isspace(c));
if (is)
{
do
{
s.data.push_back(c);
} while (is.get(c) && !isspace(c));
if (is)
is.unget();
}
return is;
}
std::ostream& operator<< (std::ostream& os, const Str& s)
{
//for (Str::size_type i = 0; i != s.size(); ++i)
//{
// os << s[i];
//}
std::ostream_iterator<char> iter(os);
for (Str::size_type i = 0; i != s.size(); i++)
{
*iter++ = s[i];
}
return os;
}
Str& Str::operator+= (const Str& s)
{
std::copy(s.data.begin(), s.data.end(), std::back_inserter(data));
return *this;
}
Str operator+ (const Str& x, const Str& y)
{
Str temp;
temp = x;
temp += y;
return temp;
}
Str operator+ (const Str& x, const char* y)
{
Str temp;
temp = x;
std::copy(y, y + std::strlen(y), std::back_inserter(temp.data));
return temp;
}
Str operator+ (const char* x, const Str& y)
{
Str temp;
std::copy(x, x + std::strlen(x), std::back_inserter(temp.data));
temp += y;
return temp;
}
bool operator< (const Str& x, const Str& y)
{
Str::size_type i = 0;
while (i != x.size() && i!= y.size())
{
if (x[i] == y[i]) ++i;
else return x[i] < y[i] ? true : false;
}
if (!x[i]) return true;
else return false;
}
bool operator> (const Str& x, const Str& y)
{
Str::size_type i = 0;
while (i != x.size() && i != y.size())
{
if (x[i] == y[i]) ++i;
else return x[i] > y[i] ? true : false;
}
if (!y[i]) return true;
else return false;
}
bool operator== (const Str& x, const Str& y)
{
Str::size_type i = 0;
while (i != x.size() && i != y.size())
{
if (x[i] == y[i]) ++i;
else return false;
}
if (!x[i] && !y[i]) return true;
else return false;
}
bool operator!= (const Str& x, const Str& y)
{
return !(x == y);
}
#endif // Str_H
//"main.cpp"
#define _SCL_SECURE_NO_WARNINGS
#include "Str.h"
#include <string>
using namespace std;
int main()
{
Str s1("abc"), s2;
string str = "hello~";
Vec<char> v1(str.begin(), str.end());
for (Vec<char>::size_type i = 0; i != v1.size(); i++)
{
cout << v1[i];
}
cout << endl;
cout << s1.size() << endl << s2.size() << endl;
if (s1){ cout << "s1 exist" << endl; }
else { cout << "s1 null" << endl; }
if (s2){ cout << "s2 exist" << endl; }
else { cout << "s2 null" << endl; }
s2.getline(cin);
if (s1 < s2)
{
cout << "<" << endl;
}
else if (s1 == s2)
{
cout << "==" << endl;
}
else
{
cout << ">" << endl;
}
cout << s1 << endl << s2 << endl;
cout << s1.size() << endl << s2.size() << endl;
cout << "test insert:" << endl;
s2.insert(s2.begin()+1, s1.begin(), s1.end());
cout << s2 << endl;
cout << "test assign:" << endl;
v1.assign("v1 is assigned");
for (Vec<char>::size_type i = 0; i != v1.size(); i++)
{
cout << v1[i];
}
cout << endl;
system("pause");
}