Soluzione 5.5

La classe TextContainer (piu` sotto si trova il codice della classe TextAnalyzer). Studiare con attenzione il corpo di tutti i metodi realizzati. In particolare
import java.util.Scanner;

public class TextContainer
{
    /*
    costruttore di un analizzatore di testo vuoto
    */
    public TextContainer()
    {
        text = new String[1];
        tSize = 0;  
    }

    /*
      verifica se il testo e` vuoto, restituisce
      true se l'oggetto non contiene testo, false altrimenti
    */
    public boolean isEmpty()
    {
        return tSize == 0;
    }

    /*
      aggiunge la stringa "stringa" in coda al testo. Termina senza errori
      se String stringa e` uguale a null.
    */
    public void add(String stringa)
    {
        if (stringa == null)
            return;
        if (tSize == text.length)
            resize();
        text[tSize] = stringa;
        tSize++;
    }

    /* 
        solito metodo resize, questa volta senza parametri e senza valori
        restituiti perche` deve elaborare campi di esemplare
    */
    private void resize()
    {
        String[] newtext = new String[2*text.length];
        System.arraycopy(text,0,newtext,0,text.length);
        text = newtext;
    }

    /*
     conta e restituisce il numero di stringhe nel testo
    */
    public int count()
    {
        return tSize;
    }

    /*
     separa le stringhe del testo in parole. Crea un nuovo oggetto di classe
     TextContainer in cui tutte le parole sono separate, e ne restituisce il
     riferimento. Usa l'insieme di delimitatori di default di Scanner, ovvero
     "\p{JavaWhitespace}" (cfr. la documentazione di Scanner, in particolare
     dei metodi delimiter e useDelimiter, e la documentazione della classe
     Pattern)
    */
    public TextContainer splitWords()
    {
        return splitWords("\\p{javaWhitespace}");
    }

    /*
     separa le stringhe del testo in parole. Crea un nuovo oggetto di classe
     TextContainer in cui tutte le parole sono separate, e ne restituisce il
     riferimento. Usa l'insieme di delimitatori specificato dalla stringa delim
     (si veda la documentazione di Scanner, in particolare dei metodi delimiter
     e useDelimiter, e la documentazione della classe Pattern)
    */
    public TextContainer splitWords(String delim)
    {
        TextContainer cont = new TextContainer();
        for (int i = 0; i < tSize; i++)
        {
            Scanner stok = new Scanner(text[i]);
            stok.useDelimiter(delim);
            while (stok.hasNext())
                cont.add(stok.next());
        }
        return cont;
    }

    /*
     Crea un nuovo oggetto di di tipo TextContainer in cui tutte le occorrenze
     della stringa "stringa" sono state eliminate.
     - Se la stringa compare piu` volte vengono eliminate tutte le occorrenze.
     - Lancia IllegalArgumentException se il parametro esplicito e` null.
     Attenzione: si devono scandire tutte le stringhe del testo perche`
     la parola da cancellare puo` comparire piu` volte nel testo.
    */
    public TextContainer remove(String stringa)
    {
        if (stringa == null)
            throw new IllegalArgumentException();
        for (int i = 0; i < tSize; i++)
        {   //questo ciclo while serve a gestire correttamente il caso in cui si
            //abbiano piu` occorrenze di stringa in elementi contigui dell'array
            int j=0;
            while (i+j < tSize && text[i+j].equals(stringa) )
                j++;
            //Ho trovato j elementi di text che coincidono con "stringa". Li
            //cancello sovrascrivendoli con la parte successiva dell'array
            System.arraycopy(text, i+j, text, i, tSize-i-j);
            tSize -= j;
        }
        TextContainer cont = copy();
        return cont;
    }

    /*
      Restituisce il numero di occorrenze nel testo della stringa "stringa". 
      Lancia IllegalArgumentException se il parametro esplicito e` null.
    */
    public int frequency(String stringa)
    {
        if (stringa == null)
            throw new IllegalArgumentException();
        int count = 0;
        for (int i = 0; i < tSize; i++)
            if (text[i].equals(stringa)) count++;
        return count;
    }

    /*
      restituisce la stringa che compare piu` volte nel testo (freq. massima).
      Se piu` stringhe hanno frequenza massima, ne restituisce una qualsiasi.
      Se il testo e` vuoto restituisce null.
    */
    public String maxFrequency()
    {
        String max = text[0];
        for (int i = 1; i < tSize; i++)
            if (frequency(text[i])>frequency(max))
                max = text[i];
        return max;
    }

    /*
      restituisce la prima stringa del testo in ordine lessicografico.
      Se il testo e` vuoto restituisce null.
    */
    public String min()
    {
        String min = text[0];
        for (int i = 1; i < tSize; i++)
            if (text[i].compareTo(min) < 0)
                min = text[i];
        return min;
    }

    /*
      restituisce l'ultima stringa del testo in ordine lessicografico.
      Se il testo e` vuoto restituisce null.
    */
    public String max()
    {
        String max = text[0];
        for (int i = 1; i < tSize; i++)
            if (text[i].compareTo(max)>0)
                max = text[i];
        return max;
    }

    /*
      trasforma il testo in stringa. Viene inserito un carattere di nuova riga (\n)
      fra le stringhe. Se il testo e` vuoto restituisce la stringa vuota "".
    */
    public String toString()
    {
        String s = "";
        for (int i = 0; i < tSize; i++)
            s = s + text[i] + "\n";
        return s;            
    }

    /*
      crea un nuovo oggetto di tipo TextContainer in cui tutti i caratteri non 
      alfabetici sono stati eliminati dalle stringhe del testo. Ad esempo elimina 
      la punteggiatura, i numeri, le parentesi. Usa il metodo 
      java.lang.Character.isLetter(char c)
    */
    public TextContainer onlyLetters()
    {
        TextContainer cont = new TextContainer();
        for (int i = 0; i < tSize; i++)
        {
            String s = "";
            for (int j = 0; j < text[i].length(); j++)
            {
                char c = text[i].charAt(j);
                if (Character.isLetter(c))  s = s + c;
            }
            if (s.length() != 0)
                cont.add(s);
        }
        return cont;
    }

    /*
     crea un nuovo oggetto di tipo TextContainer nel quale tutti i caratteri
     maiuscoli sono stati convertiti in minuscoli.
    */
    public TextContainer toLowerCase()
    {
        TextContainer cont = new TextContainer();
        for (int i = 0; i < tSize; i++)
            cont.add(text[i].toLowerCase());
        return cont;
    }

   /*
     crea una copia dell'oggetto TextContainer, e ne restituisce il riferimento
   */
   public TextContainer copy()
    {
        TextContainer cont = new TextContainer();
        for (int i = 0; i < tSize; i++)
            cont.add(text[i]);
        return cont;
    }

    private String[] text;
    private int tSize;
}

