Problema esercizio con Array

di il
6 risposte

Problema esercizio con Array

Ciao a tutti,
scrivo su questo forum perché riscontro un problema in un programma.

L'esercizio chiede di creare un portachiavi di un albergo, in cui ogni chiave deve essere identificata per nome e numero camera. Ogni cliente può depositare la chiave e poi prelevarla con nome o numero camera. Depositando una chiave, questa può essere posata nel primo posto disponibile del portachiavi.

Il mio problema è che alla creazione delle chiavi, se inserisco che voglio creare 2 o più chiavi (e quindi inserirò 2 o più nominativi), soltanto l'ultimo numero camera e l'ultimo nome, creeranno una chiave.
Vi lascio Main e le due classi "portachiavi" e "chiave".
public class JavaApplication11 {

    public static void main(String[] args) {
        
        Scanner tastiera = new Scanner(System.in); // scanner per input
        
        int num_cam; // numero camera
        int n; // numero massimo camere
        String nom; // nominativo chiave
        chiave schiave = null; // singola chiave di tipo chiave
        int risp = 0; //numero chiavi da creare

        
        System.out.print("Portachiavi \n");       
        System.out.print("Inserisci numero massimo chiavi: ");
        n = tastiera.nextInt();
        tastiera.skip("\n");
        
        portachiavi portachiave = new portachiavi(n); 
        
        for(int i=0;i<n;i++){   // creazione chiavi con numero e nom inizializzato a null
        System.out.print("Inserisci numero camera della chiave: ");
        num_cam = tastiera.nextInt();
        tastiera.skip("\n");
        nom = null;
        
        schiave = new chiave(nom, num_cam);
        portachiave.setchiave(i, schiave);    // inserimento chiavi in portachiave
        }
        
        System.out.print("Quante chiavi desideri creare ? ");
        risp = tastiera.nextInt();
        tastiera.skip("\n");
        
        for(int i=0;i<risp;i++){
            
            System.out.print("Inserisci nominativo chiave da creare: ");
                nom = tastiera.nextLine();
                schiave.setNom(nom);
                portachiave.setchiave(n, schiave);
            }

        System.out.print(schiave.toString()); //toString usato solo per controllare i dati che inserisco.
        
    }

}
public class portachiavi {
    
    private int n; //dichiarazione dimensione 
    private chiave schiave[]; //dichiarazione vettore schiave

    public portachiavi(int n) { //costruttore portachiavi
        this.n = n;
        this.schiave = new chiave[n];
    }
    
    public chiave getchiave(int i){
        if(i<0 || i>n-1){
        return null;
        }
        return schiave[i];
    }
    
    public boolean setchiave(int i, chiave lachiave){
        if(i<0 || i>n-1){
            return false;
        }
        schiave[i] = lachiave;
        return true;
    }
        
    //metodi preleva chiave per nominativo e numero camera
    
    public chiave prel_chiave_per_nom(String nom){
        
        for(int i=0;i<n-1;i++){
            
            if(nom.equals(schiave[n].getNom())){
                chiave temp = schiave[i];
                schiave[i] = null;
                
                return temp;
            } else {
            }             
        }        
        return null;
}
    
    public chiave prel_chiave_per_numcam(int num_cam){
        
        for(int i=0;i<n-1;i++){
            
            if(num_cam == schiave[n].getNum_cam()){
                chiave temp = schiave[i];
                schiave[i] = null;
                
                return temp;
            }
        }
        return null;
    }
    
    //metodo deposita chiave 
    
    public boolean dep_chiave(chiave chiave){
        for(int i=0;i<n-1;i++){
            
            if(schiave[i] == null){
                schiave[i] = chiave;
                return true;
            }
            
        } 
        return false;    
    }
    
    @Override
    public String toString(){
        String elenco = "";
        for(int i=0;i<n;i++){
            if(schiave[i] != null){
                elenco = elenco+schiave[i].getNum_cam()+" "+schiave[i].getNom()+"\n";
            }
        }
        return elenco;
    } 

}
public class chiave {
    
    private String nom;
    private int num_cam;

    public chiave(String nom, int num_cam) {
        this.nom = nom;
        this.num_cam = num_cam;
    }  
    
    public chiave() {
        this.nom = nom;
        this.num_cam = num_cam;
    }

    public String getNom() {
        return nom;
    }
    public void setNom(String nom) {
        this.nom = nom;
    }

    public int getNum_cam() {
        return num_cam;
    }
    public void setNum_cam(int num_cam) {
        this.num_cam = num_cam;
    }
    
