Java - Problema con programa de java.

 
Vista:
Imágen de perfil de jose
Val: 64
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Problema con programa de java.

Publicado por jose (73 intervenciones) el 26/09/2018 18:45:33
Buenos días,

Soy un estudiante de java, estoy realizando un pequeño programa y resulta que tengo un fallo.

Agradecería si alguien me pudiera comentar que está pasando.

Esto es lo que sale en pantalla.

La matrícula 1111aaa existe. Corresponde a 11tit
Introduce una nueva matrícula.
*****************
Introduce la matrícula:3333ccc
Introduce el dni: 33dni
Introduce el nombre del titular: 33tit
FALTA QUE PREGUNTE POR LA MATRÍCULA EN ESTA LÍNEA
Introduce el dni: 44dni
Introduce el nombre del titular: 44tit

Introduce la matrícula:4444ddd
Introduce el dni: 55dni
Introduce el nombre del titular: 55tit
Introduce la matrícula:5555eee
Introduce el dni: 55dni
DNI encontrado. Corresponde a 11tit
Introduce el nombre del titular:

Supuestamente el programa no debería preguntar por el titular si el dni está repetido en un array bidimensional, sin embargo pregunta.

El otro es que salta de preguntar la mátricula una sola vez si la matrícula está repetida

Introduce la matrícula:3333ccc
Introduce el dni: 33dni
Introduce el nombre del titular: 33tit
Introduce el dni: 44dni
Introduce el nombre del titular: 44tit
Introduce la matrícula:4444ddd

Adjunto el archivo java en 7zip para que podáis ver donde falla.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
Imágen de perfil de Kabuto
Val: 3.428
Oro
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Problema con programa de java.

Publicado por Kabuto (1381 intervenciones) el 27/09/2018 02:05:16
Hola compi.
Lamentablemente entre semana debido al trabajo, tengo muy poco tiempo libre disponible, apenas 1 horita antes de irme a dormir...y no puedo dedicarle todo el tiempo que me gustaría a revisar tu código.
Puede que hasta el domingo no pueda hacer una gran aportación.

Aún así, sí puedo comentar unas cositas que he visto ahora.

La primera es que al ejecutar tu programa, solo me ha permitido insertar una matrícula.
Y es porque en la línea 91 has cerrado el Scanner con scanner.close(). Así que elimina esa linea.
No necesitas cerrar el Scanner, o en todo caso, hazlo al final, dentro del método finPrograma()

La segunda. En la linea 86 estás usando el doble igual para comparar dos String
1
if (dni == dniConsulta)

El doble igual ha de usarse solo para tipos primitivos como int, double..
String es una clase "compleja" y usar el doble igual no significa que estemos comparando su valor, sino si referencian al mismo espacio de memoria... en fin, que es mejor usar el metodo equals() o bien el equalsIgnoreCase(), tal y como has hecho en otras lineas donde también comparabas Strings
1
if (dni.equalsIgnoreCase(dniConsulta))

Y la tercera.
Este es un asunto que no he podido comprobar bien del todo, pero sospecho que es la causa principal de los problemas.
Sin darte cuenta, estás "anidando" métodos de forma recursiva, y esto provoca efectos indeseados. Mira:

Iniciamos el programa y tal.. y entramos en pedirDatos().
Dentro de este método, llega un momento en que llamamos al método buscarDNIByMatricula().
Mientras se está ejecutando este método, no hemos terminado todavía con el método pedirDatos(), pues está esperando a que termine
el otro.
Así que ahora mismo estamos en: pedirDatos() -> buscarDNIByMatricula()

Esto no es el problema, esto es lo habitual en cualquier programa. Pero ahora sí viene el problema.
Dentro de buscarDNIByMatricula(), si resulta que la matricula está repetida, volvemos a llamar a pedirDatos()
Esta llamada no significa que nos devuelva de nuevo a la línea de ejecución del primer pedirDatos() que habíamos iniciado, ¡¡en realidad estamos iniciando un nuevo pedirDatos(), anidado dentro del pedirDatos() anterior!!
Es decir estamos en: pedirDatos() -> buscarDNIByMatricula() --> pedirDatos()

