Curso Básico de Programación
en Visual Basic

Séptima Entrega: 10/Sep/97.
por Guillermo "guille" Som

Te recomiendo que leas las entregas anteriores, aquí tienes los links:
La Primera, la Segunda, la Tercera, la Cuarta, la Quinta, la Quinta++, la Sexta.


Hola fans del curso básico, es que poco a poco se están apuntando más gente a este cursillo y eso me pone en un compromiso... ¡¡¡me vais a obligar a terminarlo!!!

Bromas aparte, espero que te siga interesando y que se lo digas a tus vecinas, compañeros de clase, gente de tu curro y demás personal que te encuentres por la calle, el bus, el metro, cuando llames a un 906 y sobre todo cuando te tomes unas copas con los amigos... a ver si al final entre todos me compráis una casita de verdad...

Vamos a ver las soluciones de los ejercicios de la sexta entrega, para ver que nivel llevas, porque me imagino que te has enterado de todo lo que ponía, ya que últimamente no recibo preguntas ni dudas ni quejas porque algo estuviera mal... salvo algún que otro despistadillo que ha empezado por la primera entrega, hace los ejercicios y me "mailea" diciéndome que no le muestra nada... y eso que lo he puesto al final de la primera entrega y en letra GORDA pa que se vea bien...
Esto pasa por bajarse las páginas, guardarlas en el disco duro y después leerla al montón de días...

Bueno, después del rapapolvo... todo para que se te olvide que esta entrega iba a estar el mes pasado...

SOLUCIONES A LOS EJERCICIOS DE LA SEXTA ENTREGA:

1.)

Private Sub Command1_Click()
    Dim A As Integer
    Dim B As Integer
    Dim i As Integer
    A = Val(Text1)
    B = Val(Text2)
    For i = A To B
	Print i
    Next
    Show
End Sub
' El bucle también se puede hacer de esta forma:
i = A
Do While i <= B
    Print i
    i = i + 1
Loop
' Y de esta también
i = A
While i <= B
    Print i
    i = i + 1
Wend
 
2.)
Private Sub Command1_Click()
	Dim A As Integer
	Dim B As Integer
	Dim C As Integer
	Dim i As Integer
	A = Val(Text1)
	B = Val(Text2)
	C = Val(Text3)
	For i = A To B Step C
		Print i
	Next
	Show
End Sub
' Otra forma de solucionarlo
i = A
Do While i <= B
	Print i
	i = i + C
Wend
 
3.)
' Añadir estas líneas:
Dim D As Integer
'...
'...For
	D = D +1
	'...
Next
Label1 = "Número de repeticiones: " & D

Y eso es todo, no pongo otras posibles formas de obtener los resultados, porque tu mismo habrás comprobado si están bien o no.


 

Ahora empezamos con la entrega real, es decir la séptima.
Ya disponemos de instrucciones suficientes para empezar a "profundizar" en las cosas más difíciles... o casi.
Ya sabes que hay que usar Option Explicit en todos los módulos de código... Esto no es obligatorio, pero si no quieres que perdamos la amistad, usalo. Gracias.
También cómo usar las variables y los diferentes tipos, puedes hacer bucles, tomar decisiones, realmente es más correcto decir: hacer que VB tome decisiones, ya sabes cómo pedir datos al usuario y también cómo mostrarlos. Sabes crear tus propias instrucciones... ¡Jo! ¡Cuanto sabes! Me tienes "anonadado"

Pero aún no sabes una cosa: cómo crear Funciones
¿Qué son las funciones?
Para simplificar, te diré que una función es un procedimiento (como el Sub), que puede devolver un valor. Normalmente se usa para que lo devuelva, aunque veremos que no siempre es necesario; de todas formas, cuando necesites un procedimiento que no necesite devolver un valor, usa el Sub.
¿Cómo declarar/codificar una función?
Ámbito Function Nombre ([parámetros]) As Tipo
Dónde Ámbito puede ser Public o Private, dependiendo de la "cobertura" o visibilidad. Ya sabes, Private sólo es visible en el propio módulo en el que se encuentra definido y Public es en todo el proyecto, incluso fuera de él...
Los parámetros son los valores que esta función puede necesitar para "cumplir" su misión. Éstos son opcionales, es decir puede tenerlos o no, incluso si tiene, puede ser uno o varios, para declarar varios parámetros hay que separarlos por comas... Los corchetes, que se suelen usar en los manuales, la ayuda, etc, sirven para indicar que son opcionales, ¡pero no se te ocurra ponerlos en ninguna función!, ya que no forman parte del lenguaje Basic...
El tipo es para saber que tipo de dato devolverá la función.

