Autor Tema: CU00334A-2 Visual Basic. Error ejercicio de ejemplo leer datos desde ficheros  (Leído 5557 veces)

Gilding

  • Sin experiencia
  • *
  • Mensajes: 44
    • Ver Perfil
Hola!

En el tema CU00334A-2 del curso de Visual Basic proponeis un ejercicio para comprobar si existe un libro dentro de un lote, y si existe que nos devuelva el precio en función de un descuento. Y en la segunda parte del ejercicio que nos devuelva el precio del lote completo.

Mi problema surge en la primera parte del ejercicio. He utilizado como base de datos del lote los datos que poneis en el ejemplo. Si introduzco un ISBN que esta en el lote, lo encuentra y me devuelve el precio correctamente aplicando el descuento. Si introduzco un ISBN que no esta en lote, me indica que no esta en el lote. El problema surge cuando introduzco como ISBN un valor que corresponde por ejemplo con uno de los precios de la base de datos, ya que me dice que si existe ese libro, me devuelve como precio el centinela que se utiliza para indicar el descuento (seria la siguiente posición en la base de datos), y por último me da un error al exceder los limites del array que contiene los datos, porque se salta el centinela que es usado como indicador de final de archivo.

Esto no debería ocurrir puesto que vamos saltando posiciones en el array de 3 en 3 para que solo lea los datos correspondientes al ISBN de cada libro. Tras volverme loco buscando el error en mi código, he probado con el que poneís de ejemplo... y sucede exactamente lo mismo. Mis preguntas son: ¿este es un error "controlado", ya sabiais que existia? ¿Como podríamos solucinar esto? Ahora ya me pica la curiosidad jejeje.

Aclaro que el archivo libros.dat al tener pocos datos, lo he creado a mano con el bloc de notas, en vez de hacerlo por código. Por si esto influyera en algo. Lo adjunto por si fuera un error del archivo

Muchas gracias por vuestro tiempo.

Un saludo!
« Última modificación: 25 de Noviembre 2014, 08:45 por Alex Rodríguez »

Mario R. Rancel

  • Administrador
  • Experto
  • ********
  • APR2.COM
  • Mensajes: 1978
    • Ver Perfil
Re:CU00334A-2 Visual Basic. Error en el funcionamiento del ejercicio de ejemplo
« Respuesta #1 en: 13 de Noviembre 2014, 09:01 »
Hola, hay distintos enfoques para la cuestión que comentas.

Enfoque 1) Se trata de un error o inconsistencia del programa. Desde este punto de vista, sería conveniente introducir instrucciones que eviten que se produzca el error de forma que la situación se mantenga controlada. Voy a tratar de plantear una vía de solución: podría introducirse un contador para determinar en qué número de línea se está leyendo un dato. Sabemos que los isbn se encuentran en las líneas 1, 4, 7, 10, etc. lo que podríamos expresar de alguna forma matemáticamente, por ejemplo algo como númeroEsIsbn si (linea - 1) mod 3 = 0. Podríamos plantear entonces una condición que sólo admita un ISBN si se encuentra en la línea adecuada. Por ejemplo: Si dato(i) es igual al isbn buscado y el número de línea es el adecuado entonces... (proceder en consecuencia) SINO continuar buscando. Habría distintas formas de resolver esto, te animo a que lo intentes y logres que el programa funcione sin que salte el error. Se trataría de un buen ejercicio de lógica aplicada a la programación.

Enfoque 2) El error se produce porque se están usando unos datos de ejemplo no reales y no se está realizando validación de datos. Al tratarse de un ejemplo didáctico, el programa no incluye validación de datos de entrada, control de errores, etc. que impedirían el error. En el enunciado se indica que un ISBN es un número de 10 dígitos, por tanto si se hace una validación de datos para comprobar que el ISBN introducido tiene 10 dígitos, no podrá haber un ISBN que coincida con un precio, ya que ningún libro alcanza un precio de diez dígitos.

Enfoque 3) Al programa le falta control de errores (aspecto del que se habla más adelante en el curso), de modo que en caso de error debería detectarse, informar al usuario y no darse lugar a una detención anómala del programa.

Podrían darse más enfoques, la programación no es "una ciencia" cerrada.

De cualquier manera, es positivo detectar las inconsistencias de los programas, valorarlas y tomar decisiones adecuadas frente a ellas.

