Benutzer:Stefan Knauf/Dateidurchsuchungsprogramm.cpp

aus Wikipedia, der freien Enzyklopädie
Zur Navigation springen Zur Suche springen


C++-Programm, das eine Datei nach dem in der main-Prozedur angegebenen Suchwort durchsucht. Soll eine Datei gleich nach mehreren Suchwörtern durchsucht werden, ist das Dateiumfassenderdurchsuchungsprogramm.cpp wesentlich praktischer, weil es für alle Suchwörter zusammen die Datei nur einmal von der Festplatte lesen muss.

Dieses Programm hier sucht nach dem exakten Suchwort und achtet natürlich auch auf Groß- und Kleinschreibung. Zumindest auf meinem Rechner arbeitet es wesentlich schneller als der sonst wunderbare LTF-Viewer (wesentlich bei Dateien, die mehrere Gigabyte groß sind, z.B. Wikipedia-Dumps – für einen 9,3 GiB großen Dump benötigt mein Programm auf meinem Rechner etwa 13 Minuten und die Volltextsuche des LTF-Viewers mehrere Stunden). Das Programm gibt eine Liste der Positionen am Bildschirm aus, an denen das Suchwort im Dokument vorkommt. Diese Stellen lassen sich dann einfach in einem geeigneten Texteditor, z.B. dem LTF-Viewer, nachschlagen.

Das Programm interpretiert jedes Byte als ein Zeichen, deswegen müssen beim Durchsuchen von in UTF-8 kodierten Dokumenten (z.B. Wikipedia-Dumps) in den Suchwörtern alle Nicht-ASCII-Zeichen durch kryptische Zeichenfolgen ersetzt werden. Ich weiß aber nicht, ob die kryptischen Zeichenfolgen vielleicht vom Betriebssystem abhängen. Zumindest wenn ich mein Programm mit Dev-C++ 4.9.9.2 (GNU-Compiler) kompiliere und unter Windows 7 laufen lasse, funktioniert es mit folgenden Umschriften:

Nicht-ASCII-Zeichen Umschrift
ä ä
á á
à à
å Ã¥
â â
ã ã
ā ā
ç ç
đ Ä‘
é é
Nicht-ASCII-Zeichen Umschrift
è è
ë ë
ě Ä›
ę Ä™
ğ ÄŸ
ḥ
í í
ī Ä«
ı ı
î î
Nicht-ASCII-Zeichen Umschrift
ï ï
ł Å‚
ö ö
ő Å‘
ó ó
ò ò
ô ô
ø ø
ř Å™
š Å¡
Nicht-ASCII-Zeichen Umschrift
ş ÅŸ
á¹­
ü ü
ú ú
ū Å«
Ä Ã„
Å Ã…
à Ã
Á Á
Ç Ã‡
Nicht-ASCII-Zeichen Umschrift
É Ã‰
Ḥ
İ Ä°
Ł Ł
Ö Ã–
Ó Ã“
Ş Åž
Ș Ș
Ü Ãœ
Ž Ž
Nicht-ASCII-Zeichen Umschrift
ß ÃŸ
„
“

Diverse ASCII-Zeichen, die spezielle Bedeutungen in der Auszeichnungssprache HTML haben, sind in Wikipedia-Dumps ebenfalls umschrieben, wenn sie im Wiki-Quelltext eines Artikels auftauchen.

Reserviertes Zeichen Umschrift
" "
< &lt;
> &gt;
& &amp;



//C++

// 30.7.2013


using namespace std;

#include<iostream> //enthält die Befehle zum Schreiben auf den Bildschirm
#include<fstream> //enthält die Befehle zum Schreiben in und zum Lesen aus Dateien
#include<string> //enthält den Kram zu Strings, also zu Zeichenketten
#include<vector> //für die praktische Vektor-Klasse vector<irgendein Typ>

void schreibeintVector (vector<int> x) //wurde nur zum Testen benötigt
 {for (int i=0; i<x.size(); i++)
   {cout << "Stelle " << i << ": " << x[i] << endl;
   }
 }

string schreibeZiffer(const long long int & z) //wandelt eine ganze Zahl von 0 bis 9 in einen String, der genau diese Zahl enthält
 {string Ziffer;
  switch (z)
   {case 1 : Ziffer = "1"; break;
    case 2 : Ziffer = "2"; break;
    case 3 : Ziffer = "3"; break;
    case 4 : Ziffer = "4"; break;
    case 5 : Ziffer = "5"; break;
    case 6 : Ziffer = "6"; break;
    case 7 : Ziffer = "7"; break;
    case 8 : Ziffer = "8"; break;
    case 9 : Ziffer = "9"; break;
    case 0 : Ziffer = "0"; break;
    default : cerr << "Der Ziffernmacher stößt auf was Unziffriges!" << endl;
   }
  return Ziffer;
 }

