# Wörter zählen



## schrobi (21. Jun 2009)

Hallo zusammen,

ich hoffe ihr könnt mir bei meinem Problem helfen.

Ich habe die Aufgabe ein Programm zu schreiben welches von einem eingegebenen String die Wörter zählt und dessen Anzahl ausgibt.

Bsp: Blaukraut bleibt Blaukraut und Brautkleid bleibt Brautkleid.
Blaukraut 2
bleibt 2
und 1
Brautkleid 2

So.
Realisiert werden soll das Ganze mit Hilfe eines Arrays welches die Worte des Strings aufnimmt, vergleicht und am Ende deren Anzahl ausgibt.

Mein "Schlachtplan" sieht folgendermaßen aus:
- String einlesen
- trim();
- Wörter zählen
- Array mit absoluter Anzahl der Wörter erstellen
- Wörter dem Array übergeben
- Wörter vergleichen
- jeweilige Anzahl der einzelnen Worte inkermentieren++
- Ausgabe der fertigen Liste

So weit die Theorie. Folgenden Code habe ich bisher:

Tester

```
import java.io.*;


public class WordCounterTester {
	
	
    /**
     *Mainmethode. Instanziert ein Objekt der Klasse WordCounter und führt 
     *dessen Methode show(); aus.
     *
     *@param args nothing.
     */
    public static void main(String[] args) {
        
        System.out.println("Bitte Text eingeben!");
        WordCounter wordCount = new WordCounter();
        wordCount.show();
         
        
    }
    
}
```

Hauptklasse

```
import java.io.*;

 
public class WordCounter {
 	 	
    String input;
 	int zaehler = 0;
 	
 	
 	
 	
 	public void readIn() {
	
        BufferedReader br = new BufferedReader(
                    new InputStreamReader(System.in));
        try {
            input = br.readLine();
        } catch (IOException e) {
            e.printStackTrace(); // Fehler ausgeben
            System.exit(0); // Programm abbrechen
        }
    }
 	
  	
 	
 	public void count() {
        readIn();
        
        int zeichen;
        int a;
        int anzahl;
        
        input = input.trim(); //Leerzeichen am Anfang entfernen.
        
        zeichen = input.length(); //Anzahl der Zeichen der Eingabe.
        
        input = " " + input;
        
        a = input.indexOf(" ");
        
        input = input.substring(a + 1);
        
                
                
                
        while (a != -1) //Funktion indexOf: wird das gesuchte String nämlich " " nicht gefunden: wird -1 ausgegeben;
        {
            boolean check = input.startsWith(" ");
            
            if (check == false) //War das Zeichen nach dem Leerzeichen kein weiteres, muss es ein
            {
                zaehler++;            //Buchstabe sein -> Anzahl Wörter +1

            }
            
            a = input.indexOf(" ");     //Setzen des Zeigers auf das nächste Leerzeichen
            input = input.substring(a + 1);    //Abschneiden des Strings bis inkl. des Leerzeichen
        }
        
        
        
        if (zeichen != 0) //der Satz enthält Wörter
        {
            System.out.println("Anzahl der im Satz enthaltenen Wörter: " + zaehler);
        }
        
        else //Wurden nur Leerzeichen eingegeben, folgt diese Ausgabe
        {
            System.out.println("Der Satz enthält keine Wörter.");
        }
       
    }
    
    public void reihung() {
        count();
        
        System.out.println("anzahl wörter: " + zaehler); 
        
        String[] reihung = new String[zaehler];
        
    }
 
 public final void show() {
 		//count();
 		reihung();
 	}
 	
 
 
 }
```

in der Methode reihung() habe ich nun ein Array erstellt welches so groß ist wie die Anzahl der Worte (denk ich jedenfalls). Nun weiss ich nicht wie ich es hinbekomme, dass  die eingegebenen Worte IN das Array gepackt und verglichen werden.

Hoffe mein Frage ist verständlich und ihr habt Lust mir ein wenig unter die Arme zu greifen.

Schrobi


----------



## Schandro (21. Jun 2009)

Falls du HashMap benutzen darfst:

