# Zeichen, Buchstaben zählen



## David2456 (15. Jan 2016)

Hallo,
ich bräuchte Hilfe bei folgender Aufgabe (b)3)).  Wie zählt man denn die einzelnen Zeichen, Buchstaben, etc aus einem Text?
Danke schonmal

Momentan habe ich

```
public class WordStatistics {


            public static void main(String[] args) {
                String inFile = args[0];
               // String outFile = args[1];
                String content = readStringFromFile(inFile);
                Out.println(content);
                int[] letterCount = getLetterCount(content);
                printLetterCount(letterCount);
               // int[][] twoGrams = getTwoGrams(content);
               // writeTwoGrams(twoGrams, null);
              //  writeTwoGrams(twoGrams, outFile);
                }
             
            public static String readStringFromFile(String content){
             
                In.open("text.txt");
                content = In.readLine();
                return content;        
            }
         
            public static int[] getLetterCount(){
             
             
            }
         
         
}
```

und weiß nicht so recht wie ich weiter machen soll. Mal abgesehen von der Zählung der Zeichen (bei der ich auch Hilfe bräuchte), wie kriege ich denn die Ausgabe zustande? Muss ich switch case Optionen schreiben? Geht vermutlich auch sinnvoller oder muss ich mit Schleifen etc. alle Abfragen aufbauen? Oder sonst wie? In der Text datei steht übrigends dieser Text:
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex
ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum


----------



## Joose (15. Jan 2016)

Um eine den Inhalt eines Strings Zeichen für Zeichen durchzugehen (und diese zu zählen und prüfen) verwendet man am besten das char[] des Strings. Siehe String Dokumentation wie die enstprechende Methode heißt.

Jedes "char" kann durch einen Dezimalwert beschrieben/ersetzt werden siehe dazu diese Tabelle: https://de.wikipedia.org/wiki/American_Standard_Code_for_Information_Interchange#ASCII-Tabelle
Dadurch ist es in Java auch möglich Vergleiche zwischen "int" und "char" zu schreiben.
Beispiel:

```
int value = 65;
char letter = 'A';
char letter2 = 66;
if(letter == value)
{
   ....
} else if(letter > 127 || letter2 < value) {
   ....
}
```

Dadurch kannst du schon mal alle die Sonderzeichen etc. rausfiltern.
In einem Array mit der Größe X kannst du für jedes Zeichen mitzählen wie oft es schon vorgekommen ist.
Wenn du zum Beispiel gerade ein "A" hast dann erhöhst du den Wert des Arrays auf Index 0. Bei einem Sonderzeichen erhöhst du den Wert auf Index 26, bei einem "." erhöhst du den Wert auf Index 27, .....
Hier musst du halt etwas überlegen 

Tipp:

```
char letter = 'A';
int index = -1;
index = 'A' - letter; // index = 0
index = 'B' - letter; // index = 1
..
letter = 'a';
index = -1;
index = 'a' - letter; // index = 0
index = 'b' - letter; // index = 1
.....
```


----------



## David2456 (15. Jan 2016)

Ok klingt logisch, aber muss ich jetzt für alle Buchstaben und Zeichen eine Variable erstellen? Oder zumindenst eine Zeile wie in deinem Tipp? Und könntest du nochmal dein ersten Code erläutern. Was macht der genau? Es prüft doch nur wenn der Char A gleich seiner ASCII Codierung ist. Heißt das jetzt wieder das ich das mit allen Zeichen machen muss?


----------



## David2456 (15. Jan 2016)

Und wie kann ich denn mein String auf die Zeichen untersuchen?


----------



## Joose (15. Jan 2016)

David2456 hat gesagt.:


> .....aber muss ich jetzt für alle Buchstaben und Zeichen eine Variable erstellen? Oder zumindenst eine Zeile wie in deinem Tipp?



Nein musst du nicht. Der Tipp sollte dir nur als Veranschaulichung dienen für den Fall das du die Vorkommen der Buchstaben in einen Array mitzählst.
Dafür musst du für jedes Zeichen den Wert vom richtigen Index erhöhen  



David2456 hat gesagt.:


> Und könntest du nochmal dein ersten Code erläutern. Was macht der genau? Es prüft doch nur wenn der Char A gleich seiner ASCII Codierung ist. Heißt das jetzt wieder das ich das mit allen Zeichen machen muss?



Der erste Code dient nur als Veranschaulichung das man mit dem primitiven Datentyp "char" ganz einfach rechnen kann im Zusammenhang mit int. Bzw Bedingungen erstellen kann.

Ansonsten bleibt dir auch noch die Möglichkeit schon vorhanden Lösungen zu suchen, davon gibt es einige im Internet (Google: java zählen buchstaben string)


----------



## David2456 (15. Jan 2016)

Ok erstmal funktioniert es. Zum testen wollten ich jetzt mal die Häufgkeit von "." zählen. Ich habe eine Methode welche mir die Anzahl der "." als int berechnet. Aber in der Aufgabenstellung steht ja das ich das als Array zurückgeben soll. Soll ich jetzt ein Array mit 127 Elementen (int[] ASCII  = new int[127]; ?) schreiben und jedem Index dem Zeichen zuordnen? Bei dem Beispiel dem 46. Index dem "." und wenn ich jetzt z.B das komplette Array seinen Indicies zugewiesen habe, wie kriege ich es denn jetzt hin das z.B beim 46 Index die Anzahl, welche in meiner Methode berechnet wird, ausgegeben wird?