La classe TextAnalyzer.
import java.util.Scanner;

public class TextAnalyzer
{
    public static void main(String[] args)
    {
        boolean debug = true;
 
        //lettura da standard input
        Scanner in = new Scanner(System.in);

        //definizione oggetto di classe AnalizzatoreDiTesto
        TextContainer testo = new TextContainer();

        //memorizzazione del testo
        while (in.hasNextLine())
        {   String riga = in.nextLine();
            testo.add(riga);
        }

        //separazione delle parole e verifica relativa
        TextContainer tSeparato = testo.splitWords("['\\p{javaWhitespace}]+");

        //eliminazione dei caratteri non alfabetici e verifica relativa
        TextContainer tAlfabetico = tSeparato.onlyLetters();

        //conversione in caratteri minuscoli e relativa verifica
        TextContainer tMinuscolo = tAlfabetico.toLowerCase();

        if (debug)
        {   System.out.println("*** Debug: testo con parole separate ***");
            System.out.println(tSeparato);
            System.out.println("*** Debug: testo solo alfabetico ***");
            System.out.println(tAlfabetico);
            System.out.println("*** Debug: testo minuscolo ***");
            System.out.println(tMinuscolo); 
        }

        //stampa del testo originale
        System.out.println("***TESTO ORIGINALE***");
        System.out.println(testo);
        System.out.println("***FINE TESTO ORIGINALE***");

        //analisi del testo
        System.out.println("\n***ANALISI DEL TESTO***");
        System.out.println("Testo di " + tMinuscolo.count() + " parole");
        System.out.println(tMinuscolo.min() + 
                            ": prima parola in ordine lessicografico");
        System.out.println(tMinuscolo.max() + 
                            ": ultima parola in ordine lessicografico");

        /*
          l'algoritmo per ordinare le parole secondo la loro frequenza non รจ
          efficiente! Studieremo algoritmi efficienti. Per ora elenchiamo
          le parole in ordine decrescente di frequenza seplicemente estraendo
          dal testo la parola di frequenza massima e cancellandola
          successivamente (cancella restituisce l'occorrenza della parola)
        */
        TextContainer tmpTesto = tMinuscolo.copy();

        int maxi = 5;
        int i = 1;
        while (i <= maxi && !tmpTesto.isEmpty())
        {   String tmpStr = tmpTesto.maxFrequency();
            int n = tmpTesto.frequency(tmpStr);
            System.out.println("\nParola piu` frequente n. " + i + ": " + 
                                tmpStr + " (" + n + " occorrenze)");

            tmpTesto = tmpTesto.remove(tmpStr);
            i++;
            if (debug)
            {
                System.out.println("\n*** Debug: testo dopo rimozione ***");
                System.out.println("*** ha " +tmpTesto.count()+ " parole ***");
                System.out.println(tmpTesto+"\n");
            }
        }
    }
}