```
String text = "Hallo Welt Hallo in Hallo Welt dumdideldei";
		
		String[] words = text.split(" ");
		HashMap <String, Integer> wordMap = new HashMap<String, Integer> (); // word | anzahl
		
		for(int i=0;i<words.length;++i){
			if(!wordMap.containsKey(words[i])){
				wordMap.put(words[i], 1);
			}
			else{
				wordMap.put(words[i],wordMap.get(words[i])+1);
			}
		}
		
		System.out.println(wordMap);
```


----------



## mvitz (21. Jun 2009)

Evtl ist für dich auch folgende Methode besser: String (Java Platform SE 6))

Danach musst du nur noch das zurückgegebene Array prüfen, ob es Wörter enthält, die Mehrfach vorkommen und wenn ja dies festhalten. Z.B. mit einer Map in der das Wort der Schlüssel ist und die Häufigkeit der Wert. Zum Schluss brauchst du dann die Map nur noch auszugeben.

Edit: Zu spät, siehe Schandros Beispiel, würde das genau so machen


----------



## schrobi (21. Jun 2009)

Hallo ihr zwei 

Danke für die Antworten aber ich denke mal dass es nicht mit einer Hashmap gelöst werden soll sondern step by step nach der Anfängerart. Werde das mit der Map natürlich mal ausprobieren.

Habt ihr denn eine Idee wie man es mit dem Array sinnig machen könnte? Ich denke mal dass mein Ansatz (Schlachtplan) recht vielversprechend ist oder habe ich irgendwo grobe Denkfehler?

Hoffe weiter auf rege Beteiligung muss jetzt aber für eine Weile offline.

Vielen Dank an alle

Schrobi


----------



## SchonWiederFred (21. Jun 2009)

```
import java.util.HashMap;
import java.util.Map;

public class Wortzähler
{
	private Map<String, Integer> wörter;

	public Wortzähler()
	{
		wörter = new HashMap<String, Integer>();
	}

	public void neuesWort(String wort)
	{
		Integer value = wörter.get(wort);
		int anzahl = 0;
		if (value != null)
		{
			anzahl = value;
		}
		wörter.put(wort, anzahl + 1);
	}

	public void neuerSatz(String satz)
	{
		for (String wort : satz.split("\\W+"))
		{
			neuesWort(wort);
		}
	}

	public void gibAus()
	{
		for (Map.Entry<String, Integer> entry : wörter.entrySet())
		{
			System.out.println(entry.getKey() + ": " + entry.getValue());
		}
	}

	public static void main(String[] args)
	{
		Wortzähler zähler = new Wortzähler();
		zähler.neuerSatz("Blaukraut bleibt Blaukraut"
				+ " und Brautkleid bleibt Brautkleid.");
		zähler.gibAus();
	}
}
```


----------



## Schandro (21. Jun 2009)

@Fred (schon wieder)
Der TO will/soll keine HashMap einsetzen, sondern es mit Arrays regeln.

@TO
Wie wärs den hiermit? 


```
String text = "a a A Hallo Welt in Hallo in Hallo Welt dumdideldei";
		
		String[] words = text.split(" ");
		Arrays.sort(words);
		
		int cnt = 1;
		String actualWord = words[0];
		for(int i=1;i<words.length;++i){
			if(!words[i].equals(actualWord)){
				System.out.println(actualWord+" kommt "+cnt+" mal vor.");
				actualWord = words[i];
				cnt = 1;
			}
			else{
				++cnt;
			}
		}
		System.out.println(actualWord+" kommt "+cnt+" mal vor.");
```


----------



## schrobi (21. Jun 2009)

Hallo ihr,

vielen Dank für die Antworten.:toll:

@Schandro
Ich denke damit wäre ich auf dem richtigen Weg. Kann heute leider nichts mehr coden. Werd das morgen mal nachvollziehen und versuchen einzubauen und mich dann bei Problemen (also definitiv ;o) ) nochmal melden.

Ich hau mich nun weg. Gute Nacht zusammen.

Schrobi


----------



## faetzminator (21. Jun 2009)