El valor devuelto por una función lo podemos usar para asignarlo a una variable: a = MiFunción()
o incluirlo en una expresión: If MiFunción() + 15 > LoQueSea Then

La ventaja real frente a los Subs es la posibilidad de devolver un valor, imaginate que quieres crearte tu propio procedimiento para averiguar si un determinado archivo existe... si lo hace como función podrías devolver un valor cero para indicar que no existe el archivo y un valor distinto de cero indicaría que el archivo en cuestión existe. Por tanto, podríamos usarlo de esta forma:
If Existe(NombreArchivo) Then ...
Ya que estamos puestos, veamos cómo hacer esta función de forma simple y así te explico una cosa muy importante de toda función: ¡poder devolver el valor!

Public Function Existe(sArchivo As String) As Integer
	Existe = Len(Dir$(sArchivo))
End Function

Para devolver un valor, éste se asigna a una variable que tiene el mísmo nombre que la función.
Ya vimos que LEN devuelve el número de caracteres de la cadena que ponemos entre los paréntesis; si, LEN también es una función, pero incluida en el propio Visual Basic.
Dir$ es otra función del VB que devuelve el nombre de un archivo, (sólo el nombre), o una cadena vacía, en caso de que no haya ninguno en la dirección pasada por el parámetro que se ha usado. Para saber más de esta función, así como de otras, puedes buscar en la ayuda...

Hemos visto que en las expresiones usamos unos operadores para hacer las comparaciones, aquí tienes los seis posibles:
= igual, > mayor que, < menor que, >= mayor o igual, <= menor o igual y <> distinto.
Recuerda que el signo igual funciona de forma diferente, según se use en un expresión o en una asignación.
Pero además de estos signos, podemos usar en nuestras expresiones unos operadores lógicos, estos son: AND, OR y NOT
Podríamos desear hacer una comparación y comprobar si varias cosas se cumplen, por ejemplo:
If A>10 And Len(Nombre)<>0 Then ...
Para que esta expresión se cumpla, deben ser ciertas las dos condiciones, es decir que A sea mayor que 10 "y" que la longitud de Nombre sea distinta de cero. Podemos usar tantas condiciones como queramos, sin pasarnos demasiado para que la cosa funciones mejor. Aquí las dos condiciones deben cumplirse, pero en este otro ejemplo:
If A>10 Or Len(Nombre)<>0 Then ...
cumpliéndose cualquiera de las dos, se acepataría como válido.
Cuando el If se procesa, se toma todo lo que hay entre IF y THEN y se considera como una sóla expresión.
Si quieres puedes asignar a una variable el resultado de una expresión, el valor devuelto siempre será 0 (cero) en caso de que no se cumpla todo lo expuesto y -1 cuando sea cierta.
Para manejar estos valores de Cierto (-1) y Falso (0), Visual Basic tiene un tipo especial llamado Boolean, los valores que puede aceptar una variable de este tipo son: True (verdadero) y False (falso).
Veamos un ejemplo:

Dim b As Boolean, i As Integer
Dim a As Integer, Nombre As String

Show

a = 15
Nombre = "Guille"
b = (a > 10 And Len(Nombre) <> 0)
i = (a > 10 Or Len(Nombre) <> 0)
Print "Valor de B "; b
Print "Valor de i "; i

¿Te has fijado en el detalle? B vale True (verdadero), sin embargo i vale -1. Pero para el caso los dos valores significan lo mismo: si estas expresiones se hubiesen usado en una comparación, las dos hubiesen devuelto un valor verdadero.

El tercer operador lógico (Not) sirve para negar algo, es decir invertir el valor contenido en una variable, o casi...
If Not A>10 Then ...
Parece lógico el resultado, ¿verdad?, si no se cumple que A sea mayor que diez, será cierto; comprobémoslo:

Dim A As Integer

'¿recuedas que tienes que poner Show?

A = 5
If Not A > 10 Then
	Print A; "no es mayor que 10"
End If

¡BINGO! ¡Funciona!
"Mu" bonito, pero... ¿que es lo que ocurre?
Se toma A > 10 y se procesa, como A no es mayor que 10, se devuelve un valor falso (0) y después se hace Not 0 que da como resultado -1 (verdadero), por tanto se cumple la condición.
Ya vimos que el valor devuelto por una variable se puede usar en una comparación, si es cero se toma como falso y si es distinto de cero, como verdadero.
Prueba ahora esto:

A = 0
If Not A Then
	Print A; "es cero"
Else
	Print A; "es distinto de cero"
