Blog Sad Hill

Etiquetas: programacion

Escribir buen código: convenciones y editores

por e1kio el Jun.17, 2010, en Informática

Continuando mi entrada anterior con consejos para escribir buen codigo aprovecharé ahora para referirme a algunas convenciones respecto a nombres identificadores de variables, constantes, etc. y a los editores con los que trabajar. De nuevo emplearé el lenguaje Pascal como ejemplo, pero estas directrices se pueden seguir prácticamente en cualquier lenguaje.

Convenciones:
Por enumerarlas de una forma rápida:
- Los nombres (identificadores) que designemos deben ser precisamente eso: identificadores. Debemos dar un nombre significativo a cada cosa, incluso nombres compuestos. Por ejemplo, a una variable que almacene la edad de una persona, no bastaría con llamarle “e“, sino que sería más útil emplear la palabra completa “edad“. Por esta misma razón, a un procedimiento que dibujase un cuadrado no le llamaría “Cuadrado” (que puede confundirse con calcular el cuadrado de un numero) sino “DibujarCuadrado“, porque eso es lo que hace y el identificador ya no deja lugar a dudas de a qué nos estamos refiriendo.
...
procedure DibujarCuadrado (lado: integer);
...

- Las variables deberían comenzar por letra minúscula. Esto es una convención que nos ayudará a distinguirlas de constantes y tipos. Por ejemplo
...
var
   n_entero: integer;
   letra: char;
...

- Las constantes, por contraposición a las anteriores, deberían estar escritas totalmente en mayúsculas. Por ejemplo:
...
const
   NULO = nil;
   MAX = 100;
...

- Los tipos de dato que nosotros definamos deberían empezar por la letra “t” seguidos del nombre de lo que ese tipo representa. Por ejemplo, el tipo “lord” no resulta muy explicativo, resulta más efectivo denominarlo:
...
type
   tListaOrdenada = array [1..MAX] of integer;
...

Así vemos claramente que se trata de una lista ordenada.
- Las funciones y procedimientos deberían comenzar por mayúscula. El nombre de las funciones tiene que representar lo que se calcula o evalúa y el de los procedimientos debe ser un verbo que indique lo que realmente hace. Por ejemplo:
...
function RaizCuadrada (numero: integer): real;
...
procedure MostrarTextoCentrado (texto: string);
...

- Utilizar nombres cortos es algo que deberíamos hacer siempre en la medida de lo posible. Por ejemplo, la función:
...
function RaizCuadrada (numero: integer): real;
...

Es evidente que calcula una raíz cuadrada del entero recibido en la variable “numero“. Sería inútil nombrarla de la siguiente forma:
...
function RaizCuadradaDeUnNumero (numero: integer): real;
...

Este nombre tan largo solo nos causaría incomodidades escribiendo el código fuente y provocará que las líneas del mismo se vuelvan demasiado largas, algo de lo que hablaré más adelante.

Editores:
Que yo sepa, todo código fuente debe ser guardado como texto plano sin ningún tipo de formato. Esto ya descarta como posibles editores a muchos procesadores de texto (Microsoft Word, OpenOffice.org Writer, Abiword, etc.). Son excelentes herramientas y por supuesto que pueden trabajar con texto plano, pero lo hacen de una forma muy engorrosa y son aplicaciones muy pesadas y que por lo general no facilitan mucho la tarea al programador, porque no han sido creadas para programar.
Un editor de texto plano puede ser desde el viejo editor de MS-DOS (que se puede lanzar en la consola con el comando “edit“) o los más básicos presentes en sistemas GNU/Linux (pico, nano, emacs, vi, etc.).


Desgraciadamente, no pueden competir con las nuevas generaciones, que han evolucionado claramente hacia no solo la creación de pequeños documentos sino la creación de código fuente en muchos lenguajes.
Habitualmente yo utilizo gEdit, presente como editor de texto por defecto en Ubuntu y que cumple mis necesidades sin problemas. Las características que más demando en un editor son:

- Un resaltado de sintaxis eficaz, adaptado al lenguaje en el que trabaje y que además no utilice colores molestos o chillones. A fin de cuentas se trata de facilitar la lectura del código. En este aspecto importa que se resalte la línea en la que nos encontramos y los cierres de paréntesis, corchetes, etc. para evitar que nos olvidemos de alguno.
- Que haga sangría del código automática e inteligente, para ayudarnos a centrarnos más en el contenido y menos en la forma.
- La posibilidad de ajustar un limite a las lineas de texto, habitualmente de 80 caracteres, que es el limite que se suele poner porque es lo que cabía en una vieja ventana de terminal (aunque hoy en día este límite sea inexistente). Esto está estrechamente relacionado con lo que contaba en el apartado anterior acerca de no utilizar nombres o instrucciones muy largas en nuestros programas. Estaría bien no rebasar este límite nunca o casi nunca. Esto permite leer el código de un plumazo sin tener que mover el documento hacia los lados y tener oculta una parte del mismo.
- Que la tipografía del texto tenga un tamaño agradable que no nos fuerce la vista o que haga que quepan pocos caracteres en pantalla. Debe tener el tamaño cómodo para trabajar sin dañar nuestras retinas y al mismo tiempo ver porciones del código lo suficientemente amplias como para que quepan nuestras funciones o procedimientos enteros o prácticamente enteros en la misma pantalla.
- Que permita deshacer/rehacer las ultimas modificaciones (un numero suficiente de ellas) para cuando necesitemos volver sobre nuestros pasos tras cambiar alguna porción de código. Muchos editores también pueden guardar automáticamente el documento cada poco tiempo para evitar pérdidas mayores.
- Que esté presente la herramienta “Buscar” y “Buscar y reemplazar”, que ahorran mucho tiempo a la hora de corregir errores que cometimos al teclear o un nombre que sabemos que hemos escrito varias veces de forma incorrecta.
- Que pueda abrir varios documentos al mismo tiempo mediante un sistema de pestañas y que también los botones, menús, … sean útiles, no estorben o desconcentren y estén bien organizados. En definitiva, que el editor tenga una interfaz bien organizada, simple y que resulte de ayuda.
- Que se puedan editar archivos remotos, porque todos los que tenemos archivos en un servidor web necesitamos, antes o después, acceder a ellos. Bien sea por encima de un protocolo FTP, SSH o similar, nuestro editor debería estar capacitado para esto. Esto quiere decir que tiene que existir una buena integración con otras tecnologías de las que dependamos: CVS, SVN, etc.
- Poder imprimir los números de línea, el resaltado de sintaxis, etc. y también imprimir a un archivo en formato PDF o PostScript.

Comentar :, , , more...

Escribir buen código

por e1kio el Jun.16, 2010, en Informática

En los últimos dos días he estado comentando con Atryx las buenas costumbres que uno debe adquirir a la hora de programar. Son muchas y algunas se refieren a como distribuir el código, otras a como documentarlo, otras a qué orden seguir al escribirlo, otras a cómo indentarlo y dividirlo en partes más simples, etc. De las conclusiones sacadas, aquí están unas pocas sugerencias y un ejemplo práctico. Me centraré en Pascal por ser este uno de los primeros lenguajes de nuestra carrera y el que mucha gente aprende por su cuenta para iniciarse en la programación estructurada, pero en general todo consejo puede ser bueno independientemente de qué lenguaje estemos utilizando.

- Distribuir el código:
Hoy en día la gran mayoría de lenguajes de programación existentes, y por supuesto los más conocidos, aceptan la distribución del código fuente de un programa en bloques que se conectan al programa principal o que se encuentran interconectados entre sí. Ya se llamen módulos, librerías, units, bibliotecas… al final todos estos nombres se refieren a un fichero que proporciona una determinada utilidad. En nuestra carrera, el ejemplo más evidente son las units de Pascal (concretamente de la implementación FreePascal) donde todas las funciones y procedimientos de uno de estos módulos se crean para proporcionar a un programa la habilidad de crear, modificar y consultar listas, colas, pilas, etc. Es importante por eso darle también un nombre apropiado a estas librerías: “lista.pas” o “juego.pas“, por ejemplo.
En otras ocasiones, un programa puede necesitar de forma recurrente operaciones mucho más simples y que no están relacionadas entre sí. Pongo por ejemplo la función que convierta una letra mayúscula en minúscula, que enlace ficheros, o el procedimiento que centre un texto en pantalla, o tal vez el algoritmo que nos devuelva un número generado aleatoriamente. Estas operaciones no tienen nada que ver entre sí y no nos proporcionarán un nuevo tipo de dato abstracto, pero son necesarias y se utilizan de forma común. Más evidente aún es la necesidad de importar en todos los módulos de un programa los tipos de datos que se emplean. En lugar de definir los tipos en cada fichero, podemos escribirlos una vez en un módulo separado y exportarlo.
En este caso, a mi me gusta emplear una denominación tomada de la denominación de paquetes de software en sistemas Debian. Igual que a una unit que proporciona una lista podríamos llamarla “lista.pas“, podríamos hablar de “general.pas” o, mi preferido, “base.pas” pues sí que contiene información y operaciones básicas comunes al resto del programa y que, por su naturaleza, no están directamente relacionadas entre sí.

- Documentar el código:
Es muy importante aprender cuando y como escribir comentarios en medio del código fuente de cualquier programa. Por ejemplo, en la siguiente sentencia no hay nada que comentar:
x := 1;
Sería inútil comentar esta instrucción pues cuando un programador abre un programa de pascal (y suponemos por tanto, que entiende fundamentalmente el lenguaje) sabrá que se trata de una asignación y que se graba el número 1 en la variable x. Los comentarios han de escribirse para otro programador, no para cualquier persona, a no ser que esa sea explícitamente nuestra intención. ¿Cuantas líneas de sintaxis igualmente sencilla hay en cualquier código fuente? Exacto, muchas. Llenar de comentarios redundantes o que explican algo tremendamente obvio solo incomodará a quien quiera leerlo y entenderlo.
No obstante, sí que resulta útil comentar fragmentos mayores, como una función, indicando sus entradas, salidas, precondiciones y poscondiciones, objetivo y quizás, alguna aclaración sobre su funcionamiento.
function esListaVacia (L: tLista): boolean;
{Objetivo: Devuelve TRUE si la lista L es una lista vacia, o FALSE en caso contrario
PreCD: La lista esta inicializada}

Tampoco estaría de más comentar las condiciones que se dan para detener un bucle cuya lógica sea un poco enrevesada o no demasiado auto-explicativa. Un ejemplo de esto puede ser:
while not (p = nil) and not (p^.num = n) do p := p^.sig;
{Est bucle se detiene si:
- Se llega al final de la lista
- Si el dato num de la posicion p es igual a n}

Otra posibilidad que nos brindan los comentarios es hacer de delimitadores. No hay problema en dejar tres lineas en blanco de separación entre unas funciones con una ligera relación y otras de carácter distinto, como tampoco importará incluir un comentario como el siguiente:
{ ############################## }
Esta linea sin importancia resulta una gran ayuda visual para organizar de forma eficiente el código, algo de lo que también hablaré más adelante.
No puedo terminar el apartado dedicado a la documentación sin hablar de la función principal de los comentarios. Es precisamente comentar una determinada instrucción o una porción de nuestro trabajo y a eso mismo ha de ceñirse, y no se han de utilizar para escribir grandes explicaciones o hablar de aspectos que no son los propios de ese código. Para eso podría recurrirse a la documentación externa, un archivo independiente donde comentar más profundamente aspectos teóricos, decisiones tomadas o desarrollar razonamientos que ayuden a entender el planteamiento general (y más abstraído del código) del programa.

- Seguir un orden al escribir código:
En casi cualquier lenguaje de programación existen sentencias o palabras de la sintaxis del lenguaje que requieren una apertura y un cierre, o el uso de más de una palabra. Por ejemplo, las palabras BEGIN y END de Pascal. Por cada BEGIN que escribamos, deberá haber otro END, así que no es descabellada la idea de que nada más escribir el primero, colocar ya el segundo y luego escribir el código en medio de ambos. Esto ayudará a no olvidarnos de ningún cierre. Lo mismo se aplica a las aperturas y cierres de paréntesis, llaves, corchetes, etc.
Incluso sentencias selectoras como IF requieren otras palabras: THEN y ELSE, por lo que nada más escribir uno, estaría bien escribir los otros dos. Lo mismo para CASE, WHILE, FOR, etc.

- Como indentar (tabular) el código:
Para que cualquier fragmento resulte más legible se puede decir que es necesario tabular las sentencias según su jerarquía en el algoritmo, y emplear también de forma inteligente los saltos de línea. Un ejemplo de lo que NO hay que hacer:
write ('escribe n: '); readln (n); if n=1 then begin write ('hola');
writeln ('aqui n es 1'); end else writeln ('hola, aqui n es otra cosa')
end; write ('escribe i: '); readln (i);

Es mucho más claro:
write ('escribe n: ');
readln (n);

if n = 1
then begin
    write ('hola');
    writeln ('aqui n es 1');
end
else writeln ('hola, aqui n es otra cosa');

write ('escribe i: ');
readln (i);

La ventaja de tener un código escrito de forma bien clara es que su lectura es mucho más sencilla y parece más fácil de depurar o mejorar. Seguramente por eso tampoco te habrás dado cuenta de que en el primer caso sobra el “end;” que hay al principio de la tercera línea ;) .

- Dividir el código en partes más simples:
Nuestro profesor de programación repite año tras año la siguiente máxima:
Si ocupa más de lo que un editor de texto puede mostrar en una sola pantalla, es demasiado largo
Razón no le falta en absoluto. Quiere decir que no hay que hacer larguísimos procedimientos de 100 líneas. Ni tan siquiera de 80, 70, 60 o 50. Utilizar unidades tan largas de código es una de las mejores maneras de cometer muchos errores: usar identificadores que ya se han usado, no cerrar parejas tipo begin-end, escribir condiciones con una lógica enrevesada… Vale la pena hacer trozos de 20 o 30 lineas y saber que ese trozo está bien que no tener que andar mirando y remirando el código fuente por n-ésima vez para que al final el error sea un punto y coma no puesto, un paréntesis no cerrado, un nombre reutilizado para algo con lo que no se puede reutilizar, etc. Además, hacer algoritmos más pequeños facilita la corrección de los mismos.

Para terminar esta entrada (que siento todavía incompleta), adjunto un pequeño fichero con un código fuente escrito en Pascal. Es una función que inserta un dato de forma ordenada en una lista dinámica. En la parte superior del fichero se encuentra la función (y la función auxiliar “CrearNodo”) ya terminada. Luego, tras una linea de comentarios a modo de separador se encuentra la función hecha paso a paso hasta llegar al resultado final, para así apreciar cómo yo escribo mi código de forma ordenada.
Ejemplo de cómo escribir código de forma ordenada
MD5: 124518af12d744c50c2356b6166e2ca6

Comentar :, , more...

Abrir archivos en Pascal: GPC y FPC

por e1kio el May.18, 2010, en Informática

Abrir un archivo en Pascal no es tan sencillo como pueda parecer porque cada implementación del lenguaje lo hará a su manera. En GNU Pascal Estándar Ampliado (ISO 10206), se deben programar unas funciones que hagan el trabajo sucio. También he contemplado la posibilidad de que el archivo no exista previamente en el directorio del programa y por eso hay dos funciones muy similares: ExisteFicheroTexto y EnlazaFicheroTexto. Aquí está el código:

function ExisteFicheroTexto (nombre: tNombreFichero): boolean;
{Objetivo: Comprueba si existe un fichero con nombre tNombreFichero
 PreCD: El fichero es externo (bindable)
 PosCD: Devuelve TRUE si existe o sino FALSE}
var b: bindingtype; f: tFicheroTexto;
begin
   unbind (f);   {desenlaza f de enlaces previos si hay}
   b := binding (f);   {ínicia b}
   b.name := nombre;
   bind (f, b);   {enlaza la variable f con el fichero argumento}
   b := binding (f);   {actualiza b}
   ExisteFicheroTexto := b.existing;
end;

function EnlazaFicheroTexto (var f: tFicheroTexto; nombre: tNombreFichero): boolean;
{Objetivo: Enlaza un fichero tFicheroTexto
 PreCD: El fichero es externo (bindable)
 PosCD: Devuelve TRUE si ha podido enlazarlo o sino FALSE}
var b: bindingtype;
begin
   unbind (f);   {desenlaza f de enlaces previos si hay}
   b := binding (f);   {inicia b}
   b.name := nombre;
   bind (f, b);   {enlaza la variable f con el fichero argumento}
   b := binding (f);   {actualiza b}
   EnlazaFicheroTexto := b.bound;
end;

En FreePascal la cosa es mucho más simple, bastará con utilizar la librería sysutils y dos palabras reservadas: FileExists y Assign. El código para un archivo prueba.txt sería:

if FileExists ('prueba.txt')
then begin
   {$i-} {Desactiva la comprobacion de errores de entrada/salida}
   assign(f, 'prueba.txt');
   {$i+} {Activa la comprobacion de errores de entrada/salida}
   if (IoResult <> 0)
   then begin
     writeln('Fichero prueba.txt no enlazado');
     halt(1); {Termina el programa}
   end
   else writeln ('Fichero prueba.txt enlazado');
end
else writeln ('Fichero prueba.txt no existe');

He subido el código fuente de los dos programas para abrir ficheros a modo ejemplo en los que esto se puede ver más detalladamente.

Comentar :, , , , more...

Tabla de caracteres ASCII estándar (del 0 al 127)

por e1kio el Abr.21, 2010, en Informática

Aquí pongo una buena tabla encontrada en esta web con la que reconocer los caracteres ASCII desde el caracter 0 al 127 que me resulta personalmente muy útil cuando un programa necesita operar con caracteres que introduce el usuario o que se leen/escriben en un fichero.
En la izquierda se pueden ver los caracteres no-imprimibles (habitualmente de control, como FF o EOT); y a la derecha en dos columnas los caracteres imprimibles entre los cuales hay dos atípicos: el caracter nº 32 es el espacio y el 127 es el caracter de borrado (DEL de delete en los teclados en inglés, SUPR de suprimir en los teclados españoles). Más información sobre ASCII en la wikipedia.

Carácteres no imprimibles     Carácteres imprimibles
Nombre Dec Hex Car. Dec Hex Car.    Dec Hex Car.    Dec Hex Car.
Nulo 0 00 NUL 32 20 Espacio 64 40 @ 96 60 `
Inicio de cabecera 1 01 SOH 33 21 ! 65 41 A 97 61 a
Inicio de texto 2 02 STX 34 22 66 42 B 98 62 b
Fin de texto 3 03 ETX 35 23 # 67 43 C 99 63 c
Fin de transmisión 4 04 EOT 36 24 $ 68 44 D 100 64 d
enquiry 5 05 ENQ 37 25 % 69 45 E 101 65 e
acknowledge 6 06 ACK 38 26 & 70 46 F 102 66 f
Campanilla (beep) 7 07 BEL 39 27 71 47 G 103 67 g
backspace 8 08 BS 40 28 ( 72 48 H 104 68 h
Tabulador horizontal 9 09 HT 41 29 ) 73 49 I 105 69 i
Salto de línea 10 0A LF 42 2A * 74 4A J 106 6A j
Tabulador vertical 11 0B VT 43 2B + 75 4B K 107 6B k
Salto de página 12 0C FF 44 2C , 76 4C L 108 6C l
Retorno de carro 13 0D CR 45 2D - 77 4D M 109 6D m
Shift fuera 14 0E SO 46 2E . 78 4E N 110 6E n
Shift dentro 15 0F SI 47 2F / 79 4F O 111 6F o
Escape línea de datos 16 10 DLE 48 30 0 80 50 P 112 70 p
Control dispositivo 1 17 11 DC1 49 31 1 81 51 Q 113 71 q
Control dispositivo 2 18 12 DC2 50 32 2 82 52 R 114 72 r
Control dispositivo 3 19 13 DC3 51 33 3 83 53 S 115 73 s
Control dispositivo 4 20 14 DC4 52 34 4 84 54 T 116 74 t
neg acknowledge 21 15 NAK 53 35 5 85 55 U 117 75 u
Sincronismo 22 16 SYN 54 36 6 86 56 V 118 76 v
Fin bloque transmitido 23 17 ETB 55 37 7 87 57 W 119 77 w
Cancelar 24 18 CAN 56 38 8 88 58 X 120 78 x
Fin medio 25 19 EM 57 39 9 89 59 Y 121 79 y
Sustituto 26 1A SUB 58 3A : 90 5A Z 122 7A z
Escape 27 1B ESC 59 3B ; 91 5B [ 123 7B {
Separador archivos 28 1C FS 60 3C < 92 5C \ 124 7C |
Separador grupos 29 1D GS 61 3D = 93 5D ] 125 7D }
Separador registros 30 1E RS 62 3E > 94 5E ^ 126 7E ~
Separador unidades 31 1F US 63 3F ? 95 5F _ 127 7F DEL
Comentar :, more...

Estructurando la información en Pascal (arrays, registros)

por e1kio el Feb.23, 2010, en Informática

En Pascal hay más formas de manejar los datos que simplemente almacenarlos en variables o establecer unas constantes.
Hay además dos tipos de dato muy importantes que son los arrays y los registros.
Un array (tambien se puede llamar vector o matriz) es una porción de memoria que almacenará un número determinado de datos de un mismo tipo.
type
  tNombre = string (30);
var
  Alumnos: array [1..100] of tNombre;

En este ejemplo, tendremos un grupo de 100 datos de tipo tNombre almacenados de forma consecutiva y al que podemos acceder de forma aleatoria. Por ejemplo, podemos escribir el nombre del alumno que se ha guardado en la posicion 20:
writeln (Alumnos[20]);
Puedes pensar en un array como si se tratase de una lista de un tamaño determinado llena de elementos de un solo tipo.
La otra estructura son los registros. Se establecen con la palabra reservada RECORD. Supongamos la siguiente colección de tipos:
type
  tNombre = string (30);
  tEdad = integer;
  tTelefono = integer;

Podemos definir una variable registro de esta forma:
var registro: RECORD
   nombre: tNombre;
   edad: tEdad;
   telefono: tTelefono;
  end;

Dado que para entrar a los campos de un registro hay que indicar la variable que lo contiene, entaríamos al campo nombre mediante “registro.nombre”, y podríamos hacer asignaciones como la siguiente:
registro.nombre := 'pepito grillo';
Obviamente podemos crear arrays y tipos no solo como variables, sino definir tipos arrays y registros, e incluso combinarlos; Por ejemplo:

type
  tNombre = string (30);
  tEdad = integer;
  tTelefono = integer;

  tRegistroAlumno = RECORD
   nombre: tNombre;
   edad: tEdad;
   telefono: tTelefono;
  end;

  tArrayAlumnos = array [1..100] of tRegistroAlumno;

Y con crear una variable de tipo tArrayAlumnos…:
var lista: tArrayAlumnos;
Tendríamos ya creada una lista, y si queremos grabar el alumno Pepito Grillo en la posicion 3, usaríamos una sentencia como esta:
lista[3].nombre := 'pepito grillo';
Es evidente como hacer en el resto de casos.
Hemos soslayado ya la idea de como construir tambien una lista estática de N elementos de cualquier tipo: usando un array podemos hacer una lista de un tipo de elementos, pero ese tipo puede ser un registro que almacene diferentes campos. Tambien dejo un codigo fuente de un programa de ejemplo:
Codigo fuente array_record.pas

Comentar :, more...

Programación en BASIC

por e1kio el Feb.21, 2010, en Informática

BASIC es uno de los primeros lenguajes de programación creados. Proviene de la época de esos grandes ordenadores de los que siempre nos impresionaba su descomunal tamaño y su minima potencia basada en tubos, válvulas y tarjetas perforadas: 1964.
Programar en BASIC puede que nos cueste adquirir algún mal hábito si no estamos acostumbrados a programar (el uso de sentencias GOTO) pero no deja de ser extremadamente clarificador para los profanos, porque de hecho se diseñó para explicar lo que era la programación. Hijos de BASIC son VisualBasic pero tambien en una gran medida Pascal, C, Phyton…
Wikipedia: BASIC
Lo primero que podemos necesitar es un intérprete. En GNU/Linux existe uno muy accesible llamado Bywater BASIC que podemos instalar con la orden:
$ sudo apt-get install bwbasic
Para lanzarlo:
$ bwbasic
Si tenemos un codigo fuente guardado en un archivo .bas (por ejemplo, programa.bas) podemos invocarlo de la siguiente forma:
$ bwbasic programa.pas
Ejecutará el programa y luego el intérprete se quedará a la espera. Podemos finalizarlo escribiendo:
quit
En BASIC, una instruccion puede ser:
10 print "hola, mundo"
El 10 es el numero de línea. BASIC las ejecutará por orden asi que si la siguiente fuese la 20 y quisiésemos añadir una en medio bastaría asignarle el 15 o cualquier otro numero entre 10 y 20. Incluso podemos escribirlas completamente desordenadas, no importa. ¡Esto sí que podría ser un mal hábito!. “print” manda escribir lo que aparezca a continuación, que es la cadena de caracteres “hola, mundo“. Por ser una cadena, debe ir entre comillas ” y “.
Si introducimos esto en el intérprete, tendremos que escribir luego:
run
Y se ejecutará. Sin embargo, podemos omitir el numero de linea y la orden se ejecutará nada más introducirla y pulsar Intro. Si guardamos esta linea en un fichero de texto vacio, podemos invocarlo como apunté antes. Generalmente los ficheros BASIC tienen extensión .bas y se deben crear como texto plano (por ejemplo, usando gEdit o el bloc de notas de Windows). He subido un archivo de ejemplo llamado “hola.bas”.
Codigo fuente hola.bas
Tambien podemos hacer un programa para sumar unos numeros a y b dados, y llamar c al resultado. En el siguiente archivo proporciono el codigo fuente y se muestra como usar la funcion let para asignar valores a una variable, algo tal como:
10 let a=8
20 let b=15
30 let c=a+b
40 print "la primera cifra es";a
50 print "la segunda cifra es";b
60 print "la suma es";c

Codigo fuente “sumar.bas”
Además podemos manejar variables de cadenas de caracteres. Lo unico que necesitamos es darles un identificador terminado en el simbolo de dolar. Revisa el archivo “cadenas.bas”.
10 let a$="esto es una cadena de caracteres"
Codigo fuente “cadenas.bas”
Y esto son solo unas pinceladas de la sencillez que encierra BASIC, sencillez que no le impide seguir siendo útil y, sobretodo, poder ser utilizado con fines educativos, tal y como fue creado.
Fichero de comprobacion md5sums.txt de los 3 programas

Comentar :, more...

Compilador de Pascal en Windows al estilo GNU/Linux

por e1kio el Feb.20, 2010, en FIC, Informática

Nuestro profesor de programación proporciona siempre a los alumnos nuevos un manual de Pascal Estandard ISO 10206 (Extendido) con un montón de información concisa sobre las palabras reservadas del lenguaje y su uso. Además al final siempre agrega un pequeño tutorial sobre como instalar los compiladores en máquinas con Debian y con Windows. Para el sistema de Microsoft, recomienda un IDE que se puede descargar desde http://www.gnu-pascal.de/binary/mingw32/. Sin embargo, este entorno integrado instala además otros programas accesorios (me viene a la cabeza un recurrente creador de asistentes de instalación o unos programas de ejemplo listos para compilar) y esto puede que no nos guste tanto. A mi personalmente me gusta más la forma de trabajo de GNU/Linux, especialmente si usamos una distro como Ubuntu y tenemos instalado gEdit y el compilador “gpc”. Basta con tener el editor y el compilador, sin llenar de cosas innecesarias nuestro disco duro, y además el resaltado de sintaxis de gEdit es eficiente y visualmente mucho más claro que el del entorno integrado.
Pero para aquellos que se sientan más cómodos trabajando en Windows (que no es malo por sí mismo, sino distinto a Ubuntu), podemos lograr deshacernos del IDE y escribir nuestros programas de forma mucho menos incómoda. Vamos a tener que bajarnos dos cosas:

1. Las librerías de MinGW (Minimal GNU for Windows) obtenibles desde Sourceforge: http://sourceforge.net/projects/mingw/files/
2. Los archivos mínimos del compilador GPC para Windows obtenibles desde la página oficial: http://gnu-pascal.de/contrib/chief/win32/mingw32/3.4.5/gpc-20070904.i386-pc-mingw32.tar.gz
Es una lástima que estos últimos no se actualicen desde 2007, pero bastaría con echar un vistazo de vez en cuando a http://www.gnu-pascal.de/binary/mingw32/ y revisar si en la categoría “GPC Snapshots and releases (Stable)” aparece algún archivo más reciente que el “gpc-20070904.i386-pc-mingw32.tar.gz” de Septiembre de 2007.
En cualquier caso, por ahora nos vale con esto. Una vez los tengamos descargados, iniciamos la instalación de las librerias GNU. Basicamente con dejar todas las opciones por defecto será suficiente. Las pantallas clave son las siguientes, y hay que seleccionar las opciones que aquí se ven:
 
Si descomprimimos el archivo del compilador, encontraremos una carpeta llamada precisamente “mingw” y dentro de la cual habrá las siguientes carpetas: bin, doc, info, lib, libexec, man.
Todas estas las copiaremos al directorio donde hemos instalado MinGW, que por defecto es “C:\Mingw\” donde encontraremos unas exactamente iguales y tendremos que sobreescribirlas.

Ahora ya están las librerías GNU y el compilador instalados y funcionan a la perfección asi que sólo nos falta un último paso: hacer que, estemos en el directorio en el que estemos, podamos invocarlos con la orden apropiada.
Para conseguirlo tenemos que agregar la ruta donde están al PATH del sistema operativo; lo que significa que cada vez que ejecutemos el comando “gpc“, el SO buscará ese programa entre sus carpetas y tambien las que haya en el PATH. Basta con hacer clic sobre “Mi PC” con el botón derecho y clicar en “Propiedades“. Luego, bajo la pestaña “Opciones avanzadas” pinchamos en “Variables de entorno“. Dentro de esta nueva ventana, debemos modificar la linea PATH y agregar al final un punto y coma (si es que no lo hay) que separe las rutas actuales de la nueva que vamos a introducir, y que no es otra que “C:\Mingw\bin“, que es donde se encuentra el programa compilador.
 
Ahora pinchamos aceptar en todas las ventanas y ya podremos utilizar el compilador desde cualquier ventana del Símbolo de sistema; las instrucciones son las mismas que en GNU/Linux:
gpc --extended-pascal programa.pas
gpc --extended-pascal -c modulo.pas

En la siguiente captura se puede ver un ejemplo donde he compilado un modulo y dos programas:

Al igual que en su sistema nativo, se genera un ejecutable llamado “a” que aquí tiene naturalmente extensión “.exe“. Pude comprobar que esto tambien es efectivo en Windows 7 (y me imagino que tambien en Vista) salvando la diferencia de que “Mi PC” se llama equipo y en sus propiedades hay que pinchar antes en la opción que aparece en la barra lateral llamada “Configuración avanzada del sistema“.
Otra buena noticia. De regalo se instala el GCC (compilador GNU de C) ya que en realidad GPC no es un compilador, sino que preprocesa el codigo fuente de Pascal a codigo fuente en C para luego invocar a gcc y compilar; asi que si has seguido todos los pasos, esto tambien preparará tu sistema para compilar programas escritos en C en este sistema operativo de forma “Ubuntu-like“.
Esta entrada no estaría completa sin un editor de texto apropiado. Y ya que queremos que se asemeje a Ubuntu, instalemos una versión para Windows del genial gEdit. Gnome la proporciona en su sitio FTP y está disponible en ftp://ftp.gnome.org/pub/GNOME/binaries/win32/gedit/. Con escojer la carpeta y el instalador correspondientes a la versión más reciente, ya podremos instalarlo y usarlo sin problemas.

Comentar :, , , , , , , more...

Programación estructurada en Pascal

por e1kio el Feb.13, 2010, en Informática

La programación estructurada es el tipo de programación al que pertenecen Pascal, C, Phyton… Basicamente dicta que el lenguaje se resume en 3 tipos de instrucciones:
- Sentencias: una instrucción sencilla
- Decisiones (selectores): se toma un camino u otro de acuerdo a una condición que puede ser verdadera o falsa (IF…THEN…ELSE…, CASE)
- Bucles (iteradores): repetición de sentencias (WHILE, FOR, REPEAT)
Una sentencia normal y corriente en Pascal puede ser
writeln ('hola mundo');
Si quisiésemos decidir si mostrarla o no de acuerdo a, por ejemplo, que una variable i valiese 1 usaríamos el IF:
if i = 1 then writeln ('hola mundo') else ('adios mundo');
Si quisiésemos repetir la instruccion un numero determinado de veces (por ejemplo tres):
for i := 1 to 3 do writeln ('hola mundo');
Otras posibilidades…
Si en vez de decidir entre dos caminos (IF…THEN…ELSE…) nuestra intención es distinguir varios, disponemos del CASE.
case i of
      1: writeln ('hola mundo');
      2: writeln ('adios mundo');
      3: ...
      ...
      otherwise: writeln ('cualquier otro caso no contemplado antes');
end;

En el caso de los bucles, las tres posibilidades se distinguen porque:
- REPEAT: comienza ejecutándose. Tras la ejecución, comprueba si se da la condición para terminar. Si es falsa, vuelve a ejecutar las instrucciones que contenga. Si es verdadera, acaba el bucle y el programa continua a partir de ese punto. Por eso se ejecuta siempre al menos una vez.
- WHILE: antes de ejecutarse por primera vez evalúa la condición. Si es verdadera, ejecuta las instrucciones de su interior y luego vuelve al principio si la condicion sigue siendo verdadera o continua a partir de ese punto si es falsa. Puede que no se ejecute nunca.
- FOR: es el bucle más seguro de todos pues no conduce a la creación de bucles infinitos. Utiliza una variable de control (en el ejemplo anterior i) a la que asigna un valor inicial. Luego toma todos los valores intermedios hasta llegar a un valor final establecido. Para cada uno de esos pasos, ejecuta las instrucciones que contiene. Se ejecuta siempre al menos una vez y la variable se avanza de forma automática.
Si tomamos el ejemplo puesto antes, vemos cómo se puede escribir con cualquiera de los bucles:
Con FOR:
for i := 1 to 3 do writeln ('hola mundo');
Con WHILE:
i := 1;
while i < = 3 do begin
      writeln ('hola mundo');
      i := i+1;
end;

Con REPEAT:
i := 1;
REPEAT
      writeln ('hola mundo');
      i := i +1;
UNTIL i > 3;

Además el bucle FOR permite usar una secuencia decreciente (útil para ordenar arrays, por poner un ejemplo):
for i:= 3 downto 1 do writeln ('hola mundo');
He subido un pequeño programa de ejemplo para ver en funcionamiento la sentencia IF y los diferentes bucles. Se compila con:
gpc --extended-pascal if_for.pas
Codigo fuente de “if_for.pas

Comentar :, more...

Tipos de datos en Pascal

por e1kio el Feb.11, 2010, en Informática

Pensemos en los datos que podemos manejar dentro de un programa. Una variable (el nombre que introduce un usuario, un número que controle un bucle, etc.) siempre debe estar asociada a un tipo de dato.
Por ejemplo, una variable muy sencilla puede ser:
var i: integer;
Esto quiere decir que manejaremos un dato (i) y ese dato será siempre un número entero (integer). Es importante distinguir entre lo que es el dato y lo que es su tipo. Además, si en un momento determinado del programa hacemos:
i := 1;
ocurrirán tres cosas. En primer lugar, el programa tomará el valor 1 y mirará si es un número entero, porque es lo que i puede almacenar. A continuación, buscará la región de memoria que se asocia al nombre i. Esta región es donde se graba el valor de la variable (no su nombre, ni su tipo). Por ultimo, copia el valor de 1 a esta región de memoria.
Es decir, i es el nombre de un espacio de memoria que puede almacenar un valor (el que nosotros le grabemos) únicamente del tipo del que se haya definido, que en este caso era integer.
Pero podemos guardar datos de más tipos. Principalmente de los tipos que el lenguaje proporciona, o de tipos que construyamos nosotros. Los tipos definidos en el lenguaje son:
- integer numeros enteros entre MININT y MAXINT
- char caracteres de la tabla ASCII
- boolean valores logicos TRUE o FALSE
- string en realidad son cadenas de CHAR
- real, complex... numeros en coma flotante (reales, complejos…)
Además puede ser que necesitemos tipos más complejos, como listas, colas, pilas, árboles de cualquier naturaleza… Estos tipos definidos por el usuario habrá que construirlos (a veces se denominan tipos abstractos) y hay que crearlos a partir de los primarios. En la asignatura de EDI se ven con más profundidad.
IMPORTANTE: Todo dato debe ser de un tipo bien definido, asi que no podemos usar una variable para almacenar ahora un entero y luego un string.

Comentar :, more...

Programación en Pascal

por e1kio el Feb.04, 2010, en Informática

Aprovechando que estoy repasando Pascal con una compañera, voy a publicar aquí un extracto de los emails que intercambiamos por si resultan útiles a alguien más.
Basicamente está orientado a hacer la práctica de programación en nuestra facultad, pero no pondré nada sobre el desarrollo especifico de esta.
Lo primero es la estructura básica de un programa en Pascal. Usaremos el GNU Pascal, basado en Pascal Estandard ISO 10206. Tenéis un compilador Windows en http://www.gnu-pascal.de pero yo creo que es preferible trabajar bajo Ubuntu (o kubuntu, xubuntu, debian, etc.). El compilador se encuentra en los repositorios oficiales y para instalarlo basta con hacer:
$ sudo apt-get install gpc
De ahi en adelante solo necesitais el editor de texto plano (por ejemplo gedit) o en Windows el editor que incluye el IDE (aunque me parece muy incómodo tanto para la vista como para configurarlo como para utilizarlo para programar). Un ejemplo de programa minimo:

 program programa1 (input, output)
 import {zona en la que importamos modulos}
 export {si es un modulo (unit), zona en la que exportamos sus funciones}


 const {declaracion de constantes}
 type {declaracion de tipos que diseñemos nosotros}
 var {declaracion de variables}


 {algunas funciones y procedimientos}
 function ...
 begin
 end;

 procedure ...
 begin
 end;

 {zona donde desarrollamos el cuerpo principal del programa}
 begin
 end.

Como siempre conviene recordar que los archivos se guardan con extension “.pas” y que el compilador se invoca:
$ gpc --extended-pascal programa.pas
si se trata de un modulo añadimos la directiva -c
$ gpc --extended-pascal -c modulo.pas
En pascal los comentarios se introducen entre corchetes { }. Por ejemplo:
{Ejemplo de comentario en Pascal}
Dejo dos archivos a disposición de quien quiera:
- Programa minimo (hola mundo)
- Ejemplo usando algunos elementos (funciones, procedimientos, variables…)

Fichero de comprobaciones md5sums.txt

Comentar :, more...

¿Buscas algo?

Usa este formulario:

¿Aún no lo has econtrado? ¡Deja un comentario!



También puedes usar las etiquetas



Software libre

Este blog apoya el uso de Ubuntu y otro software libre
Ubuntu