El primer pedirDatos(), no ha terminado.. sigue esperando a que termine buscarDNIByMatricula(), que a su vez está esperando a que termine el segundo pedirDatos() que acabamos de iniciar.
Y este segundo pedirDatos(), volverá a llamar a un segundo buscarDNIByMatricula(), el cuál es posible que llame a un tercer pedirDatos()....y esto sería el cuento de nunca acabar.

Es como la peli de Inception donde el Leonardo DiCaprio tenía un sueño, dentro de un sueño, dentro de otro sueño.... y al final el pavo ya no sabía de cuantos sueños había que despertarse para volver al mundo real xDD

Esto, hace que ocurra lo siguiente si ponemos una matricula y/o un dni ya existentes.
Fijate que tras la primera matricula repetida, luego pide el dni dos veces y pasa del vehiculo#2 al vehiculo#4.
Parece que no hay vehiculo#3, pero si lo hay, se ha repetido en la matriz.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
**** Este programa almacena datos de ******
********** Matrículas y Personas **********
*******************************************
***** Escribe - fin - para finalizar ******
*******************************************
***** Vehículo # 0
Introduce la matrícula:111mat
Introduce el dni: 111dni
Introduce el nombre del titular: 111tit
***** Vehículo # 1
Introduce la matrícula:222mat
Introduce el dni: 222dni
Introduce el nombre del titular: 222tit
***** Vehículo # 2
Introduce la matrícula:111mat
La matrícula 111mat existe. Corresponde a 111tit
 Introduce una nueva matrícula.
*****************
***** Vehículo # 2
Introduce la matrícula:333mat
Introduce el dni: 333dni
Introduce el nombre del titular: 333tit
Introduce el dni: 333dni  //VUELVE A PEDIRME EL DNI
DNI encontrado. Corresponde a 111tit //Y AHORA DICE QUE YA EXISTE Y ENCIMA QUE CORRESPONDER AL PRIMER TITULAR
***** Vehículo # 4    //NO SABEMOS QUE HA PASADO CON VEHICULO #3
Introduce la matrícula:444mat
Introduce el dni: 222dni
DNI encontrado. Corresponde a 333tit  //Y AQUI DICE QUE 222dni CORRESPONDE A 333tit, CUANDO EN REALIDA ES DE 222tit
***** Vehículo # 5
Introduce la matrícula:fin
Programa
Esta es la lista de las matrículas:
111mat
111dni
222mat
222dni
333mat
333dni
333mat   //MATRICULA REPETIDA
333dni    //AQUI EL DNI ESTA BIEN ASIGNADO, AUNQUE EN PANTALLA ME DECIA QUE ERA DE OTRO TITULAR
444mat
222dni
Esta es la lista de personas:
111dni
111tit
222dni
222tit
333dni
333tit


Tienes que evitar este "anidamiento" recursivo. pedirDatos() se está llamando así mismo dentro de su ejecución a través de buscarDNIByMatricula().
Hay que replantearse el flujo del código para evitar esto.

Iré aportándo más cosas cuando pueda. Un saludo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
2
Comentar
Imágen de perfil de jose
Val: 64
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Problema con programa de java.

Publicado por jose (73 intervenciones) el 27/09/2018 09:55:17
Hola Kabuto,

Muchas gracias por la magnifica respuesta.

Al final acabé el código. Por desgracia el centro de formación de este ciclo online es bastante malo. Por ello he de acudir a gente como tu que dais aquello que nos hace falta a los principiantes, tips para hacer los programas bien y mejorar.

Los fallos poco a poco los fui arreglando con el debug de eclipse, pero por la falta de conocimientos me ha llevado días hacer este programita, que otros les hubiese llevado menos de una hora.

Te dejo el código para que lo veas.

Muchas gracias,
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Kabuto
Val: 3.428
Oro
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Problema con programa de java.

Publicado por Kabuto (1381 intervenciones) el 28/09/2018 01:04:22
Hola Jose,
sigue habiendo anidamientos recursivos, así que siguen ocurriendo movidas raras sí el usuario decide poner a prueba la "eficiencia" del programa insistiendo en repetir matriculas o dnis.
Fíjate el resultado que he obtenido, incluso he tenido que forzar el cierre del programa porque la palabra "fin" ha dejado de tener poder alguno je je..
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
**** Este programa almacena datos de ******
********** Matrículas y Personas **********
*******************************************
***** Escribe - fin - para finalizar ******
*******************************************
***** Vehículo # 1
Introduce la matrícula:111mat
Introduce el dni: 111dni
Introduce el nombre del titular: 111tit
***** Vehículo # 2
Introduce la matrícula:111mat
La matrícula 111mat existe. Corresponde a 111tit
 Introduce una nueva matrícula.