End If

También funciona, ya que Not 0 es -1, por tanto el If lo da por cierto, si cambiamos el valor incial de A por un valor distinto de cero:

A = 5
If Not A Then
	Print A; "es cero"
Else
	Print A; "es distinto de cero"
End If

¿Que ha pasado aquí? Simple, que no es lo que esperábamos... Cuando hicimos Not 0 era evidente, ya que se convierte en -1, pero Not 5 no se convierte en cero, sino en: -6 y ya sabes que el IF considera como verdadero todo lo que no sea cero.
No quiero entrar en detalles de porqué ocurre esto, sólo decirte que la responsable de todo es la notación binaria... los ceros y unos que dicen que es el lenguaje nativo de los cacharros estos... talvez más adelante tratemos un poco de la notación binaria, pero no por ahora... recuerdo que en mis tiempos del GwBasic la usaba bastante, incluso tenía rutinas para "representar" en ceros y unos un número...
Vale, para que te entretengas probando... (
este link es para el programa completo Dec2Bin.zip 1.75 KB)

Private Function Dec2Bin(sNumDec As String) As String
    ' Recibe una cadena que será un número decimal
    ' Devuelve ese número representado por ceros y unos
    '
    Dim i As Integer
    Dim lngNum As Long      ' Long, por si las moscas
    Dim sTmp As String      ' Cadena temporal

    lngNum = Val(sNumDec)
    sTmp = ""
    For i = MaxBits - 1 To 0 Step -1
        If lngNum And 2 ^ i Then
            sTmp = sTmp & "1"
        Else
            sTmp = sTmp & "0"
        End If
    Next

    Dec2Bin = sTmp
End Function

Ahora puedes comprobar porqué NOT 5 da como resultado -6, usa esta rutina para probarlo, si escribes 5, te mostrará:
00000101 y si escribes -6 lo que muestra es: 11111010, fijate que ha cambiado todos los ceros por unos y viceversa.
Eso es lo que hace el NOT, invertir los valores binarios y como un valor binario sólo puede ser 0 ó 1, no se complica demasiado la vida. Prueba a escribir el valor 0 y el valor -1 y conviertelo a notación binaria, fijate lo que el Visual Basic normalmente ve.

Prueba con el tema de la notación binaria, así sabrás realmente cómo funciona todo esto de las comparaciones (por dentro).
Lo que nunca falla es completar la expresión, por ejemplo si haces esto:

If Not A<>0 Then
	Print A; "es CERO"
Else
	Print A; "NO es CERO"
End If

Esto siempre funcionará de la forma esperada.
Pero sería más fácil, o al menos más inteligible, hacerlo así:

If A = 0 Then
	Print A; "es CERO"
Else
	Print A; "NO es CERO"
End If

Es que algunas veces se puede uno complicar la vida más de lo necesario...

Cuando quieras comprobar un valor devuelto por cualquier expresión, puedes hacerlo asignándolo a una variable o bien mostrando el valor: Print Not A

Cuando se usa AND pra evaluar varias partes de una expresión hay que tener presente que siempre se procesan todas las condiciones y finalmente se decide si es cierto o no el valor devuelto. Esto que parece lógico, algunas veces puede llevar a confusión e incluso producir efectos no deseados en el programa.
Prueba con esta nueva versión de la función Existe. En un form debes poner una etiqueta Label1.

Private Function Existe(Archivo As String) As Integer
    Existe = Len(Dir$(Archivo))
    If Existe Then
        Label1 = Archivo & " Si existe"
    Else
        Label1 = Archivo & " No existe"
    End If
    ' Esto es más corto, pero talvez menos evidente:
    ' Label1 = Archivo & IIf(Existe, " Si", " No") & " existe"
    DoEvents
End Function
Private Sub Form_Load()

    Dim A As Integer, Nombre As String

    Show

    Label1 = ""
    Nombre = "C:\Autoexec.BIN"
    A = 5
    If A > 10 And Existe(Nombre) Then
        Print A; "mayor de 10 y " & Nombre & " existe"
    Else
        Print A; "no es mayor de 10 o " & Nombre & " no existe"
    End If
End Sub

En el ejemplo comprobarás que a pesar de que la segunda parte de la comparación no se cumpla, a no ser que tengas en tu disco C un archivo que se llame así, el caption del Label se ha cambiado. Es decir que se ha procesado la segunda parte de la expresión a pesar de que la primera A>10 es FALSA. Imagínate que en lugar de ser una función rápida, hubiese sido otra cosa que tardara un poquito más de la cuenta...
Para casos como estos, (la verdad es que no son demasiado habituales), deberías hacerlo así:

