#ifndef STRING1030_H
#define STRING1030_H
#include<iostream>
using std::string;
using std::ostream;
using std::istream;
using std::endl;
using std::cerr;
/*
* The class String1030 is for the students to practice implementing
* more class functions and making sure that their implementation
* is reasonable.
*
* It requires some skill in using arrays and overloading operators.
*
* Note that the sentinel value that MUST be part of the storage for our
* strings is '\0'. That is not special, it is just a way to tell future
* readers that we know what we are doing. We could just as well use the
* digit 0, but that can be very confusing.
*/
class String1030
{
public:
// The constructor. The "0" is the digit 0 NOT a
// character. It is used to let us know that
// nothing is being passed to the default constructor.
String1030(constchar *buf=0);
//This next is a "copy" constructor. Remember that
//we have to create new storage and then copy
//the array content. We must not just copy the pointer.
String1030(const String1030& oldstring);
// The destructor is needed because we are allocating memory.
// We must deallocate it when the object goes out of
// scope (is destroyed).
~String1030();
// Returns the number of characters stored excluding the
// the sentinel value.
int getSize(void) const;
// Resizes the storage. Must include 1 extra space for the
// sentinel value.
void setSize(int newsize);
String1030& operator=(const String1030& right);
booloperator == (const String1030& right) const ;
// Allows us to change the element at a certain index.
// refer to the IntList code.
intoperator[]( int index ) const;
char& operator[](int index);
// Returns a pointer to array storing the string.
constchar *getString();
// Replace the existing string with a new one.
void setString(constchar *carray);
private:
char *buffer;
int mysize;
};
// Basic constructor.
//
String1030 :: String1030(constchar *buff=0): mysize(0), buffer(0)
{
setSize(*buff);
}
//copy constructor
String1030::String1030(const String1030& oldstring) : mysize(0), buffer(0)
{
if (oldstring.getSize() <= 0) {
setSize(0);
}
else {
setSize(oldstring.getSize());
for (int i = 0; i< mysize; i++) {
buffer[i] = oldstring.buffer[i];
}
}
}
// Destructor call
String1030::~String1030()
{
setSize(0);
}
String1030& String1030:: operator=(const String1030& right){
// must take 'address of' the argument to compare it to the
// this pointer.
if (&right == this)
{
cerr << "Warning: attempt to copy IntList onto self" << endl;
}
else {
if (right.getSize() +1 <= 0) {
setSize(0);
}
else {
setSize(right.getSize());
for (int i = 0; i< mysize +1 ; i++) {
buffer[i] = right.buffer[i];
}
}
}
return *this; // dereference the pointer to get the object
}
char& String1030::operator[](int index)
{
if (index<0 || index >= mysize + 1) {
cerr << "Attempt to access element outside index bounds"
<< endl;
exit(1); // Maybe not reasonable but what the heck.
}
else {
return buffer[index];
}
}
int String1030::getSize() const
{
return mysize;
}
void String1030::setSize(int newsize)
{
if ( newsize <0) {
cerr << "Warning: attempt to set a size < 0" << endl;
exit(2); // is this reasonable?
}
else {
if (buffer != 0) {
delete[] buffer;
buffer = 0;
mysize = 0;
}
if (newsize != 0) {
buffer = newchar[newsize+1];
if (buffer == 0) {
mysize = 0;
cerr << "Warning: unable to allocate enough space for list" << endl;
exit(3);
}
else {
mysize = newsize;
}
}
}
}
// Returns a pointer to array storing the string.
constchar* String1030:: getString()
{
return buffer;
}
// Replace the existing string with a new one.
void String1030::setString(constchar *carray)
{
int len = 0;
for ( int tmp = 0; carray[tmp] != 0; tmp ++){
len = len + 1;
}
setSize(len);
for(int i=0; i < len +1; i++){
buffer[i] = carray[i];
}
}
bool String1030::operator == ( const String1030& right ) const
{
bool result=true;
if( right !== right.getSize() ) {
result=false;
} else {
for(int i=0; i< mysize && result == true; i++) {
result = buffer[i]==right.buffer[i];
}
}
return result;
}
ostream& operator<<( ostream& , const String1030& );
istream& operator>>( istream& , String1030& );
ostream& operator<<( ostream& L, const String1030& R)
{
if( R.getSize() > 0 ) {
L << endl;
for( int i=0; i< R.getSize(); i++ ) {
L << "[" << i << "] " << R[i] << endl;
}
} else {
cerr << "Warning: Attempt to display empty IntList" << endl;
}
return L;
}
// Note that this does NOT validate the input after the first value.
// That is intentional here. Your future code should be more robust.
//
istream& operator>>( istream& L, String1030& R)
{
int tmp;
L >> tmp;
if( tmp<=0 ) {
cerr << "First value expected to be list size, > 0." << endl;
} else {
if( tmp!=R.getSize() ) {
R.setSize(tmp);
}
for (int i=0; i< R.getSize(); i++) {
L >> R[i];
}
}
return L;
}
int String1030::operator[]( int index ) const
{
if( index<0 || index>=mysize ) {
cerr << "Attempt to access element outside index bounds"
<< endl;
exit(4); // Maybe not reasonable.
} else {
return buffer[index];
}
}
#endif