1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies. Weitere Informationen

C: Wörter, Zeichen, und Zeilen zählen

Dieses Thema im Forum "C/C++" wurde erstellt von lordosiris, 16. April 2012.

  1. lordosiris

    lordosiris Mitglied

    Hallo,

    ich möchte ein Programm schreiben, welches ein Textfile öffnet, alle Chars, Lines und Words zählt.
    Geöffnet wird die Datei mit fopen, mit fgetc werden alle Zeichen durchgegangen. Der Chars Counter wird dabei jedes mal erhöht, sollt es zufällig \n sein, wird der Lines Counter auch erhöht.
    Beim Word Counter hab ich momentan noch so meine Probleme. Momentan habe ich das mit isspace() realisiert, allerdings zählt der beispielsweise Zahlen auch als Wörter mit. ("Ich bin Hans und bin 8 Jahre alt." Wären 8 Words).

    Hier der wichtigste Teil meines C Codes:
    Code (C):
    1. do {
    2. n = fgetc (pFile); //in pFile ist das Textfile geöffnet)
    3. c++; //chars
    4. if (n == '\n') l++; //lines
    5. if (isspace(n)) w++; //words
    6. } while (n != EOF);
    Wie kann ich das hübscher/besser/effektiver regeln?
     
    Zuletzt von einem Moderator bearbeitet: 16. April 2012
  2. sheel

    sheel I love Asm Administrator

    Hi und Willkommen bei tutorials.de,

    Mehrere Leerzeichen hintereinander werden bei dir als mehrere Wörter gezählt.
    Da könnte man zB. eine Variable machen, die 1 oder 0 ist,
    je nachdem, ob man gerade "in" einem Wort ist.
    Auf diese Weise kann man dann auch zeichenweise prüfen, ob es ein gültiges Wort ist.

    Fälle, die unterschieden werden müssen:
    In einem Wort/nicht
    Aktuelles Zeichen ist Buchstabe/Space/Anderes

    Code (C++):
    1. char imwort = 0;
    2. do {
    3.     n = fgetc (pFile); //in pFile ist das Textfile geöffnet)
    4.     c++; //chars
    5.     if (n == '\n') l++; //lines
    6.  
    7.     if(!imwort) //Gerade kein Wort
    8.     {
    9.          if(isalpha(n)) //n ist ein Buchstabe
    10.          {
    11.               w++; //Als Wort(beginn) zählen
    12.               imwort = 1;
    13.          }
    14.  
    15.          else if(!isspace(n)) //Kein Buchstabe, kein Space
    16.               imwort = 1; //Etwas beginnt, aber es wird nicht gezählt
    17.  
    18.          //Space brauchen keine Behandlung, wenn man sowieso außerhalb eines Wortes ist
    19.     }
    20.  
    21.     else //in einem Wort
    22.     {
    23.          if(isspace(n)) //Space beendet das Wort
    24.               imwort = 0;
    25.  
    26.          else if(!isalpha(n)) //Kein Buchstabe, kein Space, aber im Wort: Irgendwas wie w23x89
    27.          {
    28.               w--; //Wurde beim Anfangsbuchstaben gezählt, ist aber doch kein Wort
    29.          }
    30.  
    31.          //Buchstaben im Wort brauchen keine Behandlung
    32.     }
    33.  
    34. } while (n != EOF);
    Ich würde mir wegen dem Wortzählen aber keine keine großen Umstände machen,
    sogar MS Word zählt Zahlen als Wort :D

    Gruß

    PS: Bei den Codetags gehört ein / statt \
    Habs ausgebessert.
     
    BasicC gefällt das.
  3. lordosiris

    lordosiris Mitglied

    Wenn das so ist, glaub ich werd ich das auch so stehen lassen!

    Ich schau mir auf jeden Fall deinen Code noch genauer an, zum Zwecke des Verständnisses.
    Das verschiebe ich aber glaube ich auf morgen, um die Uhrzeit seh ich vor lauter Bäumen den Wald nichtmehr!

    Danke schonmal für die sehr rasche Antwort!
     
  4. lordosiris

    lordosiris Mitglied

    Okay, also folgendes.

    Ich hab mein Programm jetzt etwas erweitert.

    Und zwar um die Möglichkeit, einen Suchstring per Parameter einzugeben, welcher in den Files gesucht wird.

    Jetzt bin ich schon soweit, dass ich die Files jeweils öffne (ist ja auch keine große Kunst), aber wie ich in den Files jetzt nach dem Suchstring suche und ggf. ausgebe: Ja, in dem eben geöffneten File befindet sich der Suchstring - dafür hab ich absolut keinen Lösungsweg.

    Ob mit fgetc, fgets, etc.. Ich google mich dumm und dämlich, aber ich raffs einfach nicht, wie ich die Wörter in der Datei mit dem Suchstring vergleichen soll.

    Hat da jemand einen Lösungsansatz?

    Vielen Dank
     
  5. cwriter

    cwriter Erfahrenes Mitglied

    Hallo

    So vielleicht?
    Code (C):
    1. char Suchstring[512];
    2. fgets(Suchstring, 512, STDIN);
    3. FILE* f = fopen("Datei.txt","r");
    4. if(f == NULL) return -1;
    5. char temp[512]; //Wenn die Datei Zeilen hat, die länger als 512 Zeichen sind, erweitern
    6. while(fgets(temp,512,f) != NULL)
    7. {
    8.      if(strstr(temp,Suchstring) != NULL) //Treffer
    9.      {
    10.           printf("Treffer in dieser Zeile: %s",temp);
    11.      }
    12. }
    13. fclose(f);
    Ungetestet.


    cwriter
     
  6. lordosiris

    lordosiris Mitglied

    Danke schön für den Vorschlag schonmal.

    Ich poste jetzt einfach mal meinen momentanen Code:

    Code (C):
    1. while ((zeile=readdir(verzeichnis)) != NULL){
    2.             printf("Folgende Datei wird durchsucht: %s\n", (*zeile).d_name);
    3.             pFile = fopen("zeile","r");
    4.             while (fgets(compare,512,pFile)!=NULL){
    5.                 if (strstr(compare,Suchstring) != NULL){
    6.                     printf("Treffer in dieser Datei!");
    7.                 }
    8.             }
    9.             n++;
    10.             fclose(pFile);
    11.         }
    Vorher öffnet er das momentane Verzeichnis.
    Solange zeile ungleich Null ist, also solange noch Dateien im Verzeichnis unbearbeitet sind, gibt er erstmal aus, welche Datei er momentan durchsucht. (Ist nur für mich eine kleine Kontrolle).
    Danach öffnet er die Datei, die zeile gerade anzeigt. Solange fgets in der Variable compare noch 512 Zeichen aus dem File pFile bekommt, kontrolliert er per strstr den Inhalt der beiden Variablen compare und Suchstring. Sollten die gleich sein, somit ungleich Null, wird "Treffer.." ausgegeben,. Dann wird noch ein Counter erhöht (nur zur Kontrolle) und das File wieder geschlossen.

    Funktionieren tut das trotzdem nicht.

    Er kompiliert zwar einwandfrei, wenn ich das Skript allerdings in einem Verzeichnis nach "Josef" suchen lasse, wobei ich genau weiß, dass es ein Txt File gibt, in welchem Josef steht, dann passiert einfach nichts. Mit Ctrl + C kann ich dann den Auftrag abbrechen.

    Vorschläge?
     
  7. sheel

    sheel I love Asm Administrator

    Erster Fehler:
    Code (C++):
    1. pFile = fopen("zeile","r");
    muss heißen
    Code (C++):
    1. pFile = fopen(zeile,"r");
    Sollte deswegen aber nicht endlos warten...hm...

    ah:
    readdir git keinen String zurück
    Da sollte der Compiler aber warnen...
     
  8. lordosiris

    lordosiris Mitglied

    Danke für den Hinweis.

    Ich hatte zeile sogar anfangs so drinnen stehen, allerdings hat mir der Compiler dabei immer einen Fehler rausgehauen.

    Code (Text):
    1. search.c:23:4: Warnung: Übergabe des Arguments 1 von »fopen« von inkompatiblem Zeigertyp [standardmäßig aktiviert]
    Jetzt ist mir schon aufgefallen, warum er wartet.

    Ich hab fgets(Suchstring,512,STDIN); drinnen stehen. Ergo wartet er natürlich auf die Tastatureingabe.

    Wenn ich das mit fgets(Suchstring,512,argv[1]); austausche, kommt eine ähnliche Kompilerfehlermeldung.

    E:/ ignoriere ich die Fehler und starte das Programm, kommt es nun zur sofortigen Beendung mit dem Hinweis "Speicherzugriffsfehler".

    C ist leider Neuland für mich und muss mir jetzt sehr kurzfristig relativ viel Stoff anschauen.
     
  9. cwriter

    cwriter Erfahrenes Mitglied

    @sheel
    readdir() gibt einen String zurück? Ohne an deiner Kompetenz zu zweifeln:
    http://pubs.opengroup.org/onlinepubs/7908799/xsh/readdir.html
    Ich glaube, es müsste das sein:
    Code (C):
    1. pFile = fopen((*zeile).d_name,"r");
    Und abstürzen tut es, weil keine Überprüfung da ist, ob die Datei geöffnet werden kann.
    Code (C):
    1. if(pFile == NULL)
    cwriter

    /EDIT: Zu deinem Post: fgets() liest eine Datei, keinen char* []. So sollte es besser gehen:
    Code (C):
    1. //Zuerst überprüfen:
    2. if(argc < 3) return;
    3. char Suchstring[512];
    4. strcpy(Suchstring,argv[1]);
     
    Zuletzt bearbeitet: 16. April 2012
    sheel und lordosiris gefällt das.
  10. sheel

    sheel I love Asm Administrator

    Zum fgets:
    Der dritte Parameter muss pFile sein, nicht der Dateiname.

    readdir:
    Gibt nicht direkt den String zurück (http://linux.die.net/man/3/readdir)
    Mach sowas:
    Code (C++):
    1. struct dirent *dateiname;
    2. ...
    3. while ((dateiname=readdir(verzeichnis)) != NULL){
    4. ...
    5. pFile = fopen(dateiname->d_name, "r");
    Bzw, was ist die Variable verzeichnis?
    Ein String oder DIR?

    @cwriter: Oh...das sollte heißen keinen String :D
    Einen String hatte er ja schon vorher...
     
    lordosiris gefällt das.
  11. lordosiris

    lordosiris Mitglied

    Code (C):
    1. fgets(Suchstring, 512, argv[1]);
    Das Ding sollte den ersten Parameter einlesen, um dann bei strstr einen Suchstring zum vergleichen zu haben.

    Meine ganzen Initialisierungen:
    Code (C):
    1.     DIR *verzeichnis;
    2.     FILE *pFile;
    3.     struct dirent *zeile;
    4.     int n=0;
    5.     char *compare;
    6.     char Suchstring[512];
    7.     Suchstring = fgets(Suchstring, 512, argv[1]);
    Das Programm momentan:

    Code (C):
    1. verzeichnis=opendir(".");
    2.         while ((zeile=readdir(verzeichnis)) != NULL){
    3.             printf("Folgende Datei wird durchsucht: %s\n", (*zeile).d_name);
    4.             pFile = fopen(zeile->d_name,"r");
    5.             while (fgets(compare,512,pFile)!=NULL){
    6.                 if (strstr(compare,Suchstring) != NULL){
    7.                     printf("Treffer in dieser Datei!");
    8.                 }
    9.             }
    10.             n++;
    11.             fclose(pFile);
    12.         }
    13.    
    14.     printf("So viele Einträge im Verzeichnis gibt es: %d\n",n);
    15.     closedir(verzeichnis);
    Wahrscheinlich seht ihr als Pro's direkt den Fehler, den ich nicht sehe?!
     
  12. cwriter

    cwriter Erfahrenes Mitglied

    @sheel
    Habe ich das k übersehen oder hast du keins geschrieben? Wenn ich es übersehen habe, entschuldige bitte.
    Zur Frage: Ein String gäbe doch einen Fehler aus? Oder geht das bei dieser Funktion?

    /Edit:
    @lordosiris
    Was ist denn der Fehler bzw. was geschieht?
    Du überprüfst immer noch nicht auf Fehler und bei fgets() als dritten Parameter einen String zu nehmen ist immer noch falsch:
    Code (C):
    1. //Zuerst überprüfen:
    2. if(argc < 3) return;
    3. char Suchstring[512];
    4. strcpy(Suchstring,argv[1]);
    Was für einen Compiler hast du eigentlich, der das nicht blockt?

    cwriter
     
    Zuletzt bearbeitet: 16. April 2012
  13. sheel

    sheel I love Asm Administrator

    @cwriter: Zuerst war kein k da, hab ich erst nach deinem Hinweis dazugeschrieben. Tippfehler :)
     
  14. lordosiris

    lordosiris Mitglied

    Ah stimmt, die Überprüfung.. Entschuldigung..

    Hab jetzt ein
    Code (C):
    1. if (pFile==NULL) perror ("Error opening file");
    2.             else {
    Nach pFile = fopen..; gesetzt.

    Wenns also nicht aufgeht kommt Error opening file.

    Führe ich das Skript nun aus kommts soweit:
    Code (Text):
    1. ./search Josef
    2. Folgende Datei wird durchsucht: remove_prefix.sh
    3. Speicherzugriffsfehler
    Compiler meckert nurmehr, dass "compare" uninitialisiert werden könnte, obwohl es doch in Verwendung ist?!

    Ich verwende Geany unter Ubuntu. war der erste, den ich gefunden habe!
     
  15. cwriter

    cwriter Erfahrenes Mitglied

    Ah, sorry, war klar.
    Du nimmst einen char*, der nicht auf NULL gesetzt wurden. Das sollte so gehen (Bin aber nicht sicher. Ich mag Pointer nicht so :p):
    Code (C):
    1. char *compare = NULL;
    Oder dann gleich einen char array: Sicherer, aber auch nicht so dynamisch:
    Code (C):
    1. char compare[512];
    Geht aber auch so:
    Code (C):
    1. char *compare = new char[512];
    Gruss
    cwriter
     
    Zuletzt bearbeitet: 16. April 2012
    lordosiris gefällt das.
  16. lordosiris

    lordosiris Mitglied

    :* :* :* :* :*

    Perfekt************!
    Funktioniert nun, er durchsucht die Files und schreibt "TREFFER!" dazu.. So einfach. Und sooo lange hab ich mich damit herumgemüht.

    Wahnsinn, willkommen in der fantastischen Welt der EDV!

    Übrigens, bald sind die 2Millionen Beiträge voll. Respekt =)
     
  17. DLRG97

    DLRG97 Grünschnabel

    Hallo Zusammen, wäre es vielleicht möglich, dass man mir das gesamte Programm zur Verfügung stellen könnte?!
     
  18. Technipion

    Technipion Erfahrenes Mitglied

    Hallo DLRG97,
    dieser Thread ist schon 6 Jahre alt. Also prinzipiell geht das (falls die Member noch aktiv sind), aber vielleicht eröffnest du mit deinem Problem einfach einen eigenen Thread? Du kannst ja deinen bisherigen Code posten, deine Gedanken, und die Stelle an der du nicht weiterkommst.

    Gruß Technipion
     
Die Seite wird geladen...