Строки -элементы таблицы
//------------------------------------------------------bk8-03.cpp
#include <string.h>
#include <conio.h>
#include <stdlib.h>
class String : TElem
{
//----- Объект класса содержит единственный элемент данных-
// динамический массив символов. Его текущая размерность
// определяется длиной строки.
char *Str;
public:
//----- Эта часть класса представляет собой переопределение
// виртуальных функций базового класса TElem под конкретные
// свойства класса строк
BOOL FromString(char *);
char *ToString();
int Compare(TElem *);
BOOL IsValid();
TElem *Copy();
int IDENT();
char *Name();
int FSize();
FPTR Update(BinFile&, FPTR=FNULL,int=1);
FPTR Append(BinFile&);
BOOL Load(BinFile&, FPTR=FNULL);
//----- Эта часть класса представляет собой переопределение
// минимально необходимого набора операций со строками.
// Операции имеют "естественный" синтаксис, близкий к син-
// таксису арифметических операций.
String(); // Конструктор
String(char *); //
~String(); // Деструктор
String(String &); // Конструктор копирования
int operator < (String &); // Операторы сравнения
int operator > (String &); //
int operator <=(String &); //
int operator >=(String &); //
int operator ==(String &); //
int operator !=(String &); //
String operator()(int); // Выделение подстроки
String operator()(int,int); //
String &operator=(String &); // Присваивание
String &operator=(char *);
String operator+(String &); // Конкатенация
String operator+(char *); //
operator int(); // Длина строки
int operator[](char *); // Поиск подстроки
int operator[](String &); //
};
//----- Прежде всего определим виртуальные функции, унас-
// ледованные от абстрактного класса TElem и переопреде-
// ленные в String.
#define STRING_ID 10 // Уникальный идентификатор класса
int String::IDENT() { return(STRING_ID); }
char *String::Name() { return("Строка"); }
TElem *String::Copy()
{
String *p = new String;
return(p);
}
int String::Compare(TElem *p)
{
String *q = (String*)p;
if (Str==NULL || q->Str==NULL) return(-1);
return(strcmp(Str,q->Str));
}
BOOL String::FromString(char *p)
{
if (Str !=NULL) delete Str;
if ((Str = new char[strlen(p)+1])==NULL) return(0);
if (p==NULL) return(0);
strcpy(Str,p);
return(1);
}
char *String::ToString()
{
char *p;
if (Str==NULL) return(NULL);
if ((p = new char[strlen(Str)+1])==NULL) return(NULL);
strcpy(p,Str);
return(p);
}
//----- Динамический массив символов Str объекта класса
// "строка" сохраняется в файле в виде записи переменной
// длины, поэтому для работы с файлом используются
// соответствующие функции. Определенное по умолчанию зна-
// чение FNULL указателя в файле - p предполагает работу
// с файлом без позиционирования, то есть как с последова-
// тельным (или потоком).
int String::FSize()
{
if (Str==NULL) return(0);
return(strlen(Str) + 1 + sizeof(int));
}
FPTR String::Append(BinFile &F)
{
if (Str==NULL) return(FNULL);
return (F.VSZAppend((void *)Str, strlen(Str)+1));
}
BOOL String::Load(BinFile &F, FPTR p)
{
int sz;
if (Str!=NULL) delete Str;
Str = NULL;
if (p !=FNULL) if (!F.seekg(p)) return(0);
if ((Str=(char *)F.VSZLoad(sz)) ==NULL) return(0);
return(1);
}
FPTR String::Update(BinFile &F, FPTR p, int mode)
{
if (Str==NULL) return(FNULL);
if (p !=FNULL) if (!F.seekg(p)) return(FNULL);
return( F.VSZUpdate((void *)Str, strlen(Str)+1, mode));
}
//----- Переопределение операций над строками
String::String()
{ Str = NULL; }
String::String(char *s)
{ Str = new char[strlen(s)+1]; strcpy(Str,s); }
String::~String() { if (Str !=NULL) delete Str; }
BOOL String::IsValid() { return(Str !=NULL); }
String String::operator+(char *p)
{
String ss;
if (Str==NULL || p==NULL) return(ss);
ss.Str = new char[strlen(Str) + strlen(p) + 1];
strcpy(ss.Str,Str);
strcat(ss.Str,p);
return(ss);
}
String String::operator+(String &two)
{ return((*this) + two.Str); }
int String::operator[](char *sub)
{
int n,i;
if (Str==NULL) return(-1);
for (n=0; Str[n]!=0; n++)
{
for (i=0; Str[n+i]!=0; i++)
if (Str[n+i] !=sub[i]) break;
if (sub[i]==0) return(n);
}
return(-1);
}
int String::operator[](String &two)
{
if (Str==NULL || two.Str==NULL) return(-1);
return((*this)[two.Str]);
}
String String::operator()( int nn)
{
String ss;
if (Str==NULL) return(ss);
if (nn >=FSize()) return(ss);
FromString(Str + nn);
return(ss);
}
String String::operator()(int nn,int sz)
{
String ss;
if (Str==NULL) return(ss);
if (nn >=FSize()) return(ss);
if (nn + sz >=FSize()) return(ss);
ss.Str = new char[sz+1];
if (ss.Str==NULL) return(ss);
strncpy(ss.Str,Str+nn,sz);
return(ss);
}
String &String::operator=(String &right)
{
if (Str !=NULL) delete(Str);
Str = new char[strlen(right.Str)+1];
if (Str==NULL) return(*this);
strcpy(Str,right.Str);
return(*this);
}
String &String::operator=(char *p)
{
if (Str !=NULL) delete(Str);
Str = new char[strlen(p)+1];
if (Str==NULL) return(*this);
strcpy(Str,p);
return(*this);
}
int String::operator int()
{
return(FSize());
}
String::String(String &right)
{
if (right.Str==NULL) { Str = NULL; return; }
Str = new char[strlen(right.Str)+1];
if (Str==NULL) return;
strcpy(Str,right.Str);
}
int String::operator < (String &two)
{ return (Compare(&two) == -1); }
int String::operator > (String &two)
{ return (Compare(&two) == 1); }
int String::operator <=(String &two)
{ return (Compare(&two) != 1); }
int String::operator >=(String &two)
{ return (Compare(&two) != -1); }
int String::operator ==(String &two)
{ return (Compare(&two) == 0); }
int String::operator != (String &two)
{ return (Compare(&two) != 0); }