string schreibeZahlmitPunkten (long long int z) //wandelt eine ganze Zahl in einen String mit Tausenderpunkten
 {string Zahl=""; //für die Ausgabe
  if (z==0)
   {Zahl="0";
   }
  else
   {if (z<0)
     {Zahl="-"+schreibeZahlmitPunkten(-1*z);
     }
    else
     {int j=0;
      while (z>0)
       {if (j==3)
         {Zahl = "."+Zahl;
          j=0;
         }
        Zahl = schreibeZiffer(z%10)+Zahl;
        z/=10;
        j++;
       }
     }
   }
  return Zahl;
 }

vector<string::size_type> durchsucheZeile (const string & Zeile, const string & Suchschluessel) //durchsucht die im ersten Argument gegebene Zeichenkette durch den Suchschlüssel im zweiten Argument und gibt die Positionen zurück, an denen der Suchschlüssel gefunden wurde; falls der Suchschlüssel leer ist, sucht die Funktion einfach nicht
 {vector<string::size_type> Trefferliste(0);
  if (Suchschluessel.size()>0)
   {for (string::size_type i=0; (i + Suchschluessel.size())<(Zeile.size() + 1); i++)
     {if (Zeile[i]==Suchschluessel[0])
       {bool passtnoch=true;
        string::size_type j=1;
        while ((j<Suchschluessel.size()) && passtnoch)
         {if (Zeile[i+j]!=Suchschluessel[j])
           {passtnoch=false;
           }
          j++;
         }
        if (passtnoch)
         {Trefferliste.push_back(i);
         }
       }
     }
   }
  return Trefferliste;
 }

void Dateiendurchsuchungsprozedur (const string & Dateiname, const string & Suchschluessel) //durchsucht eine Datei nach dem Suchschlüssel und gibt die Treffer am Bildschirm aus
 {long long int Zeilennummer=1; //um die Zeilennummer nachzuhalten
  bool gefunden=false;
  long long int Trefferzahl=0;
  ifstream Datei;
  Datei.open(Dateiname.c_str());
  if (!Datei.good())
   {cerr << "Beim Öffnen der Datei " << Dateiname << " ist ein Fehler aufgetreten!" << endl;
   }
  while (Datei.good())
   {string Zeile;
    getline(Datei, Zeile); //schreibt eine Zeile der Datei in die Variable Zeile
    vector<string::size_type> Zeilentrefferliste = durchsucheZeile(Zeile, Suchschluessel);
    if (Zeilentrefferliste.size()>0) //die Bedingung ist erfüllt, wenn der Suchschlüssel in der Zeile vorkam
     {gefunden=true;
      Trefferzahl+=Zeilentrefferliste.size();
      if (Zeilentrefferliste.size()>1) //die Bedingung ist erfüllt, wenn es mehr als einen Treffer in der Zeile gibt
       {cout << "In Zeile " << schreibeZahlmitPunkten(Zeilennummer) << " wurde das Suchwort \"" << Suchschluessel << "\" gefunden, und zwar an folgenden Positionen:\n";
        for (int i=0; i<Zeilentrefferliste.size(); i++)
         {cout << schreibeZahlmitPunkten(Zeilentrefferliste[i]+1) << '\n';
         }
       }
      else // hier gibt es genau einen Treffer in der Zeile
       {cout << "In Zeile " << schreibeZahlmitPunkten(Zeilennummer) << " wurde das Suchwort \"" << Suchschluessel << "\" nur an folgender Position gefunden:\n";
        cout << schreibeZahlmitPunkten(Zeilentrefferliste[0]+1) << '\n';
       }
      cout << endl;
     }
    Zeilennummer++;
   }
  Datei.close();
  if (gefunden==false)
   {cout << "Das Suchwort \"" << Suchschluessel << "\" wurde in der Datei " << Dateiname << " nicht gefunden." << endl;
   }
  else
   {if (Trefferzahl>1)
     {cout << "Das Suchwort \"" << Suchschluessel << "\" wurde in der Datei " << Dateiname << " an " << schreibeZahlmitPunkten(Trefferzahl) << " Stellen gefunden. Falls das Suchwort ein echtes Anfangsstück als Endstück hat, können sich die Treffer überschneiden, z.B. würde das Suchwort \"dd\" im Text \"ddd\" zweimal gefunden." << endl;
     }
    else //hier gab es in der Datei genau einen Suchtreffer
     {cout << "Das Suchwort \"" << Suchschluessel << "\" wurde in der Datei " << Dateiname << " an genau einer Stelle gefunden." << endl;
     }
   }
 }

int main()
 {Dateiendurchsuchungsprozedur("dewiki-latest-pages-articles.xml", "Wertzunahme");  //das erste Argument ist der Name der zu durchsuchenden Datei und das zweite das zu suchende Wort
  return 0;
 }