Errore Logico Ricorrente

di il
9 risposte

Errore Logico Ricorrente

Salve a tutti gli utenti; apro questo nuovo topic per segnalare una tipologia di errore (di natura logica) che non tarda mai a comparire durante parecchi dei miei abituali esercizi.
Nonostante il compilatore non sembri segnalarmi eventuali errori relativi al registro sintattico usato per scrivere, l'errore che compare,di recente ormai a tempo di esecuzione, comincia ad innervosirmi non poco.
L'errore viene evidenziato quando, immettendo i dataset in input che non comportano la verifica della condizione del ciclo di iterazione, si ha un risultato differente da quello atteso in output.
Non saprei scendere più nel dettaglio di quanto non lo abbia fatto con queste parole, e se come penso, non foste riusciti a capire quale sia l'effettivo problema, vi invito caldamente a prendere il codice ed eseguirlo, sul vostro calcolatore, con qualsiasi possibile dataset immaginabile così da poter comprendere a pieno l'errore che sto cercando di segnalare.
Mi appello dunque nuovamente al vostro saggio consiglio sperando di venirne a capo.
Essendo ricorrente in più esercizi sono stato costretto a convenzionare il titolo di questo topic in modo molto generico, non potendo scendere più nel particolare, indi per cui sarò costretto ad elencare la specifica del problema per ogni pezzo di codice postato qui sotto.
Grazie Molte in anticipo. Buona Serata.

1) ARRAY CRESCENTE:
/*1)Specifica del problema
Input: Array di interi a
Precondizioni: a non nullo e non vuoto

Output: b booleano
Postcondizioni: b e’ vero se la sequenza di elementi di a è ordinata in modo crescente

E’ un problema di Verifica Esistenziale.*/

import fiji.io.*;
class ArrayCrescente {
  public static void main(String[] args) {
    System.out.println("di quanti elementi vuoi che sia composto il tuo array?");
    final int ea = Lettore.in.leggiInt();
    int[] a = new int[ea];
    System.out.println("scrivi" + " " +ea+ " " + "interi, gli elementi della tua sequenza");
    for (int i = 0; i<ea; i++) {
    a[i] = Lettore.in.leggiInt();
    System.out.println();
    }
    Crescente(a);
    }

  public static boolean Crescente(int[] a) {
	int i;
    boolean crescente;
    for(i=0; i<a.length-1; i++) {
      if (a[i] < a[i+1]) {
      crescente = true;
      }
      else {
      crescente = false;
      }
    }
    if (crescente = true) {
    System.out.println("La sequenza è ordinata in modo crescente");
    }
    else {
    System.out.println("La sequenza non è ordinata in modo crescente");
    }
    return crescente;
  }
}
2) ADIACENTI DIVERSI:
/* 1)Specifica del problema
Input: stringa s
Precondizioni: s non nulla e non vuota

Output: b booleano
Postcondizioni: b e’ vero se tutti i caratteri adiacenti della stringa s sono differenti.

E’ un problema di verifica esistenziale. */
import fiji.io.*;
class AdiacentiDiversi {
  public static void main(String[] args) {
  System.out.println("Immetti una stringa: ");
  String s = Lettore.in.leggiLinea();
  System.out.print("");
  adiacentidiversi(s);
  }

  public static boolean adiacentidiversi(String s) {
	  int i = 0;
	  boolean adiacenti = false;
  while (i < 1) {
  adiacenti = false;
  i++;
  }
  for (i = 1; i<=s.length()-1; i++)
    if( s.charAt(0) == s.charAt(i)) {
      adiacenti = true;
      }
      else {
	  adiacenti = false;
      }
      if (adiacenti = true) {
	  System.out.println("non tutti i caratteri adiacenti della stringa s sono differenti");
      }
      else {
	  System.out.println("tutti i caratteri adiacenti della stringa s sono differenti");
      }
      return adiacenti;
      }
  }
3) SUFFISSO:
/* 1)Specifica del problema
Input: stringhe s,t
Precondizioni: s,t non nulle e non vuote
Output: b booleano
Postcondizioni: b e’ vero se la stringa t è un suffisso della stringa s.
E’ un problema di verifica esistenziale. */
import fiji.io.*;
public class Suffisso {
  public static void main (String[] args) {
  System.out.println("scrivi le due stringhe che vuoi scandire: ");
  String s = Lettore.in.leggiLinea();
  String t = Lettore.in.leggiLinea();
  suffisso(s,t);
  }

