Ein String im String suchen.

Algorithmen, Sprachunabhängige Diskussionen zu Konzepten, Programmiersprachen-Design
Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Ein String im String suchen.

Beitrag von Xin » Mi Jul 06, 2011 11:37 pm

Der Algorithmus muss in einer Klasse liegen, die mit dem Standardkonstruktor initialisiert wird.

Ich lege fest, dass dem Algorithmus zunächst die zu durchsuchenden Texte übergeben werden. Die Texte müssen nicht kopiert werden, sie bleiben im Speicher verfügbar bis die Klasseninstanz abgebaut wird.
Pro Text wird die Funktion einmal gerufen.

Code: Alles auswählen

void addText( char const * id, char const * text );
Anschließend werden die Suchwörter übergeben. Pro Suchwort wird die Funktion einmal gerufen.

Code: Alles auswählen

void addPattern( char const * pattern );
Zuletzt wird gesucht:

Code: Alles auswählen

int seek( char const * filename );
seek gibt die Anzahl der gefundenen Texte zurück.
Werden die Suchworte alle mindestens im Text einmal gefunden, wird die Id des Textes in die Datei geschrieben.

Beispiel:

Code: Alles auswählen

Text1
Text4
Die Funktion clearPatterns() setzt die Suchbegriffe zurück, so dass ich mit addPattern() neue Suchbegriffe eingeben kann.

Der Algorithmus muss entsprechend dieses Interface implementieren:

Code: Alles auswählen

class SearchBase
{
  public:
     virtual void addText( char const * id, char const * text ) = 0;
     virtual void addPattern( char const * pattern ) = 0;
     virtual void clearPatterns( void ) = 0;
     virtual int seek( char const * filename ) = 0;

     virtual ~SearchBase() = 0;
};
Die Zeitmessung beginnt nachdem der Konstruktor gelaufen ist und endet bevor der Destruktor läuft.

Code: Alles auswählen

class SearchXin : public SearchBase
{
  public:
     void addText( char const * id, char const * text );
     { /* Implementierung */ }
     void addPattern( char const * pattern );
     { /* Implementierung */ }
     void clearPatterns( void );
     { /* Implementierung */ }
     int seek( char const * filename )
     { /* Implementierung */ }

     SearchXin()
     { /* Implementierung */ }
     ~SearchBase()
     { /* Implementierung */ }
};

void main()
{
  // Texte werden geladen
  SearchXin search;

  //Zeitmessung startet
   search.addText( "text 1", text1 );
   search.addText( "text 2", text2 );
   search.addText( "text 3", text3 );
   search.addText( "text 4", text4 );
   search.addText( "text 5", text5 );

   search.addPattern( "Hallo" );
   search.addPattern( "Welt" );
   search.seek( "xin/test1.txt" );
   search.clearPatterns();
   search.addPattern( "Hello" );
   search.addPattern( "World" );
   search.seek( "xin/test2.txt" );

   // Zeitmessung endet

   //Destruktor läuft
}
Es werden maximal 10 Suchwörter pro Suche übergeben. Um einen Text als gefunden zu deklarieren müssen alle Suchwörter jeweils mindestens einmal enthalten sein.

Ich benutze keine Vectoren (std::vector) o.ä. weil ich nicht auch noch Templates abverlangen will. Die Aufgabe ist so oder schon deutlich aufwendiger als die Wortzähl-Geschichte. Ich denke, wer std::vector verwenden möchte, kann sich das als Member in seiner Klasse halten. Mit dieser vergleichsweise billigen API können auch Leute das Problem umsetzen, die sich keine Templates ansehen wollen.

In der eigenen Klasse sind beliebige Variablen erlaubt, was immer ihr wollt.

Wenn noch Fragen sind oder Hilfe braucht, kann die Fragen hier stellen.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
fat-lobyte
Beiträge: 1398
Registriert: Sa Jul 05, 2008 12:23 pm
Wohnort: ::1
Kontaktdaten:

Re: Ein String im String suchen.

Beitrag von fat-lobyte » Do Jul 07, 2011 8:33 pm

Darf man fragen wie groß die Texte ungefähr sein werden?
Wird das Programm nur einmal aufgerufen, oder wirst du es mehrmals hintereinander aufrufen?
Welche Compilerversion hast du, und auf welcher CPU wirst du die tests laufen lassen?
Ich nehme an multithreading ist nicht erlaubt?

Nachtrag: wann ist denn die Deadline für diesen Spaß?
Haters gonna hate, potatoes gonna potate.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Ein String im String suchen.

Beitrag von Xin » Do Jul 07, 2011 9:02 pm