*****************
***** Vehículo # 2
Introduce la matrícula:222mat
Introduce el dni: 222dni
Introduce el nombre del titular: 222tit
***** Vehículo # 3
Introduce la matrícula:333mat
Introduce el dni: 222dni
DNI encontrado. Corresponde a 222tit
***** Vehículo # 4                         //REPITO MATRICULA
Introduce la matrícula:111mat
La matrícula 111mat existe. Corresponde a 111tit
 Introduce una nueva matrícula.
*****************
***** Vehículo # 4                  //INSISTO...
Introduce la matrícula:111mat
La matrícula 111mat existe. Corresponde a 111tit
 Introduce una nueva matrícula.
*****************
***** Vehículo # 4             //SIGO INSISTIENDO, SOY MALA GENTE...
Introduce la matrícula:111mat
La matrícula 111mat existe. Corresponde a 111tit
 Introduce una nueva matrícula.
*****************
***** Vehículo # 4           //REPITO PERO CON OTRA
Introduce la matrícula:333mat
La matrícula 333mat existe. Corresponde a null  //YA EMPIEZA A DAR INFORMACION RARA....
 Introduce una nueva matrícula.
*****************
***** Vehículo # 4
Introduce la matrícula:fin        //QUERIA TERMINAR PROGRAMA....
Introduce el dni: fin                 //PERO VA A SER QUE NO...
Introduce el dni: 444dni
Introduce el nombre del titular: 444tit
***** Vehículo # 5
Introduce la matrícula:fin    //NADA. PARECE QUE COMO YO HE QUERIDO TOMARLE EL PELO AL PROGRAMA...
Introduce el dni: fin              //...AHORA ME LO ESTÁ TOMANDO ÉL A MI ....  O_ox
Introduce el dni: 555dni
Introduce el nombre del titular: fin
***** Vehículo # 6
Introduce la matrícula:fin
Introduce el dni:                    //AQUI YA HE FORZADO EL CIERRE DEL PROGRAMA.


Hagamos una cosa, no te atasques con este ejercicio. Sigue avanzando con otras cosas y yo estos días intento proponerte otra solución con un flujo distinto del programa. Hay que evitar que el metodo buscarDNIByMatricula() haga ninguna llamada a pedirDatos()


Además hay que decir que el hecho de tener que estar usando estructuras "primitivas" como un array bidimensional (matriz) y datos básicos como String y tal.... hace que resolver este tipo de ejercicios sea mucho más difícil.

Si pudieras crear tu propia clase Vehiculo y poder almacenarlos en una estrucutra más dinámica como un ArrayList por ejemplo, este ejercicio no te daría ni la mitad de problemas que te ha estado dando.
Pero bueno, todo llegará a su tiempo.

Como digo, tu sigue avanzando y yo en cuanto pueda propongo una solucion.

Un saludo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Kabuto
Val: 3.428
Oro
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Problema con programa de java.

Publicado por Kabuto (1381 intervenciones) el 28/09/2018 02:20:06
Pues oye.... mirando ahora un poco el programa con calma. He visto que han bastado tan solo unos pequeños cambios para hacerlo funcionar bien.
Te adjunto mi archivo . java con los cambios


Como dije antes, el problema principal eran las llamadas recursivas. Me he dado cuenta de que el método agregarVehiculo() también estaba haciendo una llamada recursiva al metodo pedirDatos()

Lo de llamada "recursiva" significa que un método, dentro de él, se está llamando a sí mismo...
La "recursividad" es una técnica muy útil para algunas tareas muy concretas como ciertos cálculos matemáticos o el desarrollo de arboles binarios (no importa si no sabes lo que son). En algún momento del ciclo que estás cursando ya te la mencionarán.
Pero para la mayoría de tareas, la recursividad es tan innecesaria, como peligrosa.

En tu programa, fijate que el método pedirDatos() se va a repetir siempre el solito mientras la variable finalizar tenga valor false y los indices de las matrices no hayan alcanzado el valor máximo. Ya se encarga el bucle while de llamarle.
Por lo tanto, no hace falta que otros métodos le llamen.

