Next: Greed-Game (ASCII-Version)
Up: Folien zur AG Objektorientiertes
Previous: Beispiel (forts.)
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 © 1997 by " << user << "\n"
<< "</h6></BODY>\n"
<< footer << endl;
if (buf)
delete buf;
}
| © 1997 Gottfried Rudorfer, C++-AG, Lehrveranstaltungen, Abteilung für Angewandte Informatik, Wirtschaftsuniversität Wien, 3/19/1998 |