Por último, comentarte que es preferible no usar el término base de datos para los datos almacenados en el archivo, ya que base de datos en programación se refiere a un sistema específico de almacenamiento de datos, distinto de un archivo (hay un artículo divulgativo sobre bases de datos en http://aprenderaprogramar.com/index.php?option=com_content&view=article&id=554:que-es-y-para-que-sirve-una-base-de-datos-principales-tipos-oracle-mysql-sqlserver-postgre&catid=46:lenguajes-y-entornos&Itemid=163)

Espero haber aclarado algo, o al menos aportado ideas sobre el asunto que te puedan servir.

Saludos

Gilding

  • Sin experiencia
  • *
  • Mensajes: 44
    • Ver Perfil
Re:CU00334A-2 Visual Basic. Error en el funcionamiento del ejercicio de ejemplo
« Respuesta #2 en: 13 de Noviembre 2014, 14:02 »
Hola Mario.

Muchas gracias por tu respuesta. Challenge Accepted! jajaja. Voy a intentar resolverlo con las indicaciones que me das en tu respuesta. Aunque no sé si sería más correcto llegar primero al tema en el que se tratan los errores, para intentar aplicar esa teoría a este problema o intentar resolverlo ya.

Gracias también por la aclaración del uso del término "base de datos". Un artículo muy interesante el que has adjuntado. No tenía muchas nociones sobre el tema, asi que me ha aclarado bastantes cosas.

Me gustaría añadir una cosa más. Sigo teniendo una "espinita" clavada con este ejercicio. Me ha quedado claro que el problema se puede resolver añadiendo algunos condicionates para realizar comprobaciones. Pero no entiendo porque no funciona correctamente el código del ejercicio. Este ejercicio lo presentais por primera vez en el curso fundamentos nivel I, en el tema CU00171A. He repasado el diagrama de flujo que exponeis en dicho tema varias veces, y para mi la lógica de ese diagrama es correcta, debería funcionar correctamente en la situación en la que ahora no lo hace (evidentemente para lo de los 10 dígitos del ISBN es completamente necesario añadir una comprobación). No comprendo donde surge el error... si la lógica es correcta: ¿Por qué falla?

De nuevo muchas gracias, y perdón por la insistencia, esto me tiene desconcertado.

Un saludo!

Mario R. Rancel

  • Administrador
  • Experto
  • ********
  • APR2.COM
  • Mensajes: 1978
    • Ver Perfil
Re:CU00334A-2 Visual Basic. Error en el funcionamiento del ejercicio de ejemplo
« Respuesta #3 en: 13 de Noviembre 2014, 16:34 »
Es interesante plantearse lo que preguntas: un algoritmo es un proceso "determinista", se ejecuta lo que hay, no hay lugar (en una primera aproximación) a resultados fuera de la lógica. En este caso, como primera aproximación para tratar de explicar lo que ocurre, intentemos seguir la traza del algoritmo.

Partimos de los datos ejemplo del enunciado e

Al ejecutar el proceso CommandLibro_Click introducimos como ISBN a buscar el 10 (que es un dato que se corresponde con un precio). Seguidamente i vale 1. Se lee como Dato(1) la primera línea, es decir, Dato(1)=55

Se entra en un bucle do while mientras i distinto de -500

Se comprueba si el dato(1) es igual al ISBN buscado y no lo es.

Por ello i pasa a valer i+3, es decir, ahora i vale 4.

Se hace Dato(4) = siguiente línea del archivo.

Aquí ya estamos observando una posible anomalía o mejora que deberíamos introducir en el programa. Si el dato en la primera línea no es el isbn buscado, las siguientes dos líneas deberían leerse y desecharse (porque no van a corresponder a un isbn).

Sin embargo esas líneas no se desechan, sino que se hace Dato(2) = 10, como es distinto de -500 se repite el bucle y ahora se comprueba con el ISBN buscado.

Si estuviéramos con ISBNs de 10 cifras, no sería posible que coincidiera la línea del precio con el isbn buscado, pero en este caso sí coincide.

Por tanto identifica que la línea del precio corresponde con el isbn, que la línea del señalero corresponde con el precio... y de ahí llega al colapso...

Saludos

Gilding

  • Sin experiencia
  • *
  • Mensajes: 44
    • Ver Perfil
Re:CU00334A-2 Visual Basic. Error en el funcionamiento del ejercicio de ejemplo
« Respuesta #4 en: 19 de Noviembre 2014, 18:00 »
Ya estoy de nuevo por aquí.

Antes de nada muchas gracias por tus respuestas Mario.

Más abajo adjunto el código del ejercicio resuelto. Aunque sigue teniendo algunas pegas:

Para empezar he tenido que recurrir a los métodos IsNumeric() y Len(), para comprobar si hay letras y para contar el número de caracteres (dígitos en este caso). Sin embargo tengo la impresión que este problema podría resolverse (y debería poder resolverse dado el punto del curso en el que se encuentra) utilizando solo if... else y while. Algo como:

Código: [Seleccionar]
Dim contador As Integer
Dim ISBN, digitosISBN As Long

contador = 0
digitosISBN = ISBN

Do while digitosISBN > 0
      digitosISBN = digitosISBN / 10
      contador = contador + 1       '[contador seria el número de dígitos del número]
Loop

Con esto evitariamos tener que recurrir a cadenas de texto (nos ahorramos comprobar si hay letras) y ahorramos alguna variable. El problema es que los ISBN pueden empezar por cero, y por ello esta solución no es válida, dado que al llegar al primer cero la condición no se cumplirá y saldrá del bucle antes de contar todos los dígitos que quedan, que serían todo ceros claro. ¿Habría alguna forma de hacerlo solo con If... else y while?

Por otro lado, aunque he añadido la comprobación de línea que mencionabas (dicho sea de paso no se si es correcta), si desactivo la comprobación de los 10 dígitos, sigue sin funcionar correctamente. Continua leyendo los datos de los precios como si fueran ISBN. He hecho bastantes comprobaciones pero sigo sin entender porque si nosotros tenemos dato(1) y despues saltamos a dato(4) con i = i + 3, el algoritmo lee dato(2) como ISBN. Si saltamos del 1 al 4, ¿Por qué lee el 2?.


El ejercicio:

Código: [Seleccionar]
Public Class Form1
    Dim dato(50) As Single
    Dim iISBN As Long
    Dim sISBN As String
    Dim precio, valorLote As Single
    Dim encontrado As Boolean

    Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
        Me.Text = "Libreria"

        LabelResultado.Text = ""

        ButtonBuscar.Text = "Buscar"
        ButtonCalcular.Text = "Calcular"

    End Sub

    Private Sub ButtonBuscar_Click(sender As Object, e As System.EventArgs) Handles ButtonBuscar.Click
        Dim i As Integer
        Dim digitosISBN As Integer

        encontrado = False

        sISBN = InputBox("¿Cuál es el ISBN del libro?", "Busqueda Libro")
        digitosISBN = Len(sISBN)

        Do Until IsNumeric(sISBN) = True And digitosISBN = 10
            MsgBox("El ISBN introducido debe tener 10 dígitos" & vbLf & "y solo puede contener números", , "Error ISBN")
            sISBN = InputBox("Introduzca un ISBN de 10 dígitos: ", "Busqueda Libro")
            digitosISBN = Len(sISBN)
        Loop

        iISBN = CLng(sISBN)

        Dim myFileToRead = New System.IO.StreamReader("C:\Users\Toshiba\Desktop\libros.dat", False)
        i = 1
        dato(i) = myFileToRead.ReadLine()
        Do While dato(i) <> -500

            If dato(i) = iISBN And (i - 1) Mod 3 = 0 Then

                dato(i + 1) = myFileToRead.ReadLine()
                dato(i + 2) = myFileToRead.ReadLine()

                precio = dato(i + 1)

                If dato(i + 2) = -66 Then
                    precio = precio - ((precio / 100) * 15)
                End If

                If dato(i + 2) = -99 Then
                    precio = precio - ((precio / 100) * 25)
                End If

                encontrado = True
                LabelResultado.Text = "Libro encontrado" & vbLf & "Su precio es: " & precio
            End If

            i = i + 3
            dato(i) = myFileToRead.ReadLine()
        Loop
        myFileToRead.Close()

        If encontrado = False Then
            LabelResultado.Text = "Libro no disponible"
        End If

    End Sub

    Private Sub ButtonCalcular_Click(sender As Object, e As System.EventArgs) Handles ButtonCalcular.Click
        Dim i As Integer

        precio = 0
        valorLote = 0

        Dim myFileToRead = New System.IO.StreamReader("C:\Users\Toshiba\Desktop\libros.dat", False)
        i = 1
        dato(i) = myFileToRead.ReadLine()

        Do While dato(i) <> -500

            dato(i + 1) = myFileToRead.ReadLine()
            dato(i + 2) = myFileToRead.ReadLine()

            precio = dato(i + 1)

            If dato(i + 2) = -66 Then
                precio = precio - ((precio / 100) * 15)
            End If

            If dato(i + 2) = -99 Then
                precio = precio - ((precio / 100) * 25)
            End If

            valorLote = valorLote + precio

            i = i + 3
            dato(i) = myFileToRead.ReadLine()
        Loop
        myFileToRead.Close()

        LabelResultado.Text = "El valor total del lote es: " & valorLote
    End Sub
End Class


Un saludo!


Mario R. Rancel

  • Administrador
  • Experto
  • ********
  • APR2.COM
  • Mensajes: 1978
    • Ver Perfil
Re:CU00334A-2 Visual Basic. Error en el funcionamiento del ejercicio de ejemplo
« Respuesta #5 en: 20 de Noviembre 2014, 08:08 »
Hola, por un lado tener en cuenta que según indicas "este problema podría resolverse (y debería poder resolverse dado el punto del curso en el que se encuentra)..."

De cara a resolver el problema en este momento del curso, se parte de la base de que los datos de entrada son correctos, por tanto no podría coincidir un isbn con un precio.

Los aspectos de validación (basados en IsNumeric() y Len() ó en condiciones más simples) exceden los objetivos de aprendizaje progresivo, es decir, es algo que se debería introducir cuando se tengan conocimientos más avanzados.

Aunque no le he ejecutado, sobre lo que comentas "sigo sin entender porque si nosotros tenemos dato(1) y despues saltamos a dato(4) con i = i + 3, el algoritmo lee dato(2) como ISBN. Si saltamos del 1 al 4, ¿Por qué lee el 2?."

Mi interpretación sería por el momento que el hecho de que hagas un salto en el índice del array no implica que hagas un salto en el dato que lees desde el fichero. Supongamos la siguiente situación:

55 -- > Dato(1)
10 -- > Dato(2)
-99 -- > Dato(3)
35 -- > Dato(4)


Frente a esta:

55 -- > Dato(1)
10 -- > Dato(4)
-99 -- > Dato(5)
35 -- > Dato(6)

Las líneas en el fichero son la 1, 2, 3, 4, 5, ... y se avanza una línea con cada instrucción readLine. Los índices del array no tienen por qué usarse en un orden determinado, y no se avanza de uno en uno obligatoriamente. Se puede establecer el índice 1 y después pasar al índice 10 dejando todos los intermedios sin establecer, por ejemplo. Por tanto los índices del array no tienen por qué corresponderse obligatoriamente con las líneas en el fichero.

Saludos,

Gilding

  • Sin experiencia
  • *
  • Mensajes: 44
    • Ver Perfil
Re:CU00334A-2 Visual Basic. Error en el funcionamiento del ejercicio de ejemplo
« Respuesta #6 en: 21 de Noviembre 2014, 11:17 »
Muchisimas gracias Mario. Ahora si que he entendido perfectamente que es lo que estaba ocurriendo. Me ha costado jejeje, pero al final lo he pillado.

Sabiendo que sucede exactamente y teniendo en cuenta que la instrucción ReadLine() solo funciona en orden (al menos en este punto del curso), creo que la solución más sencilla a este problema es guardar los datos del fichero en el array (tal vez seria conveniente hacerlo en el inicio de la aplicación, para que no abra y guarde los datos cada vez que queremos buscar algo) y después buscar los ISBN directamente en el array. De esta forma no habría lugar a error alguno.

Muchas gracias, de verdad. Era algo que empezaba a tener atravesado  ;D.

 

Sobre la educación, sólo puedo decir que es el tema más importante en el que nosotros, como pueblo, debemos involucrarnos.

Abraham Lincoln (1808-1865) Presidente estadounidense.

aprenderaprogramar.com: Desde 2006 comprometidos con la didáctica y divulgación de la programación

Preguntas y respuestas

¿Cómo establecer o cambiar la imagen asociada (avatar) de usuario?
  1. Inicia sesión con tu nombre de usuario y contraseña.
  2. Pulsa en perfil --> perfil del foro
  3. Elige la imagen personalizada que quieras usar. Puedes escogerla de una galería de imágenes o subirla desde tu ordenador.
  4. En la parte final de la página pulsa el botón "cambiar perfil".