Code imrovements on manipulating strings

I have written the code below and would be very grateful for any comments about it (how can I improve it, simplify it,...).

#ifndef String_hh
#define String_hh

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "Vect2.hh"
#include "Vector.hh"
#include "DynBaseObj.hh"
#include "List.hh"
#include "Stack.hh"
#include "Tree.hh"
#include "common.hh"

const int  MaxDimString = 4000;

////////////////////////////////////////////////////////////////////////////////////////////////////

class String {

// -- Attributes -----------------------------------------------------------------------------------

protected:

  char*  Str;                          // String.
  int  Size;                           // Size of a string.
  int  Ptr;                            // Pointer pointing to a character position in the string.

// -- Operations -----------------------------------------------------------------------------------

public:

  // Constructors:

  String();                            //

  String(                              //
    const char*  str);

  String(                              //
    const String&  str);

  explicit String(                     //
    const char  c);

  explicit String(                     //
    const int  i);

  explicit String(                     //
    const float  f);

  explicit String(                     //
    const double  d);

  // Destructors:

  ~String();                           //

  // Operators:

  operator char *() const;             //

  char&  operator [] (                 //
    const int  i);

  String&  operator  = (               //
    const String&  str);

  String&  operator  = (               //
    const char*  str);

  String&  operator += (               //
    const String&  str);

  String&  operator += (               //
    const char  c);

  String&  operator += (               //
    const char*  str);

  String&  operator >> (               //
    char&  c);

  String&  operator >> (               //
    int&  i);

  String&  operator >> (               //
    float&  f);

  String&  operator >> (               //
    double&  d);

  String&  operator >> (               //
    Vect2&  v);

  String&  operator >> (               //
    Vector<int>&  v);

  String&  operator >> (               //
    Vector<float>&  v);

  String&  operator >> (               //
    Vector<double>&  v);

  String&  operator << (               //
    const char  c);

  String&  operator << (               //
    const char*  c);

  String&  operator << (               //
    const int  i);

  String&  operator << (               //
    const float  f);

  String&  operator << (               //
    const double  d);

  String&  operator << (               //
    const Vect2  v);

  String&  operator << (               //
    const Vector<int>&  v);

  String&  operator << (               //
    const Vector<float>&  v);

  String&  operator << (               //
    const Vector<double>&  v);

  bool  Empty() const;                 //

  bool  End() const;                   //

  int  size() const;                   //

  void  Reset();                       //

  void  Rewind();                      //

  void  GoTo(                          //
    const int  ptr);

  int  Where() const;                  //

  String  Substr(                      //
    const int  beg,
    const int  end) const;

  String  ToEnd(                       //
    const int  beg) const;

  String  FromBegin(                   //
    const int  end) const;

  String&  ToUpper();                  // Convert string to uppercase.

  String&  Substitute(                 // Replaces a character in a string with another.
    const char  c1,
    const char  c2);

  bool  Search(                        //
    const String&  S,
    int&  pos) const;

  bool  IsIn(                          //
    const char  c) const;

  int  Hash() const;                   //

// ***** Other Class Member Functions ****************************************

// The following two Class Member Functions GetToken and NFields call the
// Non-Member Functions with the same names. Their declaration must be
// present after the Non-Member Functions GetToken and NFields have been
// declared.

// The Scope Declaration Operator :: is used to access a function which is
// outside the current scope. If this is omitted, the compiler will try to
// use the local Class Member Function rather than the Class Non-Member
// function. Basically, if there is some function with the same name in the
// current scope them the compiler will stop looking for other function
// names and try to use them.

  String  GetToken(                    //
    const char  del);

  int  NFields(                        //
    const char  del) const;

protected:

  int  isidigit1(                      // Returns 1 if character c is part of an integer.
    const char  c) const;

  int  isidigit2(                      // Returns 1 if character c is part of a natural number.
    const char  c) const;

  int  isddigit(                       // Returns 1 if character c is part of a floating point
    const char  c) const;              // number.

