Dr. M. Grabert Abteilung Angewandte Informationsverarbeitung 6. Dezember 2001
Johannes Mayer Blatt 5


Uni-Logo



Objektorientierte Programmierung mit C++ (WS 2001/2002)


Abgabetermin: 6. Dezember 2001


Beispiellösung

6 E-Mails auf indisch (10+10 Punkte)

Shrandra Pradesh, der Inder in ihrem Team bei der aufstrebenden Softwareschmiede BadPointer.Com, mußte leider wegen eines Krankheitsfalls seines Lieblingselefanten auf Firmenkosten für 14 Tage zurück in sein Heimatland reisen. ,,Sie springen für Shrandra wegen der Fertigstellung von Emilia ein`, sagte ihr Chef kurz in der morgendlichen Besprechung. ,,Das Programm muß Donnerstag nächste Woche an die Leute von SaiTutoren.com ausgeliefert werden! Unser Ruf steht auf dem Spiel.`` (Schon wieder!). Sie wissen, was das heißt: Einarbeiten in den kaum dokumentierten Code von Shrandra, dessen spärlichen Kommentare meist auf Hindu sind ... nur ein paar englische und deutsche Erklärungen über das Projekt ,,Emilia`` hat er in den C++ Code eingestreut ... das kann ja Eiter werden. Egal - nix wie ran!

Sie finden alle von Shrandra bisher erstellten Programme auf dem Web. Worum geht es bei dem Projekt? Emilia ist ein E-Mailreader, der Spams (unerwünschte Werbemails) filtern soll. Shrandra hat schon ganz gut vorgearbeitet. Der Aufruf ist: emilia verzeichnis. Dadurch werden alle Header von E-Maildateien auf dem angegeben Verzeichnis in den Reader geladen. Die Annahme ist, das genau eine Mail in einer Datei abgespeichert ist. Ein Objekt der Klasse email hält eine einzelne Mail und in einem Objekt der Klasse mailbox finden sich alle Mails eines Verzeichnisses wieder. Ihr Chef gibt ihnen ziemlich freie Hand beim OO-Design (oder sinnvollen Änderungen des bestehenden) - nur will er, dass bis nächste Woche die folgende Funktionalität in das Programm integriert wird:



Lösung:

\fbox{\textbf{makefile}}
\begin{verbatimtab}[8]
CC=g++
obj=main.o email.o mailbox.o date.o
\par emilia: $...
....o: email.h date.h
mailbox.o: email.h mailbox.h
date.o: date.h
\end{verbatimtab}
\fbox{\textbf{main.cc}}
\begin{verbatimtab}[8]
// (c) Shrandra Pradesh sai uni ulm 2001
...
\fbox{\textbf{email.cc}} [8] // (c) Shrandra Pradesh sai uni ulm 2001 // die E-Mailklasse #include <vector> #include <string> #include <fstream> #include <strings.h> #include ëmail.hbegintex2html_deferred

email::email() validemail = false;

// Einlesen des E-Mail-Headers aus einer Datei email::email(const char *file) ifstream in(file); // Eingabestrom oeffnen

validemail = false; if (!in) cout « can't open «<file«endl; return; filename = file; // Dateinamen merken for (int i=0; i<numkeys; i++) switch (i) case 0: keywords[i].key = "From: "; keywords[i].var = &from; break; case 1: keywords[i].key = "Return-Path: "; keywords[i].var = &replyto; break; case 2: keywords[i].key = SSubject: "; keywords[i].var = &subject; break; case 3: keywords[i].key = "To: "; keywords[i].var = &receiver; break; case 4: keywords[i].key = "Date: "; keywords[i].var = &date; break; default: ; bool isheader = true;

while (!in.eof() && isheader) string line;

getline(in, line); // komplette Zeile einlesen if (isheader && line.size()==0) isheader = false; // 1.Leerzeile? Header-Ende! if (!from.empty() && !subject.empty()) validemail = true; // echte E-Mail else if (isheader) // Suche nach Schluesselworten // eine Headerzeile abspeichern header.resize(header.size()+1, line); // Suche nach Keywors am Zeilenanfang for (int i=0; i<numkeys; i++) char * hlp = keywords[i].key; if (line.find(hlp, 0)==0) *keywords[i].var = line.substr(strlen(hlp));

if (date.size() > 0) int pos = date.find(","); if (pos != string::npos) date = date.substr(pos+1); try d_date = Date(date.c_str()); catch (const char *s) cerr « Ëxception: «< s « endl; exit(1);

in.close();

bool isAllUpper(string line) char *upper = new char[line.size()+1]; strcpy(upper, line.c_str()); char *s = upper; while (*s != 0) if (*s >= 'a' && *s <= 'z') *s = *s - 'a' + 'A'; s++; int blocks = 0; s = upper; while (*s != 0) if (*s >= 'A' && *s <= 'Z' && (blocks == 0 || blocks == 2)) blocks++; if (!(*s >= 'A' && *s <= 'Z') && blocks == 1) blocks++; s++; string lineUpper(upper); delete[] upper;

// alles ist GROSS geschrieben UND es gibt mindestens 2 Worte if (line == lineUpper && blocks >= 3) return true;

return false;

bool containsKey(string line) char *upper = new char[line.size()+1]; strcpy(upper, line.c_str()); char *s = upper; while (*s != 0) if (*s >= 'a' && *s <= 'z') *s = *s - 'a' + 'A'; s++; string lineUpper(upper); delete[] upper;

// ... oder es kommt eines der folgenden Schluesselworte // (in bel. Schreibweise - d.h. GROSS oder klein) vor if (lineUpper.find(SSEX") != string::npos) return true; if (lineUpper.find(begindisplaymath") != string::npos) return true; if (lineUpper.find("MONEY") != string::npos) return true; if (lineUpper.find(ÖFFER") != string::npos) return true;

return false;

extern bool opt_b;

bool email::isspam() if (isAllUpper(subject) || containsKey(subject)) return true;

bool spam = false;

if (opt_b) bool bodyRead = body.size() > 0;

getmail();

for (int i = 0; i < body.size(); i++) if (containsKey(body[i])) spam = true; break;

if (!bodyRead) body.resize(0);

return spam;

// Einlesen des eigentlichen E-Mailtextes einer E-Mail

void email::getmail() if (!validemail || body.size()>0) return; ifstream in(filename.c_str()); // Eingabestrom oeffnen

if (!in) cout « can't open «<filename.c_str()«endl; return; bool isheader = true; while (!in.eof()) string line; getline(in, line); // komplette Zeile einlesen if (isheader) if (line.size()==0) // Ende des Headers isheader = false; continue; body.resize(body.size()+1, line); // Zeile speichern

void email::printbody(ostream& out) const if (!body.size()) return ;

for (int i=0; i< body.size(); i++) out « body[i]«endl; if (!((i+1)string dum; getline(cin, dum); system(clear");

void email::printaddress(ostream& out) const for (int i=0; i<numkeys; i++) cout « keywords[i].key «*(keywords[i].var)«endl;

void email::printheader(ostream& out) const if (!header.size()) return ;

for (int i=0; i< header.size(); i++) out « header[i]«endl; if (!((i+1)string dum; getline(cin, dum); system(clear");

string email::getemil() string sender = getfrom(); int pos1 = sender.find(«"); int pos2 = sender.find(»"); if (pos1!=string::npos && pos2!=string::npos) sender = sender.substr(pos1+1, pos2-pos1-1); return sender;

// Ausgabe der kompletten E-Mail ostream& operator«(ostream& out, const email &e) if (!e.header.size()) return out;

e.printheader(out); out«endl; // Leerzeile e.printbody(out); return out;

\fbox{\textbf{email.h}}
\begin{verbatimtab}[8]
// die E-Mailklasse
...
\fbox{\textbf{mailbox.cc}}

\fbox{\textbf{mailbox.h}}
\begin{verbatimtab}[8]
...
\fbox{\textbf{date.h}}
\begin{verbatimtab}[8]
...

\begin{verbatimtab}[8]
...



Johannes Mayer, 2001-12-06