```
public class k {


            public static void main(String[] args) {
                String inFile = args[0];
                //String outFile = args[1];
                String content = readStringFromFile(inFile);
                Out.println(content);               
                int[] letterCount = getLetterCount(content);
                Out.println(letterCount);
               // printLetterCount(letterCount);
               // int[][] twoGrams = getTwoGrams(content);
               // writeTwoGrams(twoGrams, null);
              //  writeTwoGrams(twoGrams, outFile);
                }
              
            public static String readStringFromFile(String content){
              
                In.open("text.txt");
                content = In.readLine();
                return content;              
            }
          
             public static int[] getLetterCount(String content){
                             
                int count = 0;
                for (int i = 0; i < content.length(); i++) {
                    if (content.charAt(i) == '.') count++;
                }
              
                return ???;
              
            }
          
          
          
          
          
}
```
(Ich weiß die Methode ist falsch, aber was muss ich hinzufügen? Damit ich jetzt nicht 127 Variablen setzen muss, sprich count1-127, und die dem Array zuweisen muss) Ich steh völlig auf dem Schlauch :/


----------



## Joose (15. Jan 2016)

Du hat doch im Anfangspost explizit nach Aufgabe 3 b) gefragt. Und dort steht schon geschrieben das alle Zeichen die einem ASCII Code <= 31 entsprechen oder dem ASCII Code 127 als ein und dasselbe Zeichen gewertet werden.

Sprich von den möglichen 128 Zeichen fallen schon mal 33 zusammen auf 1, bleiben theoretisch 96 Zeichen über. Für diese kannst du nun ein Array verwenden.
Um nun vom ASCII Code auf den richtigen Index zu kommen musst du den ASCII Code immer um den selben Wert subtrahieren . Mit Ausnahme eben von den oben genannten Sonderzeichen, diese einfach auf Index 0 schreiben.

Falls dir das zu kompliziert ist versuche es vorerst einfacher. Erstelle ein Array für 128 int Werte. Jeder ASCII Code entspricht auch den richtigen Index im Array.
Wenn das funktioniert und dir klar ist warum, überlege dir wie du die ersten 32 Zeichen (ASCII Code 31 und kleiner) alle zusammenzählst und die Zeichen ab ASCII Code 32 alle nach vorne schiebst im Array.


----------



## David2456 (15. Jan 2016)

Habe jetzt eine Methode welche alle ab den Sonderzeichen bis zum Ende berechnet. Wie kann ich denn jetzt die Sonderzeichen sprich alles <32 zusammenfassen?
Hier noch die Methode

```
int[] buchstaben = new int[94];

for(int i = 0; i < 94; i++) {
   buchstaben[i] = 0;
}

In.open("text.txt");
String wort = In.readLine();
for (int i = 0; i < wort.length(); i++) {
   char buchstabe = wort.charAt(i);
   int ascii = (int)buchstabe - 32;
   if(ascii >= 0 && ascii < 94) {
     buchstaben[ascii]++;
   }
}

for(int i = 0; i < 94; i++) {
   System.out.println(" " + (char)(i + 32) + " = " + buchstaben[i]);
}
```


----------



## Bitfehler (15. Jan 2016)

David2456 hat gesagt.:


> *for* (*int* i=0; i<wort.length(); i++)



Kann es sein, dass durch deine Abbruchbedingung ein Zeichen der Eingabe verloren geht?

Wenn du ein Sonderzeichen gefunden hast, dann erhöhst du deinen Wert, der über den Index 0 angesprochen wird. Steht ja so in der Aufgabenstellung.


----------



## Joose (15. Jan 2016)

David2456 hat gesagt.:


> Wie kann ich denn jetzt die Sonderzeichen sprich alles <32 zusammenfassen?



Naja wenn ein Sonderzeichen mit einem ASCII Code < 32 auftaucht, dann müsst der Wert der Variable "ascii" ja <0 sein oder? 
(Laut deinem Code natürlich)

Fragen zu deinem Code? Wie kommst du auf eine Arraygröße von 94?
Es gibt 128 ASCII Zeichen (die Codes gehen von 0 - 127, wobei eben Code 0 schon 1 Zeichen ist )
Die Zeichen 0-31 und das Zeichen 127 (=33 Zeichen) sollen zusammengefasst werden (Sonderzeichen).
Größe: 128-33 = 95 Zeichen. Da aber natürlich die Sonderzeichen selbst auch gezählt werden müssen muss man das Array nochmal um 1 vergrößern => 96

Anmerkungen zu deinem Code:

```
int[] buchstaben = new int[94];
```

Auch wenn Java es zulässt die "[]" hinter den Variablennamen zu schreiben, sollte man sich trotzdem angewöhnen die Klammern für ein Array immer hinter den Typ zu schreiben.
1.) So kann man direkt am Typ erkennen ob es sich um ein Array handelt, andersrum sieht man das erst wenn man sich den Namen anschaut.
2.) Du erstellst ein int-Array mit den Namen "buchstaben" aber kein int mit (den Namen) buchstaben-Array 


```
for(int i = 0; i < 94; i++) {
```

Anstatt die Zahl 94 hier hardcodiert hinzuschreiben verwende doch "buchstaben.length".
Dadurch hast du den Vorteil du musst nur die Größe des Arrays anpassen und die Schleife funktioniert weiterhin richtig.
=> Code muss an max. einer Stelle geändert werden


----------