  int  isNaturalDigit(                 // Returns 1 if character c is part of a natural number.
    const char  c) const;

  int  isIntegerDigit(                 // Returns 1 if character c is part of an integer.
    const char  c) const;

  int  isFltPntDigit(                  // Returns 1 if character c is part of a floating point
    const char  c) const;              // number.

public:

  // Friends:

  friend void  GoTo(                   //
    String&  S,
    const int  ptr);

  friend int  Where(                   //
    const String&  S);

  friend String  Substr(               //
    const String&  S,
    const int  beg,
    const int  end);

  friend String  ToEnd(                //
    const String&  S,
    const int  beg);

  friend String  FromBegin(            //
    const String&  S,
    const int  end);

  friend String  ToUpper(              //
    const String&  S);

  friend bool  Search(                 //
    const String&  S,
    const String&  T,
    int&  pos);

  friend String  GetToken(             //
    String&  S,
    const char  del);

  friend int  NFields(                 //
    const String&  S,
    const char  del);

  friend int  Hash(                    //
    const String&  S);

  friend String  operator + (          //
    const String&  a,
    const String&  b);

  friend String  operator + (          //
    const String&  a,
    const char*  b);

  friend String  operator + (          //
    const char*  a,
    const String&  b);

  friend bool  operator == (           //
    const String&  a,
    const String&  b);

  friend bool  operator == (           //
    const String&  a,
    const char*  b);

  friend bool  operator == (           //
    const char*  a,
    const String&  b);

  friend bool  operator != (           //
    const String&  a,
    const String&  b);

  friend bool  operator != (           //
    const String&  a,
    const char*  b);

  friend bool  operator != (           //
    const char*  a,
    const String&  b);

  friend bool  operator < (            //
    const String&  a,
    const String&  b);

  friend bool  operator < (            //
    const String&  a,
    const char*  b);

  friend bool  operator < (            //
    const char*  a,
    const String&  b);

  friend bool  operator > (            //
    const String&  a,
    const String&  b);

  friend bool  operator > (            //
    const String&  a,
    const char*  b);

  friend bool  operator > (            //
    const char*  a,
    const String&  b);

  friend bool  operator <= (           //
      const String&  a,
      const String&  b);

  friend bool  operator <= (           //
      const String&  a,
      const char*  b);

  friend bool  operator <= (           //
      const char*  a,
      const String&  b);

  friend bool  operator >= (           //
      const String&  a,
      const String&  b);

  friend bool  operator >= (           //
      const String&  a,
      const char*  b);

  friend bool  operator >= (           //
      const char*  a,
      const String&  b);

  friend istream&  operator >> (       //
      istream&  is,
      String&  str);

  friend ostream&  operator << (       //
      ostream&  os,
      const String&  str);

};

////////////////////////////////////////////////////////////////////////////////////////////////////

