Benutzer:Stefan Knauf/Erstewoerterzaehlprogramm.cpp

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

C++-Programm, um aus einer Textdatei auszuzählen, welches Wort wie oft als erstes Wort einer Zeile vorkommt. Dem Programm müssen beim Aufruf aus der Kommandozeile zwei Parameter übergeben werden: Als ersten den Namen der Eingabedatei und als zweiten den Namen, den die Ausgabedatei erhalten soll. Ein korrekter Programmaufruf sieht beispielsweise so aus:

Erstewoerterzaehlprogramm Eingabe.txt Ausgabe.txt

Das Programm zählt nur die ersten Wörter jener Zeilen, die mindestens ein Leerzeichen enthalten. Zeilen ohne Leerzeichen werden als „komischer Sachverhalt“ protokolliert. Das Programm geht davon aus, dass die Eingabedatei in UTF-8 kodiert ist, und setzt an den Anfang der Ausgabedatei die drei Bytes „“, um anzuzeigen, dass auch die Ausgabedatei in UTF-8 kodiert ist.



//C++

// 25.9.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>
#include<time.h> //für time(NULL)
#include <algorithm> //für std::sort


struct Supername
 {string Name;
  long long int Anzahl;
 };

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<Supername> Namenermittlungsprozedur (const string & Dateiname) //zählt die ersten Vornamen aus einer Liste von Namen aus, die im Format [Vorname] [Nachname] angegeben sind
//geht davon aus, dass in jeder Zeile der Eingabedatei genau ein Name steht, der mindestens ein Leerzeichen enthält
//interpretiert das erste Wort jeder Zeile als Vornamen
 {long long int Zeilennummer=0; //um die Zeilennummer nachzuhalten
  long long int AnzahlkomischerSachverhalte=0;
  long long int AnzahlnormalerSachverhalte=0;
  vector<Supername> Supernamensliste(0); //für die Ausgabe
  ifstream Datei;
  Datei.open(Dateiname.c_str());
  if (!Datei.good())
   {Datei.close();
    cerr << "Beim Öffnen der Datei " << Dateiname << " ist ein Fehler aufgetreten!" << endl;
   }
  else
   {while (Datei.good())
     {string Zeile;
      Zeilennummer++;
      getline(Datei, Zeile); //schreibt eine Zeile der Datei in die Variable Zeile
      if (Zeilennummer==1) //zur Entfernung der UTF-8-Markierung ""
       {if (Zeile.size()>=3)
         {if ((Zeile[0]==static_cast<char>(-17))&&(Zeile[1]==static_cast<char>(-69))&&(Zeile[2]==static_cast<char>(-65))) //fragt ab, ob die ersten drei Bytes "" sind
           {Zeile=Zeile.substr(3,Zeile.size()-3);
           }
         }
       }
      string::size_type n = Zeile.find(" ");
      if (n!=string::npos)
       {AnzahlnormalerSachverhalte++;
        string Vorname;
        Vorname.resize(n);
        for (string::size_type i=0; i<Vorname.size(); i++)
         {Vorname[i]=Zeile[i];
         }
        bool schonenthalten=false;
        vector<Supername>::size_type i=0;
        while ((i<Supernamensliste.size())&&(!schonenthalten))
         {if (Supernamensliste[i].Name==Vorname)
           {Supernamensliste[i].Anzahl++;
            schonenthalten=true;
           }
          i++;
         }
        if (!schonenthalten)
         {Supername x={Vorname, 1};
          Supernamensliste.push_back(x);
         }
       }
      else
       {AnzahlkomischerSachverhalte++;
        cout << "In Zeile " << schreibeZahlmitPunkten(Zeilennummer) << " ist ein komischer Sachverhalt aufgetreten! (Die Zeile enthält kein Leerzeichen.)" << endl;
       }
     }
    Datei.close();
    cout << "Die Anzahl komischer Sachverhalte betrug " << schreibeZahlmitPunkten(AnzahlkomischerSachverhalte) << ".\n";
    cout << "Die Anzahl normal erkannter Vornamen betrug " << schreibeZahlmitPunkten(AnzahlnormalerSachverhalte) << ".\n";
   }
  return Supernamensliste;
 }

bool Supernamenvergleichsfunktion (Supername x, Supername y)
 {return (x.Anzahl>y.Anzahl);
 }

void Namenshandhabungsprozedur(const string & Eingabdateiname, const string & Ausgabedateiname)
{vector<Supername> Supernamensliste=Namenermittlungsprozedur(Eingabdateiname.c_str());
 sort (Supernamensliste.begin(), Supernamensliste.end(), Supernamenvergleichsfunktion);
 ofstream Datei;
 Datei.open(Ausgabedateiname.c_str());
 if (Datei.good())
  {Datei << static_cast<char>(-17) << static_cast<char>(-69) << static_cast<char>(-65); //um anzuzeigen, dass die Ausgabedatei in UTF-8 kodiert ist
   for (int i=0; i<Supernamensliste.size(); i++)
    {Datei << Supernamensliste[i].Name << '\t' << Supernamensliste[i].Anzahl << '\n';
    }
   cout << "Die Ausgabe befindet sich nun in der Datei " << Ausgabedateiname << "." << endl;
  }
 else
  {cerr << "Es ist ein Problem beim Öffnen der Ausgabedatei " << Ausgabedateiname << " aufgetreten!" << endl;
  }
 Datei.close();
}
 
int main(int argc, char ** argv)
 {long long int Startzeit = time(NULL);
  if (argc>2)
   {Namenshandhabungsprozedur(argv[1], argv[2]);
   }
  else
   {cout << "Dem Programm müssen beim Aufruf zwei Dateinamen übergeben werden:\n";
    cout << "Als ersten den Namen der Eingabedatei und als zweiten den Namen, den die Ausgabedatei bekommen soll.\n";
    cout << "Ein korrekter Programmaufruf sieht beispielsweise so aus: " << argv[0] << " Eingabe.txt Ausgabe.txt\n";
   }
  time_t Laufzeit=time(NULL) - Startzeit;
  if (Laufzeit==1)
   {cout << "Das Programm hat für seinen Lauf eine Sekunde benötigt.\n";
   }
  else
   {cout << "Das Programm hat für seinen Lauf " << Laufzeit << " Sekunden benötigt.\n";
   }
  cout << "\a" << endl; //gibt einen Ton aus, um das Ende des Programms zu signalisieren
  return 0;
 }