Visualizzazione dei risultati da 1 a 9 su 9
  1. #1

    Altro esercizio....altro problema...

    Stavo provando a risolvere un esercizio:

    "Si realizzi un programma Java che prende in input un file di testo e poi stampi in
    un file di output la frequenza con cui i singoli caratteri dell'alfabeto appaino nel
    documento. I simboli di punteggiatura non devono essere considerati. Inoltre non
    dovrą essere fatta distinzione tra caratteri maiuscoli e caratteri minuscoli. I caratteri
    dovranno essere visualizzati nel file di output in ordine alfabetico. Le frequenze dei
    caratteri dovranno essere espresse in forma percentuale con al pił due cifre decimali
    per ogni valore (arrotondate per difetto)."

    Ho provato a risolverlo, suppongo troverete tante stranezze..

    Ad ogni modo, il problema č che viene generata un' Exception in thread "main" java.util.NoSuchElementException.

    Dovrebbe dipendere dal fatto che continua a lavorare dopo che l'input č finito, ma non riesco a capire perchč i miei controlli non funzionano allora.

    codice:
    import java.io.*;
    import java.util.Scanner;
    
    public class EsercizioVII
    {
    	public static void main(String []args) throws IOException
    	{
    		Scanner s=null;
    		FileReader reader=null;
    		BufferedReader in=null;
    		PrintWriter out=null;
    		
    		try{
    			s=new Scanner("input.txt");
    			reader=new FileReader("input.txt");
    			in=new BufferedReader(reader);
    			out=new PrintWriter("OUTPUT.txt");
    			
    			
    			int righe=0;
    			char a=97;                     //il primo carattere che considererņ
    			double percent=0.0;
    			
    			
    			while(in.readLine()!=null)
    			{
    				righe++;
    			}
    			
    			
    			int [] ripetizioni=new int[26];
    			
    			for(int i=0; i<26; i++)                                           //Creo un array dove memorizzerņ per ogni lettera il numero di ripetizioni
    			ripetizioni[i]=0;
    			
    		
    			for(int i=0; i<26; i++)                                        //Il for mi serve per controllare le varie lettere e incrementare le ripetizioni
    			{
    				
    				//reader=new FileReader("input.txt");
    				//in=new BufferedReader(reader);
    				
    				s=new Scanner("input.txt");                            //inizializzo sempre da capo lo Scanner
    				
    				while(s.next()!=null)                                          //Finchč ci sono caratteri
    				{
    					if((Integer.parseInt(s.next()))==(int)a || (Integer.parseInt(s.next()))==(int)(a-32) || (Integer.parseInt(s.next()))==(int)(a+32)) //Se nel rigo trovo la stessa lettera maiuscola o minuscola
    						ripetizioni[i]++;
    				}
    					a++;                                           //cambio la lettera.
    					percent=(double)(ripetizioni[i])/(double)(righe);
    				
    				out.print(percent);
    				
    			}
    			}
    			
    		finally{
    			if(s!=null)s.close();
    				if(reader!=null)reader.close();
    			if(in!=null)in.close();
    			if(out!=null)out.close();
    			}
    	}
    	
    	
    }

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Un po' di cose:

    a) Se non devi lavorare "a righe" (e appunto non sembra il tuo caso da come ne parla il testo iniziale), non serve necessariamente BufferedReader e il suo readLine(). Basta usare direttamente FileReader e leggere 1 carattere per volta o meglio (per questioni di performance) leggere "a blocchi" di char per volta.

    b) Se devi conteggiare la frequenza dei soli caratteri alfabetici (senza distinzione del case) va bene appunto usare un array int[] di 26 elementi. Nota che non serve azzerare esplicitamente l'array!! Le regole di Java prevedono che gli elementi dell'array siano gią al loro valore di "default", 0 per int.

    c) Non capisco perché stai cercando di conteggiare le righe del file, non mi pare di leggere nel testo iniziale qualche cosa che indica di contare le righe e/o usare questo conteggio per fare "qualcosa".
    Le percentuali che devi calcolare io ho dedotto (e sarebbe anche intuitivo) che devono essere calcolate sul totale delle occorrenze. Cioč la somma di tutte le occorrenze rappresenta il 100% che č suddiviso tra le varie lettere. Se per es. avessi solo 3 caratteri: A 10 occorrenze, B 5 occorrenze, C 20 occorrenze, allora la somma 35 rappresenta il 100% quindi A č 10/35 (= 29% circa), B č 5/35 (14% circa) e C č 20/35 (57% circa).
    Il numero di righe quindi io deduco che non centra una mazza .....

    d) Pertanto non vedo perché devi leggere il file 2 volte.

    e) Non vedo a cosa ti serva usare Scanner, il suo next() (che tra l'altro stavi usando male perché č nella condizione del while e tu non usi il token che ti restituisce) e non serve nemmeno usare parseInt(). Non devi "parsare" nulla.
    Non devi nemmeno fare il ciclo for da i=0 per i<26 mentre stai scansionando il file.

    Rivaluta tutto molto bene, perché c'č poco che ha senso nel tuo codice.

    La cosa č molto semplice:
    - Usi FileReader.
    - leggi 1 char per volta (o meglio un blocco di char per volta).
    - per ogni carattere verifichi che sia una lettera.
    - se č una lettera ne deduci l'indice nell'array delle ripetizioni.
    - Il valore nell'array delle ripetizioni all'indice determinato lo incrementi di 1.

    Alla fine fai i calcoli delle frequenze.
    Fine della storia.
    Andrea, andbin.dev – Senior Java developer – SCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat Sheet — Java Versions Cheat Sheet

  3. #3
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,472

    Moderazione

    Originariamente inviato da Darčios89
    Altro esercizio....altro problema...
    Usiamo titoli pił significativi per le discussioni, come da Regolamento.

    Questo lo correggo io.
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  4. #4
    Mi scuso per il titolo del post.
    Non sto riuscendo a fare il controllo, non c'č bisogno di parsare??

    codice:
    String str=s.next();
    					if((Integer.parseInt(str))==a ||(Integer.parseInt(str))==a-32)
    Perchč sbaglio, il metodo s.next() dovrebbe restituire una stringa, io la converto nell'if in un intero e poi vedo se č uguale ad a(variabile di confronto dichiarata prima che cambio di volta in volta)
    oppure se č uguale ad a-32(in questo caso 65 sarą 'A')
    Perchč genera:

    Exception in thread "main" java.lang.NumberFormatException: For input string: "input.txt"

  5. #5
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da Darčios89
    Non sto riuscendo a fare il controllo, non c'č bisogno di parsare??
    Ma hai letto tutto quanto ho scritto prima??

    Non vedo perché devi usare Scanner e perché devi "parsare" qualcosa. Tu dal file con FileReader puoi leggere "caratteri" e avendo il carattere i-esimo non solo puoi fare un banale test per vedere se "cade" nel range di una lettera a-z o A-Z ma anche facilmente ricavare l'indice da usare nell'array delle occorrenze.

    codice:
    char unCarLetto;
    int indice;
    
    ....
    
    if (unCarLetto >= 'a' && unCarLetto <= 'z') {
        indice = unCarLetto - 'a';
    } else ....
    .....
    Andrea, andbin.dev – Senior Java developer – SCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat Sheet — Java Versions Cheat Sheet

  6. #6
    D'accordo, mi metto al lavoro..

  7. #7
    Si perfetto grazie, di funzionare funziona, ora c'č un piccolissimo problema, il file di output bisogna scriverlo nella seguente fora:

    Se ho :

    0.16987889

    Nell'output sarą:

    1.69.


    Ora per sostare la virgola basta moltiplicare per 10 no?
    Perņ per togliere tutte le altre cifre?
    Ho provato a convertire da double a String il mio numero, perchč ho pensato di utilizzare una charAt in modo da concatenare solo i primi caratteri che mi servono in una stringa vuota che sarą scritta.
    Il problema credo sia la virgola, mi dą un' eccezione di tipo IndexoutofBounds:

    codice:
    			for(int i=0; i<26; i++)
    			{
    				double conto=((double)ripetizioni[i]/(double)occorrenze)*10;
    				
    				int j=0;
    				String percent="";
    				String convertita=Double.toString(conto);
    				
    				while(j<=3)
    				{
    					percent+=convertita.charAt(j);
    					j++;
    				}

  8. #8
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da Darčios89
    Ora per sostare la virgola basta moltiplicare per 10 no?
    Perņ per togliere tutte le altre cifre?
    Ho provato a convertire da double a String il mio numero, perchč ho pensato di utilizzare una charAt in modo da concatenare solo i primi caratteri che mi servono in una stringa vuota che sarą scritta.
    No, evita 'ste robe.

    In generale, se si vuole troncare un double a N decimali (e qui non parliamo di formattazione in String ma proprio del calcolo) la prassi tipicamente č:
    - si moltiplica per 10^N
    - si tronca con Math.floor()
    - si divide per 10^N

    Visto che tu hai gią un valore dovuto alla divisione compreso tra 0 e 1 e vuoi ottenere una percentuale con 2 cifre decimali:

    double perc = Math.floor(ripetizione_iesima / totale_occorrenze * 10000) / 100;

    Ovviamente metti i cast a double dove necessario se non sono gią double i valori. Io ho solo scritto la cosa a livello generale.
    Andrea, andbin.dev – Senior Java developer – SCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat Sheet — Java Versions Cheat Sheet

  9. #9
    Perfetto, grazie mille per l'aiuto, adesso č tutto corretto.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.