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 |