next up previous
Next: Greed-Game (ASCII-Version) Up: Folien zur AG Objektorientiertes Previous: Beispiel (forts.)

CGI-Beispiel

Das folgende Programm verwendet die im Termin ``dynamische Speicherallokation'' vorgestellte Klasse für Hash-Tabellen.

hash.h

// Beispiel zur Veranschaulichung einer Hash-Funktion
// (c) 05/97 Gottfried Rudorfer

#include <iostream.h>
#include <new.h>
extern "C" 
{
  // for exit() 
 #include <stdlib.h>
  // for strcpy() and strlen()
 #include <string.h>  
} 

// forward reference
class Table;

class Element
{
public:
  friend class Table; 
  Element(char *key, char *value);
  ~Element();
private:
  char *key;
  char *value;
  Element *next;
};

class Table 
{
public:
  Table(unsigned int s, unsigned int m);
  ~Table();
  void Put(char *key, char *value);
  void Print();
  void Delete(char *key);
  char *Get(char *key);
private:
  unsigned int Hash(char *key);
  unsigned int hash_mult, hash_size;
  //array of pointers to Element
  Element **hash_table;
};

hash.cc

#include "hash.h"

// Konstruktor mit zwei Argumenten
Element::Element(char *new_key, char *new_value)
{
  // +1 für das terminierende '\0' !!
  key = new char [strlen(new_key)+1];
  value = new char [strlen(new_value)+1];
  
  strcpy(key, new_key);
  strcpy(value, new_value);
  next = NULL;
}

// Destruktor für obigen Konstruktor
Element::~Element()
{
  delete key;
  delete value;
}

// Konstruktor mit zwei Argumenten
Table::Table(unsigned int s, unsigned int m)
{
  hash_size = s;
  hash_mult = m;
  hash_table = new Element* [hash_size];
  for(unsigned int i=0; i<hash_size; i++)
    hash_table[i] = NULL;
}

// Destruktor für obigen Konstruktor
Table::~Table()
{
  // lösche zuerst die linked lists
  for(unsigned int i=0; i<hash_size; i++)
    if (hash_table[i] != NULL) delete [] hash_table[i];  
  // lösche die Hash-Tabelle
  delete [] hash_table;
}

unsigned int Table::Hash(char *p)
{
  unsigned long hash_val = 0;
  
  for(; *p; p++)
    hash_val = hash_val * hash_mult + *p;
  hash_val %= hash_size;
  return hash_val;
}

void Table::Put(char *new_key, char *new_value)
{
  unsigned int hash_val = Hash(new_key);
  Element *p, *e = hash_table[hash_val];
  if (e == NULL)
  {
    // new list
    hash_table[hash_val] = \
      new Element(new_key, new_value);
  }
  else
  {
    while(e != NULL)
    {
      if (!strcmp(new_key, e->key))
      {
        // key found, replace value
        delete e->value;
        e->value = new char [strlen(new_value)+1];
        strcpy(e->value, new_value);
        return;
      }
      else
      {
        p = e;
        e = e->next;
      }
    }
    // new element at the end of list
    p->next = new Element(new_key, new_value);
  }
}

char *Table::Get(char *existing_key)
{
  int hash_val = Hash(existing_key);
  Element *e = hash_table[hash_val];

  while(e != NULL)
  {
    if (!strcmp(existing_key, e->key))
      return(e->value); 
    else
      e = e->next;
  }

  return NULL;
}

void Table::Delete(char *existing_key)
{
  int hash_val = Hash(existing_key);
  Element *e = hash_table[hash_val];
  Element *p=NULL;

  while(e != NULL)
  {
    if (!strcmp(existing_key, e->key))
    {
      if (p == NULL)
      {
        // first element
        if (e->next == NULL)
        {
          // list contains only one element
          hash_table[hash_val] = NULL;
        }
        else
        {
          // second element ist now first
          hash_table[hash_val] = e->next;
        }
      }
      else
      {
        // other elements (not first)
        if (e->next == NULL)
        {
          // last element
          p->next = NULL;
        }
        else
        {
          // element in the middle of list
          p->next = e->next;
        }
      }
      delete e;
      return;
    }
    p = e;
    e = e->next;
  }
  cout << "Element not found!" << endl;
}