fat-lobyte hat geschrieben:Darf man fragen wie groß die Texte ungefähr sein werden?
Zwischen 1kb und 100mb.
fat-lobyte hat geschrieben:Wird das Programm nur einmal aufgerufen, oder wirst du es mehrmals hintereinander aufrufen?
Um eine sinnvollen Test zu fahren, muss ich häufiger suchen.
Den Ablauf habe ich ja zuvor beschrieben: Bekanntgabe aller Texte, Bekanntgabe der Suchworte, Suche, - Löschen der Suchworte (nicht der Texte!), Neue Suchworte, Suche - Löschen der Suchworte (nicht der Texte!), Neue Suchworte, Suche....
fat-lobyte hat geschrieben:Welche Compilerversion hast du, und auf welcher CPU wirst du die tests laufen lassen?
Compiler:

Code: Alles auswählen

xin@trinity:/data/home/xin/workspace/gcc/gcc/libjava/gnu/javax/naming/jndi/url/.svn/props$ gcc --version
gcc (Debian 4.4.5-8) 4.4.5
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Prozessor:

Code: Alles auswählen

xin@trinity:/data/home/xin/workspace/gcc/gcc/libjava/gnu/javax/naming/jndi/url/.svn/props$ cat /proc/cpuinfo 
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 30
model name      : Intel(R) Core(TM) i7 CPU         860  @ 2.80GHz
stepping        : 5
cpu MHz         : 2808.593
cache size      : 8192 KB
physical id     : 0
siblings        : 8
core id         : 0
cpu cores       : 4
apicid          : 0
initial apicid  : 0
fpu             : yes
fpu_exception   : yes
cpuid level     : 11
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good xtopology nonstop_tsc aperfmperf pni dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm sse4_1 sse4_2 popcnt lahf_lm ida tpr_shadow vnmi flexpriority ept vpid
bogomips        : 5617.18
clflush size    : 64
cache_alignment : 64
address sizes   : 36 bits physical, 48 bits virtual
power management:

Obenstehendes wiederholt sich für "processor 1" bis "processor 7".
Die Kiste hat 8GB RAM. Dein Programm sollte nicht mehr als 4GB verbraten. Irgendwo müssen ja auch die Texte hin. :-)
Ich werde die Programme mit mindestens 500MB und maximal 1GB zu durchsuchender Texte zuballern.
fat-lobyte hat geschrieben:Ich nehme an multithreading ist nicht erlaubt?
Solange ich eine C++-Klasse bekomme, die von der oben genannten abgeleitet ist und entsprechend von mir getestet werden kann, kannst Du tun, was immer Du willst.
Wenn Du irgendwas benutzt, was mit g++ nicht direkt kompilierbar ist, wäre ein Makefile nett und vielleicht eine Regel, die erforderliche Debian/Ubuntu-Pakete installiert.


Ich fang dann auch mal an :-)
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
fat-lobyte
Beiträge: 1398
Registriert: Sa Jul 05, 2008 12:23 pm
Wohnort: ::1
Kontaktdaten:

Re: Ein String im String suchen.

Beitrag von fat-lobyte » Do Jul 07, 2011 9:14 pm

Super, danke für die Klärung. Nur eine kleine Frage:

Code: Alles auswählen

void addText( char const * id, char const * text );
Wofür ist char const* id?
Haters gonna hate, potatoes gonna potate.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Ein String im String suchen.

Beitrag von Xin » Do Jul 07, 2011 9:35 pm

fat-lobyte hat geschrieben:Super, danke für die Klärung. Nur eine kleine Frage:

Code: Alles auswählen

void addText( char const * id, char const * text );
Wofür ist char const* id?
Die schreibst Du in das Ausgabefile, wenn Du in dem Text mit der ID das Suchwort gefunden hast.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
fat-lobyte
Beiträge: 1398
Registriert: Sa Jul 05, 2008 12:23 pm
Wohnort: ::1
Kontaktdaten:

Re: Ein String im String suchen.

Beitrag von fat-lobyte » Fr Jul 08, 2011 3:56 pm

Xin hat geschrieben:
fat-lobyte hat geschrieben:Super, danke für die Klärung. Nur eine kleine Frage:

Code: Alles auswählen

void addText( char const * id, char const * text );
Wofür ist char const* id?
Die schreibst Du in das Ausgabefile, wenn Du in dem Text mit der ID das Suchwort gefunden hast.
:roll: Sorry, Fuß->Leitung
Haters gonna hate, potatoes gonna potate.

Benutzeravatar
fat-lobyte
Beiträge: 1398
Registriert: Sa Jul 05, 2008 12:23 pm
Wohnort: ::1
Kontaktdaten:

