Delphi & Pascal (česká wiki)
Přejít na: navigace, hledání
/* ========================================================================== */
/*                                                                            */
/*   Ubytuj.cpp                       Copyright (c) TrSek alias Zdeno Sekerak */
/*   Datum:20.05.2005                                    http://www.trsek.com */
/*                                                                            */
/*   Description                                                              */
/*   Tato trieda sa stara o vsetko co suvisi z ubytovnami. Umoznuje zaradit,  */
/*   vyradit ubytovnu. Vyhladavanie podla siestich roznych kriterii. Ubytovne */
/*   su ulozene v subore ubytovne.dat.                                        */
/*   Vsetko je prezentovane v obojsmernom spojkovom zozname.                  */
/* ========================================================================== */
 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
 
#include "define.h"
#include "ubytuj.h"
 
// konstruktor
Ubytuj::Ubytuj()
{
  prvy  = NULL;
  zaz   = NULL;
  pocet = 0;
  akt   = 0;
  max_id = 0;
  find_id = -1;
 
  // vycita zo suboru
  Load();
};
 
 
// ~destruktor
Ubytuj::~Ubytuj()
{
  // ulozi do suboru
  Save();
  DeleteAll();
};
 
 
// ulozi zaznamy do suboru
void Ubytuj::Save()
{
FILE *f;
int len;
 
   // zrusime podmienky
   Find(-1,0,"");
 
   f = fopen( UBYT_FILE, "wb" );
   if( f==NULL )
       Chyba("Nemozem ulozit do suboru");
 
   // presun na zaciatok
   if( MoveFirst())
      // vsetko v poriadku ukladame data
      do {
        // ulozime staticke data
        fwrite( zaz, sizeof(Zaznam)-4, 1, f );
 
        // a teraz dynamicke, ulozime velkost pola + hodnotu
        len = strlen( zaz->nazov )+1;
        fwrite( &len, sizeof(len), 1, f );
        fwrite( zaz->nazov, len, 1, f );
 
        // a teraz dynamicke, ulozime velkost pola + hodnotu
        len = strlen( zaz->lokalita )+1;
        fwrite( &len, sizeof(len), 1, f );
        fwrite( zaz->lokalita, len, 1, f );
     }
     // ideme na dalsi
     while( MoveNext());
 
   // zavrieme
   fclose(f);
};
 
 
// ulozi zaznamy do suboru
void Ubytuj::Load()
{
FILE *f;
int len;
 
   // mensie upratovanie
   DeleteAll();
 
   f = fopen( UBYT_FILE, "rb" );
   // nieje subor tak nic
   if( f==NULL )
       return;
 
   // vsetko v poriadku ukladame data
   while( !feof(f))
   {
      // pridame
      AddNew();
 
      // precitame staticke data, okrem smernikov
      if( fread( zaz, sizeof(Zaznam)-4, 1, f ))
      {
         // velkost dynamickeho pola
         fread( &len, sizeof(len), 1, f );
         fread( pom, len, 1, f );
         Insert(1,pom);
 
         // dynamicke pole
         fread( &len, sizeof(len), 1, f );
         fread( pom, len, 1, f );
         Insert(2,pom);
 
         // ake je max_id
         if( zaz->id > max_id )
             max_id = zaz->id;
      }
      else
         Delete();
   }
 
   // zavrieme
   fclose(f);
   MoveFirst();
};
 
 
// ulozi premennu
void Ubytuj::Insert(char id, char* meno)
{
  // pozor je alokovanie miesto
  if( zaz==NULL )
      AddNew();
 
  // meno ubytovne
  if( id==1 )
  {
    zaz->dlzn = strlen(meno)+1;
    zaz->nazov = (char*) malloc( zaz->dlzn );
    strcpy( zaz->nazov, meno );
  }
 
  // meno lokality
  if( id==2 )
  {
    zaz->dlzl = strlen(meno)+1;
    zaz->lokalita = (char*) malloc( zaz->dlzl );
    strcpy( zaz->lokalita, meno );
  }
 
  // typ ubytovania
  if( id==3 ) zaz->ubytuj = (typ_ubyt) atoi(meno);
  // cena za ubytovanie
  if( id==4 ) zaz->cena   = atof(meno);
  // pocet miest v ubytovni
  if( id==5 ) zaz->pocet  = atoi(meno);
  // pocet rezervovanych
  if( id==6 ) zaz->rezerv = atoi(meno);
};
 
 
// konvertuje int do string
char* Ubytuj::ToStr(int poc)
{
   sprintf(pom, "%d", poc);
   return pom;
}
 
 
// konvertuje int do string
char* Ubytuj::ToStr(float poc)
{
   sprintf(pom, "%.2f", poc);
   return pom;
}
 
 
// vrati ako retazec
char* Ubytuj::Get(char id)
{
  // pozor je alokovanie miesto
  if( zaz==NULL )
      return "";
 
  // podla id
  if( id==0 ) return ToStr( zaz->id );
  if( id==1 ) return zaz->nazov;
  if( id==2 ) return zaz->lokalita;
  if( id==3 ) return ToStr( zaz->ubytuj );
  if( id==4 ) return ToStr( zaz->cena   );
  if( id==5 ) return ToStr( zaz->pocet  );
  if( id==6 ) return ToStr( zaz->rezerv );
  return "";
}
 
 
// vrati iba ak je integer
int Ubytuj::GetInt(char id)
{
  // pozor je alokovanie miesto
  if( zaz==NULL )
      return 0;
 
  // podla id
  if( id==0 ) return zaz->id;
  if( id==3 ) return zaz->ubytuj;
  if( id==4 ) return zaz->cena;
  if( id==5 ) return zaz->pocet;
  if( id==6 ) return zaz->rezerv;
  return 0;
}
 
 
// vrati pocet id
int Ubytuj::GetPocetId()
{
  return 6;
}
 
 
// vrati meno id
char* Ubytuj::GetName(char id)
{
  // podla id
  if( id==0 ) return "Id zaznamu";
  if( id==1 ) return "Meno ubytovne";
  if( id==2 ) return "Nazov lokality";
  if( id==3 ) return "Sposob ubytovania";
  if( id==4 ) return "Cena za ubytovanie";
  if( id==5 ) return "Pocet volnych miest";
  if( id==6 ) return "Pocet rezervovanych miest";
  return "";
}
 
 
// prejdi na prvy zaznam
int Ubytuj::MoveFirst(void)
{
   zaz = prvy;
   akt = 1;
 
   // najdeme prvy co vyhovuje podmienke
   while( !IsCondition() && ( zaz!=NULL ))
   {
     zaz = zaz->zani;
     akt++;
   }
 
   // najdene???
   return (zaz==NULL)?false:true;
}
 
 
// posun na dalsi zaznam
int Ubytuj::MoveNext(void)
{
Zaznam* old = zaz;
int old_akt = akt;
 
   if( zaz!=NULL )
   {
     zaz = zaz->zani;
     akt++;
   }
 
   // najdeme dalsi co vyhovuje podmienke
   while( !IsCondition() && ( zaz!=NULL ))
   {
     zaz = zaz->zani;
     akt++;
   }
 
   // uz dalsi nieje, vratme stary
   if( !IsCondition())
   {
       zaz = old;
       akt = old_akt;
       return false;
   }
 
   // najdene???
   return (zaz==NULL)?false:true;
}
 
 
// posun na predosli zaznam
int Ubytuj::MovePrev(void)
{
Zaznam* old = zaz;
int old_akt = akt;
 
   if( zaz!=NULL )
   {
     zaz = zaz->pred;
     akt--;
   }
 
   // najdeme dalsi co vyhovuje podmienke
   while( !IsCondition() && ( zaz!=NULL ))
   {
     zaz = zaz->pred;
     akt--;
   }
 
   // uz dalsi nieje, vratme stary
   if( !IsCondition())
   {
       zaz = old;
       akt = old_akt;
       return false;
   }
 
   // najdene???
   return (zaz==NULL)?false:true;
}
 
 
// posun nakoniec
int Ubytuj::MoveLast(void)
{
Zaznam* old = zaz;
int old_akt = akt;
 
   // najdeme dalsi co vyhovuje podmienke
   while( IsCondition() && ( zaz->zani!=NULL ))
   {
     old = zaz;
     old_akt = akt;
     zaz = zaz->zani;
     akt++;
   }
 
   // uz dalsi nieje, vratme posledny najdeny
   if( !IsCondition())
   {
       zaz = old;
       akt = old_akt;
       return false;
   }
 
   // najdene???
   return (zaz==NULL)?false:true;
}
 
 
// rezervuje neake miesta
int Ubytuj::Rezervuj(int poc)
{
   // a ako ???
   if( zaz == NULL )
       return 0;
 
  // je mozne rezervovat
  if( zaz->pocet >= poc )
  {
      zaz->pocet -= poc;
      zaz->rezerv += poc;
      return poc;
  }
 
  return 0;
}
 
 
// zrusi rezervaciu
int Ubytuj::OdRezervuj(int poc)
{
   // a ako ???
   if( zaz == NULL )
       return 0;
 
  // je mozne rezervovat
  if( zaz->rezerv >= poc )
  {
      zaz->pocet += poc;
      zaz->rezerv -= poc;
      return poc;
  }
 
  return 0;
}
 
 
//
void Ubytuj::AddNew(void)
{
  Zaznam* novy;
 
  // vytvorim nove miesto
  novy = (Zaznam*) malloc(sizeof(Zaznam));
 
  // smola uz asi niet pamate
  if( novy== NULL )
      Chyba("Malo pamete");
 
  // prepojim smerniky
  if( zaz!=NULL )
  {
      novy->zani = zaz->zani;
       zaz->zani = novy;
      novy->pred = zaz;
      novy->id = ++max_id;
 
      if( novy->zani != NULL )
          (novy->zani)->pred = novy;
  }
  else
  {
      prvy = novy;
      prvy->pred = NULL;
      prvy->zani = NULL;
      novy->id   = 1;
  }
 
  pocet++; akt++;
  zaz = novy;
 
  zaz->dlzn   = 0;
  zaz->nazov  = NULL;
  zaz->dlzl   = 0;
  zaz->lokalita = NULL;
  zaz->ubytuj = (typ_ubyt) 0;
  zaz->cena   = 0;
  zaz->pocet  = 0;
  zaz->rezerv = 0;
}
 
 
// zmazeme zaznam
void Ubytuj::Delete(void)
{
  Zaznam* pred = NULL;
  Zaznam* zani = NULL;
 
  // uz niet co
  if( zaz == NULL )
      return;
 
  // opravime smernik pred
  if( zaz->zani != NULL )
  {
    zani = zaz->zani;
    zani->pred = zaz->pred;
  }
 
  // opravime smernik za
  if( zaz->pred != NULL )
  {
    pred = zaz->pred;
    pred->zani = zaz->zani;
  }
 
  // zmazeme alokovane pamete
  if( zaz->lokalita )
      free( zaz->lokalita );
 
  if( zaz->nazov )
      free( zaz->nazov );
 
  // je to zaroven prvy ???
  if( zaz == prvy )
      prvy = zaz->zani;
 
  pocet--;
  free( zaz );
 
  // nastavime neaky smernik
  zaz = NULL;
  if( pred != NULL ) { zaz = pred; akt--; }
  if( zani != NULL ) zaz = zani;
}
 
 
// zobrazi aktualny zaznam
void Ubytuj::Show(int typ_view)
{
  if( typ_view == 0 )
  {
    printf("\n");
    printf("--------------------------------------\n");
    printf("                  ID: %s\n", Get(0));
    printf(" aktualne ubytovanie: %s\n", Get(1));
    printf("            lokalita: %s\n", Get(2));
    printf("        typ ubytovne: %s\n", Get(3));
    printf("  cena za ubytovanie: %s\n", Get(4));
    printf(" pocet volnych miest: %s\n", Get(5));
    printf(" pocet rezervovanych: %s\n", Get(6));
    printf("--------------------------------------\n");
    printf("\n");
  }
  else
  {
    printf("       ubytovanie je: %s\n", Get(1));
    printf("            lokalita: %s\n", Get(2));
    printf("--------------------------------------\n");
    printf("\n");
  }
}
 
 
// vypise na ktorom zazname som a kolko ich je
void Ubytuj::Bar(void)
{
  printf("Ubytovne aktualna/celkovo: %d/%d.\n", GetAktual(), GetPocet());
 
  // ak je podmienka
  if( find_id>-1 )
      printf("Podmienka: %s %s %s\n", GetName(find_id), GetSign(find_sign), find_meno );
}
 
 
// najdi zaznam podla id a sign
void Ubytuj::Find(char id, char sign, char* meno)
{
  find_id = id;
  find_sign = sign;
  strcpy( find_meno, meno );
  MoveFirst();
}
 
 
// vyhovuje podmienke
int Ubytuj::IsCondition()
{
  // otazka na nic dava false
  if( zaz == NULL )
      return false;
 
  // urcite lebo ziadna nieje
  if( find_id==-1 )
      return true;
 
  //  
  switch( find_id )
  {
     case 0:  return Compare( zaz->id, atof(find_meno), find_sign )? true:false;
     case 1:  return CompareS( zaz->nazov, find_meno, find_sign )? true:false;
     case 2:  return CompareS( zaz->lokalita, find_meno, find_sign )? true:false;
     case 3:  return Compare( zaz->ubytuj, atof(find_meno), find_sign )? true:false;
     case 4:  return Compare( zaz->cena, atof(find_meno), find_sign )? true:false;
     case 5:  return Compare( zaz->pocet, atof(find_meno), find_sign )? true:false;
     case 6:  return Compare( zaz->rezerv, atof(find_meno), find_sign )? true:false;
  }
 
  // niekde nieco zlyhalo
  return false;
}
 
 
// vycisti pamet
void Ubytuj::DeleteAll(void)
{
  Zaznam* pom = NULL;
  zaz = prvy;
 
  while( zaz!=NULL )
  {
    if( zaz!=NULL )
        pom = zaz->zani;
    else
        pom = NULL;
 
    Delete();
    zaz = pom;
  }
 
  // kde nic nieje ani smernik nebude
  prvy = zaz = NULL;
  pocet = akt = 0;
}
 
 
// vrati znamienko
char* Ubytuj::GetSign(char id)
{
  switch(id)
  {
    case 1: return "=";
    case 2: return "<";
    case 3: return "<=";
    case 4: return ">";
    case 5: return "=>";
    case 6: return "!=";
  }
 
 return "";
}
 
 
// compare string
int Ubytuj::CompareS(char* prvy, char* druhy, char sign)
{
int porov;
 
  porov = strcmp( prvy, druhy );
 
  if(( sign==1 ) && ( porov==0 )) return true;    // =
  if(( sign==2 ) && ( porov< 0 )) return true;    // <
  if(( sign==3 ) && ( porov<=0 )) return true;    // <=
  if(( sign==4 ) && ( porov> 0 )) return true;    // >
  if(( sign==5 ) && ( porov>=0 )) return true;    // =>
  if(( sign==6 ) && ( porov!=0 )) return true;    // !=
 
  // nic
  return false;
}
 
 
// compare integer
int Ubytuj::Compare(float prvy, float druhy, char sign)
{
  if(( sign==1 ) && ( prvy==druhy )) return true;   // =
  if(( sign==2 ) && ( prvy< druhy )) return true;   // <
  if(( sign==3 ) && ( prvy<=druhy )) return true;   // <=
  if(( sign==4 ) && ( prvy >druhy )) return true;   // >
  if(( sign==5 ) && ( prvy>=druhy )) return true;   // =>
  if(( sign==6 ) && ( prvy!=druhy )) return true;   // !=
 
  // nic
  return false;
}
 
 
// vypise chybu a skonci
// ide o osetrenie chyb ktore uz program nedokaze rozchodit
void Ubytuj::Chyba(char* text)
{
  printf("%s", text);
  exit(1);
}