void Table::Print()
{
  Element *e;
  unsigned int j;

  for (unsigned int i = 0; i < hash_size; i++)
  {
    cout << i << ":";
    e = hash_table[i];
    j = 0;
    while(1)
    {
      cout << " listelem " << j;
      if (e == NULL)
      {
        cout << ": NULL ";
        break;
      }
      else
      {
        cout << ": key: " << e->key \
             << " value: " << e->value;
        j++;
        e = e->next;
      }
        
    }
    cout << endl;
  }
}

void NoSpace()
{
  cerr << "New Failed" << endl;
  exit(1);
}

post.cc

#include <iostream.h>
#include "hash.h"
extern "C"
{
  #include <stdlib.h>
}

void parse(char *buf, Table *hash)
{
  char *t1 = new char [strlen(buf)+1];
  char *t2 = new char [strlen(buf)+1];
  int flag, i, j;
  
  flag = i = j = 0;
  *t1 = '\0'; *t2 = '\0';

  while(*buf != '\0')
  {
    switch(*buf)
    {
    case '=':
      flag = 1;
      break;
    case '&':
    case '\n':
      t1[i] = '\0'; t2[j] = '\0';
      hash->Put(t1, t2);
      flag = i = j = 0;
      *t1 = '\0'; *t2 = '\0';
      break;
    default:
      if (flag)
        t2[j++] = *buf;
      else 
        t1[i++] = *buf;
      break;
    }
    buf++;
  }
  if (t1)
  {
    t1[i] = '\0'; t2[j] = '\0';
    hash->Put(t1,t2);
  }
  delete t1;
  delete t2;
}

main(int argc, char *argv[])
{
  char *uv = "USERNAME", *av = "AGE";
  char *var="CONTENT_LENGTH";
  char *content_length = getenv(var);
  char *title="My first CGI-Program";
  char *user="Gottfried Rudorfer";
  char *header="Content-type: text/html\n\n<HTML>\n";
  char *footer="</HTML>\n";
  char *buf = NULL;
  Table hash(10, 65559);

  if (content_length)
  {
    int l = atoi(content_length);
    buf = new char [l+2];
    cin.read(buf, l+1);
    parse(buf, &hash);
  }

  cout << header
       << "<!! (c) 1997 " << user << " >\n"
       << "<!! " << argv[0] << " - initial version 0.1 alpha >\n"
       << "<TITLE>" << title << "</TITLE>\n"
       << "<BODY>\n"
       << "<H2>" << title << "</H2>\n"
       << "<HR>\n"
       << var << " is: " << content_length  << "<p>\n";
  if (content_length)
  {
    cout << "String is: " << buf << "<p>\n"
         << uv << "=" << hash.Get(uv) << "<p>\n"
         << av << "=" << hash.Get(av) << endl;
  }

  cout << "<HR>\n"
       << "<FORM METHOD=\"POST\" "
       << "ACTION=\"http://miss.wu-wien.ac.at/USERCGI/post-rudorfer\">\n"
       << "<CENTER>\n"
       << "<H3>Bitte geben Sie Ihren Namen ein:</H3>\n"
       << "<P>     Enter Username: <INPUT NAME=" << uv 
       << " TYPE=\"text\" SIZE=20>\n"
       << "<H3>Bitte geben Sie Ihr Alter ein:</H3>\n"
       << "<P>     Enter Age: <INPUT NAME=" << av <<" TYPE=\"text\" SIZE=2>\n"
       << "<P><INPUT TYPE=\"submit\" VALUE=\"Connect\">\n"
       << "<INPUT TYPE=\"reset\" VALUE=\"Clear\">\n"
       << "</CENTER>\n"
       << "</FORM>\n" 
       << "<HR>\n"
       << "<h6>\n"
       << "Copyright &#169; 1997 by " << user << "\n"
       << "</h6></BODY>\n"
       << footer << endl;

  if (buf)
    delete buf;
}


next up previous
Next: Greed-Game (ASCII-Version) Up: Folien zur AG Objektorientiertes Previous: Beispiel (forts.)

© 1997 Gottfried Rudorfer, C++-AG, Lehrveranstaltungen, Abteilung für Angewandte Informatik, Wirtschaftsuniversität Wien, 3/19/1998