Re: Ein String im String suchen.

Beitrag von fat-lobyte » Fr Jul 08, 2011 7:52 pm

So, hab jetzt ne kleine Referenzimplementierung, läuft allerdings nur auf Linux.

Features: Datei Laden, Zeit messen, Suchen.

Das Suchen funktioniert mit der Bibliotheksfunktion strstr() die es anscheinend zu schlagen gilt.

DIES IST NOCH NICHT MEIN FERTIGER ALGORITHMUS!! Ich wollte hier allen Unix benutzern nur mal ein kleines Framework zum coden bereitstellen. Viel spaß damit:
proggen_searchwords.zip
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Haters gonna hate, potatoes gonna potate.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Ein String im String suchen.

Beitrag von Xin » Sa Jul 09, 2011 4:01 pm

Ich habe mal einige Bücher und Kurzgeschichten als Beispieltexte heruntergeladen. Die Texte sind hier als ZIP-Archiv verfügbar. Mit diesen Texten teste ich. Es kann durchaus sein (und ist sehr wahrscheinlich), dass ich noch weitere Texte hinzu nehme. Die folgenden Texte werfe ich mal ins Rennen, um zu untersuchen, um eventuell Vergleichszahlen zu haben.

Um unterschiedliche Suchen zu fahren, gibt es auch zwei englische Texte.

Code: Alles auswählen

xin@trinity:/data/home/xin/workspace/gsys/trunk/apps/search$ ls -lah txt/
insgesamt 4,9M
drwxr-xr-x 2 xin xin 4,0K  9. Jul 13:53 .
drwxr-xr-x 4 xin xin 4,0K  9. Jul 16:30 ..
-rw-r--r-- 1 xin xin 138K  9. Jul 13:37 en-armsandtheman-helden.txt
-rw-r--r-- 1 xin xin 114K  9. Jul 13:34 en-macbeth.txt
-rw-r--r-- 1 xin xin 121K  9. Jul 13:12 ger-dieverwandlung.txt
-rw-r--r-- 1 xin xin 199K  9. Jul 13:28 ger-faust.txt
-rw-r--r-- 1 xin xin 312K  9. Jul 13:42 ger-flametti.txt
-rw-r--r-- 1 xin xin 157K  9. Jul 13:31 ger-helden.txt
-rw-r--r-- 1 xin xin  99K  9. Jul 13:27 ger-iphigenie.txt
-rw-r--r-- 1 xin xin 1,3M  9. Jul 13:51 ger-kritikvernunft.txt
-rw-r--r-- 1 xin xin 2,0M  9. Jul 13:46 ger-logik.txt
-rw-r--r-- 1 xin xin 123K  9. Jul 13:30 ger-macbeth.txt
-rw-r--r-- 1 xin xin 4,2K  9. Jul 13:50 ger-mord.txt
-rw-r--r-- 1 xin xin 5,5K  9. Jul 13:53 ger-tanteMarthastraenenreicherAbschied.txt
-rw-r--r-- 1 xin xin 238K  9. Jul 13:26 ger-werther.txt
-rw-r--r-- 1 xin xin  75K  9. Jul 13:48 ger-wintermaerchen.txt
-rw-r--r-- 1 xin xin 4,5K  9. Jul 13:53 ger-wurmlochrosa.txt
Weiterhin werde ich den Ablauf der Tests etwas erweitern, so dass ich nachdem die Texte bekannt gegeben sind eine zusätzliche Zwischenzeit nehmen werde.

Code: Alles auswählen

void main()
{
  // Texte werden geladen
  SearchXin search;

  //Zeitmessung startet
   search.addText( "text 1", text1 );
   search.addText( "text 2", text2 );
   search.addText( "text 3", text3 );
   search.addText( "text 4", text4 );
   search.addText( "text 5", text5 );

  // --- ZUSÄTZLICHE ZWISCHENZEIT

   search.addPattern( "Hallo" );
   search.addPattern( "Welt" );
   search.seek( "xin/test1.txt" );
   search.clearPatterns();
   search.addPattern( "Hello" );
   search.addPattern( "World" );
   search.seek( "xin/test2.txt" );

   // Zeitmessung endet

   //Destruktor läuft
}
Die Analyse der Texte kann sehr aufwendig sein, um die Suche zu beschleunigen - und darum geht es ja. Eine Textanalyse kann das Ergebnis bei wenigen Suchvorgängen massiv verfälschen, so dass der Sieger davon abhängt, ob ich 10 Suchanfragen oder 10000 mache, die Ergebnisse sind so also nicht vergleichbar. Mit der Zwischenzeit können wir die eigentliche Suche vergleichen und einen Quotienten finden (Aufwand pro Suche) und so Vergleiche bei wenigen oder vielen Suchen machen.