  public static boolean suffisso(String s, String t) {
    boolean suffisso=false;
    int i; //contatore
    if (s.length() >= t.length()) {
    for(i=t.charAt(0); i<=t.length(); i++)
      if (t.charAt(i) == s.charAt(i)) {
      suffisso=true;
     }
    }
      else {
      suffisso=false;
      }
      if (suffisso=true) {
      System.out.println("La stringa T è un suffisso della stringa S");
      }
      else {
      System.out.println("La stringa T non è un suffisso della stringa S");
      }
      return suffisso;
  }
  }

4) CARATTERI UGUALI:
/* Specifica del problema
Input: stringa s
Precondizioni: s non nulla e non vuota

Output: b booleano
Postcondizioni: b e’ vero se tutti i caratteri della stringa data sono uguali

E’ un problema di verifica universale. */
import fiji.io.*;
class CaratteriUguali {
  public static void main(String[] args) {
	System.out.println("Inserisci la stringa su cui vuoi avviare la scansione: ");
	String s = Lettore.in.leggiLinea();
	TuttiUguali(s);
}
  public static boolean TuttiUguali(String s) {
	int i;
	boolean tuttiuguali=true;
	for (i = 0; i<s.length()-1; i++) {
	  if (s.charAt(i) == s.charAt(i+1)) {
		  tuttiuguali = true;
	  }
	  else {
		  tuttiuguali = false;
    	}
	if (tuttiuguali = true) {
			System.out.println("tutti i caratteri della stringa data sono uguali;");
		}
		if (tuttiuguali = false) {
			System.out.println("non tutti i caratteri della stringa data sono uguali");
	}
	}

    return tuttiuguali;
  }
}