    @Override
    public String toString(){
        return "La chiave della stanza "+this.num_cam+" appartiene al cliente: "+this.nom+".";
    }
    
}
Inserisco anche un output in modo che possiate capire in pratica il problema.
Portachiavi
Inserisci numero massimo chiavi: 5
Inserisci numero camera della chiave: 10
Inserisci numero camera della chiave: 11
Inserisci numero camera della chiave: 12
Inserisci numero camera della chiave: 13
Inserisci numero camera della chiave: 14
Quante chiavi desideri creare ? 2
Inserisci nominativo chiave da creare: Mario
Inserisci nominativo chiave da creare: Luigi
La chiave della stanza 14 appartiene al cliente: Luigi.
Come vedete, inserisco la capienza del portachiavi e i numeri delle camere. Creo 2 chiavi e inserisco i due nomi.
Il toString riporta solamente la creazione di una chiave con il secondo nominativo e l'ultimo numero camera.
Mi chiedo quindi, perchè non crea due chiavi ? E perché non usa le camere 10-11 al posto delle ultime ?

Spero di essere stato chiaro, grazie a chi mi risponderà.

6 Risposte

  • Re: Problema esercizio con Array

    Osserva bene cosa fai nell'ultimo for (quello che cicla per il numero di chiavi chiesto in input dall'utente) e l'istruzione fuori dal for.
    Nel ciclo for stai utilizzando lo stesso oggetto "schiave" creato con l'ultima iterazione del ciclo precedente (cioè l'ultima chiave creata). Quel che fai è solamente il cambio del nome... e lo fai tutte le volte sempre e solo sull'ultima (quindi, ad ogni iterazione vai a sovrascrivere il nome assegnato precedentemente).
    Poi vai ad assegnare nel portachiavi alla posizione "n" (cioè nella posizione pari al numero di chiavi da create: non ha nessun senso) sempre lo stesso oggetto. Tra l'altro questa operazione non andrà mai a buon fine, restituendo sempre false... prova a farti stampare il valore di ritorno del metodo "setChiave".

    Poi, fuori dal ciclo for finale vai a stampare l'oggetto chiave con l'ultimo valore assegnato. Non è che il programma riporta la creazione di una sola chiave, è che tu gli hai chiesto di stamparne una.

    Devi, comunque, rivedere completamente tutto l'ultimo ciclo for. Se devi creare "nuove chiavi" da qualche parte dovrai avere un "new chiave(...)" e tu non lo fai.

    PS: i nomi delle classi, per convenzione, dovrebbero iniziare con la lettera MAIUSCOLA. Quindi "Portachiavi", "Chiave", ecc.

    Ciao.
  • Re: Problema esercizio con Array

    mattia.melodia ha scritto:


    Vi lascio Main e le due classi "portachiavi" e "chiave".
    Io aggiungo che hai scritto diversi for così:

    for(int i=0;i<n-1;i++){

    questi sono sbagliati nel senso che così NON consideri l'ultimo elemento.


    Inoltre, tastiera.skip("\n"); non è appropriato, detto in generale. Tecnicamente funziona bene SOLO sui sistemi Linux/Unix-like. Sui Windows NON funziona.


    I nomi sarebbero da migliorare:
    - le classi si mettono in UpperCamelCase (es. PuntoColorato)
    - metodi e variabili si mettono in lowerCamelCase (es. getNomePersona(), indicePosto ecc...)

    Il "_" non si usa praticamente MAI nei nomi.
  • Re: Problema esercizio con Array

    Grazie delle dritte, purtroppo non sono molto esperto.

    Facendo partire il for con i=0, la condizione dovrebbe essere appunto i<n-1, no ?

    tastiera.skip("\n") lo uso perché se no mi dà errore quando devo inserire altri numeri, posso farlo in qualche altro modo più corretto ?

    Comunque ho aggiustato il toString, ma adesso ho qualche problema a scrivere il newChiave.
    Potete aiutarmi ? Grazie mille
  • Re: Problema esercizio con Array

    mattia.melodia ha scritto:


    Facendo partire il for con i=0, la condizione dovrebbe essere appunto i<n-1, no ?
    No. Se hai 10 elementi (n=10), si entra nel corpo del for solo con i fino a 8 (e non 9 come dovrebbe) perché arrivato a 9 < 9 è false e il for termina. Ma 9 è valido come indice!!

    mattia.melodia ha scritto:


    tastiera.skip("\n") lo uso perché se no mi dà errore quando devo inserire altri numeri, posso farlo in qualche altro modo più corretto ?
    Ripeto che funziona sugli Unix-like ma NON sui Windows.

    In generale si può fare:

    tastiera.skip("\\s+");
  • Re: Problema esercizio con Array

    Bene, ho aggiustato nomi e cicli for. Adesso mi rimane il problema del metodo newChiave. Cerco di lavorarci, ma se qualcuno può semplificarmi il lavoro dandomi delle dritte, gliene sarei grato.
  • Re: Problema esercizio con Array

    Buongiorno, ho modificato un po' il codice del main scrivendo il primo for nel seguente modo.
    for(int i=0;i<n;i++){ // creazione chiavi con numCam e nom 
                
                System.out.print("Desideri creare una chiave ? "); 
                risp1 = tastiera.nextLine();
                
                if(risp1.contains("y")){
                    
                    System.out.print("Inserisci numero camera della chiave: "); 
                    numCam = tastiera.nextInt();
                    tastiera.skip("\n");
                    nom = null;
            
                    schiave = new Chiave(nom, numCam);           
                
                System.out.print("Desideri assegnarla ad un nominativo ? ");
                risp2 = tastiera.nextLine();
                
                if (risp2.contains("y")){
                    
                    System.out.print("Inserisci nominativo chiave da creare: ");
                    nom = tastiera.nextLine();
                    schiave.setNom(nom);      
                    }
                
                    pc1.setChiave(i, schiave); // inserimento chiavi in pc1
    
                    }
                }
                System.out.print(pc1.toString()); 
    E fin qui tutto okay, dato che in output avrò ad esempio il seguente risultato.
    Portachiave 
    Inserisci numero massimo chiavi: 3
    Desideri creare una chiave ? y
    Inserisci numero camera della chiave: 1
    Desideri assegnarla ad un nominativo ? y
    Inserisci nominativo chiave da creare: mario
    Desideri creare una chiave ? y
    Inserisci numero camera della chiave: 2
    Desideri assegnarla ad un nominativo ? n
    Desideri creare una chiave ? y
    Inserisci numero camera della chiave: 3
    Desideri assegnarla ad un nominativo ? y
    Inserisci nominativo chiave da creare: luigi
    1 mario
    2 null
    3 luigi
    Adesso riscontro problemi quando devo richiamare i metodi preleva e deposita scrivendo il seguente codice.
    System.out.print("Desideri prelevare o depositare una chiave ?");
            System.out.print("\n Inserisci 1 per prelevare con nome.");
            System.out.print("\n Inserisci 2 per prelevare con numero camera.");
            System.out.print("\n Inserisci 3 per depositare una chiave. \n");
            risp3 = tastiera.nextLine();
            
            if(risp3.contains("1")){
                System.out.print("Inserire nominativo della chiave da prelevare: ");
                nom = tastiera.nextLine();
                pc1.prelChiavePerNom(nom);           
            }
            System.out.print(pc1.toString());  
            
            if(risp3.contains("2")){
                System.out.print("Inserire numero camera della chiave da prelevare: ");
                numCam = tastiera.nextInt();
                pc1.prelChiavePerNumCam(numCam);           
            }
            System.out.print(pc1.toString());   
            
            }
       
        }
    Lasciando stare il terzo if che devo ancora scrivere per depChiave, qualsiasi numero io inserisca (1 o 2) ricevo i seguenti errori in output.
    Desideri prelevare o depositare una chiave ?
     Inserisci 1 per prelevare con nome.
     Inserisci 2 per prelevare con numero camera.
     Inserisci 3 per depositare una chiave. 
    1
    Inserire nominativo della chiave da prelevare: mario
    Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
    	at javaapplication11.PortaChiavi.prelChiavePerNom(PortaChiavi.java:52)
    	at javaapplication11.JavaApplication11.main(JavaApplication11.java:80)
    C:\Users\matti\AppData\Local\NetBeans\Cache\11.2\executor-snippets\run.xml:111: The following error occurred while executing this line:
    C:\Users\matti\AppData\Local\NetBeans\Cache\11.2\executor-snippets\run.xml:68: Java returned: 1
    BUILD FAILED (total time: 7 minutes 8 seconds)
    Desideri prelevare o depositare una chiave ?
     Inserisci 1 per prelevare con nome.
     Inserisci 2 per prelevare con numero camera.
     Inserisci 3 per depositare una chiave. 
    2
    1 mario
    2 null
    3 luigi
    Inserire numero camera della chiave da prelevare: 1
    Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
    	at javaapplication11.PortaChiavi.prelChiavePerNumCam(PortaChiavi.java:69)
    	at javaapplication11.JavaApplication11.main(JavaApplication11.java:87)
    C:\Users\matti\AppData\Local\NetBeans\Cache\11.2\executor-snippets\run.xml:111: The following error occurred while executing this line:
    C:\Users\matti\AppData\Local\NetBeans\Cache\11.2\executor-snippets\run.xml:68: Java returned: 1
    BUILD FAILED (total time: 32 seconds)
    Spero di esser stato chiaro. Mi scuso per le richieste forse banali, ma sono alle prime armi.
    Grazie!
Devi accedere o registrarti per scrivere nel forum
6 risposte