Ich würde es allerdings an deiner Stelle mit "\\W+" statt " " splitten, wie von SchonWiederFred bereits erwähnt.


----------



## schrobi (22. Jun 2009)

Moinmoin,

also ich habe mein Programm nun so zum laufen bekommen (mit Eurer Hilfe natürlich), dass es das macht was es soll.. Allerdings macht mich eine Sache etwas stutzig. 
DAS SIEHT SO EINFACH AUS!:lol:

Habe mal ein wenig rumgeguckt und gesehen, dass einem durch das " Arrays.sort(words);" wohl eine Menge schreibarbeit abgenommen wird.

Angenommen ich möchte dieses rausschmeissen. Geht das ohne Probleme? Also ich meine gibts da eine "einfache" Methode zu Fuß die das "Arrays.sort(words);" ersetzt?

Ansosten bleibt mir hier nurnoch mich nochmals recht herzlich zu bedanken

Schrobi


----------



## bygones (22. Jun 2009)

schrobi hat gesagt.:


> Also ich meine gibts da eine "einfache" Methode zu Fuß die das "Arrays.sort(words);" ersetzt?


wenn es eine einfache Methode gaebe braeuchte man nicht Arrays.sort()... also nein.
sei froh dass es sowas gibt und du nicht selbst implementieren musst


----------



## schrobi (22. Jun 2009)

Genau das meinte ich aber. Also sowas selbst zu schreiben. Aber wie gesagt wäre das wohl sehr viel Arbeit. Mich würde nur interessieren wie sowas aussehen würde.

Schrobi

PS. bin ja dankbar dass es diese Methode gibt und freu mich ja auch wie ein großer, dass mein Prog läuft


----------



## faetzminator (22. Jun 2009)

Schau dir z.B. Quicksort ? Wikipedia an


----------



## schrobi (22. Jun 2009)

Ok, also die Sortiermethode .sort basiert auf Quicksort habe ich nun mehreren Quellen entnommen. Dazu hätte ich nun eine Verständnisfrage. Hoffe Ihr steinigt mich gleich nicht.

Warum muss man den String vorher sortieren? Dass es mit diese Methode sehr einfach ist steht ja außer Frage. Ist ja echt wenig Code benötigt worden. Aber würde es auch ohne gehen? Also einfach den String von links nach recht "abfahren" und die Worte in einer Tabelle speichern wobei die jeweilige Anzahl der Worte dann inkrementiert wird wenn nötig.

Bitte entschuldigt diese Frage. Komm mir auch echt doof dabei vor aber irgendwie komme ich nicht darauf klar, dass der Code so simpel ist.

Schrobi


----------



## bygones (22. Jun 2009)

schau dir doch den Thread an - da wurde es doch mit Maps (was du als Tabelle schreibst) geloest


----------



## Schandro (22. Jun 2009)

> Also einfach den String von links nach recht "abfahren" und die Worte in einer Tabelle speichern wobei die jeweilige Anzahl der Worte dann inkrementiert wird


Genau das hab wir ja weiter oben bereits gepostet (die Lösung mit der HashMap). Da du aber keine HashMap einsetzen wolltest, ging diese Lösung nicht.

Oder wie würdest du so eine "Tabelle" mit Arrays programmieren? (außer ne eigene HashMap zu programmieren, diese beruht schlussendlich auch auf Arrays...  )


----------



## schrobi (22. Jun 2009)

Hm, ich war verwirrt ;o)

Meinte mit Tabelle immer ein Array, aber da es ja hier um ein eindimensionales Array laufen müsste ist natürlich auch das Wort Tabelle völlig falsch. 

Also ich habe mich entschieden es bei der  Arrays.sort(words); Version zu belassen. 
Habe dazu aber noch eine Verständnisfrage welche sich mit google nicht beantworten ließ.
Was genau macht das ("\\W+")?
Soweit ich mir aus den googletreffern und meinem Menschenverstand zusammenreimen konnte werden damit die Worte des Strings getrennt und sämtliche Sonderzeichen (chars?) wie ",.:; etc" entfernt. Ist das so richtig?

Schrobi


----------



