TEMA 1 : Conceptos básicos
1.0 Introducción
En este segundo tema se describirá la estructura básica de
un programa en lenguaje C así como la forma de visualizar distintos
tipos de datos en pantalla. Se introducirán los conceptos de tipos
de datos básicos y su utilidad.
1.1 El programa HOLA MUNDO
Este programa se ha convertido en un clásico dentro de los
libros de programación. Simplemente muestra en pantalla el mensaje
HOLA MUNDO, esto que puede parecer muy tonto es algo fundamental
puesto que si no sabemos imprimir mensajes ó datos en la pantalla
difícilmente nuestro programa se podrá comunicar con el usuario que
lo utilice.
Mostraremos el programa y a continuación describiremos cada
una de las instrucciones que lo forman.
/* Programa : HOLA MUNDO */
#include <stdio.h>
main()
{
printf ("\nHola mundo");
}
Como podemos observar se trata de un programa muy sencillo.
La primera línea es lo que se conoce como un comentario, un mensaje
que el programa añade al código del programa para explicar o aclarar
su funcionamiento o el de una parte de él. Los comentarios se pueden
situar en cualquier parte de nuestro código y se considerará como
comentarios cualquier mensaje que se encuentre entre los caracteres
/* y */.
Los "/*" y "*/" no son caracteres, sino símbolos o banderas.
La siguiente línea es lo que se conoce como directiva del
preprocesador, todos los compiladores de C disponen de un
preprocesador, un programa que examina el código antes de compilarlo
y que permite modificarlo de cara al compilador en distintos
sentidos. En temas posteriores trataremos en profundidad estas
directivas del preprocesador, pero para el desarrollo de los temas
anteriores a este debemos conocer al menos la directiva #include.
Las directivas se caracterizan por comenzar con el carácter # y se
deben incluir al comienzo de la línea aunque es probable que esto
dependa de la implementación del compilador con el que estemos
trabajando. La directiva include permite añadir a nuestro código
algún fichero de texto, de tal forma que la directiva es sustituida
por el texto que contiene el fichero indicado. En general los
ficheros que acompañan a esta directiva son ficheros .H (Header -
Cabecera), en los que se incluyen definiciones de funciones que
deseamos utilizar en nuestros programas, constantes o tipos
complejos de datos.
La librería stdio.h (STandarD Input/Output) con tiene las
funciones estándar de entrada salida, y en ella se encuentra la
función printf que utilizamos en nuestro programa. Como se observa
en el código el nombre de la función a incluir debe ir entre los
caracteres <...>. A medida que vayan surgiendo iremos indicando las
funciones estándar que deberían incorporar todos los compiladores C
y cual es su fichero de definición .H.
En la siguiente línea nos encontramos con main(). Esto
indica que aquí comienza nuestro programa, en realidad estamos
definiendo una función (esto se indica con los paréntesis al final
de la línea) pero esto lo discutiremos en temas posteriores. La
función main (principal en inglés) siempre debe existir y contendrá
el programa principal.
Finalmente nos encontramos el programa principal, una
sentencia printf entre llaves ({, }). Las llaves en C representan
bloques, y encierran un conjunto de sentencias o instrucciones (lo
que el computador ejecutará), considerando todas ellas como una
sola, permitiendo una definición homogénea de los distintos bloques
que constituyen el programa. En nuestro caso tenemos un sólo bloque
que no es ni más ni menos que el programa principal, que en nuestro
caso está compuesto por una sola sentencia (la línea que contiene el
printf). Como se observa en el código las sentencias en C deben
terminar con un punto y coma (;), #include <stdio.h> y main() no son
sentencias, dan información sobre la estructura del programa, y por
tanto no finalizan con un punto y coma.
NOTA: La razón de que la línea "main()" no tenga un punto y
coma ";" al final es debido a que la sentencia en sí termina al
cerrar el corchete, no en que dicha línea proporcione información
sobre la estructura del programa. De hecho, si el "main()"
constituyese una línea de prototipo tendría un ";" al final.
La función printf permite visualizar datos formateados en
pantalla, es decir, permite indicar un formato como si de un impreso
o formulario se tratase indicando donde se deben visualizar cada
uno. En el siguiente tema cuando se introduzcan los tipos básicos de
datos se comprenderá mejor ésto. Por ahora sólo nos interesa conocer
que printf visualiza mensajes en pantalla.
El mensaje debe ir entre comillas dobles (") y dentro de las
comillas se puede mostrar cualquier secuencia de caracteres. El
formato de esta función para este segundo tema será:
printf ("mensaje");
En el siguiente tema, cuando expliquemos en profundidad la
instrucción, ampliaremos esta definición.
En nuestro programa observamos que el mensaje de texto que
visualiza la instrucción printf comienza con los caracteres \n.
Estos caracteres nos permiten algunas funciones especiales para
controlar la forma de visualizar los mensajes, la más utilizada en
\n que significa nueva línea, así nuestra sentencia printf ("\nHOLA
MUNDO"); moverá el cursor (la posición de la pantalla donde
actualmente se visualizan los datos) a una nueva línea situándolo a
la izquierda de la pantalla y visualizará el mensaje HOLA MUNDO.
Para finalizar con este punto se indicará las secuencias
antecedidas por \ que se pueden incluir en una instrucción printf:
+-------------------------+------+
| Nueva línea | \n |
| Tabulador horizontal | \t |
| Tabulador vertical | \v |
| Backspace (<-) | \b |
| Retorno de carro | \r |
| Avance de página | \f |
| Pitido (alerta) | \a |
| Caracter \ | \\ |
| Caracter ? | \? |
| Caracter ' | \' |
| Caracter " | \" |
| Número Octal (ooo) | \ooo |
| Número Hexadecimal (hh) | \xhh |
+-------------------------+------+
Algunos comentarios sobre estos códigos. En primer lugar el
primer grupo (hasta carácter \), eran utilizados para mover el
cursor en terminales. Los terminales podían ser una pantalla o una
impresora, esta es la razón por la que nos encontramos cosas como
avance de página o retorno de carro. Los caracteres \ ? ' " son
especiales puesto que se utilizan dentro del mensaje a visualizar
para indicar como se visualiza, o sea, si escribimos \ el compilador
buscará el siguiente carácter y si es alguno de los anteriores los
visualiza sino corresponde con ninguno simplemente lo ignora, con lo
cual no podríamos visualizar el carácter \. Otro tanto sucede con
las comillas puesto que para C, las comillas representan una cadena
de caracteres, si escribimos " en nuestro mensaje se considerará que
éste termina ahí con lo que lo que se encuentre después no tendrá
sentido para el compilador.
Por último Número octal y Número hexadecimal nos permite
introducir directamente el código numérico en octal o hexadecimal
del carácter que deseemos visualizar, dependiendo del que esté
activo en nuestro computador. En general el código utilizado para
representar internamente los caracteres por los computadores es el
código ASCII (American Standard Code for Information Interchange).
En este segundo tema hemos aprendido a escribir programas
que visualicen en pantalla mensajes utilizando la función estándar
de la librería stdio. Antes de terminar unos breves comentarios. El
lenguaje C diferencia entre mayúsculas y minúsculas con lo cual
main, MAIN, MaIn, serían identificadores distintos para el
compilador, en general en C se suele escribir todo en minúsculas a
excepción de los mensajes a visualizar (cuyo uso depende del
programador) y de las constantes, esto no tiene por que hacerse así
pero digamos que se trata de una tradición de la programación en C.
Las separaciones entre líneas también son arbitrarias y su única
función es facilitar la legibilidad del código, sirviendo de
separadores entre fragmentos de programa relacionados entre sí. Y
esto es todo por ahora.
1.2 Tipos de datos básicos del C
La mayoría de los programas realizan algo útil y
generalmente para ello es necesario trabajar con grandes cantidades
de datos, si queremos realizar un programa que nos calcule un
sistema de ecuaciones tenemos que indicar cuales son las ecuaciones
para que el programa las resuelva. Por tanto un programa estará
constituido por una serie de datos y una serie de sentencias o
instrucciones que le dicen lo que tiene que hacer con esos datos.
Los lenguajes de programación disponen de una serie de tipos de
datos básicos, y proporcionan herramientas para crear estructuras a
medida que faciliten el acceso a la información. Así en nuestro caso
ficticio de resolver un sistema de ecuaciones podemos almacenar los
coeficientes de cada ecuación con lo que utilizaríamos como tipo de
dato los números, si planteásemos el problema desde un punto de
vista matricial nos interesaría tener un tipo de datos matriz y lo
ideal sería tener un tipo de datos ecuación. En este apartado
describiremos los tipos básicos que proporciona el lenguaje C y
dejaremos para temas posteriores la declaración de tipos complejos.
Estos tipos básicos son los siguientes:
+--------+---------------------------------------+
| int | Representa números enteros. |
| float | Representa números decimales. |
| double | Representa números decimales de mayor |
| | precisión. |
| char | Representa caracteres. |
+--------+---------------------------------------+
Aunque el tipo char represente caracteres internamente para
el computador no es más que un número comprendido entre 0 y 255 que
identifica un caracter dentro de el código especificado para tal
propósito en el sistema en el que nos encontremos trabajando. El
código más utilizado para este tipo de representación es el ASCII ya
mencionado anteriormente.
NOTA: Según la máquina, el compilador empleado y las opciones
de compilación activas, "char" puede interpretarse con signo o sin
signo. Esto es, de -128 a 127 o desde 0 a 255. Si se requiere una
representación que no dependa de las opciones del compilador, etc.,
se puede poner "signed char" o "unsigned char", según el caso.
Como decíamos antes el ordenador debe de disponer de los
datos necesarios para resolver el problema para el que lo queramos
programar. Difícilmente se podría resolver un sistema de ecuaciones
si no se dispone de éstas. Para ello podemos definir variables. Las
variables almacenan valores de un tipo especificado y en ellas
almacenamos los datos de nuestro problema, se denominan variables
por que su valor puede cambiar a lo largo del programa. Para
referenciar una variable especificada es necesario que la podamos
identificar para ello se utiliza un nombre o identificador que no es
más que una secuencia de caracteres, esta secuencia no puede
contener caracteres españoles (acentos y eñes), ni caracteres que
tengan alguna función especial en el C como por ejemplo los
caracteres que representan operaciones matemáticas +, -, etc...,
tampoco pueden contener espacios por lo que se suele utilizar el
carácter subrayado (_) si el identificador que deseamos asignarle a
nuestra variable está formado por varias palabras, pero en general
con los caracteres y números tenemos suficiente para dar nombres
autoexplicativos, aunque los números no pueden comenzar el nombre de
una variable. Las variables se suelen escribir con letra minúscula
aunque no es necesario y es aconsejable que los nombres sean auto
explicativos para que resulte más sencillo leer el programa (es
mejor llamar resultado a una variable que x).
Las variables se declaran indicando el tipo que van a tener
seguido de su identificador y terminando la línea con un punto y
coma. Algunos ejemplos:
int numero; /* número no sería un nombre válido */
float mi_variable;
char letra;
Si necesitamos declarar varias variables de un mismo tipo se
pueden incluir en la misma línea todos los nombres que deseemos
separándolos por una coma:
int numero1,numero2,numero3;
float coordenada_x,coordenada_y;
El compilador tiene que conocer las variables que va ha
utilizar cada bloque para reservarles sitio, por ello las variables
se suelen declarar al principio de cada bloque. Puesto que aún no
sabemos como definir funciones nuestro programa sólo dispone de un
bloque (el main()) con lo que nuestras variables deben de declararse
al comienzo del main() dentro del bloque, es decir, inmediatamente a
continuación de la llave abierta ({). Un ejemplo:
NOTA: Aunque el párrafo anterior da a entender que se puede
declarar una variable en cualquier momento, el estándar ANSI C
obliga a realizar las declaraciones al principio de cada bloque. En
el caso se variables globales la sintaxis es más flexible, para
poder utilizar el "Scope" en nuestro provecho.
main()
{
int numero;
numero =20;
}
Podemos también declarar variables fuera del bloque main().
Estas variables se conocen como variables globales y cualquier
función puede acceder a ellas, como sólo tenemos una función (main)
en este caso nos daría igual declarar las variables dentro o fuera
de main.
De poco nos servirían estos datos numéricos si no pudiésemos
realizar operaciones con ellos, el lenguaje C permite realizar las
operaciones básicas con estas variables de tipo numérico, estas son:
+---+---------------------------------------------+
| + | para indicar suma |
| - | para indicar resta |
| * | para indicar producto |
| / | para indicar división |
| % | para indicar módulo (resto división entera) |
+---+---------------------------------------------+
Podemos combinar estas operaciones en la forma que nos
plazca con variables o constantes (podemos operar variables con
números fijos) y utilizar los paréntesis, caracteres ( y ) para
indicar precedencia de las operaciones como lo haríamos en una
expresión matemática normal. En principio sólo podemos realizar
operaciones con variables que sean del mismo tipo, aunque en general
podemos operar los tipos float y double con tipos int o incluso
char, en principio no podríamos almacenar un valor float (un número
real) en una variable int (entera), para ello tendríamos que
convertir ese número real en entero de alguna forma. Podemos
convertir tipos básicos utilizando la facilidad del C conocida como
cast. Esta facilidad simplemente consiste en indicar antes de una
variable o constante el tipo al que lo deseamos convertir entre
paréntesis y el compilador se encargará del resto. Un ejemplo :
NOTA: El C también define la conversión automática de tipos.
float a;
int b;
b=30;
a=(float)b;
Para ejemplificar todo esto vamos a realizar un programa que
nos calcule el espacio recorrido por un móvil con velocidad uniforme
durante un tiempo determinado. El programa sería algo así:
#include <stdio.h>
main()
{
float e,v,t;
v = 30; /* Velocidad del móvil en Km/h */
t = 5; /* Tiempo durante el cual se mueve */
e = v*t;
printf ("\nVelocidad : %f\nTiempo : %f",v,t);
printf ("\nEspacio recorrido : %f",e);
}
Este programa calcula el espacio recorrido por un móvil en
movimiento uniforme a una velocidad indicada por la variable v,
durante un tiempo indicado por la variable t. Lo más interesante de
este programa es que hemos utilizado la función printf para
visualizar valores de variables.
Como decíamos más arriba la función printf permite
visualizar mensajes formateados, es decir, en la cadena de
caracteres entre comillas dentro del paréntesis nos indica la forma
en la que se visualizarán los datos. Ya hablamos de los caracteres
especiales como \n, ahora nos ocuparemos de la visualización de las
variables.
Cuando deseamos visualizar una variable debemos indicarlo en
la cadena de formateo (la secuencia de caracteres entre comillas)
mediante el caracter % seguido de un caracter que nos indica el tipo
de dato a visualizar. Estos tipos son los siguiente:
+-----+------------------------------------------------+
| d,i | Entero en notación decimal con signo. |
| o | Entero notación octal sin signo. |
| x,X | Entero en notación hexadecimal sin signo. |
| u | Entero en notación decimal sin signo. |
| c | Entero como caracter simple. |
| s | Cadena de caracteres. |
| f | Tipo double (ó float) de la forma [-]mmmm.ddd. |
| e,E | Tipo double (ó float) en notación científica o |
| | exponencial [-]m.dddde+-xx ó [-]m.ddddE+-xx. |
| p | Tipo puntero. |
+-----+------------------------------------------------+
Podemos así mismo indicar el número de cifras a visualizar,
intercalando entre el % y la letra que identifica el tipo de dato un
número. Si indicamos dos números separados por un punto, el primer
número indica el número total de caracteres a visualizar y el
segundo el número de cifras decimales que queremos que se muestren,
obviamente este formato sólo se utilizará con tipo float o double.
Algunos ejemplos:
printf ("%f",numero);
Visualiza un número real en el formato normal, parte entera
y parte decimal separadas por un punto.
printf ("%5.2f",numero);
Visualiza un número entero en el mismo formato que la
anterior, pero sólo visualizando 5 cifras y siendo dos de ellas
reservadas para la parte decimal.
Hasta ahora hemos visto como decir a la función printf el
formato en el que debe visualizar los datos, pero no le hemos dicho
que datos debe visualizar. Lo que se escribirá en el lugar indicado
por el % está especificado a continuación de la cadena de formateo
entre comillas, separando cada una de ellas por comas. El primer %
coincide con el primer parámetro después de las comillas, el segundo
con el segundo y así sucesivamente. De esta forma un programa como
este:
#include <stdio.h>
main()
{
int i;
float a,b;
i = 10;
a = 30.456;
b = 678.12;
printf ("\nvar1:%d var2:%6.2f var3:%6.1f",i,a,b);
}
tendrá como salida:
var1:10 var2:30.46 var3:678,1
Como se puede observar en el ejemplo si la precisión
especificada en la cadena de formateo es menor que la real del
número, la función printf aproxima a la precisión especificada.
1.3 Entrada de datos por teclado
El programa anterior para el cálculo de el espacio funciona
correctamente, pero cada vez que deseemos calcular un nuevo espacio
debemos dar valores a las variables v y t y recompilar nuestro
programa. Sería estupendo poder leer por teclado los datos de la
velocidad y del tiempo y así permitir a nuestro programa trabajar
con cualquier valor de velocidad y tiempo. Aquí es donde realmente
se comprende de donde viene el nombre de variables.
Para leer los datos por teclado se utiliza la función scanf
cuya definición se encuentra también en el fichero stdio.h. El
formato es idéntico al de printf utilizando una cadena de formateo
con los caracteres % y la letra que indica el tipo, ahora del dato
que vamos a leer, seguido de la variable en la que deseamos que se
lea antecedida por el carácter &. Nuestro programa del móvil se
convierte ahora en:
#include <stdio.h>
main()
{
float v,t,e;
printf ("\nDime la velocidad de el móvil:");
scanf ("%f",&v);
printf ("\Dime el tiempo :");
scanf ("%f",&t);
e = v*t;
printf ("\nUn móvil desplazándose a %5.2f Km/h durante
%5.2f horas, recorre una distancia de %5.2f Km",v,t,e);
}
Ahora cada vez que el programa se ejecute nos pedirá que
introduzcamos los valores de la velocidad y el tiempo y nos
proporcionará el espacio que recorreríamos, evitando de esta forma
la necesidad de recompilar el programa cada vez que deseemos
realizar un nuevo cálculo.