Te cuento un poco los cambios que he hecho:
El método buscarDNIByMatricula(), aunque no estaba mal (exceptuando la llamada recursiva a pedirDatos()) hace una serie de operaciones que no son del todo necesarias y además tal y como está planteado no tiene peso en el "flujo" del programa.
Sin embargo, debería tenerlo, pues si la matricula ya existe, todo el código que viene detrás no debe ejecutarse.

Así que lo he cambiado por otro método más simplificado y que ahora tiene peso directo en el flujo del programa.
En lugar de void, ahora es un boolean.
Si la matricula existe, devolverá TRUE y no se ejecutará el resto del código. EL metodo pedirDatos() terminará, y se volverá a repetir a través del while (y no por una peligrosa llamada recursiva)
Si la matricula NO existe, devolverá FALSE y entonces sí pasaremos a seguir pidiendo datos.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private boolean yaExisteMatricula() {
 
    for (int i = 0; i < indexMatricula; i++) {
        if (ListaMATDNIs[0].equalsIgnoreCase(matricula)) {
            System.out.println("La matrícula "+ matricula +" ya existe. Corresponde a "
                    + ListaDNINombres[i][1] + "\n Introduce una nueva matrícula."
                    + "\n*****************");
            return true;
        }
    }
 
    //Si el bucle ha conseguido terminar, es que no existe la matricula. Por tanto, retornamos false
    return false;
}


También he modificado el metodo [i]buscarPersonaByDNI()

De nuevo lo he simplificado y he aumentado su funcionalidad, ahora este metodo devuelve un String.
Si el DNI ya existe, devuelve el nombre del Titular.
Si NO EXISTE, devuelve valor null
1
2
3
4
5
6
7
8
9
10
11
12
13
private String buscarPersonaByDNI_Alternativo() {
 
    for (int i = 0; i < indexDNI; i++) {
        if (ListaDNINombres[i][0].equalsIgnoreCase(dni)) {
            //DNI encontrado, informamos y devolvemos el nombre del titular
            System.out.println("DNI encontrado. Corresponde a " + ListaDNINombres[i][1]);
            return ListaDNINombres[i][1];
        }
    }
 
    //Si el bucle ha conseguido terminar, es que no existe este DNI. Retornamos valor null
    return null;
}


Este valor que devuelve, lo recogemos en la variable nomConsulta. Y una vez recogido de nuevo alteramos el flujo del programa según dicho valor.
Si hemos obtenido un valor null, es decir, no tenemos persona con este DNI..., entonces pedimos el resto de datos y registramso un vehiculo y una persona en sus correspondients matrices.
Si hemos obtenido algo distinto de null, es decir, esta persona ya esta registrada, lo único que damos de lata es un vehiculo con los datos que ya tenemos.

Por último, he recuperado en el metodo final lo de mostrar las matrices en pantalla. Esto es útil para comprobar que se han recogido los datos correctamente.
Este es el resultado obtenido ahora. Fíjate que ya no se vuelve loco si intento repetir matriculas.
Y si repito los dni, no hay problema, reconoce correctamente al titular y se agrega el vehiculo correctamente.
Las matrices al final muestran que todo ha sido correcto. He introducido 5 vehiculos pero solo hay 3 titulares. Esto es porque los primeros titulares tienen 2 coches cada uno.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
**** Este programa almacena datos de ******
********** Matrículas y Personas **********
*******************************************
***** Escribe - fin - para finalizar ******
*******************************************
***** Vehículo # 1
Introduce la matrícula:111mat
Introduce el dni: 111dni
Introduce el nombre del titular: 111tit
***** Vehículo # 2
Introduce la matrícula:222mat
Introduce el dni: 222dni
Introduce el nombre del titular: 222tit
***** Vehículo # 3
Introduce la matrícula:111mat
La matrícula 111mat ya existe. Corresponde a 111tit
 Introduce una nueva matrícula.
*****************
***** Vehículo # 3
Introduce la matrícula:222mat
La matrícula 222mat ya existe. Corresponde a 222tit
 Introduce una nueva matrícula.