9 Risposte

  • Re: Errore Logico Ricorrente

    Ciao partiamo dal primo: un esempio di codice corretto è il seguente.
    
    class ArrayCrescente {
    	public static void main(String[] args) {
    		Scanner sc = new Scanner(System.in);
    		System.out.println("di quanti elementi vuoi che sia composto il tuo array?");
    		final int ea = sc.nextInt();
    		sc.nextLine();
    		int[] a = new int[ea];
    		System.out.println("scrivi" + " " +ea+ " " + "interi, gli elementi della tua sequenza");
    		for (int i = 0; i<ea; i++) {
    			a[i] = sc.nextInt();
    			sc.nextLine();
    		}
    
    		sc.close();
    		boolean crescente = Crescente(a);
    
    		if (crescente == true) {
    			System.out.println("La sequenza è ordinata in modo crescente");
    		}
    		else {
    			System.out.println("La sequenza non è ordinata in modo crescente");
    		}
    	}
    
    	public static boolean Crescente(int[] a) {
    		int i;
    		for(i=0; i<a.length-1; i++) {
    			if (a[i] > a[i+1]) {
    				return false;
    			}
    		}
    		return true;
    	}
    }
    Il problema nel tuo codice era di logica: nel metodo che hai chiamato Crescente (l'ho lasciato così anche se non andrebbe con la maiuscola) il valore del boolean crescente poteva assumere il valore true o false ad ogni iterazione del ciclo for. Invece no! Se trovi una coppia di elementi non ordinata devi IMMEDIATAMENTE concludere che la sequenza non è ordinata. Oltretutto il metodo Crescente dovrebbe solo ritornare un boolean (come nel mio codice) e non occuparsi della comunicazione con l'utente. A meno ovviamente di necessità specifiche.
    Poi c'era un errore quando facevi
    if(crescente=true)
    Il confronto si fa con il doppio uguale.

  • Re: Errore Logico Ricorrente

    Ti ringrazio Minomic innanzitutto per la risposta repentina che mi hai fornito;

    if(crescente=true)

    Il confronto si fa con il doppio uguale.
    Mea Culpa non c è dubbio! Mi è bastato correggere l'operatore di assegnazione per accorgermi non solo che la tipologia di errore rilevata èra di semantica dinamica e non logica ma anche a far in modo che l'esecuzione terminasse nel modo giusto. GRAZIE!
    nel metodo che hai chiamato Crescente (l'ho lasciato così anche se non andrebbe con la maiuscola)
    Non penso che la maiuscola vada ad incidere sull'esecuzione ma provvedo subito per correggere.
    public static boolean Crescente(int[] a) {
    int i;
    boolean crescente;
    for(i=0; i<a.length-1; i++) {
    if (a > a[i+1]) {
    return false;
    }
    }
    return true;
    }
    }


    L'unica cosa che mi ha fatto un pò storcere il naso sono quei due return.. ai fini della programmazione strutturata che dovrebbe di norma procedere con un punto di ingresso e uno di uscita mi sembra poco corretto; naturalmente solo per la sua leggibilità.
    Il problema che avevo comunque è stato risolto. Grazie Mille ancora per l'aiuto e Buona Serata
  • Re: Errore Logico Ricorrente

    Ciao,
    no il problema non era solo quello. Aggiungi pure il doppio uguale ma il codice continua ad essere errato. Dimostrazione: prova questo.
    Lunghezza della sequenza = 5
    Poi inserisci la sequenza 3 - 2 - 1 - 4 - 5

    La sequenza non è ordinata in modo crescente ma il tuo codice dirà di sì, mentre il mio dirà di no. Come mai? Prova a rifletterci e poi ne riparliamo.

  • Re: Errore Logico Ricorrente

    no il problema non era solo quello. Aggiungi pure il doppio uguale ma il codice continua ad essere errato. Dimostrazione: prova questo.
    Lunghezza della sequenza = 5
    Poi inserisci la sequenza 3 - 2 - 1 - 4 - 5
    Effettivamente hai ragione, dovrei riuscire ad uscire dal ciclo appena trovo un elemento che non soddisfa la condizione.. ci sto sbattendo la testa da un pò ma non riesco a trovare una soluzione che non contempli per forza l'utilizzo di due istruzioni return. Puoi darmi tu una mano?
  • Re: Errore Logico Ricorrente

    lukyluke93 ha scritto:


    non riesco a trovare una soluzione che non contempli per forza l'utilizzo di due istruzioni return.
    Ciao,
    l'utilizzo di due istruzioni return non è un errore. Ovviamente c'è una condizione if, quindi se succede qualcosa return true, altrimenti return false. Questo è il funzionamento base di un metodo che deve restituire un boolean, altrimenti se non ha la possibilità di ritornare un valore o l'altro... che senso ha?
  • Re: Errore Logico Ricorrente

    l'utilizzo di due istruzioni return non è un errore.
    Si si è più che corretto ci mancherebbe!
    è solo per curiosità o per un mio capriccio, che vorrei cercare di riscriverlo equivalentemente in modo strutturato.

    Ho provato a riscriverlo così e con tutti i dataset che ho provato fino ad ora, compresi quelli che mi hai inviato prima, sembra funzionare correttamente.. cosa ne pensi?
      public static boolean Crescente(int[] a) {
    	int i;
        boolean crescente = true;
        for(i=0; i<a.length-1; i++) {
          if (a[i] < a[i+1] && crescente) {
          crescente = true;
          }
          else {
          crescente = false;
          }
      }
      if (crescente == true) {
    	  System.out.println("La sequenza è ordinata in modo crescente");
      }
      else {
    	  System.out.println("La sequenza non è ordinata in modo crescente");
      }
        return crescente;
      }
    }
  • Re: Errore Logico Ricorrente

    In questo caso puoi fare in questo modo molto semplice:
    
    public class ArrayCrescenteDue {
    	
    	public static void main(String[] args) {
    		Scanner sc = new Scanner(System.in);
    		System.out.println("di quanti elementi vuoi che sia composto il tuo array?");
    		final int ea = sc.nextInt();
    		sc.nextLine();
    		int[] a = new int[ea];
    		System.out.println("scrivi" + " " +ea+ " " + "interi, gli elementi della tua sequenza");
    		for (int i = 0; i<ea; i++) {
    			a[i] = sc.nextInt();
    			sc.nextLine();
    		}
    
    		sc.close();
    		
    		boolean crescente = true;
    		for(int i=0; i<a.length-1; i++) {
    			if(a[i]>a[i+1]) crescente = false;
    		}
    		if(crescente) System.out.println("Crescente");
    		else System.out.println("Non crescente");
    	}
    
    }
  • Re: Errore Logico Ricorrente

    lukyluke93 ha scritto:


    Ho provato a riscriverlo così [...] cosa ne pensi?
    Per quanto riguarda il funzionamento mi sembra che sia a posto. Però devo dire che non mi sembra un codice ben strutturato. Ad esempio perché il tuo metodo ritorna un boolean? Chi lo usa quel valore ritornato dal metodo?
    Per come la vedo io hai tre possibilità:
    1 - fare come avevo fatto nel primo codice: un metodo che ritorna un boolean e il main che sfrutta questo valore per sapere cosa deve stampare all'utente
    2 - fare come ho fatto nel mio penultimo post: tutta l'elaborazione viene fatta nel main
    3 - fare come hai fatto tu ora: l'elaborazione (controllo dell'array) e la stampa del risultato vengono fatti in un metodo separato. Però a questo punto quel metodo dovrebbe essere di tipo void, dato che non restituisce nulla di interessante per il main.
  • Re: Errore Logico Ricorrente

    Un pò per soddisfazione personale, un pò per pigrizia, ho deciso di optare per la terza possibilità
    Grazie ancora Minomic per i consigli e buona giornata.
Devi accedere o registrarti per scrivere nel forum
9 risposte