Ich kann jedenfalls jetzt schon sagen, dass die Analyse Spaß macht. Kompiliere ich nämlich auf Geschwindigkeit optimiert, so ist die Analyse zwar deutlich schneller, dafür kommt sie aber auch zu ganz anderen Ergebnissen.... 8-/
(PS: Bug gefunden... wie üblich lag es nicht am Compiler... *grummel*)
(PPS: Wenn ihr euch eine Standard-Klasse zum Allozieren von Speicher anlegt, definiert auch einen Destruktor *kopf->tisch*)
(PPPS: Der fehlende Destruktor war die eine Seite... ich verbrauche trotzdem RAM wie blöd... im wahrsten Sinne des Wortes... Erkennt jemand das Problem? ^^)

Code: Alles auswählen

        array = reinterpret_cast< type * >( new char[ 1 << _arrayBitWidth * sizeof( type ) ] );
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
Kerli
Beiträge: 1456
Registriert: So Jul 06, 2008 10:17 am
Wohnort: Österreich
Kontaktdaten:

Re: Ein String im String suchen.

Beitrag von Kerli » Sa Jul 09, 2011 11:24 pm

Xin hat geschrieben:Weiterhin werde ich den Ablauf der Tests etwas erweitern, so dass ich nachdem die Texte bekannt gegeben sind eine zusätzliche Zwischenzeit nehmen werde.
Die Frage ist nur wie aussagekräftig das mit Verwendung von Threads ist. Am Besten wäre es wohl Threads zu verbieten. Da kommt es dann mehr auf die Algorithmen und nicht die Threadsicherheit an :P Ist eigentlich auch die Verwendung von C++0x erlaubt (Auch wenn dein Compiler etwas alt ist^^).
Xin hat geschrieben:(PPPS: Der fehlende Destruktor war die eine Seite... ich verbrauche trotzdem RAM wie blöd... im wahrsten Sinne des Wortes... Erkennt jemand das Problem? ^^)
Ich kenne nicht deine genauen Werte aber ich vermute einmal dass '1 << _arrayBitWidth * sizeof( type )' wohl etwas zu groß sein wird. Könnte an falscher Vermutung über Operatorenrangfolge liegen ;)
"Make it idiot-proof and someone will invent an even better idiot." (programmers wisdom)

OpenGL Tutorials und vieles mehr rund ums Programmieren: http://www.tomprogs.at

canlot
Beiträge: 393
Registriert: Di Mär 08, 2011 11:01 pm
Wohnort: NRW

Re: Ein String im String suchen.

Beitrag von canlot » Di Jul 12, 2011 11:24 am

Ich habe hier eine einfache Implementierung des Algorithmus.

Code: Alles auswählen

#include <stdio.h>
#include <stdlib.h>

int how_many_words(char *to_search, char *search)
{
    int temp = 0;
    int counter_string = 0;
    int *pointeradress = 0;
    while(*to_search != '\0')
    {
        if(*to_search == *search)
        {
            if(comparable(to_search, search, &pointeradress)== 0)
            {
                temp++;
                to_search = pointeradress;
            }
        }
        to_search++;
    }
    return temp;
}

int comparable(char *basic_string, char *search_string, int * pointeradress)
{
    while(*basic_string == *search_string && *basic_string != '\0')
    {
        basic_string++;
        search_string++;
    }
    *pointeradress = basic_string -1;
    if(*(basic_string-1) == *(search_string-1) && *search_string == '\0')
    return 0;
    else
    return 1;
}

int main(void)
{
    char * big = "Wer ein NAS als zentralen Datenspeicher einsetzt, der muss die Daten regelmäßig auf eine externe Festplatte sichern. Externe 2,5-Zoll-USB-Festplatten mit hoher Speicherkapazität sind bereits für unter 100 Euro zu bekommen. Das ist eine kleine Investition für mehr Datensicherheit.An manchen NAS-RAID-Systemen kann man auch per USB eine externe Festplatte anschließen und als Backup-Laufwerk konfigurieren. Dann spart man sich das manuelle Backup.";
    char * lol ="lolololololol lol lollol";
    char * small = "lol";
    int words = 0;

    words = how_many_words(lol, small);
    printf("Es sind  %i Woerter vorhandeln",words);
}
Tut mir Leid für die schlechte Variablenbenamsung :(
Unwissenheit ist ein Segen

Antworten