Documentos de Académico
Documentos de Profesional
Documentos de Cultura
INTRODUCCIÓN ............................................................................................................................................................. 7
¿QUÉ ES LA PROGRAMACIÓN? ............................................................................................................................ 7
¿PARA QUÉ SIRVE LA PROGRAMACIÓN? ......................................................................................................... 7
¿POR QUÉ DEBERÍAS DE APRENDER A PROGRAMAR? ............................................................................... 7
PROGRAMAR TE ENSEÑA A PENSAR ................................................................................................................. 7
FUNCIONES..................................................................................................................................................................... 8
MODIFICADORES DE UNA FUNCIÓN ................................................................................................................... 8
TIPO DE RETORNO DE UN MÉTODO ................................................................................................................... 9
NOMBRE DE LA FUNCIÓN ....................................................................................................................................... 9
ARGUMENTOS O PARÁMETROS DE UNA FUNCIÓN ....................................................................................... 9
EL BLOQUE DE CÓDIGO.......................................................................................................................................... 9
EJEMPLO DE UNA FUNCIÓN .................................................................................................................................. 9
LLAMADAS A FUNCIONES EN PROGRAMACIÓN............................................................................................ 10
COMO PASAR ARGUMENTOS O PARÁMETROS A UNA FUNCIÓN............................................................ 10
DECLARAR MÉTODOS QUE DEVUELVEN UN RESULTADO ........................................................................ 11
DEVOLUCIÓN DE UN VALOR CON RETURN .................................................................................................... 11
RECEPCIÓN DE VALORES DEVUELTOS........................................................................................................... 11
VENTAJAS DEL USO DE FUNCIONES EN PROGRAMACIÓN ....................................................................... 12
FUNCIÓN MAIN EN PROGRAMACIÓN ................................................................................................................ 12
¿ POR QUÉ EL MÉTODO MAIN DEBE ACEPTAR ESTOS ARGUMENTOS? .............................................. 12
ARRAYS ......................................................................................................................................................................... 13
CARACTERÍSTICAS PRINCIPALES DE LOS ARRAYS .................................................................................... 14
DIMENSIONALIDADES DE LOS ARRAYS........................................................................................................... 14
ARRAYS UNIDIMENSIONALES ............................................................................................................................. 15
ARRAYS BIDIMENSIONALES ................................................................................................................................ 15
ARRAYS MULTIDIMENSIONALES ........................................................................................................................ 15
DECLARACIÓN Y ACCESO DE ARRAYS EN VARIOS LENGUAJES ............................................................ 16
ARRAY EN C Y C++ ................................................................................................................................................. 16
ARRAY EN JAVA ....................................................................................................................................................... 17
ARRAY EN JAVASCRIPT ........................................................................................................................................ 18
ARRAY EN PHP ........................................................................................................................................................ 18
VARIABLES INDEFINIDAS...................................................................................................................................... 21
DECLARACIÓN DE VARIABLES EN C ................................................................................................................. 22
2
DISTINTOS TIPOS DE VARIABLES ...................................................................................................................... 22
DECLARACIÓN DE VARIABLE Y ASIGNACIÓN DE VALOR ........................................................................... 22
¿CUÁL ES LA IMPORTANCIA DE LAS DECLARACIONES DE VARIABLES EN LA PROGRAMACIÓN?
...................................................................................................................................................................................... 23
¿CUÁL ES EL PROPÓSITO DE ESPECIFICAR EL TIPO DE DATOS EN UNA DECLARACIÓN DE
VARIABLE? ................................................................................................................................................................ 23
¿CUÁLES SON LOS TIPOS DE DATOS MÁS COMUNES UTILIZADOS EN LAS DECLARACIONES DE
VARIABLES? .............................................................................................................................................................. 23
¿PUEDO MODIFICAR EL TIPO DE DATO DE UNA VARIABLE DESPUÉS DE HABERLA DECLARADO?
...................................................................................................................................................................................... 23
¿ES OBLIGATORIO ASIGNAR UN VALOR INICIAL A UNA VARIABLE EN LA DECLARACIÓN?............ 24
¿QUÉ SUCEDE SI DECLARO UNA VARIABLE CON EL MISMO NOMBRE QUE OTRA YA EXISTENTE
EN EL PROGRAMA? ................................................................................................................................................ 24
ALMACENAMIENTO................................................................................................................................................. 24
CLASIFICACIÓN PRINCIPAL DE ALMACENAMIENTO EN COMPUTADORAS .......................................... 24
DIRECCIONAMIENTO.............................................................................................................................................. 25
REPRESENTACIÓN DE MEMORIA ...................................................................................................................... 25
COLA (DEFINICIÓN) ................................................................................................................................................ 26
INICIALIZACIÓN ........................................................................................................................................................ 27
ASIGNACIÓN Y RECUPERACIÓN DE VALORES DE LOS ELEMENTOS .................................................... 28
EXTENDIENDO LA DIMENSIÓN............................................................................................................................ 29
ESTRUCTURAS ............................................................................................................................................................ 29
CARACTERÍSTICAS Y VENTAJAS ....................................................................................................................... 30
LAS 3 ESTRUCTURAS BÁSICAS .......................................................................................................................... 31
PUNTEROS .................................................................................................................................................................... 32
DECLARANDO PUNTEROS ................................................................................................................................... 33
EXPLICACIÓN ........................................................................................................................................................... 33
¿DIFERENTES DIRECCIONES? ........................................................................................................................... 34
USO EN FUNCIONES .............................................................................................................................................. 35
OPERADORES .......................................................................................................................................................... 35
OPERACIONES ARITMÉTICAS ............................................................................................................................. 35
PUNTEROS CONSTANTES.................................................................................................................................... 36
PUNTEROS GENÉRICOS ....................................................................................................................................... 37
PUNTEROS Y MATRICES ...................................................................................................................................... 38
PUNTEROS A CADENAS DE CARACTERES ..................................................................................................... 39
MATRICES DE PUNTEROS.................................................................................................................................... 39
PUNTEROS A PUNTEROS ..................................................................................................................................... 40
MATRICES DE PUNTEROS A CADENAS DE CARACTERES ........................................................................ 41
3
ASIGNANDO VALORES A PUNTEROS ............................................................................................................... 41
¿CÓMO SE USA UN PUNTERO? .......................................................................................................................... 43
MANEJO DE ARCHIVOS ............................................................................................................................................ 45
FICHEROS ................................................................................................................................................................. 46
FOPEN ........................................................................................................................................................................ 46
FCLOSE ...................................................................................................................................................................... 47
FEOF ........................................................................................................................................................................... 47
REWIND ...................................................................................................................................................................... 48
LECTURA ................................................................................................................................................................... 48
FGETC......................................................................................................................................................................... 48
FGETS ......................................................................................................................................................................... 49
FREAD......................................................................................................................................................................... 51
FSCANF ...................................................................................................................................................................... 51
ESCRITURA ............................................................................................................................................................... 52
FPUTC ......................................................................................................................................................................... 52
FPUTS ......................................................................................................................................................................... 53
FWRITE ....................................................................................................................................................................... 54
FPRINTF ..................................................................................................................................................................... 54
ARCHIVOS Y DIRECTORIOS ................................................................................................................................. 55
PERMISOS DE ARCHIVOS Y DIRECTORIOS .................................................................................................... 56
ARCHIVOS ................................................................................................................................................................. 58
LECTURA DE ARCHIVOS ....................................................................................................................................... 58
ESCRITURA EN ARCHIVOS .................................................................................................................................. 61
ARCHIVOS DE VALORES CON SEPARADORES ............................................................................................. 62
¿DÓNDE DEBERÍA ESTAR TU SITIO WEB EN TU COMPUTADORA? ........................................................ 65
UNA ACOTACIÓN SOBRE LA ENVOLTURA Y EL ESPACIADO .................................................................... 65
¿QUÉ ESTRUCTURA DEBE TENER TU SITIO WEB? ...................................................................................... 66
RUTAS DE ARCHIVO ............................................................................................................................................... 67
PROCESAMIENTO DE TEXTO .............................................................................................................................. 69
SALTOS DE LÍNEA ................................................................................................................................................... 69
REEMPLAZAR SECCIONES DEL STRING ......................................................................................................... 70
SEPARAR Y JUNTAR STRINGS............................................................................................................................ 71
MAYÚSCULAS Y MINÚSCULAS ............................................................................................................................ 73
REVISAR CONTENIDOS DEL STRING ................................................................................................................ 73
ALINEACIÓN DE STRINGS .................................................................................................................................... 74
INTERPOLACIÓN DE STRINGS ............................................................................................................................ 75
4
RESOLUCIÓN DE PROBLEMAS DE ACCESO A ARCHIVOS ......................................................................... 76
RESOLUCIÓN DE PROBLEMAS CON RUTAS DE BÚSQUEDA ( COMMAND NOT FOUND) .................. 76
¿CÓMO DIAGNOSTICAR Y CORREGIR PROBLEMAS DE RUTA DE BÚSQUEDA? ................................. 77
CAMBIO DE PROPIEDADES DE GRUPO Y ARCHIVO .................................................................................... 79
RESOLUCIÓN DE PROBLEMAS DE ACCESO A ARCHIVOS ......................................................................... 79
DETECCIÓN DE PROBLEMAS CON EL ACCESO DE RED ............................................................................ 79
CREACIÓN DE UNIDADES ........................................................................................................................................ 79
SUBPROGRAMAS Y BLOQUES COMPILADOS INDEPENDIENTEMENTE ................................................. 89
¿QUÉ ES SUBPROGRAMACIÓN? ........................................................................................................................ 89
¿CÓMO SE IMPLEMENTAN LOS SUBPROGRAMAS O FUNCIONES?........................................................ 90
API DE JAVASCRIPT ............................................................................................................................................... 90
FUNCIONES............................................................................................................................................................... 91
PARÁMETROS .......................................................................................................................................................... 91
CREACIÓN, MODIFICACIÓN Y BORRADO DE SUBPROGRAMAS............................................................... 93
COMPILADOR E INTÉRPRETE ................................................................................................................................. 93
¿QUÉ ES UN INTÉRPRETE? ................................................................................................................................. 94
¿QUÉ ES UN COMPILADOR?................................................................................................................................ 94
SOLUCIÓN HÍBRIDA DE INTÉRPRETE Y COMPILADOR ............................................................................... 95
PROGRAMACIÓN ESTRUCTURADA ................................................................................................................... 96
¿QUÉ ES LA PROGRAMACIÓN ESTRUCTURADA? ........................................................................................ 96
¿QUÉ HABÍA ANTES DE LA PROGRAMACIÓN ESTRUCTURADA? ............................................................ 96
¿QUÉ APORTÓ LA PROGRAMACIÓN ESTRUCTURADA? ............................................................................. 97
TIPOS DE FUNCIONES ........................................................................................................................................... 98
¿SE USA HOY LA PROGRAMACIÓN ESTRUCTURADA? ............................................................................... 98
¿QUÉ VINO DESPUÉS DE LA PROGRAMACIÓN ESTRUCTURADA? ......................................................... 99
BIBLIOTECA DEL SISTEMA ................................................................................................................................... 99
SISTEMA DE PROGRAMACIÓN O FRAMEWORK .......................................................................................... 100
¿CUÁL ES LA DIFERENCIA ENTONCES? ¿CUÁL USAN LOS PROGRAMADORES? ............................ 100
LA BIBLIOTECA DEL SISTEMA ........................................................................................................................... 100
¿QUÉ SON EXACTAMENTE LAS LIBRERÍAS? ............................................................................................... 101
SINTAXIS PARA DECLARAR LIBRERÍAS EN C++ .......................................................................................... 102
¿CÓMO DECLARAR UNA LIBRERÍA EN C++? ................................................................................................ 103
ACERCA DEL NAMESPACE STD ....................................................................................................................... 104
DISEÑO DE INTERFAZ DE USUARIO ................................................................................................................ 105
IMPORTANCIA DEL DISEÑO CENTRADO EN EL USUARIO ........................................................................ 106
CARACTERÍSTICAS DEL DISEÑO CENTRADO EN EL USUARIO .............................................................. 106
5
EVALUAR LOS RESULTADOS ............................................................................................................................ 107
ETAPAS DEL DISEÑO CENTRADO EN LAS PERSONAS ............................................................................. 108
LOS 6 ELEMENTOS PARA UNA METODOLOGÍA DEL DISEÑO CENTRADO EN EL USUARIO .......... 109
EL MARKETING CENTRADO EN EL USUARIO ............................................................................................... 111
CÓMO APLICAR EL DISEÑO CENTRADO EN EL USUARIO EN TU SITIO WEB ..................................... 112
INTERRUPCIONES DE DOS .................................................................................................................................... 114
FUNCIONAMIENTO DEL MECANISMO DE INTERRUPCIONES .................................................................. 115
MECANISMO Y LÍNEAS DE PETICIÓN DE INTERRUPCIÓN ........................................................................ 116
FUNCIONAMIENTO ................................................................................................................................................ 143
ACTUALIZACIÓN FIRMWARE ............................................................................................................................. 143
OVERCLOCKING .................................................................................................................................................... 144
FIRMWARE EN TARJETAS ADAPTADORAS ................................................................................................... 144
TARJETAS DE VÍDEO............................................................................................................................................ 144
MERCADO DE LOS BIOS ..................................................................................................................................... 145
ALTERNATIVAS Y SUCESORES ........................................................................................................................ 145
CONTENIDOS.......................................................................................................................................................... 146
BIOS .............................................................................................................................................................................. 146
PASOS DE PROCESO DE CARGA DE LA BIOS 6 UA 2.3.1 – BIOS............................................................ 146
TARJETA GRÁFICA................................................................................................................................................ 147
CONFIGURACIÓN DEL BIOS ............................................................................................................................... 153
ACTUALIZACIÓN DEL BIOS 30 UA 2.3.1 – BIOS............................................................................................. 154
CREAR UN CD/DVD CON LA APLICACIÓN ASUS UPDATE AL SUITE II ................................................. 154
CONTROLANDO EL FIRMWARE DEL SISTEMA 32 UA 2.3.1 – BIOS ......................................................... 155
CARACTERÍSTICAS BIOS Y UEFI 33 UA 2.3.1 – BIOS .................................................................................. 155
CARACTERÍSTICAS BIOS Y UEFI 34 UA 2.3.1 – BIOS .................................................................................. 155
SEGURIDAD EN BIOS Y UEFI 36 UA 2.3.1 – BIOS ......................................................................................... 156
SEGURIDAD EN BIOS Y UEFI 37 UA 2.3.1 – BIOS. ........................................................................................ 156
EL RELOJ Y PILA CMOS 38 UA 2.3.1 – BIOS................................................................................................... 157
EL RELOJ Y PILA CMOS 39 UA 2.3.1 – BIOS................................................................................................... 157
EL RELOJ Y PILA CMOS 40 UA 2.3.1 – BIO ..................................................................................................... 157
FABRICANTES DE BIOS 41 UA 2.3.1 – BIOS ................................................................................................... 158
CONCLUSIÓN ............................................................................................................................................................. 159
BIBLIOGRAFÍA ........................................................................................................................................................... 160
6
INTRODUCCIÓN
¿QUÉ ES LA PROGRAMACIÓN?
La programación informática es el arte de indicarle a una computadora lo que tiene que hacer
mediante un conjunto de instrucciones. Es decir, los programadores, escriben las instrucciones en
una especie de lenguaje que al principio puede parecer a los humanos un poco extraño, pero que
las máquinas saben interpretar perfectamente. La computadora lee este código, estas instrucciones,
y las ejecuta en el orden correcto. Es como si la computadora fuese un perro super obediente y
nunca te pone en duda, y hace todo lo que tú digas en el orden que se lo digas.
7
FUNCIONES
Una función, desde el punto de vista de la programación, se define como un proceso que recibe
valores de entrada (llamados argumentos) y el cual retorna un valor resultado. Adicionalmente, las
funciones son subprogramas dentro de un programa que se pueden invocar (ejecutar), desde
cualquier parte del programa, es decir, desde otra función, desde la misma función o desde el
programa principal, cuantas veces sea necesario.
Las funciones se usan cuando existen dos o más porciones de algoritmo dentro de un
programa que son iguales o muy similares, por ejemplo, en un algoritmo se puede emplear varias
veces una porción de algoritmo que eleva a una potencia dada un número real. Las funciones,
también llamados métodos, nos permiten dividir el trabajo que hace un programa, en tareas más
pequeñas separadas de la parte principal. Ese es el concepto de función en programación.
Veamos un ejemplo: imagina que desarrollas un programa, y una de las partes hace un cálculo de
un valor. Puede ser algo simple, como una suma o una resta, pero puede ser un cálculo mucho más
complicado, como puede ser la distancia entre dos objetos en un videojuego 3D.
El código que realiza que realiza las tareas del cálculo puede estar en una función. Esta función
puede ser usada de forma independiente en diferentes partes del programa, ya sea en programación
modular o en un lenguaje orientado a objetos como Java. Por lo tanto, puedes invocar la función o
método que calcula el total de una clase, o aplicar el resultado de los cálculos.
Los modificadores de un método son varias palabras clave , o palabras reservadas de un lenguaje
de programación, que puede modificar la forma en que los métodos son usados. Los modificadores
son opcionales, por eso lo hemos indicado en corchetes [ ]. Ejemplos de modificadores pueden
ser public, private, protected, virtual, static…
8
TIPO DE RETORNO DE UN MÉTODO
El tipo retorno es el tipo de valor devuelto por la función, y puede ser usado en cualquier parte del
programa. Las funciones sólo pueden devolver un valor, ya sea un tipo de datos básico, como puede
ser un número entero o un string, o dependiendo del lenguaje un objeto. Pero no podría devolver
dos números, por ejemplo. Eso lo haremos de otra manera.
NOMBRE DE LA FUNCIÓN
Los argumentos de una función, también llamados parámetros, representa una lista de variables
cuyos valores son pasados al método para ser usados por éste. Suelen ser opcionales, por eso en
el ejemplo están en corchetes [ ]. Algunos métodos no aceptan argumentos. Los parámetros de una
función tienen una serie de características que hablaremos un poco más abajo para entrar en
detalle.
EL BLOQUE DE CÓDIGO
El código del método es la secuencia de instrucciones o sentencias que la función realiza. Estas
instrucciones son las tareas que hacen que la función tenga sentido. Para saber que un bloque de
código pertenece a una función, en el ejemplo está entre llaves { }. Así sabemos cuándo acaba la
función. En algunos lenguajes nos podremos encontrar otra manera de indicar cuando empieza y
termina una función. Por ejemplo, en Visual Basic acabaría como End Sub o End Function, en
Pascal tenemos BEGIN y END.
Aquí tienes un ejemplo de una función de un método que no tiene argumentos y no retorna nada.
Total, de clase tal es un método básico ejemplo:
9
public void Dibuja()
{
println("*****");
}
Un ejemplo de un método que acepta dos argumentos y devuelve un resultado de una suma:
• No hay límite en cuanto a la cantidad de llamadas a funciones que un método puede realizar.
• Se puede invocar a los métodos en cualquier orden.
• Para funciones en objetos:
o Los métodos no necesitan ser completados en el orden que son listados en la clase,
que es dónde están declarados.
o El método llamado y el método desde dónde se llama pueden estar en la misma clase
o en diferentes clases.
Como hemos dicho anteriormente, las funciones pueden ser invocadas desde otro método, con una
lista de argumentos. Adicionalmente, las funciones pueden devolver un valor para ser usado como
resultado. Muchos de los métodos que declaras o usas desde la biblioteca que te ofrece el
compilador del lenguaje también aceptan argumentos. Pasa pasar argumentos desde un método a
otro, se hace desde los paréntesis de la llamada al método. Los argumentos pasados conservadores
literales o variables. Al llamar a un método, se deben listar los argumentos en el mismo orden que
dichos argumentos están declarados en la definición del método, además que deben pasarse todos
los argumentos requeridos. El compilador verificará si el tipo y cantidad de argumentos pasados
concuerda con el tipo, el orden y cantidad de parámetros que acepta el método llamado.
10
DECLARAR MÉTODOS QUE DEVUELVEN UN RESULTADO
Para declarar un método que devuelve un valor, se debe incluir el tipo del valor que devuelve delante
del identificador del método en la declaración de este. El siguiente ejemplo muestra un método que
acepta dos valores del tipo int y devuelve un valor de tipo int:
Para devolver un valor desde un método, se utiliza la palabra clave return. Por ejemplo, el siguiente
código devuelve el valor que tiene actualmente la variable result.
return result;
Si se invoca un método que devuelve un valor, como en el caso anterior, se puede utilizar el valor
devuelto en el método desde dónde se ha llamado. Veamos esta función:
int resultado;
resultado = Sum(4, 5);
11
VENTAJAS DEL USO DE FUNCIONES EN PROGRAMACIÓN
Los métodos son el mecanismo por el cual los objetos interactúan entre sí. En un programa es
común tener varios objetos que interactúan invocando los métodos en forma mutua.
• Hace que los programas sean más legibles y fáciles de mantener. Por ejemplo, es fácil saber
lo que un programa hace si el código está dividido en varios métodos diferentes con nombres
que describan el comportamiento de estos.
• El desarrollo y el mantenimiento es más rápido. Por ejemplo, puedes elegir crear y probar un
método por vez cada para asegurar que el programa, en su totalidad, funciona bien cuando
se ha finalizado.
• Son utilizados para que el software sea reusable. Por ejemplo, las bibliotecas de cualquier
compilador tienen muchas clases con métodos que pueden ser usados una y otra vez en los
programas.
• Se puede crear métodos para que otros programadores puedan usar.
• Los métodos permiten separar los objetos para comunicar y distribuir el trabajo realizado por
el programa.
En casi todos los lenguajes de programación, se utiliza el método main, que debe ser escrito de
forma tal que aceptan argumentos uno o más parámetros, pero nos lo encontramos como un array
de Strings.
El lenguaje de programación requiere que el método main se escriba de forma que acepte valores
cuando es ejecutado desde la línea de comando (en Windows sería la ventana Símbolo del sistema).
Por ejemplo, si quieres pasar un número con una cantidad de 22.00, se escribiría de esta manera
con parámetros:
Nombre_ejecutable 22.00
12
Para que se pueda usar en el programa, los valores numéricos pasados al método main deben ser
convertidos de cadena de caracteres, o string, a un tipo primitivo.
• Nota: El pase de argumentos al método main es una característica usada para probar
programas. Además, necesitas conocer cómo funcionan las arrays para saber cómo tratar
los diferentes argumentos pasados.
De esta manera se define una función que al ser invocada ejecute dicho código, y en el lugar donde
estaba la porción de algoritmo original, se hace un llamado (ejecución) de la función creada.
Donde,
ARRAYS
Un array es una manera de poder guardar datos del mismo tipo o clase (Enteros, carácteres,
booleanos, etc.). Es posible el acceso a cada elemento de un array a través de un número entero
que se denomina índice (pueden existir 2 o más índices según la dimensionalidad del array). La
13
numeración de estos elementos dentro del array comienza en 0 (primer elemento del array) y finaliza
en n-1 (último elemento del array) donde n es el tamaño completo de dicho array.
Para utilizar los arrays de manera adecuada se realizan las siguientes acciones sobre ellos:
• Declarar el array
• Crear el array e inicializarlo (Esta acción puede ser incluida en la declaración)
• Acceder y utilizar el array
• Tiene un nombre de variable único que representa a cada elemento dentro de él y estos
elementos son diferenciados por un índice.
• Los elementos dentro del array son guardados en posiciones de memoria de forma continua.
• Se puede acceder a cada elemento individual del array de manera directa o aleatoria.
14
ARRAYS UNIDIMENSIONALES
Un array unidimensional (vector) es aquel en el cual se puede acceder a cualquier elemento
solamente con un índice. Se puede imaginar como si se tratase de una lista de datos en la cual,
para referirnos a cada elemento de dicha lista, emplearemos un número (índice) para indicar la
posición en la que podemos encontrar dicho elemento dentro de ella.
ARRAYS BIDIMENSIONALES
En el caso de los arrays bidimensionales (También llamados tablas o matríces), son 2 los índices
necesarios para localizar cualquier elemento.
Cualquier elemento dentro del array bidimensional se puede imaginar como un elemento que se
encuentra localizado dentro de una posición determinadas en un “eje X” y un “eje Y”.
En la imagen anterior, si cogemos cualquier posición dentro del array como una posición {x,y}:
ARRAYS MULTIDIMENSIONALES
También se pueden crear arrays de más de 2 dimensiones y son los denominados Arrays
multidimensionales.
En este caso el número de índices viene determinado por el número de dimensiones de nuestro
array, por ejemplo, para un array tridimensional el número de índices sería 3. Igual que ocurre con
los otros tipos de arrays, cualquier elemento puede ser localizado mediante una posición concreta.
15
Si cogemos como ejemplo la imagen anterior, se trata de un array tridimensional, en el que, cualquier
elemento, puede ser localizado mediante una posición {x,y,z}.
Por ejemplo:
• Para el cuadrado rojo que está en la cara inferior izquierda la posición sería {0,2,0}
• Si queremos localizar el cuadrado verde de la cara inferior derecha sería {2,1,1}
Anotación: Todas las declaraciones de arrays que se van a hacer a continuación se hacen de forma
vacía, es decir, no se inicializan valores dentro de dicha declaración, pero perfectamente se pueden
inicializar valores dentro del array a la hora de la declaración.
ARRAY EN C Y C++
Para declarar un array unidimensional tanto en C como en C++, la sentencia a utilizar es:
Tipo_dato nombre_array[número_elementos];
Donde número de elementos debe ser mayor o igual a 1.
16
Un ejemplo podría ser: int ejemplo[7];
Para acceder a cualquier posición dentro dicho array, la sentencia a utilizar es:
Nombre_array[posición];
Donde “posición” debe encontrarse en el rango desde 0 a “número_elementos”-1.
Por tanto, si por ejemplo quisiéramos acceder a la posición 6 de dicho array, la sentencia a utilizar
sería ejemplo[5]; ya que, como dijimos anteriormente, los índices en los arrays comienzan en la
posición 0. En el caso de los arrays bidimensionales y multidimensionales, la declaración es igual
que para los unidimensionales aumentando el número de “corchetes” donde quedan especificadas
las dimensiones del array. Por ejemplo, para un array bidimensional un ejemplo de declaración
sería: char palabras[4][5]; mientras que si queremos declarar un array de 4 dimensiones un ejemplo
sería: bool elección[3][2][3][2]; a la hora de acceder estamos ante la misma situación aumentando
las dimensiones en la consulta. Por ejemplo: palabras[2][0]; o elección[0][0][1][2]; C es un lenguaje
de programación (considerado uno de los más importantes) que se utiliza en aplicaciones como en
sistemas operativos, además de ser la base de otros lenguajes más actuales como Java o C++.
Lo que es un array es visto en el lenguaje C como una cadena de caracteres declarados. C permiten
la utilización de cierto número de notaciones y de funciones especiales y, por ejemplo, en C++ no
es posible crear de manera sencilla un vector (o array unidimensional) capaz de almacenar una
cantidad de información indefinida, siendo necesario ingresar con antelación la cantidad de datos
(tamaño) que el vector o la matriz tendrán. Lo que son los arrays unidimensionales y bidimensionales
forman parte de la amplia variedad de estructuras de datos que ofrece el lenguaje de programación
C, siendo además una de las principales y más útiles estructuras que puedes tener como
herramienta de programación. Para declarar un array unidimensional tanto en C como en C++, la
sentencia a utilizar es:
Tipo_dato nombre_array[número_elementos]
ARRAY EN JAVA
Declarar y acceder a un array en Java es muy parecido a C o C++. La principal diferencia radica en
que Java trata a un array como si fuera un objeto mientras que en C y C++ se trata como si fuera
una variable. La sentencia utilizada para declarar un array unidimensional en Java es:
Tipo_dato nombre_array[]; Nombre_array = new tipo_dato[tamaño_array];
Y para acceder la sentencia sería:
17
nombre_array[posición];
Un ejemplo sería:
ARRAY EN JAVASCRIPT
En el caso de Javascript, para declarar un array existen 2 métodos:
Var nombre_array = new Array(); O Var nombre_array = [];
Para acceder a cualquier elemento dentro del array la sentencia sería:
nombre_array [posición];
Para arrays multidimensionales en Javascript podéis ver el siguiente tutorial.
ARRAY EN PHP
Finalmente, vamos a ver cómo declarar y acceder a los elementos de un array con PHP.
Para declarar un array unidimesional, la sintaxis sería:
$nombre_variable = array();
Ejemplo: $colores = array();
En el caso de que queramos declarar un array multidimensional (2 ó más dimensiones) simplemente
habría que ir concatenando la función array() para cada dimensión dentro de la dimensión anterior:
$nombre_variable = array(array(…));
Por ejemplo, si queremos un array bidimensional sería:
$tabla = array(array());
Mientras que si queremos uno tridimensional sería:
$variable = array(array(array()));
Para acceder a los arrays en PHP la sentencia a utilizar sería:
18
$nombre_variable[posición];
Ejemplo: $colores[3];
Y en el caso de multidimensionales simplemente basta con ir incluyendo “corchetes” con la posición
dentro de dicha dimensión. Ejemplo: $variable[3][2][0];
En programación de computadoras , una declaración es una construcción de lenguaje que especifica
las propiedades de un identificador : declara lo que una palabra (identificador) "significa". Las
declaraciones se usan más comúnmente para funciones , variables , constantes y clases , pero
también se pueden usar para otras entidades como enumeraciones y definiciones de tipos. Más allá
del nombre (el identificador en sí) y el tipo de entidad (función, variable, etc.), las declaraciones
suelen especificar el tipo de datos (para variables y constantes) o la firma de tipo (para funciones);
los tipos también pueden incluir dimensiones, como para matrices.
Se utiliza una declaración para anunciar la existencia de la entidad al compilador ; esto es importante
en aquellos lenguajes fuertemente tipados que requieren funciones, variables y constantes, y sus
tipos deben especificarse con una declaración antes de su uso, y se usa en la declaración directa .
El término "declaración" se contrasta con frecuencia con el término "definición", pero el significado
y el uso varían significativamente entre idiomas; vea abajo. Las declaraciones son particularmente
prominentes en los idiomas de la tradición ALGOL , incluida la familia BCPL , principalmente C y C
++ , y también Pascal . Java usa el término "declaración", aunque Java no requiere declaraciones y
definiciones separadas.
Una dicotomía básica es si una declaración contiene o no una definición: por ejemplo, si una
declaración de una constante o variable especifica el valor de la constante (respectivamente, el valor
inicial de una variable), o solo su tipo; y de manera similar si una declaración de una función
específica el cuerpo ( implementación ) de la función, o solo su tipo de firma. No todos los idiomas
hacen esta distinción: en muchos idiomas, las declaraciones siempre incluyen una definición y
pueden denominarse "declaraciones" o "definiciones", según el idioma.
Sin embargo, estos conceptos se distinguen en lenguajes que requieren declaración antes de su
uso (para los cuales se utilizan declaraciones directas) y en lenguajes donde la interfaz y la
implementación están separadas: la interfaz contiene declaraciones, la implementación contiene
definiciones.
En el uso informal, una "declaración" se refiere solo a una declaración pura (solo tipos, sin valor ni
cuerpo), mientras que una "definición" se refiere a una declaración que incluye un valor o cuerpo.
19
Sin embargo, en el uso formal (en las especificaciones del lenguaje), "declaración" incluye ambos
sentidos, con distinciones más precisas por lenguaje: en C y C ++, una declaración de una función
que no incluye un cuerpo se llama un prototipo de función , mientras que una declaración de una
función que incluye un cuerpo se denomina "definición de función". En Java, las declaraciones se
presentan de dos formas.
Para los métodos públicos, se pueden presentar en interfaces como firmas de métodos, que
consisten en los nombres de los métodos, los tipos de entrada y el tipo de salida. Se puede utilizar
una notación similar en la definición de métodos abstractos , que no contienen una definición. Se
puede crear una instancia de la clase adjunta, en lugar de una nueva clase derivada, que
proporciona la definición del método, se necesitaría crear para crear una instancia de la clase. A
partir de Java 8 , la expresión lambda se incluyó en el lenguaje, que podría verse como una
declaración de función.
Para las variables, las definiciones asignan valores a un área de memoria que se reservó durante
la fase de declaración. Para las funciones, las definiciones proporcionan el cuerpo de la función. Si
bien una variable o función puede declararse muchas veces, normalmente se define una vez (en C
++ , esto se conoce como la regla de una definición o ODR).
Los lenguajes dinámicos como JavaScript o Python generalmente permiten redefinir las funciones,
es decir, volver a enlazarlas ; una función es una variable muy parecida a cualquier otra, con un
nombre y un valor (la definición).
void example3(void);
20
Aquí hay algunos ejemplos de declaraciones que son definiciones, nuevamente en C:
int example2 = 5;
VARIABLES INDEFINIDAS
Al declararse las variables, el programa en ejecución reserva ese espacio de memoria según el tipo
de datos escogido. La declaración de variables es un proceso esencial en la programación, ya que
permite al programador especificar las variables que serán utilizadas en el programa y sus
respectivos tipos de datos. Es importante destacar que algunos lenguajes de programación,
como Python, no obligan al programador a declarar las variables, lo que puede tener ventajas y
desventajas en términos de eficiencia y legibilidad del código.
21
pero suelen incluir tipos simples como enteros, flotantes, caracteres y booleanos, así como tipos
más complejos como arreglos y estructuras. Cada tipo de dato ocupa un espacio específico en
la memoria, lo que tiene implicaciones en la eficiencia y gestión de recursos del programa. Es
importante destacar que, al declarar variables, el programa reserva un espacio específico en la
memoria para almacenar su valor. Por lo tanto, es necesario tener en cuenta la gestión adecuada
de la memoria en el programa, evitando errores como fugas de memoria y sobrecargas que pueden
afectar su desempeño y estabilidad.
DECLARACIÓN DE VARIABLES EN C
El siguiente código declara dos variables llamadas numero1 y numero2 que contendrán números
enteros (int) y una tercera numero3 con un número flotante (float).
En lenguaje C y C++ todas las variables deben declararse antes de ser usadas, de lo contrario
dará un error de compilación.
int main()
{
char caracter;
short valor;
int numero
long numeroLargo;
float numeroReal;
double numeroRealDoble;
return 0;}
int contador = 0;
22
Esta línea declara una variable de nombre contador del tipo entero iniciándola en valor 0 (cero).
También es posible declarar variables dentro de un bucle, las variables declaradas dentro de un
bucle serán accesibles sólo desde el propio bucle, esto es, tendrán un ámbito local para el bucle.
Las líneas de código de declaración en programación son donde se escriben las variables y sus
tipos de datos. Al declarar las variables, el programa reserva espacio de memoria según el tipo de
datos elegido.
23
programación débilmente tipados, como JavaScript, es posible cambiar el tipo de dato de una
variable durante la ejecución del programa.
¿QUÉ SUCEDE SI DECLARO UNA VARIABLE CON EL MISMO NOMBRE QUE OTRA
YA EXISTENTE EN EL PROGRAMA?
Si declaras una variable con el mismo nombre que otra ya existente en el programa, se producirá
un conflicto de nombres y el compilador o intérprete mostrará un error. Para evitar este problema,
es importante usar nombres de variables únicos y significativos en el programa.
ALMACENAMIENTO
Hay dos clases, almacenamiento primario, que son los que usa la CPU directamente
(memoria principal, memoria caché, etc) y el almacenamiento secundario, a los cuales la CPU no
accede directamente, sino que deben almacenarse previamente en uno primario. Son de
almacenamiento secundario los discos magnéticos, ópticos, cintas magnéticas, tambores
magnéticos, etc.El almacenamiento de datos puede usarse también para copias de seguridad,
ver backup.Con el correr de los años, el almacenamiento de datos informáticos ha ido bajando de
precio. Por ejemplo, 1 GB de memoria en 1956 costaba 8,2 millones de dólares.
- Almacenamiento primario: que son los que usa la CPU directamente (memoria principal, memoria
caché, etc)
- Almacenamiento secundario: a los cuales la CPU no accede directamente, sino que deben
almacenarse previamente en uno primario. Son de almacenamiento secundario los discos
magnéticos, ópticos, cintas magnéticas, tambores magnéticos, etc.
24
DIRECCIONAMIENTO
Un modo de direccionamiento especifica la forma de calcular la dirección de memoria efectiva de
un operando mediante el uso de la información contenida en registros y / o constantes, contenida
dentro de una instrucción de la máquina o en otra parte. Los modos de direccionamiento son las
diferentes maneras de especificar en informática un operando dentro de una instrucción
(lenguaje ensamblador). Cómo se especifican e interpretan las direcciones de memoria según las
instrucciones. Pueden ser:
REPRESENTACIÓN DE MEMORIA
• Secure Digital (SD)
Están basadas en el formato Multimedia Card (MMC). Las tarjetas marcadas como HC (High
Capacity) funionan a alta velocidad y tienen tasas de transferencia de datos muy altas; algunas
cámaras fotográficas digitales requieren este tipo de tarjetas para poder grabar video con fluidez o
para capturar múltiples fotografías en sucesión rápida.
• Starmedia
También conocidas como (Tarjeta de Disco Floppy en Estado Sólido). Son duraderas y su apariencia
física es similar a la de un disquete, pero con el tamaño aproximado de una estampilla de correo.
Su forma impide introducirlas en su ranura en sentido contrario.
• Memory Stick
25
Tarjetas digitales con con memoria flash diseñadas con la compañía Sony. Ademas de ser aptas
para cámaras digitales de esta marca, las Memory Stick se pueden utilizar en una gran variedad de
aparatos digitales. Estas tarjetas sirven para almacenar imágenes, música, datos, textos y gráficos
Ofrecen una alta velocidad de acceso y o necesitan ningún dispositivo para la reproducción, pues
disponen de un adaptador para disquetes.
Por su tamaño tan reducido, este formato de tarjeta se utiliza especialmente en teléfonos celulares.
Combina gran capacidad de almacenamient, alta tasa de transferencia de datos, confiabilidad,
seguridad y bajo consumo de energía. También se utiliza en reproductores de audio, cámaras
digitales (por medio de un adaptador) y asistentes digitales personales (PDA).
• Micro SD CARD
Este formato de tarjeta solo mide 10.9mm x 14.9mm x 1mm y puede almacenar vrios GB de
información. Al igual que el MINI SD, es my utilizado en teléfonos celular. En 1980, 184 mil dólares;
en 1990 eran 5.200 dólares; en 2000 eran 12 dólares, y en 2006 fueron 1,2 dólares.
COLA (DEFINICIÓN)
Una cola es una estructura de almacenamiento, donde la podemos considerar como una lista de
elementos, en la que éstos van a ser insertados por un extremo y serán extraídos por otro. Las colas
son estructuras de tipo FIFO (first-in, first-out), ya que el primer elemento en entrar a la cola será el
primero en salir de ella. Existen muchísimos ejemplos de colas en la vida real, como, por ejemplo:
personas esperando en un teléfono público, niños esperando para subir a un juego mecánico,
estudiantes esperando para subir a un camión escolar, etc.
• Como arreglos
• Como listas ordenadas
En esta unidad trataremos a las colas como arreglos de elementos, en donde debemos definir el
tamaño de la cola y dos apuntadores, uno para accesar a el primer elemento de la lista y otro que
guarde el último. En lo sucesivo, al apuntador del primer elemento lo llamaremos F, al del último
elemento A y MÁXIMO para definir el número máximo de elementos en la cola.
26
INICIALIZACIÓN
Para la inicialización de una lista de listas primero tendremos que reservar memoria para la lista (para
indicar cuántos elementos habrá en ella) y después habrá que reservar memoria para cada uno de
los elementos de dicha lista (pues son listas). Según el párrafo anterior, si se deseara una lista de n-
elementos en una lista, y que cada uno de esos elementos contuvieran una lista de m-valores, en total
se necesitaría memoria para n×m valores. Dicha reserva se realiza con una sola instrucción:
Esta es su representación gráfica. La variable lista, después del new, almacena una referencia al lugar
de la memoria donde de guardan n datos y cada uno de esos datos almacena una referencia al lugar
de la memoria donde se guarda otra lista de m datos.
Uno podría
desear que cada uno de los n-elementos de la lista esté formado por otra lista cada cual con una
longitud diferente. Por ejemplo, que el primer elemento esté formado por una lista de 2 elementos,
que el segundo elemento esté formado por una lista de 13 elementos, que el tercer elemento esté
formado por una lista de 7 elementos, y así sucesivamente. Este tipo de estructura de datos se puede
realizar también utilizando solo arrays. Para ellos se deberá de realizar estos dos pasos:
• indicar para cada uno de los términos de la lista de que longitud será la lista que
"almacenará".
27
Observa cómo se pueden construir una lista de listas de distinta longitud. En este caso es una lista de
2 elementos y cada uno es una lista. El primer elemento es una lista de 4 enteros y el segundo de 2
enteros.
Una vez reservados los espacios de memoria para todos los elementos que componen las listas de
la lista, utilizaremos el sistema de índices ya estudiado.
1. lista[i], responde al acceso del elemento i-ésimo de la lista (el cuál es otro array);
Necesitamos dos índices para acceder a cada uno de los elementos en un array de arrays.
pero como ahora lista[i] es otra lista, actuaremos sobre cada elemento utilizando este patrón:
28
for (int i=0; i<lista.length; i++) {
for (int j=0; j<lista[i].length; j++) {
acciones sobre lista[i][j]
}
}
EXTENDIENDO LA DIMENSIÓN
Todo lo explicado en los apartados anteriores sobre lista de listas se puede extender a "más
dimensiones". Por ejemplo, podemos trabajar con una lista que contenga lista y éstas a su vez
contengan otras listas.
Para añadir una nueva "dimensión" (o lista) en el array basta añadir un nuevo conjunto de
corchetes, [ ], y su índice correspondiente. Continuando con el ejemplo, se necesitará una variable
"3-dimensional", en el sentido de que se requerirán 3 índices para poder acceder a un elemento.
Una variable "3-D" se declarará como TipoDato[ ][ ][ ] variable;
Para acceder a cada uno de los elementos se necesitarán tantos índices como corchetes se utilicen
y tantos bucles (anidados) como índices para poder recorrer todos los elementos del array.
En el caso de conocer todos los elementos literales que contendrá el array existen algunos atajos.
Por ejemplo,
int[ ][ ][ ] array3D =
{ {1,3}, {5,7,8} },
};
define un array cuyos elementos son listas de listas de enteros (de distinta longitud).
ESTRUCTURAS
29
¿Repetimos? ¡No te asustes! Vamos a contarte de forma sencilla y rápida todo lo que debes saber
sobre la programación estructurada. La palabra programación, a veces, asusta. Y si le
pones estructurada justo después, más. Pero en realidad, no es para tanto. Vamos a verlo.
La programación estructurada es una corriente que nació con la vocación de facilitar la vida de los
programadores, sobre todo cuando estos debían abordar fases de mejora posteriores a la creación
del programa, y de ordenar la forma en la que se creaba cualquier tipo de programa.
Para comprenderlo mejor, vamos a hacer un pequeño viaje en el tiempo. Nos vamos al año 1966,
cuando Böhm y Jacopini proponen el teorema del programa estructurado, con el que demuestran
que cualquier programa puede ser escrito utilizando solo tres instrucciones de control.
Imagínate, ¡esto fue toda una revolución! Implicaba la construcción de programas más sencillos y
rápidos, en los que disminuía la complejidad de las pruebas y el testing para ponerlos en
funcionamiento. Avanzamos dos años más en el tiempo. En 1968, Edsger Dijkstra publicó un
célebre artículo que impactó en la computación moderna: Go To Statement Considered
Harmful. ¿Por qué es tan importante? Pues porque este científico holandés promovió activamente
el uso de lenguajes de programación estructurada, fomentando la verificación formal de programas
y la eliminación de la sentencia Goto. De hecho, Dijkstra participó en el comité que diseñó Algol 60,
el primer lenguaje de programación estructurado. La programación estructurada se convierte así,
junto con la programación orientada a objetos, en uno de los paradigmas de programación más
populares que ejecuta los lenguajes más potentes que seguro conoces, incluidos, entre otros, Java,
C, Python y C++.
CARACTERÍSTICAS Y VENTAJAS
El teorema del programa estructurado es la base teórica sobre la que se construyó esta nueva forma
de programar, ya que nos da la característica fundamental de la programación estructurada. Postula
que, simplemente con la combinación de tres estructuras básicas, es suficiente para expresar
cualquier función computable.
Vale, nadie fue declarado vencedor inmediatamente, pero sí que es cierto que ‘los Digital Workers
de los años 70’ empezaban a ver poco a poco las grandes ventajas que ofrecía la programación
estructurada sobre el código espagueti (los programas de computación antiguos que tenían una
estructura de control de flujo compleja e incomprensible). Y, ¿qué ventajas eran esas?
30
• Los programas desarrollados con la programación estructurada son más sencillos de
entender, ya que tienen una estructura secuencial y desaparece la necesidad de rastrear los
complejos saltos de líneas (propios de la sentencia Goto) dentro de los bloques de código
para intentar comprender la lógica interna.
• Como consecuencia inmediata de lo anterior, otra ventaja es que los programas resultantes
tendrán una estructura clara, gracias a que las sentencias están ligadas y relacionadas entre
sí.
• La fase de prueba y depuración de los programas se optimiza, ya que es mucho más sencillo
hacer el seguimiento de los fallos y errores y, por tanto, detectarlos y corregirlos.
• El coste del mantenimiento de los programas que usan la programación estructurada es más
reducido. ¿Por qué? Pues porque modificar o extender los programas es más fácil al estar
formados por una estructura secuencial.
• Al ser más sencillos los programas, son más rápidos de crear y los programadores aumentan
su rendimiento.
31
Y solamente con estas tres estructuras de control, ¡se pueden escribir todos los programas y
aplicaciones posibles! ¡Todos! Si estás pensando que los lenguajes de programación tienen más
estructuras, sí, es cierto, pero cualquiera de ellas puede ser construida gracias a estas tres básicas
que hemos citado. ¿Comprendes ahora todo el revuelo que se formó con el teorema de la
programación estructurada?
PUNTEROS
Un puntero no es más que una variable, en la cual se almacena una dirección de memoria. Esto
parece muy simple, pero luego da muchos quebraderos de cabeza. Al ser una dirección de memoria,
le podemos decir a un puntero que en ese lugar donde apunta queremos almacenar un valor, por
ejemplo, un número. Para realizar una explicación muy sencilla, vamos a decir que un puntero es
como un buzón de correos y nuestra memoria RAM, es similar a una comunidad de vecinos donde
hay muchos buzones. Un puntero es una variable que contiene la dirección de memoria de otra
variable que contiene al dato en un arreglo. Esto quiere decir, que el puntero apunta al espacio físico
donde está el dato o la variable. Un puntero puede apuntar a un objeto de cualquier tipo, como por
ejemplo, a una estructura o una función. Los punteros se pueden utilizar para referencia y manipular
estructuras de datos, para referenciar bloques de memoria asignados dinámicamente y para proveer
el paso de argumentos por referencias en las llamadas a funciones.
char a;
32
scanf ("%c",&a);
En este caso se le pasa la dirección de memoria de la variable a, la cual tiene reservado un espacio
en la memoria por el compilador. Podríamos hacer lo mismo con este código:
En este código, al scanf le pasamos el puntero en sí. El puntero es una variable, como bien se ha
dicho anteriormente, que contiene una dirección de memoria, por tanto, no es necesario el uso
de & para pasarle la dirección de memoria a scanf. Anteriormente hemos tenido que reservar un
espacio de memoria con malloc(), que se verá su uso más adelante.
char *a;
scanf ("%c", a);
En este caso, no hemos reservado memoria, por lo tanto la función escribirá en una dirección de
memoria que no le pertenece, y por ello se producirá la susodicha violación de segmento.
DECLARANDO PUNTEROS
Ya se dijo que un puntero es una variable que guarda la dirección de memoria de otra variable. Un
puntero se declara igual que cualquier otra variable, pero anteponiendo un * (asterisco) antes del
nombre de la variable.
Su sintaxis sería:
tipo *NombrePuntero = NULL; Se iguala a NULL para saber que no tiene asignada ninguna
dirección.
Donde tipo es el tipo de dato al que referenciará este puntero, es decir, que si se necesita guardar
la dirección de memoria de un dato int, se necesita un puntero de tipo int.
EXPLICACIÓN
Veamos el siguiente código:
#include <stdio.h>
33
int main()
{
int a=0; //Declaración de variable entera de tipo entero
int *puntero; //Declaración de variable puntero de tipo entero
puntero = &a; //Asignación de la dirección memoria de a
printf("El valor de a es: %d. \nEl valor de *puntero es: %d. \n",a,*puntero);
printf("La dirección de memoria de *puntero es: %p",puntero);
return 0;
}
Igual que cuando usamos un &, en la lectura de datos con scanf, igual de esta forma lo usamos
aquí, tal vez te acordarás de que decíamos que las cadenas de caracteres (%s) no usaban este
operador, esto es porque en una cadena de caracteres es un arreglo de caracteres, por lo que el
primer carácter es la dirección de inicio de la cadena. El operador *, nos permite acceder al valor de
la dirección del puntero, en este caso nos permite acceder al valor que contiene a la variable a.
De esta forma "a" y "*puntero" muestran el mismo dato, pero esto no quiere decir que sea lo mismo,
uno es un entero y el otro un puntero.
La impresión con %p, es para poder imprimir la dirección de memoria en valor hexadecimal (0x...),
también podemos imprimir: ...%p",&a) y funciona de la misma forma, y es lógico que tanto "a" como
"puntero" tienen la misma dirección de memoria.
¿DIFERENTES DIRECCIONES?
Tal vez notaste que en cada ejecución la dirección de memoria cambia, esto es porque es el sistema
operativo quien está encargado de administrar la memoria y es éste quien dice qué espacios podrá
tomar el programa.
Esto quiere decir que uno no puede asignarle una dirección de memoria a un puntero directamente,
es decir yo no puedo hacer lo siguiente.
int *puntero=0xbfc5b1c8;
Esto no puedo ni debo hacerlo ya que yo no sé que está haciendo esta dirección de memoria, si el
sistema la tiene o no disponible, etc... Pero sí puedo hacer esto:
34
int *puntero=NULL;
NULL, es el espacio en memoria con dirección 0, esto quiere decir que existe, lo que significa que
le asignamos una dirección válida al puntero, pero el valor que tiene NULL no se nos permite
modificarlo, ya que pertenece al sistema.
USO EN FUNCIONES
Los punteros se usan habitualmente como parámetros de funciones. El siguiente código muestra
como declarar una función que usa un puntero como argumento. Teniendo en cuenta que C pasa
todos los argumentos por valor, para poder modificar un valor desde el código de la función, se debe
usar un puntero al valor a modificar. También se usan punteros a estructuras como argumentos de
una función aún cuando la estructura no sea modificada dentro de la función. Esto es realizado para
evitar copiar todo el contenido de la estructura dentro de la pila.
OPERADORES
Ya anteriormente te poníamos algunos ejemplos de como asignar la dirección de memoria a un
puntero y de cómo acceder al valor de este.
Operador de Dirección (&): Este nos permite acceder a la dirección de memoria de una variable.
Operador de Indirección (*): Además de que nos permite declarar un tipo de dato puntero, también
nos permite ver el VALOR que está en la dirección asignada.
Incrementos (++) y Decrementos (--): Te darás cuenta que puedes usar un puntero como si de un
array se tratase, es por esto que permite estos operadores.
OPERACIONES ARITMÉTICAS
Un puntero nos permite sumar o restar números enteros, pero su funcionamiento ahora es de
posiciones, es decir que nos permitirá movernos a la siguiente dirección de memoria.
35
A un puntero no se le puede realizar multiplicaciones, divisiones, sumas o restas con otro puntero o
con un valor de tipo coma flotante (float, double...). Esto es por que un puntero no es un valor, sólo
es una dirección.
En un puntero se pueden realizar varias operaciones de tipo enteras, pero en dependencia de cómo
se usen, sus resultados pueden ser muy diferentes, a continuación les muestro algunas de estas
operaciones:
PUNTEROS CONSTANTES
Es posible que hayas pensado cómo declarar un puntero como una constante, tal vez pensaste en
un #define, o en un atributo const. Bueno es posible usar el atributo const, pero para un puntero hay
que decidir qué es lo que se quiere volver constante, ¿el valor -objeto- o la dirección?
Valor Constante:
int a=10,b=20;
const int *p = &a; //objeto constante y puntero variable
*p = 15; // ERROR: el valor apuntado por p es constante.
36
p=&b; //Correcto: p pasa a apuntar a un nuevo objeto.
Pero de esta forma no es muy útil declararlo, pues el que hicimos constante fue el valor al que
apunte p, es decir, mejor hubiésemos hecho que el puntero fuese una constante.
int a=10,b=20;
int * const p = &a; //objeto variable y puntero constante
*p = 15; // Correcto: El valor apuntado es variable.
p=&b; //ERROR: p es constante.
Para recordar de una manera fácil, todo lo que está a la izquierda o antes del “*“ es el tipo de dato
al que apunta el puntero.
int *p const en este caso la variable es un entero, pero como la palabra clave const esta a la
derecha o despues del “*”, entonces la constante es el puntero.
PUNTEROS GENÉRICOS
Un puntero a cualquier tipo de dato puede convertirse a un puntero del tipo void *. Por esto un
puntero a void *, recibe el nombre de puntero genérico.
En C, se permite la conversión implícita de punteros, pero en C++ esto no es posible, así que por
compatibilidad y buena práctica recomendamos usar la conversión explícita (cast).
Supongamos:
int *puntero;
funcion (*puntero);
....
void funcion (void *p)
int *q;
q=(int *)p; //En C se podria hacer q = p;
37
Es decir que un puntero a void se puede usar sin importar el tipo de dato, recuerden que uno no
puede trabajar con punteros que referencia a un tipo de dato diferente, como lo es un puntero a
char, con un puntero a int.
PUNTEROS Y MATRICES
Anteriormente decíamos que una matriz es una secuencia de espacios en memoria, que nos
permitían alojar datos en cada uno y un puntero es una variable que guarda la dirección de memoria,
también decíamos cómo recorre las direcciones de memoria con los operadores ++ y --.
Aquí veremos cómo puede usarse un puntero como si de una matriz se tratase, luego de que veas
que es técnicamente lo mismo, te preguntaras por que usar punteros, pero estos son muy
necesarios y únicos que nos permiten realizar cosas que con un array normal, no se puede, como
asignarle memoria dinámica, etc...
#include <stdio.h>
int main()
{
int array[10]={0,2,3,5,5,6,7,8,9,0}; //Declarar e inicializar un arreglo.
int *puntero = &array[0]; //Le damos la dirección de inicio del arreglo
int i; //variable contadora...
for (i=0;i<10;i++)
printf("%d\n",*(puntero+i)); //imprimimos los valores del puntero que es equivalente a imprimir
los valores del arreglo.
return 0;
}
Habrás notado que he usado *(puntero+i), así como explica la sección de operaciones aritméticas,
pero también podemos acceder de otras maneras como lo son:
38
PUNTEROS A CADENAS DE CARACTERES
Ya hemos visto el uso que se le puede dar a un puntero como si de un array se tratase, entonces
usando esta misma lógica podemos hacer un array de caracteres usando punteros.
Sin embargo, al tratarse de una constante de caracteres no podemos modificarla después de definir
sus valores. Como por ejemplo no podemos remplazar un carácter, o leer un nuevo valor.
Para poder modificar el valor de este puntero, este tendría que apuntar a una dirección que no sea
una constante, como un array.
Esta vez pudiste notar que sí se pudo remplazar el valor del nombre, pero aun la cantidad de
caracteres está limitada por el array original, más adelante veremos cómo solucionar esto con
memoria dinámica.
MATRICES DE PUNTEROS
Es muy probable que ya te hayas dicho: Si un puntero es una variable, ¿Puedo tener un array de
punteros? La respuesta sería NO Exactamente. Como ya habíamos explicado antes, un puntero
trabaja de la misma forma que un array, tanto que podemos decir que un puntero es un array,
entonces si definimos un array de un array, nos daría como resultados un array bidimensional. En
la práctica es mucho más común utilizar un array de punteros que un array bidimensional.
Hay que recordar que siguen siendo punteros, es decir sólo apuntan a una dirección de memoria,
por ende, hay que asignarles la dirección de memoria a cada uno de los elementos del puntero. Sin
embargo, podemos asignar en un solo ciclo todas las filas.
39
Ejemplo:
#include <stdio.h>
int main()
{
int *puntero[5]; //array de puntero
int a[5][5]; //Array bidimensional.
int i;
for (i=0;i<5;i++){
puntero[i]=&a[i]; //Asignamos las filas al puntero.
}
//Pueden imprimir tambien en un ciclo
//Tambien pueden acceder mediante un ciclo anidado a la variables del puntero[i][j]
}
PUNTEROS A PUNTEROS
Es una variable que contiene la dirección de memoria de un puntero, el cual a su vez contiene la
dirección de memoria de un tipo de dato. Se usa ** para definir un puntero a un puntero. Recuerden
que un puntero sigue siendo un espacio en memoria, pero en vez de almacenar un valor almacena
una dirección.
Si decimos que:
Ahora se entiende mejor. Al uso de punteros se le llama variables con niveles de indirección, ya que
no apuntan directamente a un valor, sino que apuntan a alguien que lo tiene. Basándonos en esto
podemos decir que *puntero1 es un puntero con un nivel de indirección y *puntero2 es un puntero
con dos niveles de indirección. En general estos tipos de datos son usados con matrices
multidimensionales.
40
MATRICES DE PUNTEROS A CADENAS DE CARACTERES
No hablaremos sobre este tema, debido a que es prácticamente una matriz de caracteres que se
usa mediante punteros, y esto es técnicamente lo mismo que hemos estado viendo anteriormente.
También podemos usar punteros a punteros y guardar múltiples cadenas.
Ejemplos:
Tenga en cuenta el siguiente bloque de código que declara 2 punteros
Las primeras 4 líneas definen la estructura. La linea 6 declara una variable que apuntará a un entero,
y la línea 7 declara una variable que apunta a algo de la estructura MyStruct. Entonces declarar un
puntero es algo que apunta a algo de algún tipo, más que contener el tipo. El asterisco ( * ) se coloca
En las siguientes líneas de código, var1 es un puntero a un entero largo ( long ) mientras var2 es
un entero largo ( long ) y no un puntero a un entero largo. En la segunda línea se declara p3 como
int myInt;
int *pPointer;
struct MyStruct dvorak;
41
struct MyStruct *pKeyboard;
pPointer = &myInt;
pKeyboard = &dvorak;
Los punteros también pueden ser asignados a referencias de memorias dinámicas creadas
comúnmente por las funciones malloc() y calloc().
#include <stdlib.h>
...
struct MyStruct *pKeyboard;
...
pKeyboard = malloc(sizeof(struct MyStruct));
...
La función malloc retorna un puntero de memoria asignada de manera dinámica (o NULL si falla).
El tamaño de esta memoria es definido de modo que pueda contener la estructura MyStruct
42
int *c, *d;
int j;
...
c = &j; /* puntero asignado usando el operador & */
d = c; /* asignando un puntero a otro */
strPointer = ASillyFunction( 3 ); /* puntero retornado de la funcion */
Cuando se retorna un puntero de una función, se debe tener cuidado de que el valor apuntado no
sea de una referencia de una variable local a la función, porque estos valores desaparecen después
de salir de la función y el puntero estaría mal referenciado, causando errores en tiempo de ejecución
en el programa.
La memoria creada dinámicamente dentro de la función puede devolverse como puntero, el valor
de retorno, aunque es creado en una variable local la dirección como tal se devuelve por valor
dejando esta información válida. Además, en esta comunidad en lugar de tener el nombre puesto
en el buzón, cada uno va a tener un identificador único.
Como se puede ver en la imagen, hay muchos buzones (zonas de memoria), pero no todas las
podemos usar, ya que hay buzones que son nuestros y otros que son de otros vecinos (otros
programas). El buzón b5 tiene un papel con el número 23 escrito (en esa posición identificada
como b5 está almacenado el número 23). El buzón b1 es un puntero, ya que lo que tiene
almacenado (b5), no es un valor, sino un identificador de otro buzón (una dirección de memoria).
43
de que lo introdujo en el buzón que no era, entonces se le ocurre dejarnos en el buzón correcto (b1),
un papel donde pone “tu paquete está en b5“. La manera de obtener el valor es bien sencilla,
nosotros abriríamos b1, veríamos que lo que hay dentro es el papel y entonces diríamos, para
alcanzar el valor, tengo que ir a b5 y obtener su contenido.
En la imagen superior se puede ver cómo funcionan realmente los punteros. El carácter * representa
a un puntero en C. Si quieres aprender este lenguaje te recomiendo este curso de programación en
C. En la dirección de memoria 0x67 tenemos almacenado un 5. Podemos decir que la variable cuya
dirección de memoria es 0x67 es un entero o dicho de otra manera, que tenemos un entero de valor
5 almacenado en 0x67. En la dirección de memoria 0x75 tenemos almacenado otra dirección de
memoria, la 0x67. En este caso tenemos un puntero a entero, ya que tenemos en 0x75 almacenada
la dirección de memoria de un entero. Es importante recalcar que tenemos dónde está el entero, no
cuál es su valor.
De igual manera, en la dirección 0x88 tenemos almacenado otra dirección de memoria, pero en este
caso no es un puntero a entero, ya que la dirección de memoria almacenada no es la de un entero
sino la de un puntero a entero. Esto da como resultado que tenemos un puntero a puntero a entero.
Como ves es fácil generalizar su funcionamiento partiendo de este ejemplo. Respecto al uso dentro
de un programa, los punteros se usan ya que permiten realizar operaciones de manera más eficiente
al trabajar con direcciones de memoria. Por ejemplo, si tuviéramos que intercambiar el valor de dos
cadenas de texto de 200bytes cada una, es mucho más eficiente cambiar los punteros a cada una
de las cadenas (2 bytes, uno por puntero), que copiar el contenido. El tener que gestionar
manualmente estos punteros, quizás hacen de C un lenguaje complejo para empezar a programar.
44
Ejemplo práctico:
Muchos se preguntarán todo esto está muy bien, pero es cierto o me están engañando. Para ello os
dejamos el siguiente programa en C, que os puede servir para afianzar vuestros conocimientos con
los punteros.
#include <stdio.h>
#include <stdlib.h>
int main(){
int valor =5 ;
int *p;
int **pp;
p=&valor;
pp=&p;
printf("Contenido en memoria: %8d Direccion de memoria: %p Tipo de dato: int\n", valor, &valor );
Direccion de memoria: 0x5fcad8 Tipo de dato: int** El valor al que apunta mi puntero a entero es: 5
MANEJO DE ARCHIVOS
El manejo de archivos se convertir en un tema fundamental dentro del campo de la Programación,
pues en ellos radica parte la información, que nuestros programas generen, tanto al usuario como
a nosotros los programadores. Así como hemos revisado la salida y entrada por pantalla y teclado
45
respectivamente, veremos ahora la entrada y/o salida de datos utilizando ficheros, lo cual será
imprescindible para un gran número de aplicaciones que deseemos desarrollar.
FICHEROS
El estándar de C contiene varias funciones para la edición de ficheros, éstas están definidas en la
cabecera stdio.h y por lo general empiezan con la letra f, haciendo referencia a file. Adicionalmente
se agrega un tipo FILE, el cual se usará como apuntador a la información del fichero. La secuencia
que usaremos para realizar operaciones será la siguiente:
filename: una cadena que contiene un nombre de fichero válido. opentype: especifica el tipo de
fichero que se abrirá o se creará. Una lista de parámetros opentype para la función fopen son:
Adicionalmente hay tipos utilizando "b" (binary) los cuales no serán mostrados por ahora y que solo
se usan en los sistemas operativos que no pertenecen a la familia de unix.
46
FCLOSE
Esta función sirve para poder cerrar un fichero que se ha abierto.
Un valor de retorno cero indica que el fichero ha sido correctamente cerrado, si ha habido algún
error, el valor de retorno es la constante EOF.
Un ejemplo pequeño para abrir y cerrar el archivo llamado fichero.in en modo lectura:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
FILE *fp;
fp = fopen ( "fichero.in", "r" );
if (fp==NULL) {fputs ("File error",stderr); exit (1);}
fclose ( fp );
return 0;
}
Otra cosa importante es que el lenguaje C no tiene dentro de sí una estructura para el manejo de
excepciones o de errores, por eso es necesario comprobar que el archivo fue abierto con éxito "if
(fp == NULL)". Si fopen pudo abrir el archivo con éxito devuelve la referencia al archivo (FILE *), de
lo contrario devuelve NULL y en este caso se deberá revisar la dirección del archivo o los permisos
de este. En estos ejemplos solo vamos a dar una salida con un retorno de 1 que sirve para señalar
que el programa termino por un error.
FEOF
Esta función sirve para determinar si el cursor dentro del archivo encontró el final (end of file). Existe
otra forma de verificar el final del archivo que es comparar el caracter que trae fgetc del archivo con
el macro EOF declarado dentro de stdio.h, pero este método no ofrece la misma seguridad (en
especial al tratar con los archivos "binarios").
47
La función feof siempre devolverá cero (Falso) si no es encontrado EOF en el archivo, de lo contrario
regresará un valor distinto de cero (Verdadero).
REWIND
Literalmente significa "rebobinar", sitúa el cursor de lectura/escritura al principio del archivo.
LECTURA
Un archivo generalmente debe verse como un string (una cadena de caracteres) que esta guardado
en el disco duro. Para trabajar con los archivos existen diferentes formas y diferentes funciones. Las
funciones que podríamos usar para leer un archivo son:
Las primeras dos de estas funciones son muy parecidas entre si. Pero la tercera, por el numero y el
tipo de parámetros, nos podemos dar cuenta de que es muy diferente, por eso la trataremos aparte
junto al fwrite que es su contraparte para escritura.
FGETC
Esta función lee un caracter a la vez del archivo que está siendo señalado con el puntero *archivo.
En caso de que la lectura sea exitosa devuelve el caracter leído y en caso de que no lo sea o de
encontrar el final del archivo devuelve EOF.
48
Esta función se usa generalmente para recorrer archivos de texto. A manera de ejemplo vamos a
suponer que tenemos un archivo de texto llamado "prueba.txt" en el mismo directorio en que se
encuentra la fuente de nuestro programa. Un pequeño programa que lea ese archivo será:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *archivo;
char caracter;
archivo = fopen("prueba.txt","r");
if (archivo == NULL)
{
printf("\nError de apertura del archivo. \n\n");
}
else
{
printf("\nEl contenido del archivo de prueba es \n\n");
while((caracter = fgetc(archivo)) != EOF)
{
printf("%c",caracter);
}
}
fclose(archivo);
return 0;
}
FGETS
Esta función está diseñada para leer cadenas de caracteres. Leerá hasta n-1 caracteres o hasta
que lea un cambio de línea '\n' o un final de archivo EOF. En este último caso, el carácter de cambio
de línea '\n' también es leído.
49
char *fgets(char *buffer, int tamaño, FILE *archivo);
El primer parámetro buffer lo hemos llamado así porque es un puntero a un espacio de memoria del
tipo char (podríamos usar un arreglo de char). El segundo parámetro es tamaño que es el limite en
cantidad de caracteres a leer para la funcion fgets. Y por último el puntero del archivo por supuesto
que es la forma en que fgets sabra a que archivo debe leer.
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *archivo;
char caracteres[100];
archivo = fopen("prueba.txt","r");
if (archivo == NULL)
{
exit(1);
}
else
{
printf("\nEl contenido del archivo de prueba es \n\n");
while (feof(archivo) == 0)
{
fgets(caracteres,100,archivo);
printf("%s",caracteres);
}
system("PAUSE");
}
fclose(archivo);
return 0;
}
50
Este es el mismo ejemplo de antes con la diferencia de que este hace uso de fgets en lugar de fgetc.
La función fgets se comporta de la siguiente manera, leerá del archivo apuntado por archivo los
caracteres que encuentre y a ponerlos en buffer hasta que lea un carácter menos que la cantidad
de caracteres especificada en tamaño o hasta que encuentre el final de una línea (\n) o hasta que
encuentre el final del archivo (EOF). En este ejemplo no vamos a profundizar más que para decir
que caracteres es un buffer, los pormenores serán explicados en la sección de manejo dinámico de
memoria.
El beneficio de esta función es que se puede obtener una linea completa a la vez. Y resulta muy útil
para algunos fines como la construcción de un parser de algún tipo de archivo de texto.
FREAD
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
Esta función lee un bloque de una "stream" de datos. Efectúa la lectura de un arreglo de elementos
"count", cada uno de los cuales tiene un tamaño definido por "size". Luego los guarda en el bloque
de memoria especificado por "ptr". El indicador de posición de la cadena de caracteres avanza hasta
leer la totalidad de bytes. Si esto es exitoso la cantidad de bytes leídos es (size*count). Parámetros:
size : Tamaño en bytes de cada elemento (de los que voy a leer).
FSCANF
La función fscanf funciona igual que scanf en cuanto a parámetros, pero la entrada se toma de un
fichero en lugar del teclado.
Podemos ver un ejemplo de su uso, abrimos el documento "fichero.txt" en modo lectura y leyendo
dentro de él.
#include <stdio.h>
int main ( int argc, char **argv )
51
{
FILE *fp;
char buffer[100];
fp = fopen ( "fichero.txt", "r" );
fscanf(fp, "%s" ,buffer);
printf("%s",buffer);
fclose ( fp );
return 0;
}
ESCRITURA
Así como podemos leer datos desde un fichero, también se pueden crear y escribir ficheros con la
información que deseamos almacenar, Para trabajar con los archivos existen diferentes formas y
diferentes funciones. Las funciones que podríamos usar para escribir dentro de un archivo son:
Mostramos un ejemplo del uso de fputc en un "fichero.txt", se escribira dentro del fichero hasta que
presionemos la tecla enter.
#include <stdio.h>
int main ( int argc, char **argv )
{
FILE *fp;
52
char caracter;
fp = fopen ( "fichero.txt", "a+t" ); //parámetro para escritura al final y para file tipo texto
printf("\nIntroduce un texto al fichero: ");
while((caracter = getchar()) != '\n')
{
printf("%c", fputc(caracter, fp));
}
fclose ( fp );
return 0;
}
FPUTS
La función fputs escribe una cadena en un fichero. la ejecución de la misma no añade el carácter
de retorno de línea ni el carácter nulo final. El valor de retorno es un número no negativo o EOF en
caso de error. Los parámetros de entrada son la cadena a escribir y un puntero a la
estructura FILE del fichero donde se realizará la escritura.
#include <stdio.h>
int main ( int argc, char **argv )
{
FILE *fp;
char cadena[] = "Mostrando el uso de fputs en un fichero.\n";
fp = fopen ( "fichero.txt", "r+" );
fputs( cadena, fp );
fclose ( fp );
return 0;
}
53
FWRITE
Esta función está pensada para trabajar con registros de longitud constante y forma pareja
con fread. Es capaz de escribir hacia un fichero uno o varios registros de la misma longitud
almacenados a partir de una dirección de memoria determinada. El valor de retorno es el número
de registros escritos, no el número de bytes. Los parámetros son: un puntero a la zona de memoria
de donde se obtendrán los datos a escribir, el tamaño de cada registro, el número de registros a
escribir y un puntero a la estructura FILE del fichero al que se hará la escritura.
Un ejemplo concreto del uso de fwrite con su contraparte fread y usando funciones es:
#include <stdio.h>
int main ( int argc, char **argv )
{
FILE *fp;
char cadena[] = "Mostrando el uso de fwrite en un fichero.\n";
fp = fopen ( "fichero.txt", "r+" );
fwrite( cadena, sizeof(char), sizeof(cadena), fp ); //char cadena[]... cada posición es de
tamaño 'char'
fclose ( fp );
return 0;
}
FPRINTF
La función fprintf funciona igual que printf en cuanto a parámetros, pero la salida se dirige a un
archivo en lugar de a la pantalla. El prototipo correspondiente de fprintf es:
54
#include <stdio.h>
int main ( int argc, char **argv )
{
FILE *fp;
char buffer[100] = "Esto es un texto dentro del fichero.";
fp = fopen ( "fichero.txt", "r+" );
fprintf(fp, buffer);
fprintf(fp, "%s", "\nEsto es otro texto dentro del fichero.");
fclose ( fp );
return 0;
}
ARCHIVOS Y DIRECTORIOS
El sistema de archivos de un sistema Linux típico está formado por los siguientes directorios bajo el
directorio raíz:
55
/bin Contiene los programas ejecutables que son parte del sistema operativo Linux. Muchos
comandos de Linux como cat, cp, ls, more y tar están ubicados en este directorio.
/boot Contienen el kernel (o núcleo) de Linux y otros archivos necesarios para el administrador de
inicio LILO, que realiza la carga inicial del sistema operativo cuando la computadora se enciende.
/dev Contienen todos los archivos de acceso a dispositivos. Linux trata cada dispositivo (terminales,
discos, impresoras, etc.) como si fuera un archivo especial.
/home Contiene los directorios HOME de los usuarios. El directorio HOME el directorio inicial en el
que se encuentra posicionado un usuario al ingresar al sistema, por lo que también se conoce
como directorio de logín o de conexión.
/lib Contiene los archivos de biblioteca utilizados por las aplicaciones y utilidades del sistema, así
también como las librerías pertenecientes a diferentes lenguajes de programación.
/lost+found Directorio para archivos recuperados por el proceso de reparación del sistema de
archivos, que se ejecuta luego de una caída del sistema y asegura su integridad luego de que el
equipo haya sido apagado de manera inapropiada.
/mnt Es un directorio vacío que se usa normalmente para montar dispositivos como disquetes y
particiones temporales de disco.
/proc Contiene archivos con información sobre el estado de ejecución del sistema operativo y de los
procesos.
/sbin Contienen archivos ejecutables que son comandos que se usan normalmente para la
administración del sistema.
/tmp Directorio temporal que puede usar cualquier usuario como directorio transitorio.
/usr Contiene archivos de programa, de datos y de librerías asociados con las actividades de los
usuarios.
/var Contiene archivos temporales y de trabajo generados por programas del sistema. A diferencia
de /tmp, los usuarios comunes no tienen permiso para utilizar los subdirectorios que contiene
directamente, sino que deben hacerlo a través de aplicaciones y utilidades del sistema.
En cualquier sistema multiusuario, es preciso que existan métodos que impidan a un usuario no
autorizado copiar, borrar, modificar algún archivo sobre el cual no tiene permiso. En Linux las
medidas de protección se basan en que cada archivo tiene un propietario (usualmente, el que creó
el archivo). Además, los usuarios pertenecen a uno o más grupos, los cuales son asignados por el
56
Administrador dependiendo de la tarea que realiza cada usuario; cuando un usuario crea un archivo,
el mismo le pertenece también a alguno de los grupos del usuario que lo creó.
Así, un archivo en Linux le pertenece a un usuario y a un grupo, cada uno de los cuales tendrá
ciertos privilegios de acceso al archivo. Adicionalmente, es posible especificar qué derechos tendrán
los otros usuarios, es decir, aquellos que no son el propietario del archivo ni pertenecen al grupo
dueño del archivo.
En cada categoría de permisos (usuario, grupo y otros) se distinguen tres tipos de accesos: lectura
(Read), escritura (Write) y ejecución (eXecute), cuyos significados varían según se apliquen a un
archivo o a un directorio.
En el caso de los archivos, el permiso R (lectura) habilita a quién lo posea a ver el contenido del
archivo, mientras que el permiso W (escritura) le permite cambiar su contenido. El permiso X
(ejecución) se aplica a los programas y habilita su ejecución.
Para los directorios, el permiso R permite listar el contenido del mismo (es decir, “leer” el directorio,
mientras que el W permite borrar o crear nuevos archivos en su interior (es decir, modificar o
“escribir” el directorio). El permiso X da permiso de paso, es decir, la posibilidad de transformar el
directorio en cuestión en el directorio actual (ver comando cd).
En los listados de directorio, los permisos se muestran como una cadena de 9 caracteres, en donde
los primeros tres corresponden a los permisos del usuario, los siguientes tres a los del grupo y los
últimos, a los de los demás usuarios. La presencia de una letra (r, w o x) indica que el permiso está
concedido, mientras que un guión (-) indica que ese permiso está denegado.
Los permisos de un archivo o directorio pueden cambiarse desde el administrador de archivos KFM
utilizando la ventana de propiedades o utilizando el comando chmod.
57
ARCHIVOS
Todos los datos que un programa utiliza durante su ejecución se encuentran en sus variables, que
están almacenadas en la memoria RAM del computador.
Para que un programa pueda guardar datos de manera permanente, es necesario utilizar un medio
de almacenamiento persistente, de los cuales el más importante es el disco duro.
Los datos en el disco duro están organizados en archivos. Un archivo es una secuencia de datos
almacenados en un medio persistente que están disponibles para ser utilizados por un programa.
Todos los archivos tienen un nombre y una ubicación dentro del sistema de archivos del sistema
operativo.
Los datos en un archivo siguen estando presentes después de que termina el programa que lo ha
creado. Un programa puede guardar sus datos en archivos para usarlos en una ejecución futura, e
incluso puede leer datos desde archivos creados por otros programas.
Un programa no puede manipular los datos de un archivo directamente. Para usar un archivo, un
programa siempre abrir el archivo y asignarlo a una variable, que llamaremos el archivo lógico.
Todas las operaciones sobre un archivo se realizan a través del archivo lógico.
Dependiendo del contenido, hay muchos tipos de archivos. Nosotros nos preocuparemos sólo de
los archivos de texto, que son los que contienen texto, y pueden ser abiertos y modificados usando
un editor de texto como el Bloc de Notas. Los archivos de texto generalmente tienen un nombre
terminado en .txt.
LECTURA DE ARCHIVOS
archivo = open(nombre)
nombre es un string que tiene el nombre del archivo. archivo es el archivo lógico a través del que
se manipulará el archivo.
58
Es importante recordar que la variable archivo es una representación abstracta del archivo, y no los
contenidos de este.
La manera más simple de leer el contenido es hacerlo línea por línea. Para esto, basta con poner el
archivo lógico en un ciclo for:
Una vez que los datos han sido leídos del archivo, hay que cerrarlo:
archivo.close()
Por ejemplo, supongamos que tenemos el archivo himno.txt que tiene el siguiente contenido:
Puro Chile
es tu cielo azulado
puras brisas
te cruzan también.
El archivo tiene cuatro líneas. Cada línea termina con un salto de línea (\n), que indica que a
continuación comienza una línea nueva.
archivo = open('himno.txt')
for linea in archivo:
print linea[0]
archivo.close()
El ciclo for es ejecutado cuatro veces, una por cada línea del archivo. La salida del programa es:
P
e
p
t
Otro ejemplo: el siguiente programa imprime cuántos símbolos hay en cada línea:
59
archivo = open('himno.txt')
for linea in archivo:
print len(linea)
archivo.close()
La salida es:
11
20
13
19
+---+---+---+---+---+---+---+---+---+---+---+
| P | u | r | o | | C | h | i | l | e | \n| = 11 símbolos
+---+---+---+---+---+---+---+---+---+---+---+
Para obtener el string sin el salto de línea, se puede usar el método strip, que elimina todos los
símbolos de espaciado al principio y al final del string:
archivo = open('himno.txt')
for linea in archivo:
print len(linea.strip())
archivo.close()
10
19
60
12
18
Lo importante es comprender que los archivos son leídos línea por línea usando el ciclo for.
ESCRITURA EN ARCHIVOS
Los ejemplos anteriores suponen que el archivo por leer existe, y está listo para ser abierto y leído.
Ahora veremos cómo crear los archivos y cómo escribir datos en ellos, para que otro programa
después pueda abrirlos y leerlos.
El segundo parámetro de la función open indica el uso que se le dará al archivo. 'w' significa
«escribir» (write en inglés).
Si el archivo señalado no existe, entonces será creado. Si ya existe, entonces será sobreescrito.
Hay que tener cuidado entonces, pues esta operación elimina los datos del archivo que existía
previamente.
Una vez abierto el archivo, uno puede escribir datos en él usando el método write:
a = open('prueba.txt', 'w')
a.write('Hola ')
a.write('mundo.')
a.close()
Una vez ejecutado este programa, el archivo prueba.txt será creado (o sobreescrito, si ya existía).
Al abrirlo en el Bloc de Notas, veremos este contenido:
Hola mundo.
Para escribir varias líneas en el archivo, es necesario agregar explícitamente los saltos de línea en
cada string que sea escrito. Por ejemplo, para crear el archivo himno.txt que usamos más arriba,
podemos hacerlo así:
a = open('himno.txt', 'w')
61
a.write('Puro Chile\n')
a.write('es tu cielo azulado\n')
a.write('puras brisas\n')
a.write('te cruzan también.\n')
a.close()
Además del modo 'w' (write), también existe el modo 'a' (append), que permite escribir datos al final
de un archivo existente. Por ejemplo, el siguiente programa abre el archivo prueba.txt que creamos
más arriba, y agrega más texto al final de él:
a = open('prueba.txt', 'a')
a.write('\n')
a.write('Chao ')
a.write('pescao.')
a.close()
Hola mundo.
Chao pescao.
De haber abierto el archivo en modo 'w' en vez de 'a', el contenido anterior (la frase Hola mundo) se
habría borrado.
Una manera usual de almacenar datos con estructura de tabla en un archivo es la siguiente: cada
línea del archivo representa una fila de la tabla, y los datos de una fila se ponen separados por algún
símbolo especial.
Por ejemplo, supongamos que queremos guardar en un archivo los datos de esta tabla:
Yayita Vinagre 39 49 58 55
62
Nombre Apellido Nota 1 Nota 2 Nota 3 Nota 4
Si usamos el símbolo : como separador, el archivo, que llamaremos alumnos.txt, debería quedar
así:
Perico:Los Palotes:90:75:38:65
Yayita:Vinagre:39:49:58:55
Fulanita:De Tal:96:100:36:71
El formato de estos archivos se suele llamar CSV, que en inglés son las siglas de comma-separated
values (significa «valores separados por comas», aunque técnicamente el separador puede ser
cualquier símbolo). A pesar del nombre especial que reciben, los archivos CSV son archivos de
texto como cualquier otro, y se pueden tratar como tales.
Los archivos de valores con separadores son muy fáciles de leer y escribir, y por esto son muy
usados. Como ejemplo práctico, si usted desea hacer un programa que analice los datos de una
hoja de cálculo Excel, puede guardar el archivo con el formato CSV directamente en el Excel, y
luego abrirlo desde su programa escrito en Python.
Para leer los datos de un archivo de valores con separadores, debe hacerlo línea por línea, eliminar
el salto de línea usando el método strip y luego extraer los valores de la línea usando el método split.
Por ejemplo, al leer la primera línea del archivo de más arriba obtendremos el siguiente string:
'Perico:Los Palotes:90:75:38:65\n'
>>> linea.strip().split(':')
['Perico', 'Los Palotes', '90', '75', '38', '65']
Como se trata de un archivo de texto, todos los valores son strings. Una manera de convertir los
valores a sus tipos apropiados es hacerlo uno por uno:
valores = linea.strip().split(':')
nombre = valores[0]
63
apellido = valores[1]
nota1 = int(valores[2])
nota2 = int(valores[3])
nota3 = int(valores[4])
nota4 = int(valores[5])
valores = linea.strip().split(':')
nombre, apellido = valores[0:2]
nota1, nota2, nota3, nota4 = map(int, valores[2:6])
O podríamos dejar las notas en una lista, en vez de usar cuatro variables diferentes:
Por ejemplo, un programa para imprimir el promedio de todos los alumnos se puede escribir así:
archivo_alumnos = open('alumnos.txt')
for linea in archivo_alumnos:
valores = linea.strip().split(':')
nombre, apellido = valores[0:2]
notas = map(int, valores[2:6])
promedio = sum(notas) / 4.0
print '{0} obtuvo promedio {1}'.format(nombre, promedio)
archivo_alumnos.close()
Para escribir los datos en un archivo, hay que hacer el proceso inverso: convertir todos los datos al
tipo string, pegarlos en un único string, agregar el salto de línea al final y escribir la línea en el
archivo.
Si los datos de la línea ya están en una lista o una tupla, podemos convertirlos a string usando la
función map y pegarlos usando el método join:
64
archivo.write(linea)
Como siempre, usted debe preferir la manera que le parezca más simple de entender.
Un sitio web consta de muchos archivos: texto del contenido, código, hojas de estilo, contenido
multimedia, etc. Cuando estás creando un sitio web, necesitas ensamblar estos archivos en una
estructura sensible en tu computadora local, asegurarte de que puedan comunicarse entre sí y hacer
que todo su contenido se vea bien antes de que eventualmente los cargues en un servidor. El
manejo de archivos analiza algunos problemas que debes tener en cuenta, para que puedas
configurar una estructura de archivos adecuada para tu sitio web.
Cuando estés trabajando en un sitio web localmente en tu computadora, debes mantener todos los
archivos relacionados en un solo directorio que refleje la estructura de archivos del sitio web
publicado en el servidor. Este directorio se puede ubicar en cualquier lugar que desees, pero debes
colocarlo en algún lugar donde lo puedas encontrar fácilmente, tal vez en tu escritorio, en tu
directorio de inicio o en la raíz de tu disco duro.
1. Elige un lugar para almacenar los proyectos de tus sitios web. Dentro del lugar elegido, crea
un nuevo directorio llamado proyectosweb (o algo similar). Aquí es donde vivirán todos los
proyectos de tus sitios web.
2. Dentro de este primer directorio, crea otro directorio para almacenar tu primer sitio web.
Llámalo pruebasitio (o algo más imaginativo).
Notarás que, a lo largo de este artículo, te pedimos que nombres los directorios y archivos
completamente en minúsculas sin espacios. Esto es porque:
65
en pruebasitio/MiImagen.jpg y luego, en un archivo diferente intentas invocar la imagen
como pruebasitio/miimagen.jpg, puede que no funcione.
2. Los navegadores, servidores web y lenguajes de programación no manejan los espacios de
manera consistente. Por ejemplo, si usas espacios en tu nombre de archivo, algunos
sistemas pueden tratar el nombre de archivo como dos nombres de archivo. Algunos
servidores reemplazarán las áreas en tus nombres de archivo con "%20" (el código de
caracteres para espacios en URI), lo cual provocará que todos tus enlaces se rompan. Es
mejor separar las palabras con guiones, en lugar de guiones bajos: mi-
archivo.html vs. mi_archivo.html.
La respuesta corta es que debes usar un guión para los nombres de tus archivos. El motor de
búsqueda de Google trata un guión como un separador de palabras, pero no considera un guión
bajo de esa manera. Por estos motivos, es mejor adquirir el hábito de escribir los nombres de los
directorios y archivos en minúsculas, sin espacios y con palabras separadas por guiones, al menos
hasta que sepas lo que estás haciendo. De esa manera, tropezarás con menos problemas en el
futuro.
A continuación, veamos qué estructura debería tener tu sitio de prueba. Las cosas más comunes
que tendrás en cualquier proyecto de sitio web que crees son un archivo de índice HTML y
directorios para contener imágenes, archivos de estilo y archivos de script. Crea estos ahora:
66
Nota: En las computadoras con Windows, es posible que tengas problemas para ver los nombres
de los archivos, porque de manera predeterminada, Windows tiene activada una opción
llamada Ocultar extensiones para tipos de archivos conocidos. Generalmente, la puedes desactivar
yendo al Explorador de Windows, seleccionando la opción Opciones de directorio..., desmarcando
la casilla de verificación Ocultar extensiones para tipos de archivo conocidos y luego haciendo clic
en Aceptar. Para obtener información más específica sobre tu versión de Windows, puedes buscar
en la web.
RUTAS DE ARCHIVO
Para que los archivos se comuniquen entre sí, debes proporcionar una ruta de archivo entre ellos,
básicamente una ruta, para que un archivo sepa dónde está otro. Para demostrarlo, insertaremos
un poco de HTML en nuestro archivo index.html y haremos que muestre la imagen que elegiste en
el artículo ¿Cómo se verá tu sitio web?
HTMLCopy to Clipboard
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Mi página de prueba</title>
</head>
<body>
<img src="" alt="Mi imagen de prueba" />
</body>
</html>
3. La línea <img src="" alt="Mi imagen de prueba"> es el código HTML que inserta una imagen
en la página. Necesitamos decirle al HTML dónde está la imagen. La imagen está dentro del
directorio images, que está en el mismo directorio que index.html. Para recorrer la estructura
67
del archivo desde index.html hasta nuestra imagen, la ruta del archivo que necesitamos
es images/nombre-archivo-imagen. Por ejemplo, nuestra imagen se llama firefox-icon.png,
por lo que la ruta del archivo es images/firefox-icon.png.
4. Inserta la ruta del archivo en tu código HTML entre las comillas dobles del código src="".
5. Guarda tu archivo HTML, luego cárgalo en tu navegador web (haz doble clic en el archivo).
¡Deberías ver tu nueva página web mostrando tu imagen!
1. Para vincular a un archivo destino en el mismo directorio que el archivo HTML de invocación,
simplemente usa el nombre del archivo, p. ej. mi-imagen.jpg.
2. Para hacer referencia a un archivo en un subdirectorio, escribe el nombre del directorio
delante de la ruta, más una barra inclinada, p. ej. subdirectorio/mi-imagen.jpg.
3. Para vincular a un archivo destino en el directorio arriba del archivo HTML que lo invoca,
escribe dos puntos. Por ejemplo, si index.html estuviera dentro de un subdirectorio
de pruebasitio y mi-imagen.jpg estuviera dentro de pruebasitio, puedes hacer referencia
a mi-imagen.jpg desde index.html utilizando ../mi-imagen.jpg.
4. Los puedes combinar tanto como desees, por ejemplo, ../subdirectorio/otro-subdirectorio/mi-
imagen.jpg.
Nota: El sistema de archivos de Windows tiende a utilizar barras invertidas, no barras diagonales,
p. ej. C:\windows. Esto no importa en HTML, incluso si estás desarrollando tu sitio web en Windows,
debes usar barras diagonales en tu código.
68
Así como hemos revisado la salida y entrada por pantalla y teclado respectivamente, veremos ahora
la entrada y/o salida de datos utilizando ficheros, lo cual será imprescindible para un gran número
de aplicaciones que deseemos desarrollar.
PROCESAMIENTO DE TEXTO
Hasta ahora, hemos visto cómo los tipos de datos básicos (strings, enteros, reales, booleanos) y las
estructuras de datos permiten representar y manipular información compleja y abstracta en un
programa. Sin embargo, en muchos casos la información no suele estar disponible ya organizada
en estructuras de datos convenientes de usar, sino en documentos de texto.
Por ejemplo, las páginas webs son archivos de puro texto, que describen la estructura de un
documento en un lenguaje llamado HTML. Usted puede ver el texto de una página web buscando
una instrucción «Ver código fuente» (o algo parecido) en el navegador. A partir de este texto, el
navegador extrae la información necesaria para reconstruir la página que finalmente usted ve.
Un texto siempre es un string, que puede ser tan largo y complejo como se desee. El procesamiento
de texto consiste en manipular strings, ya sea para extraer información del string, para convertir un
texto en otro, o para codificar información en un string. En Python, el tipo str provee muchos métodos
convenientes para hacer procesamiento de texto, además de las operaciones más simples que ya
aprendimos (como s + t, s[i] y s in t).
SALTOS DE LÍNEA
Un string puede contener caracteres de salto de línea, que tienen el efecto equivalente al de
presionar la tecla Enter. El caracter de salto de línea se representa con \n:
>>> a = 'piano\nviolin\noboe'
>>> print a
piano
violin
oboe
Los saltos de línea sólo son visibles al imprimir el string mediante la sentencia print. Si uno quiere
ver el valor del string en la consola, el salto de línea aparecerá representado como \n:
>>> a
'piano\nviolin\noboe'
69
>>> print a
piano
violin
oboe
Aunque dentro del string se representa como una secuencia de dos símbolos, el salto de línea es
un único caracter:
>>> len('a\nb')
3
En general, hay varios caracteres especiales que se representan comenzando con una barra
invertida (\) seguida de una letra. Experimente, y determine qué significan los caracteres
especiales \t y \b:
print 'abcde\tefg\thi\tjklm'
print 'abcde\befg\bhi\bjklm'
Para incluir una barra invertida dentro de un string, hay que hacerlo con \\:
El método s.replace(antes, despues) busca en el string s todas las apariciones del texto antes y las
reemplaza por despues:
70
'Lo mor ostobo sorono'
Hay que tener siempre muy claro que esta operación no modifica el string, sino que retorna uno
nuevo:
s.split() separa el strings en varios strings, usando los espacios en blanco como separador. El valor
retornado es una lista de strings:
>>> oracion = 'El veloz murcielago hindu comia feliz cardillo y kiwi'
>>> oracion.split()
['El', 'veloz', 'murcielago', 'hindu', 'comia', 'feliz', 'cardillo', 'y', 'kiwi']
Además, es posible pasar un parámetro al método split que indica cuál será el separador a usar (en
vez de los espacios en blanco):
Esto es muy útil para pedir al usuario que ingrese datos en un programa de una manera más
conveniente, y no uno por uno. Por ejemplo, antes hacíamos programas que funcionaban así:
Ingrese a: 2.3
71
Ingrese b: 1.9
Ingrese c: 2.3
El triángulo es isósceles.
s.join(lista_de_strings) une todos los strings de la lista, usando al string s como «pegamento»:
72
MAYÚSCULAS Y MINÚSCULAS
>>> s = 'hola'
>>> t = 'Hola'
>>> u = 'HOLA'
>>> s.isupper(), s.islower()
(False, True)
>>> t.isupper(), t.islower()
(False, False)
>>> u.isupper(), u.islower()
(True, False)
>>> t
'Hola'
>>> t.upper()
'HOLA'
>>> t.lower()
'hola'
>>> t.swapcase()
'hOLA'
73
>>> objeto = 'paraguas'
>>> objeto.startswith('para')
True
>>> objeto.endswith('aguas')
True
>>> objeto.endswith('x')
False
>>> objeto.endswith('guaguas')
False
ALINEACIÓN DE STRINGS
Los métodos s.ljust(n), s.rjust(n) y s.center(n) rellenan el string con espacios para que su largo sea
igual a n, de modo que el contenido quede alineado, respectivamente, a la izquierda, a la derecha
y al centro:
>>> contenido.ljust(20)
'hola '
>>> contenido.center(20)
' hola '
>>> contenido.rjust(20)
' hola'
datos = [
('Pepito', (1991, 12, 5), 'Osorno', '***'),
('Yayita', (1990, 1, 31), 'Arica', '*'),
('Fulanito', (1992, 10, 29), 'Porvenir', '****'),
74
]
for n, (a, m, d), c, e in datos:
print n.ljust(10),
print str(a).rjust(4), str(m).rjust(2), str(d).rjust(2),
print c.ljust(10), e.center(5)
INTERPOLACIÓN DE STRINGS
El método format permite usar un string como una plantilla que se puede completar con distintos
valores dependiendo de la situación.
Las posiciones en que se deben rellenar los valores se indican dentro del string usando un número
entre paréntesis de llaves:
Estas posiciones se llaman campos. En el ejemplo, el string s tiene dos campos, numerados del
cero al uno.
Para llenar los campos, hay que llamar al método format pasándole los valores como parámetros:
75
>>> '{0} y {1}'.format('carne', 'huevos')
'carne y huevos'
>>> '{1} y {0}'.format('carne', 'huevos')
'huevos y carne'
Otra opción es referirse a los campos con un nombre. En este caso, hay que llamar al
método format diciendo explícitamente el nombre del parámetro para asociarlo al valor:
Siempre que tenga un problema de esta clase, investigue una de las tres siguientes posibilidades:
• Puede que la ruta de búsqueda del usuario haya cambiado o que los directorios en la ruta
de búsqueda no se encuentren en el orden correcto.
Este capítulo describe brevemente cómo reconocer los problemas de cada una de estas tres áreas
y se sugieren posibles soluciones.
76
• El comando no está disponible en el sistema.
Para solucionar un problema de la ruta de búsqueda, necesita saber el nombre de ruta del directorio
donde el comando se encuentra almacenado.
Si se encuentra la versión incorrecta del comando, hay un directorio que tiene un comando con el
mismo nombre en la ruta de búsqueda. En este caso, puede que el directorio correspondiente se
encuentre más adelante en la ruta de búsqueda o que directamente no se encuentre en ninguna
parte. Puede mostrar la ruta de búsqueda actual con el comando echo $PATH. Utilice el
comando type para determinar si está ejecutando la versión incorrecta del comando. Por ejemplo:
$ type acroread
acroread is /usr/bin/acroread
• Visualice la ruta de búsqueda actual a fin de verificar que el directorio para el comando
no esté en la ruta ni esté mal escrito.
$ echo $PATH
• Compruebe lo siguiente:
o ¿Es correcta la ruta de búsqueda?
77
bash $HOME/.profile $ PATH=$HOME/bin:/sbin:/usr/local Los nombres de ruta se separan
y ksh93 /bin ... con dos puntos.
$ export PATH
$ which command
En este ejemplo, se muestra que el ejecutable mytool no está en ninguno de los directorios de la
ruta de búsqueda con el comando type.
$ mytool
-bash: mytool: command not found
$ type mytool
-bash: type: mytool: not found
$ echo $PATH
/usr/bin:
$ vi $HOME/.profile
(Add appropriate command directory to the search path)
$ . $HOME/.profile
$ mytool
Si no puede encontrar un comando, consulte la página del comando man para la ruta de directorio.
78
CAMBIO DE PROPIEDADES DE GRUPO Y ARCHIVO
Con frecuencia, las propiedades de los archivos y los directorios cambian porque un superusuario
edita los archivos. Al crear directorios principales para los usuarios nuevos, asegúrese de asignarles
la propiedad del archivo punto (.) en el directorio principal. Si los usuarios no tienen la propiedad de
“.”, no pueden crear archivos en su directorio principal.
También pueden surgir problemas de acceso cuando cambia la propiedad del grupo o cuando un
grupo del que un usuario es miembro se suprime de la base de datos /etc/group.
Para obtener información sobre cómo cambiar los permisos o la propiedad de un archivo al que no
puede acceder.
CREACIÓN DE UNIDADES
Comentamos en el tema 10 que en muchos lenguajes de programación podemos manejar una serie
de bibliotecas externas (en inglés, library) de funciones y procedimientos, que nos permitían ampliar
el lenguaje base.
En Turbo Pascal, estas bibliotecas reciben el nombre de "unidades" (unit), y existen a partir de la
versión 5. También existen en otras versiones de Pascal recientes, como Free Pascal.
En su momento, empleamos la unidad CRT, que nos daba una serie de facilidades para manejar la
pantalla en modo texto, el teclado y la generación de sonidos sencillos.
Iremos viendo otras unidades estándar cuando accedamos a la pantalla en modo gráfico, a los
servicios del sistema operativo, etc. Pero hoy vamos a ver cómo podemos crear las nuestras
propias.
79
¿Para qué? Nos podría bastar con teclear en un programa todas las funciones que nos interesen.
Si creamos otro programa que las necesite, pues las copiamos también en ese y ya está, ¿no?
La primera es que los programas sean más modulares. Que podamos dejar aparte las funciones
que se encargan de batallar con el teclado, por ejemplo, y en nuestro programa principal sólo esté
lo que realmente tenga este programa que lo diferencie de los otros. Esto facilita la legibilidad y con
ello las posibles correcciones o ampliaciones.
Pero vamos a lo práctico...Una "unit" tiene dos partes: una pública, que es aquella a la que podremos
acceder, y una privada, que es el desarrollo detallado de esa parte pública, y a esta parte no se
puede acceder desde otros programas. La parte pública se denota con la palabra "interface", y
la privada con "implementation".
Debajo de interface basta indicar los nombres de los procedimientos que queremos "exportar", así
como las variables, si nos interesase crear alguna. Debajo de implementation escribimos realmente
estos procedimientos o funciones, tal como haríamos en un programa normal.
Nota: este ejemplo NO SE PUEDE EJECUTAR. Recordemos que una Unit es algo auxiliar, una
biblioteca de funciones y procedimientos que nosotros utilizaremos DESDE OTROS PROGRAMAS.
Después de este ejemplo de Unit incluyo un ejemplo de programa cortito que la emplee.
{--------------------------}
80
{ Ejemplo en Pascal: }
{ }
{ la CRT }
{ MICRT1.PAS }
{ }
{ }
{ Comprobado con: }
{--------------------------}
unit miCrt1;
81
begin
write( texto );
end;
Este ejemplo declara un procedimiento "AtXY" que hace un GotoXY y un Write en un solo paso.
{--------------------------}
{ Ejemplo en Pascal: }
{ }
{ unit "MICRT1" }
{ PMICRT1.PAS }
{ }
{ }
{ Comprobado con: }
{--------------------------}
program PruebaDeMiCrt1;
82
uses miCrt1;
begin
end.
Este programa no necesita llamar a la unidad CRT original, sino que nuestra unidad ya lo hace por
Ahora vamos a mejorar ligeramente nuestra unidad, añadiéndole un procedimiento “pausa”:
{--------------------------}
{ Ejemplo en Pascal: }
{ }
{ MICRT2.PAS }
{ }
{ }
{ Comprobado con: }
{--------------------------}
{-------------------}
83
interface { Parte "pública", que se exporta }
procedure Pausa;
{-------------------}
puede utilizarla }
begin
write( texto );
end;
begin
end;
{-------------------}
Un programa que usase esta unidad, junto con la CTR original podría ser:
{--------------------------}
{ Ejemplo en Pascal: }
{ }
{ Prueba de la unidad }
84
{ MICRT2 }
{ PMICRT2.PAS }
{ }
{ }
{ Comprobado con: }
{--------------------------}
program PruebaDeMiCrt2;
begin
ClrScr; { De Crt }
pausa; { de miCrt2 }
end.
Finalmente, hay que destacar que las unidades pueden contener más cosas además de funciones
y procedimientos: pueden tener un "trozo de programa", su código de inicialización, como por
ejemplo:
{--------------------------}
{ Ejemplo en Pascal: }
{ }
85
{ Unidad que mejora la }
{ MICRT3.PAS }
{ }
{ }
{ Comprobado con: }
{--------------------------}
{-------------------}
acceder a ella }
procedure Pausa;
{-------------------}
86
puede utilizarla }
begin
write( texto );
end;
begin
end;
begin
{--------------------------}
{ Ejemplo en Pascal: }
{ }
{ Prueba de la unidad }
{ MICRT3 }
{ PMICRT3.PAS }
{ }
87
{ Este fuente procede de }
{ }
{ Comprobado con: }
{--------------------------}
program PruebaDeMiCrt3;
begin
ClrScr; { De Crt }
pausa; { de miCrt3 }
end.
Se podría hablar mucho más sobre las unidades, pero intentaré ser breve:
Al compilar una unidad se crea un fichero con extensión .TPU (.PPU para Free Pascal), al que se
puede acceder desde nuestros programas con dos condiciones: que empleemos la misma versión
de compilador (el formato de estos ficheros variaba en cada versión de Turbo Pascal, y quizá
también entre versiones de Free Pascal), y que sepamos cómo es la parte pública (interface).
Nota: Por eso mucha gente distribuía sus bibliotecas de rutinas Pascal en forma de TPU: se podía
usar las facilidades que nos daban (si teníamos la misma versión de Pascal), pero como no teníamos
disponible la fuente, no podíamos modificarlo ni redistribuirlo con nuestro nombre, por ejemplo.
88
Hoy en día, se tiende más a ceder todo el código fuente, y pedir a los usuarios que conserven el
copyright y/o envíen al autor las mejoras que propongan.
En Turbo Pascal 7 para MsDos, cada unidad tiene su propio segmento de código (esto va para
quien conozca la estructura de la memoria en los PC), así que cada unidad puede almacenar hasta
64k de procedimientos o funciones. Los datos son comunes a todas las unidades, con la limitación
64k en total (un segmento) para todos los datos (estáticos) de todo el programa.
Si queremos almacenar datos de más de 64k en el programa, tenga una o más unidades,
deberemos emplear variables dinámicas, distintas en su manejo de las que hemos visto hasta ahora
(estáticas)
La cabecera, compuesta por el nombre del subprograma, los parámetros y el tipo de valor de
retorno. El cuerpo, compuesto por las declaraciones, las instrucciones y el manejo de excepciones.
¿QUÉ ES SUBPROGRAMACIÓN?
En definitiva, es una manera elemental de crear y mantener el código de los programas, que nos
permite dividir los problemas en partes más pequeñas, más fáciles de implementar. Sirven por tanto
para organizar nuestro código, pero nos ofrecen diversas otras ventajas.
89
con algoritmos que pueden operar de manera independiente. Esas piezas de código se pueden
invocar desde diversos sitios de un programa, las veces que se desee, o se necesite.
Por ejemplo, si tenemos una aplicación de gestión empresarial, podrías tener un programa que te
resuelva todo el tema de facturación. Sin embargo, ese objetivo puede ser lo suficientemente grande
y complejo para crear varios subprogramas. Por ejemplo, uno para crear facturas, otro para borrarlas
otro para enviarlas por email al cliente, y así puedes tener tantos subprogramas como necesites,
abonar facturas, marcarlas como pagadas, crear clientes, etc. Incluso, puede haber subprogramas
que llaman a otros subprogramas, quizás al crear la factura necesitas invocar el subprograma que
crea un cliente.
Esa estructura de funciones y funciones que llaman a otras funciones (aquí cuando me refiero a
funciones no es más que un sinónimo de subprograma), es la base del primer modo de jerarquizar
que apareció en los lenguajes de programación, que nos ayuda no solo a resolver un problema
complejo, sino que nos permite entenderlo mejor y también facilita el mantenimiento del código, una
vez el programa ya ha sido creado. Pero, además, la subprogramación facilita muchas otras
necesidades de un buen programa, como la de no repetirse uno mismo y reutilizar el código que se
ha escrito en el mayor número de oportunidades posible. En el vídeo que verás más abajo nos
explican muy bien la necesidad de las funciones y cómo y por qué sirven para reutilizar el código.
API DE JAVASCRIPT
90
En el último bloque de esta clase se dio a conocer el API de Javascript, de una manera introductoria.
Se explicó que cualquier lenguaje ofrece un conjunto de funciones ya listas para realizar tareas
básicas, como entrada y salida de datos, trabajo con fechas, estructuras de datos como arrays,
trabajo con cadenas, matemáticas, etc. Javascript es un lenguaje con una extensísima cantidad de
funciones, que no solo nos sirven para realizar programación básica, sino que nos permite además
controlar miles de aspectos del navegador, como la ventana, el historial de navegación, el
almacenamiento local y un largo etc.
FUNCIONES
Las funciones son muy similares a los procedimientos con la diferencia que éstas siempre
devolverán un valor. Su estructura es la siguiente:
IS [parte declarativa]
BEGIN
instrucciones
[EXCEPTION excepciones]
END;
La cláusula RETURN de la cabecera nos especifica el tipo de valor que nos va a devolver la función.
PARÁMETROS
Además, podemos hacer el paso de parámetros de un tipo a otro. Generalmente si los tipos son
compatibles PL/SQL lo hace automáticamente. En cualquier caso, podemos hacerlo de forma
manual utilizando las siguientes notaciones:
91
• Posicional: el compilador asocia los parámetros actuales a los formales, basándose en
suposición.
• Nominal: el símbolo => después del parámetro actual y antes del nombre del formal, indica
al compilador correspondencia.
• Mixta: nos permite usar las dos notaciones anteriores.
Para que esto quede más claro pasamos a escribir un ejemplo de paso de parámetros y conversión
de tipos.
PROCEDURE departamento(
n_departamento INTEGER,
localidad VARCHAR2
IS...
DECLARE
num_departamento INTEGER;
aula VARCHAR(30)
BEGIN
...
END;
Esto nos pasaría los parámetros num_departamento al mismo tipo que n_departamento y localidad
al mismo tipo que aula.
Los parámetros que soporta PL/SQL pueden ser de entrada, salida o entrada/salida
• IN.- Nos permite pasar valores a un subprograma. Dentro del subprograma, el parámetro
actuá como una constante. Puede ser una variable, constante, literal o expresión.
92
• OUT.- Permite devolver valores al bloque que llamó al subprograma. Dentro del
subprograma, el parámetro actúa como una variable no inicializada. Solo puede ser una
variable.
• IN OUT.- Permite pasar un valor inicial y devolver un valor actualizado. Dentro del
subprograma, el parámetro actuá como variable inicializada. Puede intervenir otras
expresiones. El valor actual debe ser una variable. El formato genérico es el siguiente:
[ { := | DEFAULT} <valor>]
Además, es importante recordar que al especificar parámetros debemos indicar el tipo, pero no el
tamaño.
Cuando creamos subprogramas con SQL * PLUS utilizando los comandos CREATE, Oracle
automáticamente compila el código fuente, genera el código objeto y los guarda en el diccionario de
datos, quedando disponibles para su utilización. Para volver a compilar un subprograma
almacenado utilizaremos la orden ALTER en vez del CREATE y su formato es el siguiente:
Para ver el código de un subprograma almacenado podemos ejecutar una sentencia como esta;
Nota: PL/SQL implementa la recursividad en los subprogramas, esto quiere decir, que un programa
puede llamarse a sí mismo.
COMPILADOR E INTÉRPRETE
A la hora de elegir un lenguaje de programación, se debe prestar especial atención a dos cosas: por
una parte, el lenguaje debe contar con todos los componentes básicos necesarios para el proyecto
de software que se quiera desarrollar. Por la otra, tiene que permitir programar e implementar este
proyecto de la manera más sencilla posible. La buena legibilidad y simplicidad del código fuente son
93
fundamentales para garantizar lo segundo, porque estas características no solo facilitan el
aprendizaje del lenguaje de programación, sino también, obviamente, su posterior utilización en el
día a día.
En primer lugar, para que el ordenador o el procesador puedan comprender las instrucciones que
contiene un programa desarrollado previamente, el código fuente escrito en los lenguajes de
programación actuales debe convertirse a un formato legible por máquina. De este procedimiento,
dependiendo del lenguaje de programación, se encarga un compilador o un intérprete. ¿Qué son
exactamente estos dos programas? Y ¿en qué se diferencian?
¿QUÉ ES UN INTÉRPRETE?
El proceso de conversión no finaliza hasta que se ha interpretado todo el código. Solo se interrumpe
prematuramente si se produce un fallo durante el procesamiento, lo que simplifica mucho la
resolución de los errores, ya que la línea de código problemática se detecta inmediatamente
después de ocurrir el fallo.
¿QUÉ ES UN COMPILADOR?
94
intermedio (también llamado código objeto) que, a menudo, es compatible con diversas plataformas
y que, además, también puede ser utilizado por un intérprete.
Tanto los compiladores como los intérpretes cumplen la función de convertir el código de software
que se ha escrito a un formato ejecutable y legible por máquina. Sin esta traducción, los
procesadores informáticos no podrían ejecutar el software en lenguajes como C, C++, PHP, Python
o Ruby, lo que convierte estos programas en unos componentes imprescindibles para utilizar
ordenadores, portátiles o smartphones. En los apartados anteriores, hemos visto que compiladores
e intérpretes presentan algunas diferencias básicas, algo que debe tenerse especialmente en
cuenta a la hora de elegir un lenguaje de programación adecuado para desarrollar un nuevo
software. En la siguiente tabla, se resumen los aspectos clave que caracterizan intérpretes y
compiladores:
Si observamos las diferencias entre compilador e intérprete, vemos claramente los puntos fuertes y
débiles de cada solución para traducir el código fuente: con el intérprete, los programas se pueden
ejecutar de inmediato y, por lo tanto, se inician mucho más rápido. Además, el desarrollo es mucho
más fácil que con un compilador, porque el proceso de depuración (es decir, la corrección de
errores) se lleva a cabo igual que la traducción, línea por línea. En el caso del compilador, primero
debe traducirse todo el código antes de poder resolver los errores o iniciar la aplicación. Sin
embargo, una vez que se ejecuta el programa, los servicios del compilador ya no son necesarios,
mientras que el intérprete continúa utilizando los recursos informáticos.
Para compensar los puntos débiles de ambas soluciones, también existe el llamado modelo de
compilación en tiempo de ejecución (en inglés, just-in-time-compiler, o “compilador justo a tiempo”).
Este tipo de compilador, que a veces también se conoce por el término inglés compreter (acrónimo
de compiler e interpreter), rompe con el modelo habitual de compilación y traduce el código del
programa durante el tiempo de ejecución, al igual que el intérprete. De esta forma, la alta velocidad
de ejecución típica de los compiladores se complementa con la simplificación del proceso de
desarrollo.
95
Java es uno de los ejemplos más conocidos de lenguaje basado en compilación en tiempo de
ejecución: el compilador JIT, que figura entre los componentes del Java Runtime Environment
(JRE), mejora el rendimiento de las aplicaciones Java traduciendo el código de bytes en código
máquina de manera dinámica.
PROGRAMACIÓN ESTRUCTURADA
Si no tienes claro lo que es un paradigma te recomendamos la lectura del artículo sobre los
paradigmas de la programación.
96
El "GOTO", que viene de las palabras "go to" (ir a), permitía mencionar una línea de código a la que
el flujo de ejecución debía saltar. Gracias a esta instrucción era posible volver a ejecutar un pedazo
de código, saltarse unas cuantas líneas de código y cosas así. Durante mucho tiempo se había
programado con esa costumbre, pero daba como resultado programas difíciles de entender, ya que
no existía una clara distribución de las responsabilidades y tampoco facilitaba la organización del
código.
Probablemente muchos de los lectores no habrán tenido que lidiar con la sentencia "GOTO" y no se
hagan una idea de cómo eran los programas en aquella época. Básicamente consistían en bloques
de código lineal, carentes de forma y estructura, con muy complicado mantenimiento. Sobre todo,
era imposible ver a simple vista cómo iba a ejecutarse en programa y para hacerse una idea era
necesario seguir una traza, que saltaba de un lugar a otro del maremagnum de sentencias, de
manera enredada.
De hecho, el término del "código spaghetti" viene justamente de esa falta de forma y la disposición
del código sin una estructura definida, todo mezclado.
En lugar del "GOTO" la programación estructurada propone una pieza nueva que no existía
anteriores paradigmas de la programación, que es la subrutina, o función.
Gracias a las funciones era posible organizar el código de una manera mucho más clara, creando
pequeñas piezas de código que eran fácilmente utilizables, que aportaban semántica al código y
que conseguían definir una estructura jerárquica.
Con las funciones se pudo comenzar a separar las partes del código en pequeñas piezas fácilmente
comprensibles y mantenibles, a delegar la responsabilidad en rutinas que eran capaces de resolver
un problema y sobre las cuales el programador podía despreocuparse de su funcionamiento interno,
porque sabía que ellas serían capaces de resolver sus problemas.
A la capacidad de ser capaces de obviar los detalles no relevantes de algo es a lo que llamamos
"abstracción". En términos de programación vino gracias a las funciones. El programador puede
simplemente entender qué hace una función sin preocuparse en cómo está desarrollada por dentro,
lo que le permite centrarse en las partes que le interesan en cada momento y deshacer la
complejidad del software.
En resumen, algunas de las ventajas que nos aporta este estilo de programación son las siguientes:
97
• Capacidad de organización jerárquica del código. Unas funciones principales llaman a otras
funciones secundarias y éstas llaman a otras, creando una jerarquía de funciones fácilmente
entendibles.
• Permiten la abstracción, evitando que el programador necesite entender todo el código como
un único bloque.
• Aumenta la capacidad de depuración, ya que cada una de las unidades "función" se pueden
probar por separado.
• Se puede aumentar drásticamente el número de líneas de las aplicaciones sin que éstas se
vuelvan un caos.
• Aumenta la velocidad de desarrollo y, además, la capacidad de que varias personas puedan
participar en el desarrollo de un proyecto.
• Todo ello reduce la complejidad del software y los costes de desarrollo.
TIPOS DE FUNCIONES
A las subrutinas, el concepto que hoy conocemos por simplemente como "funciones", algunos
lenguajes de programación lo dividieron en dos tipos de estructuras:
Aunque la programación estructurada es algo que ya viene de lejos hoy en día todavía es altamente
usada en muchos proyectos y son la base de la mayoría de los lenguajes de programación actuales.
De hecho, muchos lenguajes populares como Javascript o PHP la fomentan de base, igual aunque
también incorporan otros paradigmas distintos.
98
Pero, que se use para aprender, no quiere decir que no se use todavía para resolver los problemas
actuales. Lenguajes como Javascript, aunque soportan otros paradigmas, la tienen muy arraigada
y aplicaciones realmente complejas están resueltas en Javascript con una organización del código
basada en funciones. Igual ocurre con otros lenguajes como PHP.
Muchos otros lenguajes de programación como Java usan cosas de programación estructurada,
pero requiere el desarrollo de clases, de programación orientada a objetos, por lo que no siempre
son usados como primer lenguaje para aprender a programar. también hay que decir que en la
actualidad los equipos de desarrollo están más y más organizando el código con clases, aunque los
lenguajes puedan ser usados solo con funciones. Quizás la comunidad donde más se usan las
funciones para organizar el código sea la de Javascript, aunque en este lenguaje se usan mucho
los objetos, incluso objetos creados de manera literal, como con JSON.
Otros paradigmas como la programación funcional también vinieron después y son capaces de
resolver de manera muy elegante ciertos problemas. Actualmente hay muchos lenguajes de
programación funcional como Haskell o Scala, aunque a decir verdad no terminan de cuajar al 100%
porque no facilitan el desarrollo de todos los tipos de aplicaciones.
Pues bien, una biblioteca de programación, o library como se le dice en inglés, es como ir a Ikea.
Aquí no hay que construir la casa, sino buscar ayuda con los muebles y su disposición dentro de la
casa. En este caso, no se trata de que quieras llevar a cabo el esfuerzo de crear una mesa de
madera tallando un árbol y barnizándola. Simplemente, vas y compras la mesa que más te gusta.
En este caso, se diría que tú tienes el control sobre la disposición de las cosas en tu casa.
99
De manera similar, un programador usa una biblioteca de programación donde toma pedazos de
código (muebles) para llevar a su casa (su código de programación) para cambiar un poco las cosas
aquí y allá. Por ejemplo, en esta reseña hablan de una aplicación web que usa un library.
En cierta manera, los frameworks son como plantillas en donde debes colocar la información que
pide el código de programación para usarla en caso de que ocurra cierto evento con la aplicación
web. Por ejemplo, si el usuario hace click en esta web y ocurre un error, enviar tal mensaje de
advertencia con información adicional sobre cómo evitar el error. Por supuesto, las funciones que
traen los frameworks son más complejas.
Los programadores usan un término para establecer la diferencia entre ambos: inversión del control.
Es decir, a nivel de código una biblioteca y un sistema de programación son similares. La diferencia
está en quién tiene el control. En el caso de las bibliotecas, el programador tiene el control. Cuando
alguien usa esta herramienta, la situación es similar a cuando vas a una biblioteca física: tienes tu
lugar donde lees y, cuando necesitas otro libro, vas y buscas en los estantes.
En el caso de los sistemas, el programador no tiene el control. Aquí sucede similar a estas
situaciones donde debes llenar un formulario: no puedes cambiar nada, sino agregar la información
que te solicitan. Tanto los frameworks como las libraries están estrechamente relacionadas. El
primero está contenido en el segundo. De modo que, el programador usa ambos en función de lo
que necesite crear para su aplicación web.
Junto con los compiladores de C y C++, se incluyen ciertos archivos llamados bibliotecas más
comúnmente librerías. Las bibliotecas contienen el código objeto de muchos programas que
100
permiten hacer cosas comunes, como leer el teclado, escribir en la pantalla, manejar números,
realizar funciones matemáticas, etc. Las bibliotecas están clasificadas por el tipo de trabajos que
hacen, hay bibliotecas de entrada y salida, matemáticas, de manejo de memoria, de manejo de
textos y como imaginarás existen muchísimas librerías disponibles y todas con una función
específica.
Nota: Existe una discusión sobre el nombre de estos archivos. Muchas personas consideran que el
nombre adecuado es archivos de biblioteca, y están en lo correcto. Sin embargo, la mayoría
llamamos a estos archivos librerías, y también me incluyo entre estos. El error proviene del nombre
en inglés, que es library. Este término se traduce como biblioteca, y no como librería. De este modo
a lo largo de esta sección las llamaré de cualquiera de las dos formas, para estar más claros.
Hay un conjunto de bibliotecas (o librerías) muy especiales, que se incluyen con todos los
compiladores de C y de C++. Son las librerías (o bibliotecas) ANSI o estándar. También hay librerías
que no son parte del estándar, pero en esta sección sólo usaremos algunas bibliotecas (o librerías)
ANSI.
Nota 2: Sé que esto pinta aburrido, pero es muy útil y las librerías nos facilitan enormemente el
trabajo a la hora de programar. Recuerda que antes de hablar librerías y demás es necesario
dominar algunos conceptos de fundamentación en general y otros temas importantes (ciclos,
condicionales y demás) Ahora veamos algunas librerías y como es su sintaxis.
En C++, se conoce como librerías (o bibliotecas) a cierto tipo de archivos que podemos importar o
incluir en nuestro programa. Estos archivos contienen las especificaciones de diferentes
funcionalidades ya construidas y utilizables que podremos agregar a nuestro programa, como por
ejemplo leer del teclado o mostrar algo por pantalla entre muchas otras más.
Al poder incluir estas librerías con definiciones de diferentes funcionalidades podremos ahorrarnos
gran cantidad de cosas, imaginemos por ejemplo que cada vez que necesitemos leer por teclado,
debamos entonces crear una función que lo haga (algo realmente complejo), al poder contar con
las librerías en C++, podremos hacer uso de una gran variedad de funciones que nos facilitarán la
vida y aumentarán el modularidad de nuestros códigos. Las librerías no son únicamente archivos
externos creados por otros, también es posible crear nuestras propias librerías y utilizarlas en
nuestros programas. Las librerías pueden tener varias extensiones diferentes, las más comunes
son: .lib, .bpl, .a, .dll, .h y algunas más ya no tan comunes.
101
En conclusión: Las librearías son archivos (no siempre externos) que nos permiten llevar a cabo
diferentes tareas sin necesidad de preocuparnos por cómo se hacen sino simplemente entender
cómo usarlas. Las librearías en C++ permiten hacer nuestros programas más modulares y
reutilizables, facilitando además crear programas con funcionalidades bastante complejas en unas
pocas líneas de código.
La declaración de librerías, tanto en C como en C++, se debe hacer al principio de todo nuestro
código, antes de la declaración de cualquier función o línea de código, debemos indicarle al
compilador que librerías usar, para el saber que términos estaran correctos en la escritura de nuestro
código y cuáles no. La sintaxis es la siguiente: #include <nombre de la librería> o alternativamente
#include "nombre de la librería". Cualquiera de las 2 formas es válido en C++ (no estoy seguro si en
C sea válido), ten en cuenta que siempre el nombre de la librería debe ir entre " y " o entre < y >. En
tu código puedes declarar todas las librerías que quieras, aunque en realidad no tienen sentido
declarar una librería que no vas a usar en tu programa, sin embargo no existe límite para esto.
A continuación, pondremos algunas de las librerías de uso más común de C++ y que forman parte
de las librerías estándar de este lenguaje.
102
• Ostream: Algoritmos estándar para los flujos de salida.
• Queue: Parte de la STL relativa a contenedores tipo queue (colas de objetos).
• Librería stdio: Contiene los prototipos de las funciones, macros, y tipos para manipular datos
de entrada y salida.
• Librería stdlib: Contiene los prototipos de las funciones, macros, y tipos para utilidades de
uso general.
• String: Parte de la STL relativa a contenedores tipo string; una generalización de las cadenas
alfanuméricas para albergar cadenas de objetos. Muy útil para el fácil uso de las cadenas de
caracteres, pues elimina muchas d elas dificultades que generan los char.
• Typeinfo: Mecanismo de identificación de tipos en tiempo de ejecución.
• Vector: Parte de la STL relativa a los contenedores tipo vector; una generalización de las
matrices unidimensionales C/C++.
• Forward_list: Esta librería es útil para implementar con gran facilidad listas enlazadas simples.
• List: Permite implementar listas doblemente enlzadas (listas enlazadas dobles) facilmente.
• Iterator: Proporciona un conjunto de clases para iterar elementos.
• Regex: Proporciona fácil acceso al uso de expresiones regulares para la comparación de
patrones.
• Thread: Útil para trabajar programación multihilos y crear múltiples hilos en nuestra
aplicación.
• Time: Útil para obtener marcas de tiempo durante ejecución. Se usa con frecuencia para
conocer el tiempo exacto durante un programa.
Veamos a continuación como se haría la declaración de unas cuantas librerías conocidas, recuerda
que ese puede declarar todas las librerías necesarias y siempre debe hacerse al comienzo del
código fuente.
#include "iostream"
#include "string"
#include <math.h>
#include <conio.h>
103
Con esto debió quedar claro, como declarar librerías C++ al interior de un código fuente. Lo único
adicional, es la línea que dice using namespace std; esta línea nos ayuda a declarar un espacio de
nombre que evita tener que usarlo cada que accedemos a alguna función especifica de una librería.
Teniendo este namespace declarado podemos llamar por ejemplo el comando cout >>, que
pertenece a la librería iostream, sin embargo sin este namespace sería std::cout >>, imagina tener
que hacer esto cada vez que uses algún comando o función de las librerías, sería bastante tedioso.
Todas las librerías estándar de C++ contienen una declaración del espacio de nombre std, es decir
que todas las librerías que hacen parte del estándar de C++ colocan entidades dentro de este
espacio de nombre.
Por esta razón cuando declaramos el uso del espacio de nombre std por medio de "using
namespace std;", podemos evitar estar escribiendo std::cout o std::cin, etc en nuestro código.
El espacio de nombre std como tal no es una librería sino simplemente un namespace, por esta
razón no reemplaza la declaración de las librerías del código, simplemente facilita la escritura de
éste al momento de usar las entidades de las librerías estándar. Sin embargo si vamos a hacer uso
de una o varias librerías estándar de C++ es recomendable que declaremos el namespace std, para
no tener que estar constantemente escribiendo cosas similares a las que puse hace unas líneas
como std::cin o similares, dado que únicamente se puede acceder a la entidades de las librerías
estándar por medio del espacio nombre std.
Muy bien, ahora veamos algunos ejemplos simples del uso de librerías o bibliotecas en C++
En el siguiente ejemplo veremos el uso de la librería stdlib.h que posee una gran variedad de
funcionalidades, para este ejemplo usaremos la función rand que nos permite generar un número
aleatorio.
#include <stdlib.h>
#include <iostream>
#include
104
int main ()
// Se genera una semilla diferente cada vez (basada en el tiempo exacto de ejecución)
// Se debe llamar siempre, para generar números realmente diferentes cada vez
srand (time(NULL));
cout << rand(); //Se genera el número con rand y se muestra en pantalla
return 0;
En el anterior código hemos hecho uso de dos librerías: iostream y stdlib. La librería o biblioteca
iostream, nos permitirá hacer uso del cin y el cout para obtener o imprimir valores por pantalla,
respectivamente mientras stdlib nos dará acceso a la función rand que generará por nosotros un
número cualquiera.
El diseño centrado en el usuario es un proceso iterativo que dirige sus objetivos a los usuarios y sus
necesidades. Sus creadores se apoyan en una variedad de técnicas de investigación y diseño para
crear productos altamente utilizables y accesibles.
Los diseñadores emplean una combinación de métodos y herramientas de investigación, como las
encuestas, entrevistas o lluvia de ideas con la finalidad de comprender a profundidad las
necesidades del usuario.
El término «experiencia del usuario» lo acuñó Donald Norman en 1993, cuando trabajaba para
Apple. A mediados de la década de 1990, muchas empresas de tecnología lo utilizaron como un
diferenciador de producto clave. El libro de Norman, La psicología de los objetos cotidianos (1988),
sigue siendo un referente para el diseño centrado en el usuario, en él promociona el desarrollo
iterativo y las relaciones entre el usuario y el objeto.
105
Si lo piensas, la experiencia del usuario no es un fenómeno nuevo. Ha existido que los humanos
comenzaron a interactuar con herramientas y máquinas. Se encuentra en todo lo que tocamos y
creamos, desde objetos físicos hasta en la experiencia de hacer una página web.
El diseño centrado en el usuario es vital para lograr el reconocimiento de marca por parte del cliente.
No solo facilita la vida de los usuarios, sino que permite establecer un canal de comunicación con
ellos, gracias a sus virtudes.
En otras palabras, un diseño centrado en el usuario consigue captar su atención y retener su interés.
ya que este puede interactuar con el sitio de una manera intuitiva, sin la necesidad de capacitación
o experiencia.
Como estrategia, el diseño centrado en el usuario es crucial para una nueva o pequeña empresa.
Usualmente se dice «la primera impresión es la que cuenta», por ello, el uso del diseño centrado en
el usuario puede hacer o deshacer el reconocimiento de tu marca.
Si alguna vez te has encontrado en un sitio web y no entiendes lo que ofrece o no puedas navegar
fácilmente por la página, es muy probable que hayas cerrado la ventana e intentado con otra página.
Finalmente, si tu empresa depende del tráfico de Internet, debes asegurarte de que el diseño
centrado en el usuario esté a la altura y que capte y aborde toda la experiencia del usuario. Para
esto, puedes pedir la ayuda de profesionales de disciplinas que aportan mejoras al proceso de
diseño, como psicólogos, ingenieros de software y hardware, lo mismo que de expertos en dominios
y los propios usuarios.
Para abarcar toda la experiencia del usuario considera involucrar a los usuarios en la evaluación y
garantizar que la supervisión del diseño centrado en el usuario sea a largo plazo. El diseño centrado
en el usuario es una forma poderosa de descubrir qué funciona bien, qué no y por qué. Tus usuarios
son un sistema de alerta temprana que puedes utilizar para corregir el curso y ajustar un diseño
ideal que te ayude a alcanzar tus objetivos.
106
3. Sentimiento de facilidad
Este será el resultado de una planificación y diseño intuitivos por parte de los equipos de trabajo.
Será cuando el usuario se sienta capaz de realizar sus propios procesos de conocimiento y
exploración, sin la necesidad de recurrir a consultas especializadas en la red. De esta manera, el
usuario permanecerá más tiempo con tu marca, pues todas sus necesidades se satisfarán.
Este proceso expone aspectos positivos y negativos que tu equipo pudo haber pasado por alto en
áreas vitales, como la usabilidad y la accesibilidad. El diseño centrado en el usuario es un proceso
iterativo que se enfoca en la comprensión de los usuarios y su contexto en todas las etapas de
diseño y desarrollo.
Cada iteración del enfoque del diseño centrado en el usuario implica cuatro fases distintas.
Los diseñadores tratan de comprender el contexto de los usuarios que usan un sistema. Las
encuestas, focus groups y sondeos ayudan a entender las necesidades de las personas y a ponerse
en sus zapatos cuando se trata de interactuar con un sitio web, una aplicación o un contenido digital.
Estos identifican y especifican los requisitos de los usuarios, como el tipo de dispositivos desde los
que acceden a un sitio, debido a que mirar el contenido desde la pantalla de una computadora no
es lo mismo que hacerlo desde el teléfono móvil.
Por otro lado, la mayoría de los usuarios de una app prefieren ver videos explicativos que leer un
texto para conocer sus funciones. También podría aumentar la demanda de un sistema operativo
que no habían considerado sus desarrolladores.
107
3. Diseñar las soluciones
En esta fase, los diseñadores crean las soluciones específicas a las necesidades del usuario y que
se adapten a los objetivos de la empresa o marca. Es importante discernir entre aquellos cambios
que son relevantes tanto para usuarios como creadores, porque es imposible darles gusto a todas
las personas en el planeta. Así que hay que enfocarse en lo que ayudará a dar una gran experiencia
a quienes lo piden realmente.
En esta etapa se evalúan los resultados según el contexto y los requisitos de los usuarios a fin de
verificar qué tan bien se está desempeñando el diseño. Es decir, se visualiza qué tanto se acercó al
nivel que coincide con los requerimientos específicos de los usuarios y si satisface todas sus
necesidades relevantes.
Como la palabra lo indica, iteración implica repetir varias veces un proceso con la intención de
alcanzar el objetivo deseado. A partir de aquí, el equipo de diseño puede realizar más iteraciones
de estas cuatro fases hasta que los resultados de la evaluación sean satisfactorios.
De esta manera, es que podemos centrarnos en tres principios fundamentales para crear un diseño
centrado en el usuario de una manera más ágil y efectiva.
1. Obedece a un análisis
Esto significa que cada acción que ejecute el usuario será planeada y prevista por el diseño centrado
en él. En este sentido no hay coincidencias ni espacios abiertos, ya que cada aspecto será
considerado por un equipo de trabajo que logré no solo pensar en el usuario en primer término, sino
que logré, incluso, adelantarse a lo que quiere y busca.
108
3. Prueba y verifica
Finalmente, la única manera de lograr un diseño centrado en el usuario es por medio de un constante
proceso de pruebas. Así que prueba y modifica cada aspecto cuantas veces sea necesario, pues
en esto se basa la seguridad y funcionalidad que tu diseño centrado en el usuario pueda otorgar.
El diseño centrado en el usuario es un proceso en el que las decisiones están dirigidas por y hacia
el usuario y los objetivos que pretende satisfacer el producto. La usabilidad del diseño es evaluada
y mejorada en el proceso.
Estos, involucran a un grupo invitado de usuarios intencionados y reales de un sitio para que
compartan sus pensamientos, sentimientos, actitudes e ideas sobre un determinado tema.
Organizar grupos focales dentro de tu organización también puede ser muy útil para lograr la
aceptación de un proyecto. Es mejor usar los grupos focales utilizan con mayor frecuencia como
una entrada para el diseño. Generalmente producen datos no estadísticos y son un buen medio
para obtener información sobre un dominio. Es necesario tener un moderador y un analista
experimentados para que un grupo focal sea efectivo.
2. Pruebas de usabilidad
Las sesiones de prueba de usabilidad evalúan un sitio mediante la recopilación de datos de las
personas a medida que lo usan. Se invita a una persona a asistir a una sesión en la que se le pedirá
que realice una serie de tareas, mientras un moderador toma nota de las dificultades que encuentre.
Se puede pedir a los usuarios que sigan el protocolo de pensar en voz alta. Esta técnica les permite
verbalizar lo que están haciendo y por qué lo están haciendo. Debes tener en cuenta que el uso de
esta técnica ralentizará considerablemente las tareas de los usuarios. También puedes cronometrar
a los usuarios para conocer cuánto tiempo los lleva completar las tareas, lo que es una buena
medida de eficiencia. Normalmente se requiere la presencia de dos especialistas por sesión: uno
para moderar y otro para detectar problemas.
109
Las pruebas de usabilidad se pueden emplear al inicio de un diseño o al final de un proyecto. Este
método representa una excelente manera de descubrir cuáles son los problemas de usabilidad más
probables en tu sitio o producto y se puede utilizar para generar datos no estadísticos o estadísticos.
Las pruebas de usabilidad requieren que haya un diseño disponible para probar, incluso si es solo
en papel. Este método funciona mejor si se centra en la recopilación de comentarios no estadísticos
sobre un diseño, a través de la técnica de «hablar en voz alta» o medidas estadísticas.
3. Clasificación de tarjetas
Se le presenta a un participante un paquete de fichas sin clasificar. Cada tarjeta tiene una
declaración escrita que se relaciona con una página de un sitio o de una parte del proyecto. Se le
pide al participante que clasifique estas tarjetas en grupos y luego que nombre esos grupos. Los
resultados de múltiples usuarios se combinan y analizan estadísticamente. La clasificación de
tarjetas generalmente se usa como una entrada al diseño. Es una excelente manera de sugerir
buenas categorías para el contenido de tu sitio y derivar la arquitectura de información, por ejemplo.
Asimismo, se puede utilizar para generar datos estadísticos. Hay que proporcionar a los
participantes una prueba en algunas tarjetas fáciles de reconocer, como de deportes o animales.
Con esto se les prepara sobre lo que se espera que hagan durante el ejercicio, por lo que el resultado
puede ser una sesión más productiva.
4. Diseño participativo
En este método no solo se les pide a los usuarios sus opiniones sobre temas de diseño, sino que
los involucra activamente en los procesos de diseño y toma de decisiones. El diseño participativo
generalmente se usa dentro de un miniproyecto para generar prototipos que se incorporen al
proceso de diseño de un proyecto general. Un ejemplo sería un taller de diseño participativo en el
que los desarrolladores, diseñadores y usuarios trabajen juntos para crear un prototipo inicial. Este
prototipo inicial se incorporaría a un proceso de diseño más tradicional.
Los proyectos que solo utilizan diseño participativo son muy raros. Como las sesiones de diseño
participativo pueden ser muy fluidas requieren un moderador experimentado con un conocimiento
profundo del dominio para guiarlas.
110
5. Cuestionarios
Los cuestionarios son el método más conocido. Son el medio para pedir a los usuarios sus
respuestas a un conjunto predefinido de preguntas. Representan una buena forma de generar datos
estadísticos. Los cuestionarios generalmente se emplean cuando un equipo de diseño solo tiene
acceso remoto con los usuarios de un sitio. También se utiliza cuando se está buscando un tamaño
de muestra mayor que el que puede lograrse por medio del contacto directo. Es por esta razón que
los cuestionarios generalmente se administran por correo o medios electrónicos.
Los cuestionarios permiten el análisis estadístico de los resultados, lo que puede aumentar la
credibilidad de un estudio a través de su apariencia científica. Esto hace que sea aún más importante
que el cuestionario esté bien diseñado y que contenga preguntas no sesgadas.
6. Entrevistas
Este método generalmente involucra a un entrevistador que habla con un participante a la vez. Las
ventajas de una entrevista son que se puede explorar en detalle el punto de vista de un participante.
También se puede identificar cualquier malentendido entre el entrevistador y los participantes, el
cual se puede abordar rápidamente. Por lo general, el resultado de una entrevista es exclusivamente
no estadístico. Es fundamental que los informes de las entrevistas sean analizados a profundidad
por profesionales experimentados.
Las entrevistas generalmente se emplean al principio del proceso de diseño para obtener una
comprensión más detallada de un dominio y área de actividad o requisitos específicos.
En el pasado, las estrategias de marketing solían centrarse en el producto. El trabajo del vendedor
era informar a los clientes potenciales de todos los beneficios y ventajas de su mercancía. Sin
embargo, la industria está encontrando formas nuevas e innovadoras para atraer a los clientes a
sus negocios. El marketing centrado en el usuario es una estrategia que consiste en poner al cliente
en el centro de lo que hace tu empresa. Cada proceso debe comenzar y terminar con el cliente en
mente. Esto más que una mera estrategia, es una cultura organizacional. Las empresas centradas
en el cliente han demostrado ser un 60 % más rentables que las empresas centradas en el producto.
111
deben elegir el que sea más acorde con su marca. Una de las mejores maneras de comenzar es a
través de un enfoque inbound marketing.
Se trata de crear un marketing que los usuarios amen y busquen. Para obtener este tipo de
marketing es esencial tener en cuenta tres aspectos: el contenido, el usuario al que está destinado
y el contexto de uso. La información sobre estos tres aspectos se recopila mediante un análisis
constante durante el proceso de creación.
Para lograr esto, se debe implementar una metodología que se divide en tres etapas: atraer,
interactuar y deleitar. Así, las experiencias que crea tu empresa deben satisfacer a tus clientes
desde la etapa inicial hasta el proceso posterior a la compra. Si tu objetivo es desarrollar relaciones
rentables a largo plazo, centra el interés en tus clientes en todo momento.
Una gran herramienta para usar en este paso es un generador de buyer persona. Esto puede
ayudarte a formular un usuario objetivo para el que está diseñado y fundamentado tu producto.
Recuerda que tener esta plantilla no reemplaza la comunicación con tus usuarios. Realizar una
112
investigación adecuada de los usuarios mediante entrevistas y la interacción con ellos es crucial
para cualquier proceso de diseño centrado en el usuario.
Es por eso que una buena investigación de usuarios es indispensable para el éxito de tu proyecto.
Ahora que conoces a tus usuarios y sus necesidades, es hora de comprender sus métricas de éxito.
Esto significa tener una idea clara de dos aspectos:
• Requisitos comerciales. Estos son los objetivos y resultados que quieres conseguir, como la
cantidad de leads o el alcance del diseño.
• Requisitos de usuario. Esto es todo lo que el usuario puede obtener del proceso, entre ellos
los problemas que está resolviendo el diseño.
Ambos abordan el gran por qué: ¿por qué este diseño es beneficioso tanto para la empresa como
para el usuario? ¿Por qué vale la pena destinar tiempo para hacerlo ahora?
Ahora que has identificado las necesidades de tus usuarios, así como sus métricas para el éxito, es
el momento de establecer y diseñar soluciones para ellos. Esta etapa del proceso significa construir
y decidir junto con los diseñadores aspectos como el mapa del sitio, flujo de usuario, maquetas,
imágenes, iconos y paleta de colores. Una vez que tu equipo de diseño haya abordado los
problemas de tus usuarios objetivo, es hora de continuar al paso final.
Este paso será un vistazo general a tu producto final para ver si cumple con todos los objetivos que
se propuso en el paso dos. Algunas preguntas que te puedes hacer son:
Ahora debes pensar en lo que necesita tu sitio web para operar formalmente. Así que como primer
paso consulta este artículo que te ayudará a emprender esta tarea desde cero. Recuerda que
además de tu contenido debes prestar atención a la rueda de colores que conforman tu sitio y
también a otros aspectos tales como crear iconos en el menú y cuerpo de tu sitio web.
113
Así que ya sea si llegas a generar este elemento puedes ayudarte de las herramientas que tenemos
diseñadas para facilitarte este proceso.
6. Repite el proceso
Esta es la iteración: volver al paso uno y comenzar otra vez el proceso de diseño centrado en el
usuario, pero con el conocimiento que adquiriste en la primera ronda. Aunque técnicamente no es
un paso, es lo que viene después de los 4 pasos mencionados para asegurar el éxito del ejercicio.
INTERRUPCIONES DE DOS
En informática una interrupción es una señal recibida por el procesador de una computadora, que
indica que debe «interrumpir» el curso de ejecución actual y pasar a ejecutar código específico para
tratar esta situación, una suspensión temporal de la ejecución de un proceso, para pasar a ejecutar
una subrutina de servicio de interrupción, la cual, generalmente, no forma parte del programa, sino
que pertenece al sistema operativo o al BIOS.
Son generadas por los dispositivos periféricos habilitando una señal del CPU (llamada IRQ del inglés
"interrupt request") para solicitar atención del mismo.
Por ejemplo, cuando un disco duro completa una lectura solicita atención al igual que cada vez que
se presiona una tecla o se mueve el ratón.
La primera técnica que se empleó para esto fue el polling, que consistía en que el propio procesador
se encargara de sondear los dispositivos periféricos cada cierto tiempo para averiguar si tenía
pendiente alguna comunicación para él. Siendo muy ineficiente, ya que el procesador consumía
constantemente tiempo y recursos en realizar estas instrucciones de sondeo.
El procesador, en este caso, no sondea a ningún dispositivo, sino que queda a la espera de que
estos le avisen (le "interrumpan") cuando tengan algo que comunicarle (ya sea un evento, una
transferencia de información, una condición de error, etc.).
114
FUNCIONAMIENTO DEL MECANISMO DE INTERRUPCIONES
Todos los dispositivos que deseen comunicarse con el procesador por medio de interrupciones
deben tener asignada una línea única capaz de avisar al CPU cuando le requiere para realizar una
operación. Esta línea se denomina IRQ.
Las IRQ son líneas que llegan al controlador de interrupciones, un componente de hardware
dedicado a la gestión de las interrupciones, y que puede estar integrado en el procesador principal
o ser un circuito separado conectado al mismo. El controlador de interrupciones debe ser capaz de
habilitar o inhibir las líneas de interrupción y establecer prioridades entre las mismas.
También puede darse el caso de que una rutina de tratamiento de interrupción sea interrumpida
para realizar otra rutina de tratamiento de una interrupción de mayor prioridad a la que se estaba
ejecutando; aunque hay interrupciones que no se pueden deshabilitar (conocidas como
interrupciones no enmascarables o NMI).
Un procesador principal que no tenga un controlador de interrupciones integrado suele tener una
única línea de interrupción llamada habitualmente INT.
Esta línea es activada por el controlador de interrupciones cuando tiene una interrupción que servir.
Al activarse esta línea, el procesador consulta los registros del controlador de interrupciones para
averiguar cuál IRQ hay que atender.
A partir del número del IRQ busca en la tabla de vectores de interrupción la dirección de la rutina a
la que debe llamar para atender la petición del dispositivo asociado a dicha IRQ.
1. Salvar el estado del procesador (valores de registros y flags) y el valor del contador de programa,
IP, en la pila, de manera que, en la CPU, al terminar el proceso de interrupción, pueda seguir
ejecutando el programa a partir de la última instrucción.
2. La CPU salta a la dirección donde está almacenada la rutina de servicio de interrupción (Interrupt
Service Routine, o abreviado ISR) y ejecuta esa rutina que tiene como objetivo atender al dispositivo
que generó la interrupción.
115
3. Una vez que la rutina de la interrupción termina, el procesador restaura el estado que había
guardado en la pila en el paso 2 y retorna al programa que se estaba usando anteriormente.
El bus de control de la placa base dispone de líneas específicas para el sistema de interrupciones.
Un PC típico dispone en su placa base de un controlador de interrupciones 8259 de Intel o de un
circuito integrado análogo.
Este dispositivo electrónico dispone de hasta 16 líneas IRQ, numeradas desde el 00 hasta el 15. En
las nuevas placas base este circuito está integrado junto con el resto del chipset y permite hasta 24
interrupciones.
Aunque internamente se manejan 16 líneas, no todas tienen contacto en los zócalos del bus externo
(son las marcadas con asterisco en la tabla que sigue). La razón de esta ausencia en los zócalos
de conexión es que son de asignación fija, y solo son usadas por ciertos dispositivos instalados en
la propia placa base.
En concreto la línea NMI está asignada al mecanismo de control de paridad de la memoria, la línea
0 está asignada al cronómetro del sistema y la línea 1 al chip que controla el teclado (dispositivos
que pueden requerir atención urgente por parte del procesador). Es costumbre denominar IRQx a
las que tienen prolongación en el bus.
Teóricamente las restantes líneas podrían ser asignadas a cualquier nuevo dispositivo, pero en la
práctica algunas están reservadas a dispositivos estándar. Por ejemplo, IRQ3 está casi siempre
asignado al puerto serie COM2 y el IRQ4 al COM1; IRQ6 al controlador estándar de disquetes y
IRQ7 al puerto de impresora LPT1.
116
Atendiendo a la fuente que las produce, las interrupciones pueden clasificarse de la siguiente forma:
Interrupciones de hardware.
Estas son asíncronas a la ejecución del procesador, es decir, se pueden producir en cualquier
momento independientemente de lo que esté haciendo el CPU en ese momento. Las causas que
las producen son externas al procesador y a menudo suelen estar ligadas con los distintos
dispositivos de entrada o salida.
Excepciones
Son aquellas que se producen de forma síncrona a la ejecución del procesador y por tanto podrían
predecirse si se analiza con detenimiento la traza del programa que en ese momento estaba siendo
ejecutado en la CPU. Normalmente son causadas al realizarse operaciones no permitidas tales
como la división entre 0, el desbordamiento, el acceso a una posición de memoria no permitida, etc.
Son aquellas generadas por un programa en ejecución, para generarlas, existen distintas
instrucciones en el código máquina que permiten al programador producir una interrupción, las
cuales suelen tener nemotécnicos tales como INT (por ejemplo, en DOS se realiza la instrucción
INT 0x21 y en Unix se utiliza INT 0x80 para hacer llamadas de sistema).
Interrupciones de hardware
Son aquellas interrupciones que se producen como resultado de, por lo general, una operación de
E/S. No son producidas por ninguna instrucción de un programa sino por las señales que emiten los
dispositivos periféricos para indicarle al procesador que necesitan ser atendidos.
117
Excepciones
Son un tipo de interrupción sincrónica típicamente causada por una condición de error en un
programa, como por ejemplo una división entre 0 o un acceso inválido a memoria en un proceso de
usuario. Normalmente genera un cambio de contexto a modo supervisor para que el sistema
operativo atienda el error. Así pues, las excepciones son un mecanismo de protección que permite
garantizar la integridad de los datos almacenados tanto en el espacio de usuario como en el espacio
kernel. Cuando el Sistema Operativo detecta una excepción intenta solucionarla, pero en caso de
no poder simplemente notificará la condición de error a la aplicación/usuario y abortará la misma.
Interrupciones por software, también denominadas llamadas al sistema son aquellas generadas por
un programa mientras este está ejecutándose. En general, actúan de la siguiente manera:
Un programa en ejecución llega a una instrucción que requiere del sistema operativo para alguna
tarea, por ejemplo, para leer un archivo en el disco duro (cuando un programa necesita un dato
exterior, se detiene y pasa a cumplir con las tareas de recoger ese dato).
En ese momento por tanto llama al sistema y se interrumpe virtualmente hasta recibir respuesta, en
el ejemplo anterior hasta que no se haya leído el disco y el archivo esté en memoria principal.
Durante esa espera las instrucciones que se ejecutarán no serán del programa, sino del sistema
operativo. Una vez este termine su rutina ordenará reanudar la ejecución del programa auto
interrumpido en espera. Por último, la ejecución del programa se reanuda.
Hay dos alternativas para determinar la dirección de la rutina de servicio de interrupción que se debe
ejecutar al recibir una interrupción determinada:
Direcciones fijas
Se hallan cableadas en el procesador y por tanto nunca pueden ser cambiadas. Esto implica que
las RSI siempre estarán en una determinada posición de la memoria.
En este grupo se incluyen aquellas que presentan una dirección variable y que, por tanto, no se
halla cableada en el procesador. De esta manera el dispositivo debe dar información acerca de la
localización de la dirección de comienzo de la RSI asociada a dicho periférico.
118
Determinación de la fuente que genera la interrupción
Hay distintas formas de identificar la fuente de una determinada interrupción. La primera alternativa
que se consideró fue asignar una línea (un bit) para cada interrupción, lo cual suponía un gran costo
en cuanto a la relación de número de dispositivos y número de bits usados y a menudo limitaba el
número de dispositivos que se podían conectar.
Por ello, se pensó con posterioridad en que en cada patilla de interrupción debería poder conectarse
más de un dispositivo, debiendo implementar por tanto una metodología que permitiese identificar
de forma unívoca de qué dispositivo se trataba. Para ello hay varias directrices:
Direcciones variables
Hay distintas metodologías de diseño para las interrupciones con direcciones variables. En la
actualidad, las alternativas que son implementadas de manera habitual son las siguientes:
Direccionamiento absoluto
Direccionamiento relativo
Esta alternativa tiene una ventaja sobre la anterior y es que permite especificar la dirección de
comienzo con menos bits y por tanto simplifica el diseño.
Ahora bien, tiene una desventaja principal y es que limita el número de dispositivos que podemos
conectar y además ciertos bits de la dirección quedan fijados de forma permanente por la CPU lo
que reduce la capacidad de reubicabilidad de la ISR. Una alternativa que utilizan ciertos
procesadores como el 8080 o el 8085 es que en vez de enviar solamente la dirección de comienzo
de la ISR se envía también el código de la operación de salto (por ejemplo CALL).
Direccionamiento indirecto
Se mantiene una tabla de vectores de interrupción (direcciones de comienzo de las distintas ISR) y
a cada interrupción se le asocia un número que será el índice por el cual se accederá a la tabla y se
recuperará la información de la dirección de comienzo. Necesita señales de conformidad o
119
handshaking para sincronizar al procesador con la interfaz, ya que esta última tiene que indicarle al
procesador cuando va a enviarle el índice que necesita para buscar el vector de interrupción (INT)
y el procesador deberá enviar otra señal para indicar que se ha reconocido la interrupción (INTA#).
Hay distintas formas de identificar la fuente de una determinada interrupción. La primera alternativa
que se consideró fue asignar una línea (un bit) para cada interrupción, lo cual suponía un gran costo
en cuanto a la relación de número de dispositivos y número de bits usados y a menudo limitaba el
número de dispositivos que se podían conectar. Por ello, se pensó con posterioridad en que en cada
patilla de interrupción debería poder conectarse más de un dispositivo, debiendo implementar por
tanto una metodología que permitiese identificar de forma unívoca de qué dispositivo se trataba.
Para ello hay varias directrices
Polling:
Esto tiene una ventaja y es que es barato a nivel de coste hardware ya que el polling se implementa
en software, no obstante, tiene otras desventajas que no podemos olvidar y es que suele ser lento
porque tiene que comprobar en serie todos los dispositivos y establece una prioridad en los
dispositivos (el orden de sondeo) y por tanto puede provocar inanición.
Interrupciones vectorizadas
Como ventajas podemos destacar que suele ser rápido, pero implica un alto costo en el hardware.
Hardware paralelo
Se utiliza un registro de interrupción cuyos bits se controlan de forma independiente por las señales
de petición de interrupción de cada periférico. Según la posición de cada bit en el registro, se
establece la prioridad.
Sistemas de prioridad
El sistema operativo necesita un mecanismo para priorizar las interrupciones y tratar primero las
más urgentes.
Interrupciones simultáneas
120
No tienen por qué ocurrir de manera simultánea, sino que se refiere a que en un momento dado
puede haber varias interrupciones activas.
Interrupciones anidadas
Mientras se está procesando una determinada rutina de servicio de interrupción sucede otra señal
de interrupción.
Inhibición de interrupciones
Interrupciones simultáneas
Una de ellas es que exista algún hardware que tenga como entradas las señales de interrupción y
de cómo salida la interrupción más prioritaria que está activa en ese momento.
Polling
Daisy-chain (conexión en cadena): se puede conectar los distintos dispositivos en cadena, en orden
decreciente de prioridad y por tanto la señal de reconocimiento de interrupción (INTA#) solo será
pasada al siguiente dispositivo en caso de que el anterior (más prioritario) no haya solicitado los
servicios del procesador.
Sin embargo, algo importante es que las señales de interrupción que van al procesador están
conectadas todas a un mismo cable, por tanto, deberemos utilizar alguna técnica especial para que
no se produzca un cortocircuito. Para evitar precisamente que la pista se cortocircuite se utiliza la
técnica del open-collecto o «colector abierto» y consiste en conectar el colector de un transistor a la
pista común (un transistor por cada dispositivo) y por tanto estarán tantos colectores conectados
como dispositivos tengamos (se entiende que son dispositivos que mandan petición de interrupción
al procesador).
121
Interrupciones anidadas
El primero se basa en inhabilitar las interrupciones mientras se está ejecutando una determinada
RSI. Esto puede realizarlo el hardware de manera automática en algunos procesadores, pero en
otros será el usuario el encargado de deshabilitarlas en caso de que no desee que ninguna otra
interrupción pueda interrumpir el transcurso normal de la rutina de servicio de interrupción. No es
aconsejable deshabilitar las interrupciones durante mucho tiempo ya que esto puede provocar
errores y pérdida de información.
Inhibición de interrupciones
Hay distintas alternativas de inhibición de interrupciones. Como ya hemos visto estas se pueden
hacer de manera automática por el hardware en algunos casos mientras que en otros será el usuario
el encargado de realizarlo por software y esto depende de la arquitectura del procesador que
consideremos. Las distintas opciones son:
Deshabilitar todas las interrupciones. Para esto basta con inhibir el bit del registro de flag dedicado
a las interrupciones.
Deshabilitar al principio de la RSI y activarlas de nuevo al finalizar la misma. Puede ser de manera
automática o por el usuario.
Desactivar solo las interrupciones que tengan menor prioridad que la asociada a la RSI que se está
ejecutando en ese momento.
Deshabilitar de forma selectiva distintos niveles de prioridad de interrupción. Para lo cual se emplean
registros especiales denominados máscaras en el que cada uno de sus bits identifican a un nivel
distinto y modificando su contenido se puede establecer que niveles están activos en ese momento.
Se puede cambiar por el programador.
Ensamblador Interrupciones
122
Son aquellas programadas por el usuario, es decir, el usuario decide cuando y donde ejecutarlas,
generalmente son usadas para realizar entrada y salida.
Son aquellas que son provocadas por dispositivos externos al procesador su característica principal
es que no son programadas, esto es, pueden ocurrir en cualquier momento en el programa.
Aquellas en las que el usuario decide si quiere o no ser interrumpido. Interrupciones por hardware
no enmascarables (NMI): Aquellas que siempre Interrumpen al programa.
Las interrupciones por software se ejecutan con ayuda de las instrucciones: INT e IRET, además se
tiene 256 interrupciones: de la 00 a la FF.
Esta área se encuentra en el segmento 0000:0000. Para cada una de las direcciones se utilizan 4
bytes, dos bytes para el segmento y 2 para el desplazamiento. La instrucción INT tipo, realiza las
siguientes tareas
5. Calcula el área donde está la dirección de la rutina de servicio de la siguiente manera: tipo*4, en
el vector de interrupciones.
123
Salvar el IP de la dirección de regreso.
Calcula el área donde está la dirección de la rutina de servicio de la siguiente manera: tipo*4, en el
vector de interrupciones
Al encender la computadora se ejecuta un programa; llamada rutina iniciadora; que inicia todo el
sistema dicho programa esta almacenado en la memoria ROM, y forma parte del BIOS que es un
conjunto de rutinas básicas para realizar E/S a dispositivos.
4. Realiza el proceso conocido como el BOOT STRAP que consiste en leer el sector del disco en
memoria, dicho sector contiene un programa que pasará el sistema operativo a la memoria y le
transfiere el control.
Las interrupciones del BIOS siempre están disponibles al usuario, en cambio las del sistema
operativo, sólo si es sistema se ha cargado en memoria. BIOS permite realizar entrada y salida a
dispositivos, el acceso a estas rutinas es también por medio de interrupciones de software y
enviando parámetros a través de los registros.
La interrupción 21h permite leer de teclado, escribir en vídeo, escribir en impresora, leer y escribir
de dispositivo auxiliar, además realizar cambios en el vector de interrupciones, obtener y poner tanto
la fecha como la hora.
124
Manejo de Vídeo
Las computadoras usan los llamados al sistema de vídeo o adaptadores de display, para desplegar
información en la pantalla.
La función del controlador del display es definir el tipo de pantalla usada, definir y controlar el cursor,
asignar color y generar los caracteres
-Modo texto
-Caracteres alfanuméricos
-Modo gráfico
-Despliega puntos
El controlador de display controla al cursor, que nos dice donde se va a escribir el siguiente carácter.
Los caracteres pueden verse como la unión de punto dentro de una matriz para formar el carácter
deseado. En los dos modos de vídeo se tienen dos tipos de resolución: Alta y mediana resolución,
aunque ya no se utiliza la resolución mediana; la resolución, nos brinda mejor imagen. La pantalla
se puede ver como si fuera una matriz de puntos o caracteres.
Cada elemento en la matriz se encuentra almacenado en la memoria RAM del adaptador de vídeo,
de ahí se toma para ser enviado a la pantalla. En modo texto cada elemento ocupa solo 2 bytes,
uno mantiene el código ASCII del carácter y el otro un atributo con el que se desplegará dicho
carácter.
El modo gráfico utiliza 4 bytes, 3 bytes para el color y el cuarto es para el atributo. Atributos:
Background (fondo) y Foreground (frente).
La matriz de vídeo se mapea en memoria por renglones, es decir, primero se almacena el renglón
cero, enseguida el renglón uno y así sucesivamente. Escribir un carácter en vídeo equivale a escribir
en la RAM de vídeo. Todos los sistemas de vídeo tienen RAM para almacenar más de una pantalla;
cada pantalla se distingue por un número y se le conoce como página.
125
Para escribir un carácter en directo a RAM se necesita: Dir(i, j) = Dir_incial_de_vídeo + 80*2*i + j*2.
Si se escribe un carácter de esta forma se le conoce como manejo directo de memoria. Para este
tipo de acceso, se puede utilizar las funciones de la interrupción 10h.
-En lenguaje de bajo nivel con la INT 21h del sistema operativo DOS
Con funciones del BIOS con la INT 10h. Con el manejo directo de vídeo metiendo el carácter en
memoria
El teclado envía un carácter al CPU y lleva el código de barrido (Scan Code) que sólo es un número
y después lo transforma a ASCII. Interrupciones por Hardware En las PC que trabajan con el
procesador, se tienen 2 tipos de interrupciones, como ya se mencionó; las NMI llegan a través de
una línea directamente al procesador y cuando ésta se activa, el CPU provoca una interrupción por
software del tipo 2.
Además, se tienen 8 líneas que reciben las interrupciones enmascarables, también llamadas IRQ
(Interrupt ReQuest), asociada a estas líneas se tiene una bandera IF (Interrupt Flag) para determinar
si se acepta o no las interrupciones. Si IF = 1 entonces IRQ’s están habilitadas Si IF = 0 entonces
IRQ’s deshabilitadas.
Las 8 líneas de IRQ llegan directamente al CPU, antes son detenidas por un circuito llamado el
control de interrupciones. La función de este circuito es determinar cuál de las 8 líneas puede entrar
a interrumpir al CPU en caso de provocarse dos o más interrupciones a la vez. Esta determinación
se lleva a cabo en base en dos cosas:
Prioridad
Las IRQ están numeradas: IRQ 0 IRQ 1 IRQ7 Las de más alta prioridad es la IRQ 0 y la de más
baja prioridad es la IRQ 7 Habilitación en el registro de máscaras:
126
El registro de máscaras
Se puede leer o escribir en el puerto 21h. Además de que el registro de máscaras habilita o
deshabilita el CPU. El IRQ 0 está conectado a un circuito que es el TIMER. El IRQ 1 está conectado
con una línea al teclado.
El IRQ 6 está conectado a las unidades de disco. Timer (INT 8): Las PC tiene internamente un
circuito que es el Timer, y el cual tiene la función de interrumpir el CPU, un número de veces
determinado por segundo.
Teclado
El teclado tiene incluido un procesador, cuya función es estar censando continuamente las teclas y
si alguna de ellas se presiona entonces provoca una interrupción IRQ 1 y además le envía al
procesador central a través del puerto 60h, el código de barrido asociado a esa tecla. Entonces se
ejecuta una INT 9, cuya función es leer el código de barrido del puerto y convertirlo a código ASCII,
si es el caso, o bien interpretar el código de barrido para cambiar el estado del teclado. Finalmente,
ambos códigos se colocan en un buffer para que puedan leerse por medio de la INT 16h
Son una facilidad soportada por el BIOS que los programas DOS, u otro tipo de programas como
cargadores de arranque, así como sistemas operativos usan para acceder al hardware más básico
de un computador PC Compatible (arquitectura x86).
Algunos sistemas operativos también usan el BIOS para probar e inicializar recursos de hardware
durante las primeras etapas del arranque.
127
Estas llamadas pueden verse como parte de la funcionalidad de un sistema operativo implementada
en memoria no volátil por el propio fabricante del computador.
Los sistemas operativos de PC primitivos se apoyaban en estas llamadas para realizar parte de sus
operaciones de entrada/salida. Sin embargo, estas llamadas están implementadas en modo real,
mientras que muchos sistemas operativos ya funcionan en Modo Protegido.
Tales sistemas operativos han de cambiar a modo real antes de realizar la llamada de interrupción
y regresar a modo Protegido después. Linux y las versiones recientes de sistemas Windows ya no
aprovechan estas llamadas e implementan enteramente todo el acceso al hardware en rutinas
propias.
Invocar una interrupción puede hacerse usando la instrucción INT en lenguaje ensamblador de los
procesadores x86. Por ejemplo, para imprimir un carácter a la pantalla usando la interrupción 10h
del BIOS, las siguientes instrucciones deberán ser ejecutadas:
00h CPU: Ejecutado después de un intento de división por cero o cuando un cociente no cabe en
el destino
01h CPU: Ejecutado después de cada instrucción de código de máquina mientras la bandera de
trazado esté activo
02h CPU: NMI. Usado por el Power On Self Test (POST) para errores de memoria
03h CPU: La más baja interrupción no reservada, es usada exclusivamente para depuración, y el
manejador INT 03h siempre es implementado por un programa de depuración
04h CPU: Numeric Overflow. Usualmente causado por la instrucción INTO cuando la bandera de
desbordamiento está activada
05h Ejecutado cuando es presionado Shift-Print Screen, así como cuando la instrucción BOUNDh
detecta una falla de límite
128
06h CPU: Llamada cuando una excepción de opcode indefinido (código inválido). Usualmente
instalado por el sistema operativo
07h CPU: Llamada cuando se intenta usar una instrucción de coma flotante y no está disponible
un coprocesador numérico
08h IRQ0: Implementada por el componente de temporización del sistema; llamado 18,2 veces
por segundo (una cada 55 ms) por el PIC
09h IRQ1: LLamada después de que cada tecla es presionada o soltada (como también durante
el tiempo en que una tecla es mantenida presionada)
0Bh IRQ3: Llamada por los puertos seriales 2 y 4 (COM2 y COM4) cuando es necesaria atención
0Ch IRQ4: Llamada por los puertos seriales 1 y 3 (COM1 y COM3) cuando es necesaria atención
0Dh IRQ5: Llamada por el controlador del disco duro (PC/XT) y el segundo puerto paralelo LPT2
(AT) cuando es necesaria atención
0Eh IRQ6: Llamada por el controlador de disco floppy cuando es necesaria atención
0Fh IRQ7: Llamada por el primer puerto paralelo LPT1 (impresora) cuando es necesaria atención
10h
Servicios de video - Instalado por el BIOS o el sistema operativo; llamado por programas de software
03h Get Cursor Position And Shape Lee la posición y la forma del cursor
04h Get Light Pen Position Lee la posición del Light Pen
07h Clear/Scroll Screen Down Borra la pantalla / Desplazamiento (Scroll) hacia abajo
08h Read Character and Attribute at Cursor Lee un carácter y su atributo en la posición del cursor
129
09h Write Character and Attribute at Cursor Escribe un carácter y su atributo en la posición del
cursor
12h Instalado por el BIOS o el sistema operativo; retorna el tamaño de la memoria convencional
13h Servicios de disco de bajo nivel; instalado por el BIOS o el sistema operativo; llamado por
programas de software
09h Init Fixed Drive Parameters Inicia los parámetros de la unidad fija (disco duro)
16h Get Floppy Drive Media Change Status Lee el estado de cambio del medio de la unidad
floppy
130
14h Rutinas para la comunicación vía el puerto serial. Usado por programas de software
C1h Get Extended BIOS Data Area Segment Lee el segmento del área de datos extendida
del BIOS
E8h 01h Get Extended Memory Size (Newer function, since 1994). Gives results for memory
size above 64 Mb. Lee el tamaño de la memoria extendida
E8h 20h Query System Address Map. The information returned from e820 supersedes what is
returned from the older AX=E801hh and AH=88hh interfaces. Información sobre el Mapa de
memoria del sistema
16h Implementado por el BIOS o el sistema operativo. Provee rutinas a ser llamadas por programas
de software que se comunican con el teclado
131
AH Descripción (Ing) Descripción (Esp)
02h Read Keyboard Shift Status Lee el estado de las teclas de desplazamiento (SHIFT,
CTRL, ALT)
12h Read Keyboard Shift Status Extended Lee el estado de las teclas de desplazamiento
extendido. Servicios de Impresora - Usado por los programas de software para comunicarse con la
impresora
Ejecuta el IBM ROM BASIC: Los computadores personales de originales de IBM contienen el BASIC
en ROM para ser ejecutado por esta rutina en el evento de una falla en la carga (boot). LLamado
por el BIOS
19h Boot Strap Loader. Después del POST, esta interrupción es usada por el BIOS para cargar
el sistema operativo
1Ah Servicios del Real Time Clock (RTC) (Reloj de Tiempo Real) - Llamado por programas de
software para comunicarse con el RTC
AH Descripción
132
04h Lee la fecha del RTC
1Bh Instalado por el sistema operativo; automáticamente llamado por INT 9h cuando ha sido
presionado Ctrl-Break
1Ch Llamado automáticamente por INT 08h; disponible para el uso por programas de software
cuando una rutina necesita ser ejecutada regularmente
1Dh No debe ser llamado; simplemente un puntero para la Tabla de Parámetros del Video (VPT),
que contiene datos sobre modos de video
1Eh No debe ser llamado; simplemente un puntero para la Tabla de Parámetros del Disquete
(DPT), conteniendo una variedad de información concerniente a las unidades de disquete
1Fh No debe ser llamado; simplemente un puntero para Tabla la Tabla de Caracteres de Gráficos
de Video (VGCT), que contiene los datos para los caracteres ASCII 80h a FFh
41h Puntero de dirección: Tabla de Parámetros del Disco Fijo (FDPT) (Primera unidad de disco)
46h Puntero de dirección: Tabla de Parámetros del Disco Fijo (FDPT) (Segunda unidad de disco)
133
El vector de interrupción 13 puede apuntar a un hook de software en vez de la rutina en el BIOS,
con el que algunos virus búlgaros son conocidos para usar en contra del software de monitoreo de
virus.1
A medida que el tiempo pasó y el BASIC ya no fue despachado en todos los PC, esta interrupción
simplemente exhibiría un mensaje de error indicando que no fue encontrado ningún dispositivo
booteable (el famoso "No ROM BASIC", o un mensaje más explicativo en versiones posteriores del
BIOS). En otras versiones del BIOS se solicitaba al usuario insertar un volumen booteable y
presionar una tecla, y después que el usuario lo hiciera, retornaría al bootstrap loader para tratar de
cargar de nuevo.
Esta particularidad lo distingue del resto de los programas, entre los cuales se pueden citar a los
sistemas operativos (que son los que permiten el funcionamiento de la computadora), los lenguajes
de programación (aquellos que dan las herramientas necesarias para desarrollar los programas
informáticos en general) y las utilidades (pensadas para realizar acciones de mantenimiento y tareas
generales).
El software es el elemento intangible y lógico que forma parte de una computadora. El hardware, en
cambio, es el componente material y físico. Se dice que los sistemas operativos constituyen el lazo
que une al software con el hardware.
Los procesadores de texto, las hojas de cálculo y las bases de datos forman parte de los
denominados programas de aplicación.
Esto demuestra que las aplicaciones informáticas sirven para automatizar tareas como la
contabilidad o la redacción de textos.
134
Cabe destacar que el paquete o suite de oficina más popular a escala internacional es Office, un
producto impulsado por Microsoft.
Esta compañía, fundada en 1975 por Bill Gates y Paul Allen, es la firma de software más grande del
mundo. Su actividad no se agota en los programas de aplicación, sino que la empresa también
desarrolla el sistema operativo más popular: Windows.
En el caso de los procesadores podemos destacar a Microsoft Word, que es el más utilizado
actualmente en todo el mundo y que se caracteriza o define porque le ofrece la posibilidad al usuario
de llevar a cabo la creación, diseño e impresión de documentos textuales de diversa tipología como
pueden ser informes, cartas, redacciones. Microsoft Excel, por su parte, es el programa de
aplicación más extendido en materia de hojas de cálculo.
En multitud de empresas de distinta índole, y también a nivel personal, se opta por hacer uso de
dicho software que se utiliza frecuentemente en lo que son labores de tipo contable y financiero. En
materia de las bases de datos, hay que destacar como programación de aplicación a Access que
está diseñado tanto para poder trabajar con aquellas en el ámbito profesional como en el más
personal.
Gracias al mismo se pueden desarrollar desde tablas para guardar los datos pertinentes hasta
consultas para recuperar cierta información pasando por formularios para actualizar aquellos o los
informes que se utilizan para llevar a cabo la impresión de los datos que se estimen oportunos.
No obstante, no podemos pasar por alto que estos tres programas pertenecientes a Microsoft tienen
un importante rival desde hace algún tiempo: OpenOffice. Y es que es una llamada “suite
informática” de tipo libre que cuenta con una serie de aplicaciones que permiten realizar las mismas
tareas que aquellos nos ofrecen.
En concreto los rivales serían OpenOffice Writer como procesador de textos, OpenOffice Calc como
hojas de cálculo y OpenOffice Base que funciona como base de datos.
En ocasiones, los programas de aplicación son diseñados a medida, es decir, según las
necesidades y pretensiones de cada usuario, por eso, el software permite resolver dificultades
específicas. En otros casos, se trata de paquetes integrados que solucionan problemas generales
e incluyen múltiples aplicaciones. Por ejemplo, un paquete de oficina combina aplicaciones como
procesadores de textos y hojas de cálculo.
Como se mencionó anteriormente la interfaz para accesar a los servicios de DOS es por medio de
la instrucción INT. Los servicios de DOS, que se accesan con las interrupciones [0x20,0x3f]. La
135
interrupción 0x21 es la fuente principal de los servicios de MS-DOS. Las funciones de la interrupción
0x21 se llaman colocando el número de la función deseada en el registro del procesador AH,
colocando cualquier parámetro necesario en los demás registros y ejecutando la insterrupción 0x21.
Servicio Acción
136
0x13 Borra archivos
137
0x2E Habilita o inicializa el switch verify
138
0x46 Forza la duplicación de un manejador de archivo
139
0x5F04 Cancela la redirección DOS 3+
El sistema básico de entrada-salida o BIOS (del inglés Basic Input/Output System) es un estándar
de facto que define la interfaz de firmware para computadoras IBM PC compatibles1. También es
conocido como BIOS del sistema, ROM BIOS y BIOS de PC. El nombre se originó en 1975, en el
BIOS usado por el sistema operativo CP/M.2
El firmware del BIOS es instalado dentro de la computadora personal (PC), y es el primer programa
que se ejecuta cuando se enciende la computadora.
El propósito fundamental del BIOS es iniciar, y probar el hardware del sistema y cargar un gestor de
arranque o un sistema operativo desde un dispositivo de almacenamiento de datos. Además, el
BIOS provee una capa de abstracción para el hardware, por ejemplo, que consiste en una vía para
que los programas de aplicaciones y los sistemas operativos interactúen con el teclado, el monitor
y otros dispositivos de entrada/salida.
Las variaciones que ocurren en el hardware del sistema quedan ocultas por el BIOS, ya que los
programas usan servicios de BIOS en lugar de acceder directamente al hardware. Los sistemas
operativos modernos ignoran la capa de abstracción provista por el BIOS y acceden al hardware
directamente.
El BIOS del PC/XT de IBM original no tenía interfaz interactiva con el usuario. Los mensajes de error
eran mostrados en la pantalla, o codificados por medio de una serie de sonidos. Las opciones en la
PC y el XT se establecían por medio de interruptores y jumpers en la placa base y en las placas de
los periféricos. Las modernas computadoras compatibles Wintel proveen una rutina de
configuración, accesible al iniciar el sistema mediante una secuencia de teclas específica. El usuario
puede configurar las opciones del sistema usando el teclado y el monitor.
El software del BIOS es almacenado en un circuito integrado de memoria ROM no volátil en la placa
base. Está específicamente diseñado para trabajar con cada modelo de computadora en particular,
interconectando los diversos dispositivos que componen el conjunto de chips complementarios del
sistema.
140
En computadoras modernas, el BIOS está almacenado en una memoria flash, por lo que su
contenido puede ser reescrito sin retirar el circuito integrado de la placa base. Esto permite que el
BIOS sea fácil de actualizar para agregar nuevas características o corregir errores, pero puede hacer
que la computadora sea vulnerable a los rootkit de BIOS.
El MS-DOS (PC DOS) fue el sistema operativo de PC dominante desde principios de la década de
1980 hasta mediados de la década de 1990. Dependía de los servicios del BIOS para las funciones
de disco, teclado y visualización de textos. Windows NT, Linux y otros sistemas operativos de modo
protegido en general no lo usan después de cargarse en memoria.
El sistema básico de entrada-salida o BIOS (del inglés Basic Input/Output System) es un estándar
de facto que define la interfaz de firmware para computadoras IBM PC compatibles1. También es
conocido como BIOS del sistema, ROM BIOS y BIOS de PC. El nombre se originó en 1975, en el
BIOS usado por el sistema operativo CP/M.2
El firmware del BIOS es instalado dentro de la computadora personal (PC), y es el primer programa
que se ejecuta cuando se enciende la computadora.
El propósito fundamental del BIOS es iniciar, y probar el hardware del sistema y cargar un gestor de
arranque o un sistema operativo desde un dispositivo de almacenamiento de datos. Además, el
BIOS provee una capa de abstracción para el hardware, por ejemplo, que consiste en una vía para
que los programas de aplicaciones y los sistemas operativos interactúen con el teclado, el monitor
y otros dispositivos de entrada/salida.
Las variaciones que ocurren en el hardware del sistema quedan ocultas por el BIOS, ya que los
programas usan servicios de BIOS en lugar de acceder directamente al hardware. Los sistemas
operativos modernos ignoran la capa de abstracción provista por el BIOS y acceden al hardware
directamente.
El BIOS del PC/XT de IBM original no tenía interfaz interactiva con el usuario.
Los mensajes de error eran mostrados en la pantalla, o codificados por medio de una serie de
sonidos. Las opciones en la PC y el XT se establecían por medio de interruptores y jumpers en la
placa base y en las placas de los periféricos. Las modernas computadoras compatibles Wintel
proveen una rutina de configuración, accesible al iniciar el sistema mediante una secuencia de teclas
específica.
141
El usuario puede configurar las opciones del sistema usando el teclado y el monitor.
El software del BIOS es almacenado en un circuito integrado de memoria ROM no volátil en la placa
base. Está específicamente diseñado para trabajar con cada modelo de computadora en particular,
interconectando los diversos dispositivos que componen el conjunto de chips complementarios del
sistema.
En computadoras modernas, el BIOS está almacenado en una memoria flash, por lo que su
contenido puede ser reescrito sin retirar el circuito integrado de la placa base. Esto permite que el
BIOS sea fácil de actualizar para agregar nuevas características o corregir errores, pero puede hacer
que la computadora sea vulnerable a los rootkit de BIOS.
El MS-DOS (PC DOS) fue el sistema operativo de PC dominante desde principios de la década de
1980 hasta mediados de la década de 1990.
Dependía de los servicios del BIOS para las funciones de disco, teclado y visualización de textos.
Windows NT, Linux y otros sistemas operativos de modo protegido en general no lo usan después
de cargarse en memoria. La tecnología de BIOS está en un proceso de transición hacia la interfaz
de firmware extensible unificada (UEFI) desde el año 2010.3
El acrónimo BIOS fue inventado por Gary Kildall4 y apareció por primera vez en 1975 en el sistema
operativo CP/M56 describiendo la parte específica de la máquina del CP/M cargado durante el
arranque que interactúa directamente con el hardware2 (por lo general, una máquina de CP/M solo
tiene un simple arranque en su ROM).
Las versiones de MS-DOS o PC DOS contienen un archivo denominado bajo alguno de los
siguientes nombres: IO.SYS, IBMBIO.COM, IBMBIO.SYS, o DRBIOS.SYS. Este archivo se conoce
como el BIOS DOS o Sistema I/O DOS, y contiene la parte de hardware específico de bajo nivel del
sistema operativo. Junto con el hardware específico, pero independiente del BIOS del sistema
subyacente al sistema operativo que reside en la memoria ROM, este representa el análogo al CP/M
BIOS.
En otros tipos de computadoras, se emplean en su lugar los términos monitor de arranque, gestor
de arranque, y ROM de arranque. Algunos equipos basados en PowerPC y Sun utilizan Open
Firmware para este propósito. Con la introducción de las máquinas PS/2, IBM dividió el sistema
BIOS en porciones en modo real y modo protegido. La porción de modo real estaba destinada a
proporcionar retrocompatibilidad con los sistemas operativos como DOS, y por lo tanto fue
nombrado CBIOS (para compatibilidad del BIOS), mientras que el ABIOS (por Advanced BIOS)
142
proporcionaba nuevas interfaces adaptadas específicamente para sistemas operativos multitarea
como OS/2.
Hay algunas alternativas a la funcionalidad de la legacy BIOS en el mundo x86: Extensible Firmware
Interface, Open Firmware (usado en la OLPC XO-1), y Coreboot.
FUNCIONAMIENTO
Cuando se reinicia el procesador x86, se carga el contador de programa con una dirección fija en la
parte superior del espacio de direccionamiento en modo real de 1 megabyte. La dirección de la
memoria del BIOS está situada de tal manera que se ejecutará cuando el equipo se pone en marcha
primero.
Entonces, una instrucción de salto dirige el procesador para iniciar la ejecución de código en el
BIOS. Si el sistema acaba de ser encendido o el botón de reinicio fue presionado (arranque en frío),
se ejecuta completamente la autoprueba de encendido (POST). Si se inició Ctrl+Alt+Supr ("arranque
en caliente"), se detecta un valor de indicador especial en la memoria no volátil (NVRAM) y la BIOS
no ejecuta el POST. Esto ahorra un tiempo que es utilizado para detectar y probar toda la memoria.
La NVRAM está en el reloj en tiempo real (RTC).
El indicador de pruebas de autodiagnóstico identifica e inicializa los dispositivos del sistema, como
la CPU, la RAM, interruptores y controladores DMA y otras partes del chipset, tarjeta de vídeo,
teclado, unidad de disco duro, unidad de disco óptico y otro hardware básico. La BIOS localiza el
software gestor de arranque localizado en un dispositivo almacenamiento designado como
dispositivo de arranque, tal como un disco duro, un disquete, CD o DVD, carga y ejecuta ese
software, dándole el control del PC. Este proceso se conoce como arranque o secuencia de
arranque.
ACTUALIZACIÓN FIRMWARE
Para una referencia de placa base el fabricante puede publicar varias revisiones del BIOS, en las
cuales se solucionan problemas detectados en los primeros lotes, se codifican mejores
controladores o se da soporte a nuevos procesadores. La actualización de este firmware puede ser
realizado con algún programa para quemar una nueva versión directamente desde el sistema
operativo, los programas son propietarios de cada compañía desarrolladora del firmware y por lo
general pueden conseguirse en internet junto al BIOS propiamente dicho.
143
La actualización del BIOS es percibida como no exenta de riesgos, dado que un fallo en el
procedimiento conduce a que la placa base no arranque. Debido a ello algunos fabricantes usan
sistemas como el bloqueo de arranque, que es una porción de BIOS que está protegida y que no es
actualizable a diferencia del resto del firmware.
OVERCLOCKING
Algunos chips de BIOS permiten el overclocking, una acción en el que la CPU se ajusta a una
velocidad de reloj más alta que su ajuste de fábrica.
Un sistema puede contener diversos chips con firmware BIOS además del que existe en la placa
base: tarjetas de vídeo, de red y otras cargan trozos de código en la memoria (con ayuda de la BIOS
principal) que permite el funcionamiento de esos dispositivos. El BIOS de video es visible como un
integrado separado.
TARJETAS DE VÍDEO
A diferencia de otros componentes del sistema, la tarjeta de vídeo debe funcionar desde el arranque
inicial, mucho antes de que cualquier sistema operativo esté siendo cargado en la memoria RAM:
144
en los sistemas con vídeo integrado, el BIOS de la placa base contiene las rutinas necesarias para
hacer funcionar el vídeo de la placa.
Los primeros ordenadores (que no poseían vídeo integrado) tenían BIOS capaces de controlar
cualquier tarjeta adaptadora MDA y CGA. En 1984 cuando aparecieron sistemas nuevos como el
EGA fue necesario agregar una BIOS de vídeo para mantener la compatibilidad con esos sistemas
que no tenían las rutinas de manejo para el nuevo estándar; desde esa época las tarjetas de vídeo
incluyen un firmware propio.
El BIOS de estas adaptadoras provee herramientas básicas para manejar el hardware de vídeo que
ofrece la tarjeta. Cuando el computador inicia, algunas de esas tarjetas muestran en pantalla la
marca de esta, el modelo y la versión del firmware además del tamaño de la memoria de vídeo.
La gran mayoría de los proveedores de placas base de arquitectura x86 delegan a terceros la
producción de los BIOS. Los fabricantes suelen escribir y publicar actualizaciones del firmware en
las cuales se corrigen problemas o se da compatibilidad a nuevos productos. Los principales
proveedores de BIOS son American Megatrends (AMI) y Phoenix Technologies (que compró Award
Software International en 1998). Existen proyectos de BIOS bajo el esquema de Software libre, como
Coreboot, que ofrecen firmwares alternativos para unas pocas referencias de placas base.
ALTERNATIVAS Y SUCESORES
Para obtener software comparable en otros sistemas informáticos, consulte Arranque (informática).
La Unified Extensible Firmware Interface (UEFI) complementa el BIOS en muchas máquinas
nuevas. Inicialmente escrito para la Arquitectura Intel Itanium, UEFI ahora está disponible para
plataformas de arquitectura x86 y ARM; el desarrollo de especificaciones está dirigido por el Unified
EFI Forum, un grupo de interés especial de la industria.
El arranque EFI solo ha sido compatible con las versiones de Microsoft Windows compatibles con
la Tabla de particiones GUID,7 el Núcleo Linux 2.6.1 y posteriores, y macOS en Mac basados en
Intel.8 A partir de 2014, el nuevo hardware de PC se envía predominantemente con firmware UEFI.
La arquitectura de protección de rootkit también puede evitar que el sistema ejecute los cambios de
software propios del usuario, lo que hace que UEFI sea controvertido como un reemplazo de BIOS
heredado en la comunidad de Hardware libre. Además, Windows 11 requiere UEFI para arrancar.
145
CONTENIDOS
BIOS
BIOS (Sistema básico de entradas y salidas, del inglés “Basic Input/Output System“) es un
componente esencial que se usa para controlar el hardware.
Es un pequeño programa, que se carga en la ROM (Memoria de sólo lectura), tipo de memoria que
no puede modificarse y en la EEPROM (Memoria de sólo lectura que es programable y que puede
borrarse eléctricamente). De allí proviene el término “flasher”, que designa la acción de modificar el
EEPROM. Al ser una memoria, contiene dos tipos de software. El POST y el SETUP. 5 UA 2.3.1 –
BIO que se carga en la ROM (Memoria de sólo lectura), tipo de memoria que no puede modificarse
y en la EEPROM (Memoria de sólo lectura que es programable y que puede borrarse eléctricamente
Es un pequeño programa). De allí proviene el término “flasher”, que designa la acción de modificar
el EEPROM. Al ser una memoria, contiene dos tipos de software. El POST y el SETUP.
Los pasos que realiza la BIOS para el encendido y carga del Sistema Operativo son:
1) Se Inicia la BIOS y se ejecuta la prueba de encendido (POST), así como los recursos asignados.
146
4) La Aplicación está cargada y ejecutándose
Si en algún momento el POST encuentra un error, intentará continuar con el inicio del ordenador.
Sin embargo, si el error es serio, el BIOS detendrá la carga del sistema y hará una de las siguientes
acciones. De ser posible, mostrará un mensaje en la pantalla (porque el dispositivo puede no haber
sido inicializado o puede presentar errores)
Emitirá una secuencia de sonidos que permite diagnosticar el origen del error. Enviará un código
(denominado código POST) al puerto serial del ordenador, que puede recuperarse a través de
hardware especial de diagnósticos. Si no hay problemas, la BIOS emitirá un sonido corto para
informar que no hay errores. Para simplificar los códigos de sonidos, podemos decir que se
producen 2 tipos de sonidos muy característicos independientemente del tipo de fabricante de BIOS:
RAM por lo que será necesario retirarlos los módulos, limpiarlos (usar una goma de borrar sobre los
contactos metálicos) y probarlos uno a uno en cada una de las ranuras de memoria de la Placa
Base. Suele ser más fiable probar cada módulo de memoria en otro PC para detectar el módulo
defectuoso o sospechar que el problema reside en la propia placa base.
TARJETA GRÁFICA
Si los pitidos son una secuencia melódica y no se repiten, seguramente el problema resida en la
tarjeta gráfica, especialmente si ésta es AGP, que suelen desplazarse fruto de la dilatación de los
147
metales en sus contactos. En este caso, retiraremos la tarjeta, limpiaremos los contactos también
con una goma de borrar y la probaremos de nuevo. Si es necesario probarla en otra placa base. Los
Mac también informan de fallos mediante la BIOS. La musiquita que se reproduce cuando inicias un
Mac, se corresponde con el pitido de la BIOS en el resto de los ordenadores.
Sin embargo, no tienen una larga lista de error: si se reproducen dos tonos diferentes tu Mac te
advierte de que hay un problema con la placa base o el bus SCSI. SETUP: Configuración de la BIOS
10 UA 2.3.1 – BIOS
La mayoría de los BIOS tienen un programa de configuración que permite modificar la configuración
básica del sistema. Este tipo de información se almacena en una memoria CMOS o RAM-CMOS,
autoalimentada (por medio de una batería), para que la información permanezca almacenada
incluso si el ordenador se encuentra apagado (la memoria RAM se reinicia cada vez que se inicia el
sistema). Cada equipo cuenta con varios BIOS: El BIOS de la placa base, la BIOS que controla el
teclado y la BIOS de la tarjeta de video. Eventualmente, el BIOS para controladoras SCSI, que se
utiliza para iniciar desde un dispositivo SCSI, el que luego se comunica con el DOS, sin que se
necesite un controlador adicional. (El BIOS de la tarjeta de red para iniciar desde una red).
Por lo general, son todas muy similares, teniendo una estructura donde la pantalla de inicio estará
dividida en pestañas y opciones que indican sus características de uso y ayuda. Partes de la BIOS
13 UA 2.3.1 – BIOS
• Main
148
Configuración básica del sistema: opciones generales (algunas de ellas informativas) y de
configuración de dispositivos de almacenamiento.
• Advanced
Configuración avanzada del sistema: configuración de los puertos, del chipset, etc.
• Boot
• Security
Configuración de seguridad.
• Power
• JUSTw00t!
• Exit
Opciones de salida y configuración predeterminada de carga del BIOS (carga de valores por
defecto). Partes de la BIOS 14 UA 2.3.1 – BIO
La información que nos facilita la BIOS puede ayudarnos a saber que equipos son los que están
instalados en nuestro equipo y conocer alguno de sus características principales.
• CPU
• RAM
• Discos Duros
• Etc
La BIOS, nos permite personalizar las características de nuestro equipo con el fin de ajustarlo a
nuestras características y sacarlo el mayor rendimiento posible: Overclocking
Por ejemplo: Antes de cambiar nada de la BIOS es importante comprender claramente como estos
cambios pueden afectar a nuestro PC.
149
Configuración de la BIOS: Fecha y Hora 16 UA 2.3.1 – BIOS Campos: System Time y System Data.
Es importante configurar con la hora y fecha correctas, ya que el sistema operativo y otros
programas lo toman como referencia.
Puede configurar parámetros avanzados del BIOS para deshabilitar dispositivos que no se necesitan
o que el PC no utiliza.
Establece el orden de arranque o la secuencia de arranque del Pc en base a una lista ordenada.
Esta lista se encuentra en la ficha Boot del BIOS. En los nuevos PCs, puede venir en la opción
Advanced BIOS Features.
El orden de arranque puede incluir HDD, Unidades Ópticas, Unidades Disquete, Arranque de red y
medios flash. Para permitir el arranque desde una unidad USB, habilite esta opción en el BIOS.
Se puede configurar la BIOS para modificar la velocidad del reloj de la CPU. Con este procedimiento,
podemos aumentar o disminuir la velocidad para que el PC funcione rápidamente pero a una mayor
temperatura, aumentando por lo tanto el rendimiento, o que funcione más lentamente para que tenga
una mayor refrigeración. Aumentar la velocidad del reloj de la CPU por encima de las
recomendaciones del fabricante se conoce como Overclocking
Para poder utilizar software de virtualización (máquinas virtuales) en las que un programa
informático de virtualización emula las características de un sistema de computación completo,
incluidos el hardware, el BIOS, el sistema operativo y los programas, puede haber BIOS que
habiliten o no esta opción, y para ello haya que realizar el pertinente ajuste en la BIOS
150
Encriptación de unidades. Se puede encriptar un HDD para evitar el robo de datos. La encriptación
convierte los datos en un código incomprensible, que sin la contraseña correcta, hace que el PC no
pueda arrancar, aunque se coloque en otro PC el HDD, haciendo imposible descifrar los datos.
Módulo de plataforma segura: el chip del módulo de plataforma segura (TPM, Trusted Platform
Module) contiene elementos de seguridad, como claves y contraseñas de encriptación
Configuración de la BIOS:
Lojack:
Se trata de un sistema de Absolute Software para proteger el PC, que se divide en dos partes: La
primera parte es un programa denominado Módulo de persistencia, que el fabricante instala en el
BIOS.
El Módulo de persistencia instala el Agente de aplicación si se lo elimina del PC. Una vez que se
activa el Módulo de persistencia, no se puede apagar.
Configuración de la BIOS
Las placas base cuentan con sensores térmicos para controlar el hardware sensible al calor. Un
sensor térmico común se encuentra debajo del socket de la CPU.
151
Este sensor controla la temperatura de la CPU y puede aumentar la velocidad del ventilador de la
CPU para refrigerarla en caso de que se caliente demasiado. Algunas configuraciones del BIOS
también reducen la velocidad de la CPU para disminuir la temperatura de dicho componente. En
algunos casos, el BIOS apaga el PC para evitar que se dañe la CPU.
Otros sensores térmicos controlan la temperatura dentro del gabinete o la fuente de energía.
Además, los sensores térmicos controlan la temperatura de los módulos RAM, los conjuntos de
chips y otro hardware especializado.
El BIOS aumenta la velocidad de los ventiladores o apaga el PC para evitar recalentamiento y daños.
Configuración de la BIOS
Algunas configuraciones del BIOS permiten configurar perfiles para establecer las velocidades de
los ventiladores a fin de lograr un resultado específico.
Los siguientes son algunos perfiles comunes para la velocidad del ventilador de la
Standard (Estándar)
Turbo (Turbina)
Silent (Silencioso)
Manual
Es posible controlar el voltaje de la CPU o los reguladores de voltaje de la placa base. Si los voltajes
son demasiado altos o bajos, pueden dañarse los componentes del PC.
152
Si advierte que el voltaje especificado no es correcto o no está cerca del valor correcto, asegúrese
de que la fuente de energía funcione correctamente. Si la fuente de energía envía los voltajes
correctos, es posible que los reguladores de voltaje de la placa base estén dañados.
En algunas configuraciones del BIOS, se puede controlar la velocidad de la CPU y es posible que
algunas configuraciones del BIOS también permitan controlar uno o más buses.
Posiblemente, deba mirar estos elementos para determinar si un cliente o técnico introdujo en forma
manual la configuración correcta de la CPU, o si el BIOS la detectó en forma automática.
Las velocidades incorrectas de los buses pueden provocar un aumento de la temperatura dentro de
la CPU y en el hardware conectado, o pueden ocasionar que las tarjetas adaptadoras y la RAM no
funcionen correctamente
Algunas carcasas de PC tienen un interruptor que se activa cuando se abre la carcasa. Es posible
configurar el BIOS para que registre cuándo se activa el interruptor, de modo que el propietario
pueda saber si se manipuló el gabinete. Este interruptor está conectado a la placa base
Si advierte un problema con un dispositivo conectado al sistema o con una función básica (un
ventilador o con el control de voltaje y temperatura), puede utilizar el diagnóstico incorporado del
sistema para determinar dónde se encuentra el problema. El programa proporciona una descripción
del problema o un código de error para realizar procesos de resolución de problemas adicionales.
153
Revisa el disco duro para detectar áreas dañadas. Si se encuentran áreas dañadas, esta
herramienta intenta recuperar los datos, trasladarlos a un área en buenas condiciones y marcar el
área dañada como defectuosa para que no se la vuelva a utilizar. Utilice esta prueba si sospecha
que el disco duro no funciona correctamente, si el PC no arranca o si el disco duro emite ruidos
inusuales.
Verifica que los módulos de memoria funcionen correctamente. Utilice esta prueba si el PC se
comporta de manera irregular o no arranca.
Verifica que la batería funcione correctamente. Reset de la BIOS 29 UA 2.3.1 – BIOS Si el cambio
en algunas de las configuraciones de la BIOS no produce el efecto deseado o convierte al equipo
en un sistema inestable: Si podemos acceder a la BIOS tendremos que volver a cargar los
parámetros por defecto o de fábrica… hay que buscar la opción Load Default.
Si no podemos acceder a la BIOS debemos detectar en la placa el jumper Clear CMOS ó Clear RTC
RAM (si es una placa ASUS) y seguir las instrucciones del fabricante (apagar equipo, desconectar
fuente de alimentación, mover el jumper de posición durante x segundos, etc…
La actualización de la BIOS se aconseja que se lleve a cabo para poder usar nuevas funciones del
sistema informático. Es un proceso delicado, cada vez más sencillo, pero debemos tener especial
cuidado a la hora de llevarlo a cabo. Un fallo puede hacer el equipo inservible. Hay que asegurarse
de que el fichero de actualización corresponda al modelo de BIOS del equipo. Algunos modelos de
placa base permiten crear un CD/DVD de arranque con la actualización. En el momento de arranque
se realizará esa actualización. Para los modelos ASUS puede haber varias opciones
La Unified Extensible Firmware Interface (UEFI), un nuevo estándar para PCs diseñado para
reemplazar la BIOS. Fue desarrollado en colaboración con más de 140 compañías con el objetivo
de mejorar la interoperabilidad del software y solucionar las limitaciones del BIOS, entre las que se
encuentra la seguridad. Por lo tanto, resulta interesante conocer las diferencias entre BIOS y UEFI
y sus características, para saber cuál es la mejor forma de protegerse
154
CONTROLANDO EL FIRMWARE DEL SISTEMA 32 UA 2.3.1 – BIOS
Para empezar, es importante aclarar que el firmware es una porción de código almacenado en una
en una memoria ROM que se utiliza para establecer las instrucciones que controlan las operaciones
de los circuitos de un dispositivo. Este componente de código va integrado al hardware del
dispositivo, pero puede ser modificado a través de órdenes externas con el objetivo de mantenerlo
actualizado y funcionando de acuerdo con los requerimientos propios del sistema. La función
primordial del BIOS es inicializar los componentes de hardware y lanzar el sistema operativo.
Además, con su carga se inicializan otras funciones de gestión importantes como la energía y la
gestión térmica. Por otra parte, el UEFI se puede cargar en cualquier recurso de memoria no volátil,
lo cual permite que sea independiente de cualquier sistema operativo. Debido a estas
características, posee las mismas funciones que BIOS, pero con características adicionales.
Dado que la BIOS inicializa el sistema, hay algunas características fundamentales asociadas a su
ejecución:
Puede ejecutar código para verificar la integridad de todos los componentes del firmware antes de
que se ejecute y lance el sistema operativo. Probar los componentes clave de hardware en el
ordenador para garantizar que toda la información cargue correctamente y no genere problemas
sobre la información. Controla módulos adicionales como la tarjeta de vídeo o la tarjeta de red de
área local, entre otros dispositivos. Selecciona el dispositivo de arranque que puede ser el disco
duro, una unidad de CD o un dispositivo USB.
El proceso de arranque UEFI tiene características similares, pero la diferencia es que el código se
ejecuta en 32 – o 64-bit de modo protegido en la CPU, no en modo de 16 bits como suele ser el
caso de BIOS. En el caso de Windows 8 y superiores, se puede activar el modo UEFI y Secure
Boot,lo cual da un nivel adicional de protección a los sistemas.
155
SEGURIDAD EN BIOS Y UEFI 36 UA 2.3.1 – BIOS
Como la primera porción de código ejecutada por un dispositivo es alguno de estos dos estándares,
deben considerarse como un componente crítico para la seguridad. De hecho, gestionar la
seguridad en la BIOS permite fortalecer el equipo desde el encendido. Dado que se ha detectado
una posible vulnerabilidad que afectaría el modo Secure Boot del UEFI, es importante tener algunas
recomendaciones de seguridad que nos ayudan a elevar los niveles de seguridad en nuestro equipo:
Todos los cambios a BIOS o UEFI deberán utilizar un mecanismo autenticado de actualización o un
mecanismo seguro de actualización local. El mecanismo de actualización local seguro sólo se debe
usar para cargar la primera imagen o para recuperarse de una corrupción en el sistema de arranque.
También garantizará la autenticidad e integridad de la imagen de actualización, especialmente si se
trata de BIOS. Para evitar la modificación no intencional o maliciosa del sistema, deberán estar
protegidos con un mecanismo que no se pueda reemplazar fuera de una actualización autenticada
El mecanismo de actualización será el único capaz de modificar el BIOS del sistema sin necesidad
de intervención física. Al tener presentes estas medidas de seguridad lograremos, independiente
del modelo de arranque utilizado en nuestro dispositivo, que este garantice la integridad de nuestra
información.
Una de las funciones de UEFI, es el Secure Boot, aunque es una característica útil que previene
que algún tipo de malware tome control sobre Windows, también previene que cualquier otro sistema
operativo, como distribuciones de Linux o incluso versiones anteriores de Windows, como Windows
7 o XP, puedan bootear o ser instaladas en el ordenador. Es por esta razón que muchos usuarios
fracasan cuando intentan arrancar desde un disco o pendrive con otro sistema operativo, con la
intención de probarlo o instalarlo en su ordenador.
Windows 8.1 fue diseñado para arrancar rápidamente, tan rápido que no puedes tomar decisiones
antes del arranque como solías hacer para ingresar a las opciones de la BIOS.
Por esta razón Microsoft buscó otras alternativas para que el usuario pueda arrancar la BIOS o al
UEFI. Alternativas nada cómodas y que están escondida bajo un mar de clics y menús que marean
al más diestro
156
EL RELOJ Y PILA CMOS 38 UA 2.3.1 – BIOS
El reloj en tiempo real (o RTC) es un circuito cuya función es la de sincronizar las señales del
sistema. Está constituido por un cristal que, cuando vibra, emite pulsos (denominados pulsos de
temporizador) para mantener los elementos del sistema funcionando al mismo tiempo.
La frecuencia del temporizador (expresada en MHz) no es más que el número de veces que el cristal
vibra por segundo, es decir, el número de pulsos de temporizador por segundo. Cuanto más alta
sea la frecuencia, mayor será la cantidad de información que el sistema pueda procesar
157
La información sobre el hardware en el ordenador (como el número de pistas o sectores en cada
disco duro) se almacena directamente en el CMOS. Como el CMOS es un tipo de almacenamiento
lento, en algunos casos, ciertos sistemas suelen proceder al copiado del contenido del CMOS en la
memoria RAM (almacenamiento rápido); el término “memoria shadow” se utiliza para describir este
proceso de copiado de información en la memoria RAM.
IMPORTANTE: Cuando la hora del ordenador se reinicia de manera continua o si el reloj se atrasa,
generalmente sólo debe cambiarse la pila.
Los principales proveedores de BIOS son American Megatrends (AMI) y Phoenix Technologies (que
compró Award Software Internationalen 1998).
158
CONCLUSIÓN
Programar significa tener la habilidad de crear y codificar un algoritmo para que pueda ser ejecutado
por una computadora. Es decir, se desarrollan un conjunto de instrucciones que le indican a la
computadora cómo hacer ciertas tareas. En la actualidad, la programación es catalogada como
un lenguaje tecnológico fundamental.
La programación es fundamental para acrecentar el avance tecnológico dentro de las industrias que
para llevar a cabo sus funciones necesitan de sitios y aplicaciones creadas a partir de los códigos.
No es novedad que vivimos en un mundo computarizado donde la tecnología forma parte de todo
lo que hacemos. Por eso, aprender cómo funciona y saber modificarla será ideal para poder
identificar las necesidades de la sociedad y así abarcarlas a través de la programación. Un ejemplo
para destacar es cómo la tecnología fue el campo que primero se ajustó a las condiciones actuales
del mundo. La pandemia que vivenciamos este 2020 implicó nuevas adaptaciones a nuestra manera
de vivir, surgiendo distintas plataformas o reinventándose las ya existentes. Mantener las clases de
todos los niveles educativos, el trabajo remoto, el crecimiento de las compras online, la telemedicina,
garantizar el entretenimiento, etc. Todas estas variantes representan oportunidades con las que los
programadores se han tenido que enfrentar al comienzo del año para poder ofrecer los servicios
indispensables de una manera diferente y eficiente. Los y las expertas afirman que aprender a
programar también permite el desarrollo de las capacidades como el pensamiento lógico, la
creatividad y el ingenio. Estas se potencian y facilitan la resolución de problemas y la automatización
de tareas a partir de una computadora. Estas características no solo resultan fructíferas para el
ámbito laboral, sino que pueden aplicarse al crecimiento personal de los individuos.
En este punto es imprescindible un mayor compromiso educativo que permita formar a más jóvenes
y adultos en el área IT y así respaldar la creciente demanda laboral.
159
BIBLIOGRAFÍA
▪ Quetglás, Gregorio; Toledo Lobo, Francisco; Cerverón Lleó, Vicente (1995). Fundamentos
de informática y programación. Valencia: Editorial V.J.
▪ Wicham, Hadley (2019). Advanced R. Florida: Editorial Chapman and Hall/CRC.
▪ Cerrada Somolinos, José y Collado Machuca, Manuel (2015). Fundamentos De
Programación. Madrid: Editorial Universitaria Ramón Areces.
▪ Casale, Juan Carlos (2012). Introducción a la Programación. Buenos Aires: Editorial Fox
Andina.
▪ Martínez López, Pablo (2013). Las bases conceptuales de la Programación: una nueva
forma de aprender a programar. La Plata: Editorial de la Universidad Nacional de Quilmes.
▪ Ada Lovelace - Wikipedia.
▪ Difference engine - Wikipedia.
▪ Generaciones de las computadoras.
▪ Generaciones de ordenadores.
▪ Historia de la programación - Wikipedia.
▪ Konrad Zuse - people.idsia.ch.
▪ Los huesos de Napier, la multiplicación árabe y tú.
▪ Significado de computación.
160