Buchstabenhäufigkeit, histogramm



  • Hallo, ich habe versucht die Buchstabenhäufigkeit zu programmieren und anschließend die als Histogramm auszugeben. Klappt irgendwie nicht. Wo könnte das Fehler liegen? danke im voraus

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    void balkendiagramm( int *zaehler ){
    int i,j;
    int charCount[26][2];

    for(i=0;i<26;i++){

    printf("%c:",(char)charCount[i][0]);

    for(j = 1; j<=charCount[i][1]; j++)

    printf("*");

    printf("\n");
    }

    }
    int main(){
    char text[1024];
    FILE * datei;
    int charCount[26][2];
    int i, Inhalt,j;

    datei=fopen("sample.txt","r");
    if(datei!= NULL){
    fscanf(datei,"%1024c",text);
    text[1024]='\0';

    fclose(datei);
    }
    for(i=0,Inhalt='a';Inhalt<='z';i++,Inhalt++)
    {
    charCount[i][0]=Inhalt;
    charCount[i][1]=0;
    }
    printf("Haefigkeit der Buchstaben:\n");
    for(i=0;text[i]!='\0';i++){
    for(j=0;j<26;j++){
    if(text[i]==charCount[j][0]){
    charCount[j][1]++;}
    }
    }
    balkendiagramm(&charCount[26][1]);

    system("PAUSE");
    return 0;
    }



  • Du gibst in Zeile 10 und 14 charCount aus obwohl es nicht initialisiert wurde und den Parameter verwendest du nicht. ???
    In Zeile 32 und 48 gibt es einen Überlauf. ( text[1024] geht von text[0] bis text[1023].

    Gib mal eine genauere Fehlerbeschreibung als "klappt nicht" und formatiere den Code ordentlich.



  • Die Fehler liegen irgendwo im Code.

    Der Aufruf von balkendiagramm und die PAramter der Funktion passen nicht zusammen.
    Auch wenn du den Compiler mit einfügen von Sonderzeichen ruhig gestellt hast.

    Ohne Code-tags kann man dein Programm sehr schlecht nachvollziehen, da die Einrückungen verloren gehen.

    Benutze das eingelesen Zeichen als Index. Aus dem Index ergibt sich auch das Zeichen, so dass du nur ein 1D-Array brauchst.

    fscanf nimmt man zum einlesen von einzelnen Werten oder Wörtern.
    Ganze Zeilen liest man mit fgets ein,
    ganze Dateien liest man mit fread ein.

    Für einzelne Zeichen nimmt man fgetc



  • Hallo nara99

    Tolle Idee eine Datei mal so aufzuzeigen!
    Du könntest da auch jedes Byte einzeln zählen. Vieleicht inspiriert dich
    dein von mir nur geringfügig verändertes Prog. Problem ist vorher sollte man
    die Fensterbreite kennen, da ja die Häufigkeit richtig dargestellt werden sollte.
    Hier dein Prog leicht verändert:

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    
    void balkendiagramm( unsigned char letter[])
    {
     int i, j, erstes, letztes, maximal;
     maximal = 0;
     for(i=0; i<= 255; i++)
      if (letter[i] > maximal) maximal = i;
     letztes = 0;
     for(i=255; i >= 0; i--)
      if (letter[i] != 0 )
       {
        letztes = i;
        break;
       }
     erstes = 0;
     for(i=0; i <= 255; i++)
      if (letter[i] != 0 )
       {
        erstes = i;
        break;
       }
     printf("Haeufigster Buchstabe: %c=%d dez\n", maximal, maximal);
     printf("Erstes autretendes ASCII-Zeichen Nr.:  %d\n", erstes);
     printf("Letztes autretendes ASCII-Zeichen Nr.: %d\n\n", letztes);
    
    printf("ASCII   Haeufigkeit\n");
    for(i = erstes; i<= letztes; i++)
     {
      if ((i >= 32) && (i <127))
       printf("\n%3d=%c %4d  ", i, i, letter[i]);
       else
       printf("\n%3d=   %4d  ", i, letter[i]);
       for(j=0; j < letter[i]; j++)
        printf("*");
       //printf("\n");
      }
    }
    
    int main()
    {
    unsigned char letter[256];
    char filename[500];
    FILE *datei;
    int  i, zeichen;
    long filelength;
    
    printf("Dateistatisitik\n");
    printf("Bitte Dateinamen eingeben: ");
    scanf("%s", filename);
    
    datei=fopen(filename, "rb");
     if(datei == NULL)
      {
       printf("Datei %s konnte nicht geoeffnet werden.\n", filename);
       return 1;
      }
      else
      {
       /* vorher Dateilänge mit ftell() feststellen */
       fseek(datei, 0L, SEEK_END);
       filelength = ftell(datei);
       fseek(datei, 0L, SEEK_SET);
       printf("Dateilänge von %s:  %ld Byte\n\n", filename, filelength);
    
       for ( i = 0; i <= 255; i++)
        letter[i] = 0;
    
       for ( i = 0; i < filelength; i++)
        if((zeichen = fgetc(datei)) != EOF )
         letter[zeichen]++;
    
      }
    fclose(datei);
    printf("\nDatei geschlossen.\n");
    
    balkendiagramm(letter);
    
    system("PAUSE"); 
    
    return 0;
    }
    

    Experimentierst du etwa mit Dechiffrierung von verschlüsselten Dateien
    oder Texten, welche mit Hilfe der Substitution und symmetrischen Verfahren kodiert wurden?
    Mit deiner Methode kann man nachweisen, das das "e" in der deutschen Sprache
    bei weitem der am häufigsten verwendete Buchstabe ist. Damals wurde das den
    deutschen U-Bootfahrern im 2ten Weltkrieg zum Verhängnis. Damals hatten die
    in englischen Blechley Park unter der Mithilfe des Mathematikers Alan Turing
    entworfenen Rechenmaschinen("Bombs"), deutsche Funksprüche auf die statistische Häufigkeit von Buchstaben
    und verwendeten Textpassagen wie "Führerhauptquatier" oder "Oberkommando" getestet und
    entschlüsselt. Die Wirkung der Arbeiten der damaligen britischen Geheimorganisation
    "Ultra" dürfte hinlänglich bekannt sein.

    Sorry wegen der kleinen Exkursion in Geschichte, aber ich hatte mich mal für Kurzwellenfunk interessiert. Da lernt
    man so etwas.

    INFO für Anfänger:

    die ASCII-Zeichen 0 bis 32 dienten früher als Steuerzeichen für die
    Datenübertragung über die damalige serielle Schnittstelle RS232.
    Deren damalige Bedeutung:

    Hier eine Liste der Bedeutung der ASCII-Zeichen
    
    von 0 bis 32 als Steuerzeichen für Datenübertragung,
    
    Drucker, Bildschirmsteuerzeichen, usw.:
    
    00 NULL, no Operation, ..........NUL keine Operation
    01 Start of Heading .............SOH Vorspannanfang
    02 Start of Text ................STX Textanfang
    03 End of Text ..................ETX Textende
    04 End of Transmission ..........EOT Übertragungsende
    05 Enquiry ......................ENQ Stationsanruf
    06 Acknowledge ..................ACK Bestätigung
    07 Bell..........................BEL Klingel
    08 Backspace.....................BS Rückwärtsschritt
    09 HAT...........................Horizontal Tabulation
    10 Line Feed.................... LF Zeilenvorschub
    11 Vertical Tabulation VT
    12 Form Feed FF..................Formularvorschub, Schirmlöschen
    13 Carrige Return ...............CR Wagenrücklauf
    14 Shift out ....................SO Umschalten aus
    15 Shift in .....................SI Umschalten ein
    16 Data Link Escape..............DLE Austritt aus der Datenverbindung
    17 Device Control 1..............DC1 Gerätesteuerung 1
    18 Device Control 2..............DC2 Gerätesteuerung 2
    19 Device Control 3..............DC3 Gerätesteuerung 3
    20 Device Control 4..............DC4 Gerätesteuerung 4
    21 Negative Acknowledge .........NAK Fehlermeldung
    22 Synchronous Idle .............SYN Synchronisierung
    23 End of Transm.Block...........ETB Datenblockende
    24 Cancel .......................CAN ungültig
    25 End of Medium ................EM Datenträgerende
    26 Substitute ...................SUB Character Zeichen ersetzen
    27 Escape........................ESC Rücksprung
    28 File Separator................FS Filetrennung
    29 Group Separator...............GS Gruppentrennung
    30 Record Separator .............RS Untergruppentrennung
    31 Unit Separator ...............US Einheitentrennung
    32 Space ........................SP Leerschritt
    

    Wie diese Zeichen heute wichtig sind für Sitor-A, Sitor-B, Navtex,
    RTTY, Amtor-Verfahren, und der ITA2 (Baudot code), welche für die
    Datenübertragung per Kurzwellenfunk zu Schiffen wichtig sind, entzieht
    sich leider meiner Kenntnis.


Log in to reply