Private Sub Form_Load()

    Dim A As Integer, Nombre As String

    Show

    Label1 = ""
    Nombre = "C:\Autoexec.BIN"
    A = 5
    If A > 10 Then
        If Existe(Nombre) Then
            Print A; "mayor de 10 y " & Nombre & " existe"
        Else
            Print A; "es mayor de 10 pero " & Nombre & " no existe"
        End If
    Else
        Print A; "no es mayor de 10 o " & Nombre & " no existe"
    End If
End Sub

Talvez sea más largo y haya que usar más código, pero en ocasiones es más "resultón".
Usando este nuevo "estilo", sólo se comprobará si existe el archivo cuando A sea mayor que diez.
Lo que debes sacar en claro de todo esto es que después de un THEN puedes "anidar" más expresiones IF...THEN...ELSE. Incluso se puede usar en una sola línea, sólo que el resultado "visual" del código no es tan "presentable"...

If A > 10 And Existe(Nombre) Then Print A; "mayor de 10 y " & Nombre & " existe" Else Print A; "no es mayor de 10 o " & Nombre & " no existe"

Aunque podríamos usar el caracter _ que se puede usar en VB para separar líneas largas, pero es como si estuviese toda en la misma línea, así que la línea anterior, se quedaría así:

If A > 10 And Existe(Nombre) Then _
    Print A; "mayor de 10 y " & Nombre & " existe" _
Else _
    Print A; "no es mayor de 10 o " & Nombre & " no existe"

Fíjate que a pesar de aparentar que es un BLOQUE IF, no tiene el END IF del final, esto es porque yo lo he "estructurado" de esa forma, no porque sea lo mismo. El uso de _ es sólo estético y para VB todo se trata de una misma línea, por tanto tendrá un límite de caracteres posibles a usar, el límite que VB le ponga, que creo que es 1024... pero no me hagas demasiado caso...

Antes he mencionado la palabra "anidación", ésta se usa para indicar que una serie de instrucciones están dentro de otras. En este caso hemos anidado dos IF... THEN, pero lo más habitual es hacerlo con los bucles (FOR, DO, etc.), veámoslo:

Dim i%, j%, c%
For i = 1 To 10
    For j = 1 To 10
	c = c + 1
    Next
Next
Print c

Lo que debes saber, o al menos tener en cuenta, es que cuando anidamos varios bucles, lo externos empiezan antes (elemental querido Watson), pero los internos finalizan primero (...) y hasta que no lo hagan, no podrán continuar los de fuera.
En el ejemplo, por cada repetición del bucle i, se completa un bucle j. Por eso el valor de c es 100 (10*10)
Esto, en ocasiones, puede ralentizar el programa, y dar la impresión de que el programa se ha quedado "colgado", prueba a poner otro bucle dentro del j y cambia los valores máximo de los dos bucles internos a 1000, te recomiendo que la variable c sea LONG y que te sientes... No hace falta que hagas la prueba, es una chorrada...
Lo que interesa es que dentro de un proceso cualquiera y por supuesto también en los bucles, podríamos necesitar que el Visual Basic nos mostrara alguna indicación de que está "ocupado", por ejemplo cambiando la forma del cursor del ratón, como hacen otros programas, incluso el propio VB cuando está "atareado". Para ello tendremos que cambiar la propiedad MousePointer para que muestre el reloj de arena:

MousePointer = vbHourGlass ' vbHourglass es igual a 11, por si tienes usas el VB3
'... lo que sea
MousePointer = vbDefault ' 0 si usas VB3

Pero algunas veces el cursor no se cambia... para asegurarnos que cambie, usa el DoEvents después de asignar el valor para el reloj de arena. De esta forma permitimos que Windows procese sus mensajes (¿recuerdas?) y así tiene ocasión de cambiar el puntero del ratón.

Bueno, hasta aquí llega esta entrega. No hay ejercicios, sólo te pediría que revisaras la ayuda y te leyeras lo que allí pone referente a las instrucciones que vamos viendo... aunque me imagino que tendrás otras cosas que hacer...
El caso es que no hay ejercicios y ya está.

Siguiendo con la costumbre todas las entregas anteriores, te pido tus comentarios sobre esta entrega y el curso en general, más que nada para saber si voy bien encaminado y no me pierdo, lo que pretendo es que se entienda y que aprendas...

Ya me contarás.
Nos vemos en la próxima entrega, que espero que no sea tan tardona como esta...


 

entrega anterior ir al índice siguiente entrega

Ir al índice principal del Guille