String::String() {
  Size = 0;
  Ptr = 0;
  Str = new char[1];
  Str[0] = 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

String::String(
  const char*  str) {

  Size = strlen(str);
  Ptr = 0;
  Str = new char[Size+1];
  strcpy(Str, str);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String::String(
  const String&  str) {

  Size = str.Size;
  Ptr = str.Ptr;
  Str = new char[Size+1];
  strcpy(Str, str.Str);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String::String(
  const char  c) {

  Size = 1;
  Ptr = 0;
  Str = new char[Size+1];
  Str[0] = c;
  Str[1] = 0;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String::String(
  const int  i) {

  char  tmp[7];
  sprintf(tmp, "%i", i);
  Size = strlen(tmp);
  Ptr = 0;
  Str = new char[Size+1];
  strcpy(Str, tmp);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String::String(
  const float  f) {

  char  tmp[15];
  sprintf(tmp, "%f", f);
  Size = strlen(tmp);
  Ptr = 0;
  Str = new char[Size+1];
  strcpy(Str, tmp);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String::String(
  const double  d) {

  char tmp[15];
  sprintf(tmp, "%f", d);
  Size = strlen(tmp);
  Ptr = 0;
  Str = new char[Size+1];
  strcpy(Str, tmp);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String::~String() {
  delete Str;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

String::operator char *() const {

  char*  tmp = new char[Size+1];
  strcpy(tmp, Str);
  return tmp;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline char&  String::operator [] (
  const int  i) {

  if ((i < 0) || (i >= Size)) { error("Index out of size in operator []"); }
  return Str;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String&  String::operator = (
  const String&  str) {

  delete Str;
  Size = str.Size;
  Str = new char[Size+1];
  strcpy(Str, str.Str);
  Ptr = str.Ptr;
  return *this;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String&  String::operator  = (
  const char*  str) {

  return ( *this = String(str) );

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String&  String::operator += (
  const String&  str) {

  char  *temp = new char[Size+1];
  strcpy(temp, Str);
  delete Str;
  Size = Size + str.Size;
  Str = new char[Size+1];
  strcpy(Str, temp);
  delete temp;
  strcat(Str, str.Str);
  return *this;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String&  String::operator += (
  const char  c) {

  return ( *this += String(c) );

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String&  String::operator += (
  const char*  str) {

  return ( *this += String(str) );

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String&  String::operator >> (
  char&  c) {

  if (Ptr == Size) { return *this; }
  c = Str[Ptr++];
  return *this;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String&  String::operator >> (
  int&  i) {

  int  b, e;
  char*  c;

  i = 0;

  // Search first digit
  for (b = Ptr; ( !isNaturalDigit(Str) && (b < Size) ); b++);
  if (b == Size) { return *this; }

  // Search last digit
  for (e = b + 1; ( isIntegerDigit(Str[e]) && (e < Size) ); e++);
  c = new char[e-b];
  strncpy(c, Str + b, (e - b) + 1);
  c[e-b] = 0;
  i = atoi(c);
  delete c;
  Ptr = e;
  return *this;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String&  String::operator >> (
  float&  f ) {

  int  b;
  f = 0;

  // Search first digit
  for (b = Ptr; ( !isFltPntDigit(Str) && (b < Size) ); b++)
  if (b == Size) { return *this; }

  // Search first non-digit
  f = atof(Str + b);
  for (b = b; (isFltPntDigit(Str) && (b < Size)); b++)  { b = b; }
  Ptr = b;
  return *this;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String&  String::operator >> (
  double&  d) {

  int  b;
  d = 0;

  // Search the first digit
  for (b = Ptr; ( !isFltPntDigit(Str) && (b < Size) ); b++)
  if (b == Size) { return (*this); }

  // Search the first non-digit
  d = atof(Str + b);
  for (b = b; ( isFltPntDigit(Str) && (b < Size) ); b++)  { b = b; }
  Ptr = b;
  return *this;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String&  String::operator >> (
  Vect2&  v) {

  Real  x, z;
  (*this) >> x >> z;
  v = Vect2(x, z);
  return *this;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String&  String::operator >> (
  Vector<int>&  v) {

  int  i;
  List<int>  L;

  while ( !End() ) {
      (*this) >> i;
      L += i;
  }

  v.resize( L.size() );
  for (i = 0; i < L.size(); i++)  { v = L; }
  return *this;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String&  String::operator >> (
  Vector<float>&  v) {

  float  f;
  List<float>  L;

  while( !End() ) {
      (*this) >> f;
      L += f;
  }

  v.resize(L.size());
  for (int i = 0; i < L.size(); i++)  { v = L; }
  return *this;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String&  String::operator >> (
  Vector<double>&  v) {

  double  d;
  List<double>  L;

  while ( !End() ) {
      (*this) >> d;
      L += d;
  }

  v.resize( L.size() );
  for (int i = 0; i < L.size(); i++)  { v = L; }
  return *this;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline String&  String::operator << (
  const char  c) {

  *this += String(c);
  return *this;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline String&  String::operator << (
  const char*  c) {

  *this += String(c);
  return  *this;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline String&  String::operator << (
  const int  i) {

  *this += String(i);
  return *this;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline String&  String::operator << (
  const float  f) {

  *this += String(f);
  return *this;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline String&  String::operator << (
  const double  d) {

  *this += String(d);
  return *this;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline String&  String::operator << (
  const Vect2  v) {

  *this += "(" + String(v.X) + "," + String(v.Z) + ")";
  return *this;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String&  String::operator << (
  const Vector<int>&  v) {

  for (int i = 0; i < v.size(); i++) {
      (*this) += String(v);
      if (i < (v.size() - 1))  { *this += " "; }
  }
  return *this;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String&  String::operator << (
  const Vector<float>&  v) {

  for (int i = 0; i < v.size(); i++) {
      (*this) += String( v );
      if (i < (v.size() - 1))  { (*this) += " "; }
  }
  return *this;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String&  String::operator << (
  const Vector<double>&  v) {

  for (int i = 0; i < v.size(); i++) {
      (*this) += String( v );
      if (i < (v.size() - 1)) { (*this) += " "; }
  }
  return *this;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

void  String::Reset() {
  if (Size > 0) { delete Str; }
  Ptr = Size = 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void  String::GoTo(
  const int  ptr) {

  assert((ptr < Size) && (ptr >= 0));
  Ptr = ptr;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

bool  String::Empty() const {
  return Size == 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

bool  String::End() const {
  return Ptr == Size;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline int  String::size() const {
  return Size;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline void  String::Rewind() {
  Ptr = 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline int  String::Where() const {
  return Ptr;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

String  String::Substr(
  const int  beg,
  const int  end) const {

  assert( (beg <= end) && (beg < Size) && (end < Size) && (beg >= 0) && (end >= 0) );

  char*  s = new char[end-beg+2];
  for (int i = beg; i <= end; i++)  { s[i-beg] = Str; }
  s[end-beg+1] = 0;
  return String(s);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String  String::ToEnd(
  const int  beg) const {

  assert(beg > 0);
  char*  s = new char[Size-beg+1];
  if (beg >= Size) return (String(""));
  for (int i = beg; i < Size; i++)  { s[i-beg] = Str; }
  s[Size-beg] = 0;
  return String(s);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String  String::FromBegin(
  const int  end) const {

  assert((end < Size) && (end > 0));
  char  *s = new char[end+2];
  for (int i = 0; i <= end; i++)  { s = Str; }
  s[end+1] = 0;
  return String(s);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String&  String::ToUpper() {

  for (int i = 0; i < Size; i++) {
    if ((Str >= 'a') && (Str <= 'z'))  { Str -= 'a' - 'A'; }
  }
  return *this;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

// Replaces a character with another.

String&  String::Substitute(
  const char  c1,
  const char  c2) {

  for (int i = 0; i < Size; i++) {
    if (Str == c1)  { Str = c2; }
  }
  return *this;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

bool  String::Search(
  const String&  str,
  int&  pos) const {

  char*  p = strstr(Str, str.Str);
  pos = str.size();
  if (p == NULL) return false;
  for (pos = 0; (p != Str + pos) && (pos < Size); pos++);

  return true;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

bool  String::IsIn(
  const char  c) const {

  for (int i = Ptr; i < Size; i++) {
    if (Str == c) return true;
  }

  return false;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

/*

// Returns 1 if character c is part of an integer.

inline int  String::isidigit1(
  const char  c) const {

  return ((c >= '0') && (c <= '9')) || (c == '+') || (c == '-');

}

////////////////////////////////////////////////////////////////////////////////////////////////////

// Returns 1 if character c is part of a natural number.

inline int  String::isidigit2(
  const char  c) const {

  return ( (c >= '0') && (c <= '9') );

}

////////////////////////////////////////////////////////////////////////////////////////////////////

// Returns 1 if character c is part of a floating point number.

inline int  String::isddigit(
  const char  c) const {

  return ( ((c>='0') && (c<='9')) || (c=='.') || (c=='+') || (c=='-') || (c=='e') || (c=='E') );

}

*/

////////////////////////////////////////////////////////////////////////////////////////////////////

// Returns 1 if character c is part of a natural number.

inline int  String::isNaturalDigit(
  const char  c) const {

  return ( (c >= '0') && (c <= '9') );

}

////////////////////////////////////////////////////////////////////////////////////////////////////

// Returns 1 if character c is part of an integer.

inline int  String::isIntegerDigit(
  const char  c) const {

  return ( ((c >= '0') && (c <= '9')) || (c == '+') || (c == '-') );

}

////////////////////////////////////////////////////////////////////////////////////////////////////

// Returns 1 if character c is part of a floating point number.

inline int  String::isFltPntDigit(
  const char  c) const {

  return ( ((c>='0') && (c<='9')) || (c=='.') || (c=='+') || (c=='-') || (c=='e') || (c=='E') );

}

////////////////////////////////////////////////////////////////////////////////////////////////////

int  String::Hash() const {

  int  h = 0;
  for (int i = 0; i < Size; i++)  { h += Str; }
  return h;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String  GetToken(
  String&  S,
  const char  del = ' ') {

  int  b = S.Ptr, e;
  if (S.Ptr == S.Size) return (String(""));
  while ((b < S.Size) && (S.Str == del)) { b++; }
  e = b;
  while ((e < S.Size) && (S.Str[e] != del)) { e++; }
  if (b == S.Size) return (String(""));
  S.Ptr = e;
  e--;

  return S.Substr(b, e);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

int  NFields(
  const String&  S,
  const char  del = ' ') {


  // Get only the number of tokens
  int  i = 0;
  int  count = 0;

  do {

      while ((i < S.Size) && (S.Str == del)) { i++; }

      if (i < S.Size) count++;
      else return count;

      while ((i < S.Size) && (S.Str != del)) { i++; }
      if (i == S.Size) return count;

  } while (i < S.Size);

  return count;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

//  The Class Member Function GetToken is defined here because it needs to
//  access the Non-Member Function GetToken which must first be declared to
//  be used.

//  The Scope Declaration Operator :: is used to access a function which is
//  outside the current scope. If this is omitted, the compiler will try to
//  use the local Class Member Function rather than the Class Non-Member
//  function. Basically, if there is some function with the same name in the
//  current scope them the compiler will stop looking for other function
//  names and try to use them.

inline String  String::GetToken(
  const char  del = ' ') {

  return ( ::GetToken(*this, del) );

}

////////////////////////////////////////////////////////////////////////////////////////////////////

//  The Class Member Function NFields is defined here because it needs to
//  access the Non-Member Function NFields which must first be declared to
//  be used.

//  The Scope Declaration Operator :: is used to access a function which is
//  outside the current scope. If this is omitted, the compiler will try to
//  use the local Class Member Function rather than the Class Non-Member
//  function. Basically, if there is some function with the same name in the
//  current scope them the compiler will stop looking for other function
//  names and try to use them.

inline int  String::NFields(
  const char  del = ' ') const {

  return ( ::NFields(*this, del) );

}

////////////////////////////////////////////////////////////////////////////////////////////////////

int  Hash(
  const String&  S) {

  int  h = 0;
  for (int i = 0; i < S.Size; i++) { h += S.Str; }
  return h;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

int  Hash(
  const char*  S) {

  int  i = 0;
  int  h = 0;
  while (S != 0)  { h += S[i++]; }
  return h;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline String  operator + (
  const String&  a,
  const String&  b) {

  String Y(a);
  Y += b;
  return Y;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline String  operator + (
  const String&  a,
  const char*  b) {

  return ( a + String(b) );

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline String  operator + (
  const char*  a,
  const String&  b) {

  return ( String(a) + b );

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline bool  operator == (
  const String&  a,
  const String&  b) {

  return ( strcmp(a.Str, b.Str) == 0 );

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline bool  operator == (
  const String&  a,
  const char*  b) {

  return ( a == String(b) );

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline bool  operator == (
  const char*  a,
  const String&  b) {

  return ( String(a) == b );

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline bool  operator != (
  const String&  a,
  const String&  b) {

  return ( strcmp(a.Str, b.Str) != 0 );

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline bool  operator != (
  const String&  a,
  const char*  b) {

  return ( a != String(b) );

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline bool  operator != (
  const char*  a,
  const String&  b) {

  return ( String(a) != b );

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline bool  operator < (
  const String&  a,
  const String&  b) {

  return ( strcmp(a.Str, b.Str) < 0 );

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline bool  operator < (
  const String&  a,
  const char*  b) {

  return (a < String(b));

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline bool  operator < (
  const char*  a,
  const String&  b) {

  return (String(a) < b);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline bool  operator > (
  const String&  a,
  const String&  b) {

  return (strcmp(a.Str, b.Str) > 0);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline bool  operator > (
  const String&  a,
  const char*  b) {

  return (a > String(b));

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline bool  operator > (
  const char*  a,
  const String&  b) {

  return (String(a) > b);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline bool  operator <= (
  const String&  a,
  const String&  b) {

  return (strcmp(a.Str, b.Str) <= 0);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline bool  operator <= (
  const String&  a,
  const char*  b) {

  return (a <= String(b));

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline bool  operator <= (
  const char*  a,
  const String&  b) {

  return (String(a) <= b);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline bool  operator >= (
  const String&  a,
  const String&  b) {

  return (strcmp(a.Str, b.Str) >= 0);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline bool  operator >= (
  const String&  a,
  const char*  b) {

  return (a >= String(b));

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline bool  operator >= (
  const char*  a,
  const String&  b) {

  return (String(a) >= b);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

istream&  operator >> (
  istream&  is,
  String&  str) {

  char  buf[MaxDimString], c;
  if (is.peek() == '\n')  { is.get(c); }
  is.getline(buf, MaxDimString, '\n');
  assert( !is.bad() );
  delete str.Str;
  str.Size = strlen(buf);
  str.Str = new char[str.Size+1];
  strcpy(str.Str, buf);
  str.Ptr = 0;
  return is;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline ostream&  operator << (
  ostream&  os,
  const String&  str) {

  return (os << str.Str);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline void  GoTo(
  String&  S,
  const int  ptr) {

  assert((ptr < S.Size) && (ptr >= 0));
  S.Ptr = ptr;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

inline int  Where(
  const String&  S) {

  return S.Ptr;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String  Substr(
  const String&  S,
  const int  beg,
  const int  end) {

  assert( (beg <= end) && (beg <  S.Size) && (end <  S.Size) && (beg >= 0)
    && (end >= 0) );

  char*  s = new char[end-beg+2];
  for (int i = beg; i <= end; i++)  { s[i-beg] = S.Str; }
  s[end-beg+1] = 0;
  return String(s);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String  ToEnd(
  const String&  S,
  const int  beg) {

    assert(beg > 0);
    char*  s = new char[S.Size-beg+1];
    if (beg >= S.Size) return String("");
    for (int i = beg; i < S.Size; i++)  { s[i-beg] = S.Str; }
    s[S.Size-beg] = 0;
    return String(s);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String  FromBegin(
  const String&  S,
  const int  end) {

  assert((end < S.Size) && (end > 0));
  char*  s = new char[end+2];
  for (int i = 0; i <= end; i++)  { s = S.Str; }
  s[end+1] = 0;
  return String(s);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

String  ToUpper(
  const String&  S) {

  String  T(S);
  for (int i = 0; i < S.Size; i++) {
      if ((T.Str >= 'a') && (T.Str <= 'z'))  { T.Str -= 'a' - 'A'; }
  }
  return T;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

bool  Search(
  const String&  S,
  const String&  T,
  int&  pos) {

  char*  p = strstr(S.Str, T.Str);
  pos = S.size();
  if (p == NULL) { return (false); }
  for (pos = 0; (p != S.Str+pos) && (pos < S.Size); pos++);
  return (true);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

#endif