// Für alle auf der Befehlszeile angegebenen Files:
// - Gib alle Wörter im File einzeln in einer Zeile aus
// - Lass alles weg, was kein Wort ist
// - Gib am Ende jedes Files die Anzahl der Wörter
//   und die Länge des längsten Wortes aus
//
// Aufruf: woerter file1 file2 file3 ...
//
// Klaus Kusche, 2012, 2022

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>

int main(int argc, const char *argv[])
{
  if (argc == 1) {     // kein File angegeben!
    fprintf(stderr, "Usage: %s file ...\n", argv[0]);
    exit(EXIT_FAILURE);
  }

  // Wert für das exit() am Ende von main
  // bei Fehler in einem File:
  // mach mit dem nächsten File weiter,
  // aber merk dir den Fehler!
  int exCode = EXIT_SUCCESS;

  for (int i = 1; i < argc; ++i) {   // Schleife pro File
    
    int words = 0;  // Anzahl Worte
    int max = 0;    // Länge des bisher längsten Wortes
    int chars = 0;  // Länge des aktuellen Wortes (wenn 0: Nicht in einem Wort)
    
    FILE *f = fopen(argv[i], "r");
    if (f == NULL) {
      fprintf(stderr, "%s: cannot open %s for reading: %s\n",
              argv[0], argv[i], strerror(errno));
      exCode = EXIT_FAILURE;
      continue;            // mit nächstem File weitermachen
    }
    
    int c;          // Aktueller Buchstabe (int wegen EOF!!!)
    while ((c = fgetc(f)) != EOF) {
      if (isalpha(c)) {    // wir sind in einem Wort
        if (putchar(c) == EOF) {  // Zeichen ausgeben
          fprintf(stderr, "%s: cannot write stdout: %s\n",
                  argv[0], strerror(errno));
          exit(EXIT_FAILURE);  // Weitermachen ohne Output wäre sinnlos
        }
        ++chars;           // Zeichen zählen
      } else {             // wir sind *nicht* in einem Wort
        if (chars > 0) {   // ... aber wir waren beim vorigen Zeichen
                           //     noch in einem Wort: Wort beenden!
                           // Am Ende des Wortes: Zeilenvorschub ausgeben
          if (putchar('\n') == EOF) {  
            fprintf(stderr, "%s: cannot write stdout: %s\n",
                    argv[0], strerror(errno));
            exit(EXIT_FAILURE);  // Weitermachen ohne Output wäre sinnlos
          }
          ++words;         // ... Wort zählen
          if (chars > max) { // ... und max. Länge prüfen
            max = chars;
          }
          chars = 0;       // Wort ist erledigt, bereit für nächstes Wort
        }
      }
    }
    
    // Hat fgetc wegen des Datei-Endes oder wegen eines Fehlers EOF geliefert?
    if (ferror(f)) {
      fprintf(stderr, "%s: cannot read %s: %s\n",
              argv[0], argv[i], strerror(errno));
      exCode = EXIT_FAILURE;
    }
    // Wir haben die Datei fertig gelesen
    // Zumachen ist ganz wichtig,
    // sonst geht uns bei sehr vielen Dateien der Speicher aus!
    if (fclose(f) == EOF) {
      fprintf(stderr, "%s: cannot close %s: %s\n",
              argv[0], argv[i], strerror(errno));
      exCode = EXIT_FAILURE;      
    }
    // Ausgabe auf stderr, damit die normale Wort-Ausgabe nicht gestört wird
    fprintf(stderr, "%s: %d words, longest %d\n", argv[i], words, max);
  }

  // fclose auf stdout, damit alle Schreibfehler sicher erkannt werden!!
  // man darf auch die std...-Files schließen!
  if (fclose(stdout) == EOF) {
    fprintf(stderr, "%s: cannot close stdout: %s\n",
            argv[0], strerror(errno));
    exit(EXIT_FAILURE);
  }

  exit(exCode);
}