## Schandro (22. Jun 2009)

> \\W+


Das ist ne regular expression (RegEx)

Das \\W steht für: ein Zeichen, das weder Buchstabe noch Zahl noch Unterstrich ist
Normalerweise lautet der Ausdruck:
\W  
da man aber innerhalb des Java-Quellcodes die backslashes maskieren muss wenn man das Zeichen "\" verwenden will, muss man einen zweiten \ davorschreiben.

Das + steht für: Der voranstehende Ausdruck muss mindestens einmal vorkommen, darf aber auch mehrfach vorkommen.


Insgesamt bedeutet split("\\W+") also, das an jeder Stelle, wo ein oder mehrere Zeichen vorkommen, die nicht Buchstabe, Zahl oder Unterstrich sind, der String geteilt wird. Jeder einzelner dieser Teilstrings steht dann nacheinander im String-Array, das returnt wird. Die stellen ansich, an denen die Strings geteilt wurden, kommen nicht mehr vor! (Deswegen beinhaltet das words-Array keine Leerzeichen mehr...)


----------



## schrobi (22. Jun 2009)

Aah danke.
Guck ich mir mal an den Wiki-Link.


----------



## schrobi (29. Jun 2009)

Hallo liebe Forumsmitprogger

Ich muss euch ein letztes Mal (in diesem Semester  ) um Hilfe bitten.

Also hier erstmal mein fertiger, funktionierender Quellcode:

Tester:

```
import java.io.*; 

/**.
 *WordCounterTester.java
 *Programm zum Testen der Klasse WordCounter.java
 *
 */
public class WordCounterTester {

    /**
     *Mainmethode. Instanziert ein Objekt der Klasse WordCounter und führt 
     *dessen Methode show(); aus.
     *
     *@param args nothing.
     */
    public static void main(String[] args) {
        
        //Aufforderung zur Eingabe eines Strings.
        System.out.println("Bitte Text eingeben!");
        
        //Erstelleun einer neuen Instanz der Klasse WordCounter.
        WordCounter wordCount = new WordCounter();
        
        //Aufrufen der Mehtode show(); der Klasse WordCounter.
        wordCount.show();
    }
    
}
```

und das Hauptprog:

```
import java.io.*; 
import java.util.Arrays; 

/**.
 *WordCounter.java
 *Zaehlt die einzelnen Worte in einem Text und gibt deren Anzahl aus.
 *
 */
 
public class WordCounter {

    /** Eingabe des Nutzers. */ 	
    String eingabe;
 	
 	/** Methode zum Einlesen der Nutzereingabe.*/	
 	public void readIn() {
	
        BufferedReader br = new BufferedReader(
                    new InputStreamReader(System.in));
        try {
            eingabe = br.readLine();
        } catch (IOException e) {
            e.printStackTrace(); // Fehler ausgeben
            System.exit(0); // Programm abbrechen
        }
    }
  	
 	/** Methode zum verarbeiden des eingelesenen Strings.*/ 
    public void count() {
    	
    	//ruft die Methode readIn(); auf.
    	readIn();
    	
    	//Teilen des Strings und Uebergabe der Teilstrings in das Array woerter[].      
        String[] woerter = eingabe.split("\\W+");
        
        Arrays.sort(woerter);
        
        int zaehler = 1;
        String wort = woerter[0];
        
        for (int i = 1; i < woerter.length; ++i) {
            if (!woerter[i].equals(wort)) {
                System.out.println(wort + " kommt " + zaehler + " mal vor.");
                wort = woerter[i];
                zaehler = 1;
            } else {
                ++zaehler;
            }
        }
        System.out.println(wort + " kommt " + zaehler + " mal vor.");
    }
  
    /** Methode zum Ausgeben der berechneten Werte.*/
    public final void show() {
        
        //ruft die Methode count(); auf.
 		count();
  	}
 
}
```

Soo, nun zum Problem.
Habe als Feedback folgendes bekommen:


> Ich habe aber im Forum einen Betrag geschrieben, wie wir uns die Lösung der Aufgabe vorstellen.
> 
> Was wir unbedingt erwarten, ist das sie die Wörter mit der zugehörigen Anzahl in einer Liste/Array vom Type WordCounter speichern und in einem übergeorneten Objekt WordTable organisieren.



Der Forumsbeitrag von dem die Rede ist:

```
public static void main(String[] args) {
String testText = "was wahr ist, ist wahr, und was falsch ist, ist falsch.";
WordCounter wc = new WordCounter(testText);
wc.countWords(); // countWords() müsste dann public sein!
}
```



> Der Tester erzeugt und benutzt einen Wordcounter (siehe oben). WordCounter.countWords() benutzt ein WordTable. WordTable organisiert die gefunden Wörter aus der Zeichenkette in einem Attribut vom Typ WordElement[] (hier als Beispiel ein Array vom Typ WordElement). Beachten sie dabei, dass WordElement ein eigener datentyp ist, der sowohl das Wort als auch die Anzahl aufnehmen kann. Einzelne Objekte von WordElement können wie in anderen Array über einen Index angesprochen werden (wordElementArray_.getWord(), wordElementArray.getCount(), etc.)._


_

So, nun steh ich wieder davor und denk.. hääää?
Wäre nett wenn mir das mal jemand auf "n00bisch" also anfängertauglich und evtl. mit Beispiel erklären würde.

Vielen Dank schonmal

Euer viel fragender Schrobi_


----------



## Schandro (29. Jun 2009)

Ich würds so verstehen:
(das printTable gehört nicht zu deiner Aufgabenstellung)

```
package snippetbin.wordcounter;

import java.util.Arrays;


public class Main {
	
	public static void main(String[] args) {
		String testText = "was wahr ist, ist wahr, und was falsch ist, ist falsch.";
		WordCounter wc = new WordCounter(testText);
		System.out.println(wc.countWords());
		wc.printTable();
	}
}

class WordCounter{
	
	private String originalText;
	private WordTable wordTable;
	
	public WordCounter(String text){
		this.originalText = text;
		
		String[] words = originalText.split("\\W+");
		wordTable = new WordTable(words.length); // words.length stellt sicher, dass die WordTable auf jedenfall groß genug initialisiert wird.
	
		for(String word : words){
			wordTable.addWord(word);
		}
	}
	

	
	public int countWords(){
		return wordTable.getDifferentWordsCnt();
	}
	
	public void printTable(){
		wordTable.printTable();
	}
}

class WordTable{
	private WordElement[] elements;
	private int nextEmptyArrayPosition = 0;
	
	public WordTable(int maxSize){
		elements = new WordElement[maxSize];
	}
	
	public int getDifferentWordsCnt(){
		return nextEmptyArrayPosition;
	}
	
	public void printTable(){
		for(WordElement element : elements){
			if(element == null){
				break;
			}
			System.out.println(element);
		}
	}
	
	public void addWord(String word){
		int index = getIndex(word);
		if(index == -1){
			newWord(word);
		}
		else{
			elements[index].setCnt(elements[index].getCnt()+1);
		}
	}
	
	private void newWord(String word){
		try{
			elements[nextEmptyArrayPosition++] = new WordElement(1,word);
		}
		catch(ArrayIndexOutOfBoundsException e){
			e.printStackTrace();
			System.out.println("Die WordTable ist nicht groß genug.");
		}
	}
	
	
	private int getIndex(String word){
		for(int i=0;i<nextEmptyArrayPosition;++i){
			if(elements[i].getWord().equals(word)){
				return i;
			}
		}
		
		return -1; // elements enthält das gesuchte Word noch nicht
	}
}

// Container-Class
class WordElement{
	private String word;
	private int cnt; // wie oft es vorkommt
	
	public WordElement(int cnt, String word) {
		this.cnt = cnt;
		this.word = word;
	}
	
	public String getWord() {
		return word;
	}
	public void setWord(String word) {
		this.word = word;
	}
	public int getCnt() {
		return cnt;
	}
	public void setCnt(int cnt) {
		this.cnt = cnt;
	}
	
	@Override
	public String toString(){
		return cnt+" x "+word;
	}
	
}
```


----------