*****************
***** Vehículo # 3
Introduce la matrícula:333mat
Introduce el dni: 111dni
DNI encontrado. Corresponde a 111tit
***** Vehículo # 4
Introduce la matrícula:444mat
Introduce el dni: 222dni
DNI encontrado. Corresponde a 222tit
***** Vehículo # 5
Introduce la matrícula:555mat
Introduce el dni: 555dni
Introduce el nombre del titular: 555tit
***** Vehículo # 6
Introduce la matrícula:fin
 
 
	MATRICULAS Y DNI
	111mat	111dni
	222mat	222dni
	333mat	111dni
	444mat	222dni
	555mat	555dni
 
 
	DNI Y NOMBRES
	111dni	111tit
	222dni	222tit
	555dni	555tit
 
Programa finalizado
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de jose
Val: 64
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Problema con programa de java.

Publicado por jose (73 intervenciones) el 28/09/2018 09:43:41
Hola Kabuto,

Lo de la llamada recursiva era para obligar a que me pidiese la mátricula. Por desgracia no podemos crear más métodos de los que hay creados.

Ni siquiera podemos evitar llamar desde pedirDatos() a BuscarPersonaByDNI por ello no podemos utilizar un if tal como este
if (!yaExisteMatricula()) { para evitar el código que lea el código si no corresponde.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private void agregarVehiculo() {
		ListaMATDNIs[indexMatricula][0]= matricula;
		ListaMATDNIs[indexMatricula][1]= dni;
		indexMatricula++;
		if(indexMatricula == MAX){
			finalizar = true;
		}else {
			/*
			 * OJO, LLamada recursiva. Hay que evitarlo.
			 * De hecho, aqui no hay que llamar a pedirDatos()
			 * Este metodo volverá a ejecutarse el solito porque
			 * ahora mismo finalizar == false
			 */
 
			//pedirDatos();
		}
	}
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Kabuto
Val: 3.428
Oro
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Problema con programa de java.

Publicado por Kabuto (1381 intervenciones) el 29/09/2018 00:33:05
pedirDatos() sí debe llamar a BuscarPersonaByDNI(), pero BuscarPersonaByDNI() no debe llamar a pedirDatos()

Mi metodo yaExisteMatricula(), lo llamé así porque resulta más intuitivo su función, pero puede llamarse tal y como te dijo el profesor.

Tampoco es necesario que sea de tipo boolean, no tampoco hace falta que buscarPersonaByDNI() devuelva un String. Pero de este modo es mucho más eficiente.

Si por ejemplo nos dan una matricula repetida. El método pedirDatos() ya no debería de seguir haciendo absolutamente nada de nada.
Simplemente finalizar y dejar que el bucle while vuelva a invocarlo y así comenzar de nuevo.

Por eso es interesante que el metodo de comprobar si existe la matricula sea boolean, para decidir por donde ha de "fluir" el flujo del programa.
Si la matricula no existe, pido datos.
si no, no hago nada.

Pero al permitir que el código siga fluyendo, hay que complicar el código innecesariamente (hay un exceso de variables en el código, ya veo que es lo que te pide el profesor) y por eso tomaste la decisión de invocar a pedirDatos() cuando el pedirDatos() que ya se está ejecutando, no ha terminado, ni puede ya que logre terminar (recuerda como por más que repetí la palabra "fin" el programa no terminaba).

Pero bueno, de verdad que no has de preocuparte por nada de esto. Yo también me he encontrado con tener que escribir códigos más complejos de lo necesario por cumplir con las exigencias de profesores.

No te atasque, sigue avanzando. Con el tiempo tú mismo verás como un programa además de ser eficaz, también puede ser codificado de forma eficiente (eficacia y eficiencia son cosas distintas) cuando puedas hacerlo a tu bola, sin ataduras ni exigencias.

Lo importante de este ejercicio en realidad, es familiarizarse con las matrices, y eso ya está conseguido.

Un saludo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de jose
Val: 64
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Problema con programa de java.

Publicado por jose (73 intervenciones) el 28/09/2018 09:28:54
Hola Kabuto,

Es cierto que lo podríamos plantear de otra forma, nos llevaría menos tiempo y fallaría menos. Lo que planteamos algunos pero el profe quiere que sea con los métodos y variables que nos ha propuesto, nos dío el esqueleto y a partir de hay utilizar el método descendente para hacer funcionar el programa.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar