Prólogo - Departamento de Lenguajes y Sistemas Informáticos

Anuncio
Prólogo
El posible lector de este manual, puede preguntarse y con razón, ¿Por qué es necesario otro
libro de C? Efectivamente en las bibliotecas de nuestros centros hay numerosos libros de texto
para aprender C. Asimismo en la red hay también infinidad de manuales o apuntes editados
por distintos departamentos universitarios. Por tanto, necesidad como tal no hay. Sin
embargo, aparte de aquello tan castizo de “cada maestrito tiene su librito”, el objetivo de
estos apuntes es dar una visión ligeramente distinta de la habitual. Desde nuestro punto de
vista, la enseñanza del lenguaje C en los estudios de ingeniería se presenta de una forma
antipática, dando más importancia al lenguaje a que el alumno aprenda a programar.
El objetivo de estas páginas es aprender C pero simultáneamente aprender a programar con
algunos fundamentos adecuados para un curso de iniciación a la programación. Algunas
cuestiones que distinguen en los temas que siguen son las siguientes:








Se simplifica el lenguaje C obviando algunos detalles que no añaden ninguna
funcionalidad interesante: sentencia do_while, operador ?, operador ++ como prefjo,
operadores de bits, tipos sin sentido actualmente como short, unsigned, etc.
Se trabaja con funciones desde el primer momento, planteando todos los problemas
para ser resueltos mediante ellas. De esta forma el alumno debe aprender desde el
principio los conceptos de modularidad y reutilización.
Las variables arrays o struct deben ser siempre declaradas a través de sus tipos
previamente definidos. Igualmente los argumentos de las funciones deben ser tipos
declarados.
Los arrays siempre son tratados diferenciando tamaño y dimensión. Las funciones que
tratan arrays como entrada o salida deben recibir o devolver el tamaño del array
respectivamente.
Los tratamientos de los algoritmos básicos sobre arrays: recorridos, filtros, búsqueda,
etc, se exponen mediante esquemas.
Los punteros se explican más tarde de lo que suele ser habitual, y sólo con su uso
imprescindible, esto es, para definir argumentos de entrada/salida a funciones.
En los problemas siempre se pide una función y el programa principal que la invoque.
Numerosos ejercicios reutilizan las funciones de problemas anteriores. Los problemas
son algorítmicos, puros de aprender a programar, pero no son algoritmos que podrían
denominarse de “idea feliz”, sino que tienen un esquema claro asociado.
No se hace apenas mención a los típicos y tan extendidos problemas o ejercicios,
pensados más para desarrollar la memoria que para aprender a programar. No
encontrará en este manual los ejercicios que dan importancia fundamental a la
sintaxis del C, buscando más el error del alumno que su aprendizaje.
José C. Riquelme Santos
Catedrático de Universidad
ETS Ingeniería Informática
Universidad de Sevilla
Autor: José C. Riquelme (Universidad de Sevilla)
TEMA 1. Conceptos de programación.
1. Conceptos básicos.
Ordenador o computador. Un ordenador es un sistema capaz de almacenar y procesar
con gran rapidez una gran cantidad de información. Además, un ordenador tiene
capacidad para comunicarse con el exterior, recibiendo datos, órdenes y programas
como entrada (por medio del teclado, del ratón, de un dispositivo USB, Bluetooth, etc.),
y proporcionando resultados de distinto tipo como salida (en la pantalla, por la
impresora, mediante un fichero en disco, etc.).
Partes de un ordenador. Un computador en general, o un PC en particular, constan de
distintas partes interconectadas entre sí y que trabajan conjunta y coordinadamente. Las
principales son:
• Procesador o CPU (Central Processing Unit, o unidad central de proceso). Se encarga
de realizar las operaciones aritméticas y lógicas, así como de coordinar el
funcionamiento de todos los demás componentes.
• Memoria principal o memoria RAM (Random Access Memory). Es el componente del
computador donde se guardan los datos y los programas que la CPU está utilizando. Se
llama también a veces memoria volátil, porque su contenido se borra cuando se apaga el
ordenador, o simplemente cuando se reinicializa.
• Disco duro. El disco duro es capaz de mantener la información –datos y programas–
de modo estable, también con el computador apagado. El computador no puede trabajar
directamente con los datos del disco, sino que antes tiene que transferirlos a la memoria
principal. De ordinario cada disco duro está fijo en un determinado computador.
• Dispositivos externos de memoria. Desde los antiguos disquetes, los CD o DVD o las
memorias USB son elementos que sirven para transportar y guardar de manera fácil
información y datos que nos interese guardar. Con la aparición de la “nube” o sitios en
internet que nos permiten guardar e intercambiar datos entre ordenadores conectados
(Google Drive, Dropbox, etc), estos dispositivos cada vez tienen menos uso.
• Pantalla o monitor. Es el elemento “visual” del sistema. A través de él el computador
se comunica de forma gráfica o mediante texto con el usuario.
• Ratón. Es el dispositivo más utilizado para introducir información no alfanumérica,
como por ejemplo, seleccionar una entre varias opciones en un menú o caja de diálogo.
Su principal utilidad consiste en mover con facilidad el cursor por la pantalla.
• Teclado. Es el elemento más utilizado para introducir información alfanumérica en el
ordenador.
Programa informático. Es una lista de instrucciones con una finalidad concreta que se
ejecutan habitualmente de modo secuencial (una detrás de otra) aunque en ciertos
ordenadores es posible también en paralelo. Estas instrucciones se escriben en un
fichero fuente siguiendo unas reglas que vienen dadas por un lenguaje de programación
concreto. Normalmente un programa procesa unos datos a partir de una entrada de
información y presenta al acabar unos resultados de salida.
Almacenamiento de datos. La memoria de un computador está constituida por un gran
número de unidades elementales, llamadas bits, que almacenan sólo unos o ceros. Un
conjunto de 8 bits recibe el nombre de byte u octeto. La capacidad de almacenamiento
de memoria de un ordenador suele medir en Kilobytes (1024 bytes), Megabytes o
Tema 1. Conceptos de programación
simplemente "megas" (1024 Kbytes) y Gigabytes o "gigas" (1024 Mbytes). Durante la
ejecución de un programa las instrucciones y datos están habitualmente en la memoria
principal o RAM. Los datos de entrada a un programa suelen ser introducidos desde
teclado o leídos desde un almacenamiento externo. Los datos de salida suelen ser
mostrados en pantalla o escritos en un archivo.
Sistema Operativo. Es un programa o conjunto de programas que en un sistema
informático gestiona los recursos de hardware y facilita el uso de programas de
aplicación como el explorador de ficheros o el navegador web.
Lenguajes de programación. Las instrucciones de un programa deben estar escritas en
un lenguaje comprensible por el ordenador y dependiendo de la cercanía de ese lenguaje
a la máquina concreta se hablan de lenguajes de bajo o alto nivel. El lenguaje de más
bajo nivel es el lenguaje máquina binario constituido por un conjunto de unos y ceros,
que evidentemente es incomprensible para el ser humano. A partir de ahí los lenguajes
ensambladores constituyen el siguiente nivel, comprensibles pero difíciles de
programar. Finalmente los lenguajes de alto nivel son capaces de escribir instrucciones
con una estructura sintáctica comprensible por el programador y que convenientemente
“traducidas” son capaces de ejecutarse en un ordenador. Lenguajes de alto nivel
primitivos como Fortran o Cobol de mediados del siglo XX han ido evolucionando
hasta lenguajes como Java o Python. Todos los programas excepto los escritos en
código máquina binario deben ser “traducidos” para que puedan ser ejecutados. El
fichero fuente traducido se suele denominar fichero ejecutable.
Compilador. Un compilador es un programa que “traduce” un conjunto de
instrucciones escritas en un lenguaje de alto nivel a un lenguaje comprensible por el
ordenador. Normalmente el compilador está integrado con otras funcionalidades
constituyendo un Entorno de Desarrollo Integrado (IDE en inglés). Un IDE además
del compilador, suele disponer de un editor, un depurador y otras herramientas que
facilitan la construcción y prueba de programas. Una de las principales tareas de un
buen compilador es ayudar al programador a descubrir los errores sintácticos del
programa. Como se ha dicho anteriormente los lenguajes de alto nivel tienen una
sintaxis bastante estricta, es decir, la estructura de cada instrucción y sus relaciones con
las demás están fuertemente condicionadas por un conjunto de reglas sintácticas. Estas
reglas obligan al programador a ser muy cuidadoso en la escritura de un programa para
que pueda ser traducido por el compilador. Un buen IDE debe proporcionar información
adecuada sobre por qué una instrucción no está bien escrita para que el programador
pueda corregirla. Otra tarea básica del IDE es el depurador o facilidad que ofrece la
posibilidad de ejecutar paso a paso un programa controlando si el orden de las
sentencias y los datos que procesa son los que se esperaba o no.
2. Programación de ordenadores
2.1 El lenguaje C. El lenguaje C es un lenguaje de programación creado en 1972 por
Dennis M. Ritchie en los Laboratorios Bell. Es un lenguaje cuyo origen es la
implementación del sistema operativo Unix. C es apreciado por la eficiencia del código
que produce y es el lenguaje de programación más popular para crear software de
sistemas, aunque también se utiliza para crear aplicaciones. Se trata de un lenguaje de
medio nivel pero con muchas características de bajo nivel. Dispone de las estructuras de
control típicas de los lenguajes de alto nivel pero, a su vez, dispone de sentencias y
Autor: José C. Riquelme (Universidad de Sevilla)
operadores que permiten un control a muy bajo nivel, esto es, cercano a la máquina. La
compilación de un programa C se realiza en varias fases que normalmente son
automatizadas y ocultadas por el IDE:
1. Preprocesado consistente en modificar el código fuente en C según una serie de
instrucciones (denominadas directivas de preprocesado) simplificando de esta
forma el trabajo del compilador.
2. Compilación que genera el código objeto a partir del código ya preprocesado.
3. Enlazado que une los códigos objeto de los distintos módulos y bibliotecas
externas (como las bibliotecas del sistema) para generar el programa ejecutable
final.
El fichero fuente de un programa en C tiene la extensión .c, el código objeto después de
la fase de compilación mantiene el mismo nombre y la extensión .obj, finalmente el
fichero ejecutable después de la fase de enlazado tiene la extensión .exe.
2.2 Ventajas del lenguaje C.







Aunque la portabilidad es un estándar en los actuales lenguajes de
programación, el C fue uno de los primeros en la portabilidad de los ficheros
fuente. Quiere esto decir que un programa desarrollado en una determinada
máquina y sistema operativo podrá ser ejecutado en otra, con mínimas
modificaciones y una simple recompilación. Esto fue conseguido gracias a la
adopción en 1989 del conocido como ANSI C, también llamado C estándar. De
esta manera, ANSI C está soportado hoy en día por casi la totalidad de los
compiladores y cualquier programa escrito sólo en C estándar funciona (una vez
compilado) correctamente en cualquier plataforma que disponga de una
implementación de C compatible.
Un núcleo del lenguaje simple, con funcionalidades añadidas importantes, como
funciones matemáticas y de manejo de archivos, proporcionadas por bibliotecas.
Es un lenguaje muy flexible que permite programar con múltiples estilos. Ésta es
una cualidad que también puede ser un problema cuando se está aprendiendo a
programar.
Un sistema de tipos que impide operaciones sin sentido.
Acceso a memoria de bajo nivel mediante el uso de punteros.
Un conjunto reducido de palabras clave.
Permite definir tipos de datos como vectores y estructuras que permite
manipular como un todo un conjunto de datos.
2.3 Otros conceptos relacionados.
Ingeniería del Software. El desarrollo de aplicaciones software con las restricciones
habituales de todo proceso productivo, esto es, con el menor esfuerzo y coste y la mejor
calidad posible, requiere de una metodología propia. La ingeniería del software es la
disciplina que trata de dar un enfoque sistemático y disciplinado al diseño, desarrollo y
mantenimiento del software. Desde este punto de vista, en la actualidad podemos
afirmar que la programación de ordenadores no es un arte, a pesar de que durante años
la mala interpretación del título de la obra de DE Knuth “The Art of Computer
Programming” parecía decir lo contrario. La programación de ordenadores debe ser
Tema 1. Conceptos de programación
entonces contemplada como un proceso ingenieril, base de la ingeniería del software y
pilar fundamental de numerosos problemas que resuelven las distintas ingenierías.
Algoritmo. Según la RAE un algoritmo es un conjunto ordenado y finito de
operaciones que permite hallar la solución de un problema. Ejemplos cotidianos de
algoritmos suelen ser las recetas de cocina o las instrucciones para montar un mueble.
En la programación de ordenadores se suele entender por algoritmo una lista de
instrucciones que se ejecutan secuencialmente, que normalmente recibe de entrada un
conjunto de datos y después de realizar operaciones aritméticas o lógicas con ellos
produce un determinado resultado de salida. Un algoritmo suele representarse en
programación mediante un diagrama de flujo o un seudocódigo.
Diagrama de flujo. Es una representación gráfica de las sentencias de un algoritmo
donde cada tipo de sentencia tiene una forma determinada: rombo (bifurcación
condicional), rectángulo (asignación), cuadrilátero (lectura o escritura), etc. Las líneas
que unen estas figuras representan la secuencia u orden en que se deben ejecutar. Los
diagramas de flujo fueron muy usados en los años 70 y 80 del siglo pasado, pero ahora
se consideran obsoletos porque no son apropiados para representar fácilmente la
división de un problema en módulos ni para representar adecuadamente tipos de datos
estructurados. El siguiente diagrama de flujo calcula el factorial de un número:
Leer n
i=1
f=1
NO
i≤n
SÍ
f=f*i
i=i+1
Escribir n y f
Seudocódigo. Es un conjunto de instrucciones que en un lenguaje natural intentan
describir un algoritmo. El lenguaje empleado para escribir el seudocódigo de un
algoritmo suele ser una variante unificada de las principales sentencias o estructuras de
control usadas por la mayoría de los lenguajes de programación. De esta manera un
seudocódigo se aproxima bastante a la versión final de un programa codificado pero sin
Autor: José C. Riquelme (Universidad de Sevilla)
tener en cuenta las exigencias sintácticas de un lenguaje de programación. Por ejemplo
el seudocódigo del problema anterior sería:
Inicio
Leer n
Hacer i igual a 1
Hacer f igual a 1
Mientras i sea menor o igual a n
Hacer f igual a f × i
Hacer i igual a i + 1
FinMientras
Escribir el factorial de n es f
Fin
Código fuente. Es el conjunto de sentencias escritas en un lenguaje de programación
que una vez compiladas permiten al ejecutarse resolver un problema. Por ejemplo, un
programa en C que resuelve el problema anterior es el siguiente:
#include <stdio.h>
void main(void){
int i, f, n;
scanf("%d",&n);
i=1;
f=1;
while (i<=n){
f=f*i;
i++;
}
printf("el factorial de %d es %d\n",n,f);
}
Fundamentos de Programación. En esta asignatura se sentarán las bases de la
programación de ordenadores, siguiendo un conjunto de reglas que convierten la
construcción de software en un proceso ingenieril, donde no sólo es importante que el
código funcione correctamente, sino que además esté bien hecho, esto es, sea fácil de
diseñar, programar y mantener. Para ello en esta asignatura insistiremos desde el
principio en tres cuestiones que consideramos básicas:


La primera es la obligación de estructurar el código en trozos más pequeños que
resuelvan un subproblema concreto. Estos trozos de código han recibido a lo
largo de los años distintos nombres: módulos, subrutinas, procedimientos,
funciones, etc. Un módulo principal invocará la ejecución de los otros módulos.
El módulo principal se comunicará con los módulos mediante el uso de
parámetros. En C estos módulos reciben el nombre de funciones. El módulo
principal de nuestros programas en C entonces será habitualmente una sucesión
de llamadas a funciones.
La segunda cuestión es la necesidad de definir los tipos de datos antes de usarlo.
Como se ha dicho anteriormente el C es un lenguaje que da mucha libertad al
programador y a pesar de ser un lenguaje fuertemente tipificado permite ciertas
licencias en su uso que no se permitirán en esta asignatura. Los tipos
Tema 1. Conceptos de programación

estructurados, vectores (array) o registros (struct) deben definirse como tipos
siempre que se vayan a usar.
No se usarán las características del C que son de bajo nivel. Esto es, no se hará
uso de cuestiones como la aritmética de punteros, ni se accederá a los vectores a
partir de sus direcciones de memoria. Únicamente en los casos estrictamente
necesarios, esto es, el paso de argumentos de entrada/salida en las funciones se
hará uso del concepto de puntero.
Modularización. En las líneas anteriores se ha resuelto el problema de obtener el
factorial de un número mediante diagrama de flujo, seudocódigo y código en C.
Imaginemos que quisiéramos calcular el factorial de varios números. Por ejemplo, para
calcular el valor de un número combinatorio, es necesario calcular tres factoriales:
( )
(
)
¿Es adecuada por tanto la solución que se ha hecho antes? La respuesta es que no,
porque en su construcción se ha ignorado la primera de las reglas que hemos enunciado
para esta asignatura. La modularización de un programa tiene numerosas ventajas:







Reduce la complejidad del problema que se quiere resolver dividiéndolo en
problemas más sencillos.
Elimina el código duplicado, favoreciendo la reutilización de código y
ahorrando en el tiempo de desarrollo de las aplicaciones.
Limita los efectos de los cambios al módulo que se desea modificar.
Oculta detalles de implementación en problemas complejos.
Facilita la depuración y prueba de las aplicaciones.
Mejora la legibilidad del código.
Facilita la portabilidad del código.
Por todo lo anterior, la mejor forma de resolver el problema de dado un número calcular
su factorial es definir un módulo o subprograma (función en C) que reciba como
argumento el entero n y devuelva el valor de su factorial. El concepto de función en C
es el mismo que el usado en matemáticas. Por ejemplo, la función f(x)=2*x+3, contiene
el concepto de que se recibe una entrada x y se devuelve un valor calculado como su
doble más tres. Por tanto, para esta asignatura la única solución válida en C para
calcular el factorial de un número sería:
#include <stdio.h>
int factorial(int);
void main(void){
int n, fac;
scanf("%d",&n);
fac=factorial(n);
printf("el factorial de %d es %d\n",n,fac);
}
int factorial (int m){
Autor: José C. Riquelme (Universidad de Sevilla)
int i, f;
i=1;
f=1;
while (i<=m){
f=f*i;
i++;
}
return f;
}
3. Ejercicios.
Intente escribir un seudocódigo que intente resolver los siguientes problemas. Para cada
problema identifique claramente qué debe recibir como entrada y qué debe devolver
cómo salida.
1.
2.
3.
4.
5.
6.
7.
8.
9.
Obtenga la suma de los n primeros números naturales.
Dados dos números devolver el menor de los dos
Dados dos números devolver el mayor de los dos
Obtenga la suma de los números que hay entre dos números naturales, ambos
incluidos.
Dados dos números naturales a y b halle la potencia de a elevado a b.
Dados tres valores con los coeficientes de una ecuación de segundo grado,
obtenga según los casos sus dos soluciones o raíces, una sola raíz o indique que
no hay solución real.
Lea un número indeterminado de números hasta que lea uno negativo y calcule
la media de los valores leídos.
Lea un número indeterminado de números hasta que lea uno negativo y calcule
el máximo.
Lea un número indeterminado de números hasta que lea uno negativo y calcule
el mínimo.
Descargar