Está en la página 1de 36

FUNDAMENTOS DE PROGRAMACIN

Curso 2012/13
Versin: 1.0.4

Tema 12. Introduccin al Lenguaje C


Autor: Miguel Toro Bonilla, Jos C. Riquelme
Revisin: Francisco Javier Ferrer Troyano
Tiempo estimado: 10 horas

1.

Introduccin ................................................................................................................................................ 1

2.

Elementos en C............................................................................................................................................ 2
2.1.

Estructura de un programa en C......................................................................................................... 2

2.2.

Tipos, declaraciones, operadores, expresiones.................................................................................. 7

2.3.

Punteros ............................................................................................................................................ 12

3.

Bloques y sentencias de control ............................................................................................................... 13

4.

Funciones para trabajar con la entrada y salida estndar ...................................................................... 14

5.

Tablas, cadenas de caracteres y estructuras............................................................................................ 17


5.1.

Tablas (arrays) .................................................................................................................................. 17

5.2.

Cadenas de caracteres ...................................................................................................................... 19

5.3.

Estructuras y punteros a estructuras ............................................................................................... 21

6.

Funciones y procedimientos: paso de parmetros .................................................................................. 22

7.

Funciones de tratamiento de ficheros de texto....................................................................................... 25

8.

Ejercicios propuestos ................................................................................................................................ 30

1. Introduccin
El lenguaje C es un lenguaje de programacin creado en 1972 por Dennis M. Ritchie en los Laboratorios Bell.
Es un lenguaje cuyo origen es la implementacin del sistema operativo Unix. C es valorado por la eficiencia
del cdigo que produce y es el lenguaje de programacin ms popular para crear software de sistemas,
aunque tambin se utiliza para crear aplicaciones. Se trata de un lenguaje de medio nivel pero con muchas
caractersticas de bajo nivel. Dispone de las estructuras de control tpicas de los lenguajes de alto nivel pero,
a su vez, dispone de sentencias y operadores que permiten un control a muy bajo nivel, esto es, cercano a la
mquina. La compilacin de un programa C se realiza en varias fases que normalmente son automatizadas y
ocultadas por el IDE:
1. Precompilacin, consistente en modificar el cdigo fuente en C segn una serie de instrucciones
(denominadas directivas de precompilacin), simplificando de esta forma el trabajo del compilador.
Algunas de las tareas de las que se encarga el precompilador son la inclusin de ficheros y la
expansin de macros.
2. Compilacin, que genera el cdigo objeto a partir del cdigo ya preprocesado.

Fundamentos de Programacin

3. Enlazado, que une los cdigos objeto de los distintos mdulos y bibliotecas externas (como las
bibliotecas del sistema) para generar el programa ejecutable final.
El fichero fuente de un programa en C tiene la extensin .c, el cdigo objeto despus de la fase de
compilacin mantiene el mismo nombre y la extensin .obj y, finalmente, el fichero ejecutable despus de la
fase de enlazado tiene la extensin .exe. La Figura 1 muestra un esquema de las fases del proceso de
compilacin en C y los archivos que se generan en cada una de ellas. Hay que mencionar que la fase de
precompilacin no genera ningn archivo fsicamente en disco, y que el archivo con extensin .c que
aparece en la figura no es ms que una modificacin del archivo .c que se hace en memoria.

Figura 1. Fases de compilacin en C y archivos generados en el proceso.

C es un lenguaje no orientado a objetos, por lo que las tcnicas y el estilo de programacin son muy
diferentes a las que hemos usado en Java. En C seguimos una filosofa de programacin denominada
programacin estructurada. Introduciremos los elementos de C, y cuando sea necesario, veremos los
elementos que se comparten con Java y los que no. En general decimos que C es un lenguaje de ms bajo
nivel que Java.

2. Elementos en C
2.1. Estructura de un programa en C
El cdigo de un programa en C se compone de un conjunto de ficheros con extensiones .h y .c. Los ficheros .h
contienen declaraciones y definiciones de tipos mientras que los ficheros .c contienen el cdigo de los
mtodos (ahora llamados funciones y procedimientos).
La estructura de un programa en C no es nica, habiendo cierta libertad; sin embargo vamos a considerar
una nica estructura posible en la asignatura. Aunque el cdigo se suele estructurar en ms de un fichero, de

12. Introduccin al Lenguaje C

momento vamos a ver la estructura de un programa en C en un nico fichero fuente .c que ser de la forma
siguiente:
Importaciones
Definicin de constantes y macros
Definicin de tipos
Declaracin de funciones y procedimientos
void main () { // Definicin de la funcin principal
declaracin de variables;
instrucciones;
}
Definicin de las funciones declaradas anteriormente

Cuando un programa en C tiene pocas funciones (tres o cuatro) suele ponerse todo el cdigo en un solo
fichero .c. Sin embargo, cuando el programa se hace ms complejo, suele organizarse el cdigo en varios
ficheros. La organizacin mnima es un fichero de cabecera o .h, que normalmente tiene todas las
declaraciones de constantes, tipos y funciones; un fichero .c con nicamente el programa principal, y otro
fichero .c con la definicin o cdigo de las funciones. Dependiendo de la complejidad del programa y de las
relaciones entre funciones, se puede organizar el cdigo con varios ficheros .h y varios .c con las funciones
agrupadas por su funcionalidad.
Importaciones
En C es habitual usar un conjunto de funciones ya predefinidas por el compilador y situadas en libreras.
Estas funciones estn declaradas en ficheros que tienen la extensin .h (de header o fichero de cabecera). En
la declaracin de importaciones el programador indica al compilador qu libreras va a necesitar. Hay
numerosas libreras de funciones y adems cada programador y cada entorno puede aadir funciones
propias.
Tres ejemplos de archivos de cabecera muy utilizados son stdio.h, math.h y string.h. El archivo de cabecera
stdio.h (standard input/output) contiene declaraciones de funciones de lectura (tanto desde teclado como
desde fichero) y de escritura (tanto en pantalla como en fichero). El archivo de cabecera math.h contiene
declaraciones de funciones matemticas (raz cuadrada, potencia, trigonomtricas, etc.) y, finalmente,
string.h contiene declaraciones de funciones para tratamiento de cadenas de caracteres.
Cada declaracin de importacin debe ir en una sola lnea y comienza con #include. Cada lnea de este tipo
indica al preprocesador que incluya en ese punto el fichero que le sigue. Si el nombre de fichero est entre
mayor y menor (< >), el archivo de cabecera declara funciones de una librera estndar de C o una librera
proporcionada por el entorno de programacin. En este caso, el compilador busca el cdigo de las funciones
declaradas en estos archivos de cabecera en una ruta definida por el entorno. Si el fichero est entre , el
archivo de cabecera declara funciones implementadas por el programador, y entonces el compilador busca
el cdigo de las funciones declaradas en la ubicacin del cdigo fuente del programador. Una forma genrica
de definir estos dos tipos de importaciones es la siguiente:
#include <fichero1.h>
#include fichero2.h

Ejemplos concretos de importaciones son los siguientes:

Fundamentos de Programacin

#include <stdio.h>
#include <math.h>
#include punto.h

Estas lneas son similares a las declaraciones import de JAVA, y en ellas se indica que en el fichero se usan las
declaraciones de algunas funciones de entrada/salida (stdio.h), de algunas funciones matemticas (math.h),
y algunas funciones definidas por el programador relacionadas con un tipo punto (punto.h).
Definicin de constantes
Una constante es un identificador que se asocia a un valor que no cambia durante toda la ejecucin del
programa. Habitualmente se usa para una mejor documentacin del programa o para hacer ms fcil su
mantenimiento y cambio. La forma habitual de declarar una constante es una lnea que comienza por la
declaracin #define. Con esta lnea se indica al preprocesador que en lo que sigue sustituya el nombre de la
constante por su valor. Hay dos tipos segn el nombre vaya seguido de parntesis o no.
#define identificador1 expresion1

Ejemplos:
#define
#define
#define
#define

PI 3.14159
MAXIMO 999
ULTIMA_LETRA 'Z'
MENSAJE "Introduzca su edad: "

Ntese que entre el identificador y el valor NO HAY carcter =, que la sentencia NO termina en punto y coma
y que la constante no necesita declararse de un determinado tipo, sino que el valor determina el tipo. Las
constantes es usual escribirlas con letras maysculas.
Declaracin de tipos
El C proporciona un conjunto de tipos bsicos ya definidos (int, float, char, etc.) y tambin permite que el
programador defina sus propios tipos. Los tipos ms habituales que se definen en C son los tipos
enumerados, los tipos tabla o array y los tipos registro o struct (apartado 5).
Con la clusula typedef se pueden declarar nuevos tipos. La sintaxis de la clusula typedef es la siguiente:
typedef especificacin_tipo nombre_tipo;

Ejemplos:
typedef enum {R, G, B} Color;
typedef enum {falso, cierto} boolean;

En el ejemplo anterior se ha declarado el tipo Color como un enumerado que puede tomar tres posibles
valores (R, G y B), y el tipo boolean como otro enumerado que puede tomar los valores falso y cierto. Hay
que tener en cuenta que, realmente, con la sentencia typedef no se crean nuevos tipos como tales, sino que
se crean sinnimos para tipos que ya existen o nombres para tipos que podran especificarse de otra forma.
El usar typedef nos permite utilizar estos nombres a la hora de declarar variables. Por ejemplo, en las dos

12. Introduccin al Lenguaje C

siguientes lneas se crean una variable de tipo Color llamada c, y otra de tipo boolean llamada a. Adems,
esta ltima se inicializa con el valor cierto.
Color c;
boolean a = cierto;

Declaracin de funciones
Las funciones en C deben declararse mediante su prototipo. ste debe escribirse antes de su invocacin por
el programa principal. El prototipo de una funcin consiste en definir cul va a ser su nombre, qu tipos de
datos tiene como entrada (argumentos) y qu tipo de dato devuelve.
Para explicar estos conceptos hay que introducir los conceptos de valor de retorno y de argumentos. Toda
funcin bien definida debe recibir uno o varios valores a partir de los cuales calcular un valor de salida. El
ejemplo ms cercano son las funciones matemticas, como la potencia, que puede recibir dos argumentos,
uno real (base) y otro entero (exponente) y devuelve un real con el resultado de la base elevada al
exponente. Por tanto, los argumentos son base y exponente y el resultado o valor de retorno la potencia.
Para declarar una funcin basta con darle un nombre y declarar los tipos de los argumentos y del valor de
retorno de sta usando la siguiente sintaxis:
tipo_retorno nombre_funcion (tipo_arg1, tipo_arg2,, tipo_argn);

Ejemplos de declaracin de prototipos de funciones son:


float potencia (float,int);
long factorial(int);
char aMayuscula(char);
int mcd(int,int);
void mostrarColor(Color);

En la primera lnea se define el prototipo de una funcin llamada potencia, que tiene dos argumentos, uno
de tipo float, y otro de tipo int, y cuyo resultado es de tipo float. Luego se declara una funcin factorial que
tiene un argumento de tipo int, y cuyo resultado es de tipo long. Le sigue una funcin aMayuscula que tiene
un argumento de tipo char y un resultado de tipo char. A continuacin se declara una funcin mcd con dos
argumentos de tipo int y con resultado de tipo int. Por ltimo, mostrarColor es una funcin que tiene un
argumento de tipo Color, y no devuelve nada (es de tipo void).
Ntese que un prototipo siempre termina en el separador punto y coma (;) y que los tipos de los argumentos
estn entre parntesis y separados por comas.
Funcin principal
Todo programa en C debe tener una funcin principal que debe denominarse main. Aunque puede tener
distintos formatos de cabecera lo usual es void main(void). A continuacin, entre llaves estar el cdigo que
resuelve el problema para el que se crea el programa. Lo usual es que la mayora del cdigo de la funcin
main consista en invocaciones a las funciones en las que se habr dividido el problema. La estructura del
cdigo que va entre llaves es similar a la de cualquier otra funcin y se ver con ms detalle en el siguiente
apartado (Definicin de funciones).

Fundamentos de Programacin

Definicin de funciones
Finalmente el fichero fuente en C termina con la definicin de las funciones que se usan en el programa, que
sern invocadas desde el main, o bien desde otras funciones. Las funciones se definen una a continuacin de
otra.
La definicin de una funcin es el conjunto de sentencias o instrucciones necesarias para que la funcin
pueda realizar su tarea cuando sea llamada. En otras palabras, la definicin es el cdigo correspondiente a la
funcin. Adems del cdigo, la definicin de la funcin debe incluir una primera lnea que es una cabecera
similar a la declaracin o prototipo que hemos visto. Esta cabecera debe incluir, de forma obligatoria, los
nombres de las variables que van a ser los argumentos de la funcin. Estas variables se llaman argumentos o
parmetros formales, a diferencia de los argumentos que estn en la invocacin a las funciones, que se
llaman argumentos o parmetros reales. Veamos un ejemplo con la funcin potencia:
float potencia (float base, int exponente) {
float resultado = 1.0;
int i = 1;
while (i <= exponente) {
resultado = base * resultado;
i = i+1;
}
return resultado;
}

Las variables base y exponente son los argumentos formales y, a su vez, son variables locales en el cdigo de
la funcin.
Sin detenernos, de momento, en qu hace esta funcin, s podemos entender qu significan los parmetros
formales. Las variables base y exponente sirven de comunicacin entre la invocacin y el cdigo de la
funcin; de esta manera, la invocacin:
pot = potencia (3.4f, 2);

hace que la variable base tome el valor 3.4 y exponente el valor 2, que son denominados parmetros reales.
Si la invocacin se hiciera en vez de con constantes con valores de variables, por ejemplo:
pot = potencia (a, b); // a de tipo float y b de tipo int

Los parmetros reales seran a y b. Cuando se invoca a la funcin potencia, el valor de a se transfiere a base,
y el de b, a exponente. La funcin potencia realiza una serie de clculos con los valores recibidos de base y
exponente y obtiene un valor que se guarda en la variable local resultado. Esta variable es devuelta en la
ltima sentencia de la funcin, y su valor se transfiere a la invocacin de la funcin y es asignada a su vez a la
variable pot.
Es importante repetir que los parmetros formales en la cabecera de la funcin son variables locales a la
funcin, es decir, slo tienen sentido dentro del cdigo de la funcin, y es un error muy comn querer

12. Introduccin al Lenguaje C

definirlos otra vez dentro de la funcin. Las variables i y resultado tambin son variables locales de la funcin
potencia.
Si una funcin no devuelve ningn valor su tipo de retorno ser void. Por razones histricas estas funciones
suelen llamarse procedimientos. Por ejemplo, se usan habitualmente para imprimir resultados en pantalla,
ya que son funciones que estructuran bien el cdigo y son reutilizables pero no devuelven ningn valor.
2.2. Tipos, declaraciones, operadores, expresiones
Los tipos bsicos son:
char, que representa un carcter.
int / long, que representa un nmero entero.
float / double, que representa un nmero real.
void, que representa un tipo sin valores.
Los tipos bsicos de C equivalen a los tipos predefinidos de Java, aunque no existen ni el tipo boolean, ni el
tipo String. En ANSI C, un booleano se modela mediante un valor entero. Si el valor es 0, se considera falso, y
si es distinto de cero se considera cierto. En nuestra asignatura, definiremos un tipo boolean a partir de un
enumerado con los valores falso y cierto, de la siguiente forma:
typedef enum {falso, cierto} boolean;

La forma de trabajar con cadenas de caracteres se ver ms adelante.


Declaracin de variables
A diferencia de Java, las declaraciones de variables deben ir al principio de un bloque. Tienen como mbito
hasta el final del bloque. La declaracin de las variables se hace de acuerdo con el siguiente formato:
tipo lista_de_identificadores;

Ejemplos:
char c;
int i, j;
long potencia;
double radio, longitud;

Expresiones
Como en Java, las expresiones son combinaciones de constantes, variables operadores y funciones. Todas las
expresiones, si tienen una sintaxis correcta, tienen un tipo.
Los operadores disponibles en C son similares a los de Java. Se clasifican en aritmticos, relacionales, lgicos
y de asignacin. Ms adelante veremos otros tipos de operadores.
Operadores Aritmticos: operan sobre datos de tipo numrico. Forman expresiones cuyo tipo es real
(float/double) o entero (int/long) y son los siguientes:

Fundamentos de Programacin

+
*
/
%
++
--

Suma
Resta
Multiplicacin
Divisin
Resto
Cambio de signo
Incremento
Decremento

Todos estos operadores se pueden aplicar a constantes, variables y expresiones. El resultado es el que se
obtiene de aplicar la operacin correspondiente entre los dos operandos. El nico operador que requiere
una explicacin adicional es el operador resto %. En realidad su nombre completo es resto de la divisin
entera. Este operador se aplica solamente a constantes, variables o expresiones de tipo int. Por ejemplo,
17%3 es 2, puesto que el resto de dividir 17 por 3 es 2. Por tanto, si a%b es cero, a es mltiplo de b.
Ejemplos de expresiones aritmticas son:
(votos/electores)*100
a*x*x + b*x + c
horas*3600 + minutos*60 + segundos
(alto-bajo)/2

Las expresiones pueden contener parntesis (...) que agrupan algunos de sus trminos, como ocurre en el
primer ejemplo. Puede haber parntesis contenidos dentro de otros parntesis. El significado de los
parntesis coincide con el habitual en las expresiones matemticas. Es habitual la inclusin de espacios en
blanco para mejorar la legibilidad de las expresiones.
Operadores relacionales: operan sobre elementos de diferentes tipos construyendo expresiones de tipo
lgico. El tipo boolean no existe en C, como ya se han indicado anteriormente. En su lugar se suele usar un
entero que si es cero indica falso y en otro caso verdadero. Aunque nosotros usaremos el tipo boolean
definido como un enumerado, no debemos olvidar que en C se usa normalmente un entero en su lugar. Los
operadores relacionales en C son los siguientes:
>
<
>=
<=
==
!=

Mayor que
Menor que
Mayor o igual que
Menor o igual que
Igual que
Distinto

La forma general de uso de estos operadores es la siguiente:


expresion1 op expresion2

12. Introduccin al Lenguaje C

donde op es uno de los operadores (==, <, >, <=, >=, !=). El funcionamiento de estos operadores es el
siguiente: se evalan expresion1 y expresion2, y se comparan los valores resultantes. El resultado de la
comparacin es un valor booleano, que en C se representa por un entero. Si el valor de este entero es cero,
se considera falso y si es distinto de cero se considera cierto.
Ejemplos de expresiones relacionales son:
x >= (y+z)
contador < 10
numero%2 == 0
ordenado != cierto

Operadores Lgicos. Estos operadores operan sobre valores lgicos construyendo expresiones de tipo lgico:
Los operadores lgicos son operadores que permiten combinar los resultados de los operadores
relacionales, comprobando que se cumplen simultneamente varias condiciones, que se cumple una u otra,
etc. El lenguaje C tiene tres operadores lgicos:
&& Y
|| O
!
Negacin
Su forma general de uso es la siguiente:
expresion1 && expresion2
expresion1 || expresion2
! expresion

El operador && devuelve un valor cierto si expresion1 y expresion2 son ciertas (o distintas de 0), y falso (o 0),
en caso contrario, es decir, si una de las dos expresiones o las dos son falsas (iguales a 0). Por otra parte, el
operador || devuelve cierto si al menos una de las expresiones es cierta. Finalmente, el operador ! cambia el
valor de expresion de cierto a falso o viceversa.
Ejemplos de expresiones lgicas son:
(opcion < 5) || (opcion > 20)
(opcion >= 5) && (opcion <= 20)
! encontrado

Operadores de Asignacin. Son los operadores =, +=, -=, etc. con una semntica similar a la de Java. Los
operadores de asignacin sirven para dar valor a una variable a partir del resultado de una expresin o el
valor de otra variable (en realidad, una variable es un caso particular de una expresin).
El operador de asignacin ms utilizado es el smbolo =. Su forma general es:
nombre_de_variable = expresion;

La semntica de esta expresin es la siguiente: en primer lugar, se evala la expresion y, en segundo lugar, se
almacena el valor obtenido en la variable cuyo identificador aparece a la izquierda del smbolo igual

10

Fundamentos de Programacin

(realizndose la correspondiente conversin de tipo si es necesario). Por ejemplo, dadas dos variables x e y,
donde x vale 7 e y vale 3,
x
y

7
3

despus de la asignacin
y = x + 1;

el contenido de ambas variables ser:


x
y

7
8

Como se ve, el efecto de la asignacin es destructivo: cuando se asigna un nuevo valor a una variable se
pierde el valor anterior de la variable.
Hay dos errores relacionados y que son tpicos en programadores principiantes. Uno es intentar poner a la
izquierda del = una expresin en vez de una variable, y el segundo es no entender bien una asignacin
cuando intervienen slo dos variables, por ejemplo:
x = y;

En este caso, el valor que tuviera y se almacena en x, haciendo que el anterior valor de x desaparezca.
Por supuesto, la variable y no sufre ninguna modificacin.
En C todos estos operadores son operadores binarios bsicos con la misma prioridad. Son legales, aunque no
recomendables, expresiones del tipo:
a = b = c = 18;

Una expresin construida con un operador de asignacin tiene el tipo del operando izquierdo y devuelve el
valor asignado a ese operando izquierdo.
Adems de los operadores vistos hasta ahora, el lenguaje C dispone de otros operadores que veremos ms
adelante, en especial los operadores que trabajan con direcciones de memoria.
Existen otros cuatro operadores de asignacin (+=, -=, *= y /=) formados por los cuatro operadores
aritmticos seguidos por la asignacin. Estos operadores simplifican algunas operaciones recurrentes sobre
una misma variable. Su forma general es:
variable op= expresion;

donde op representa cualquiera de los operadores (+, - , *, /). La expresin anterior es equivalente a:

12. Introduccin al Lenguaje C

variable = variable op expresion;

Por ejemplo, las dos asignaciones siguientes son equivalentes:


suma += valor;
suma = suma + valor;

Precedencia y asociatividad. El resultado de una expresin depende del orden en el que se ejecutan las
operaciones. Por ejemplo, veamos la expresin 3 + 4 * 2. Si evaluamos primero la suma (3+4), y despus el
producto (7*2), el resultado es 14; sin embargo, si primero se evala el producto (4*2), y luego la suma
(3+8), el resultado es 11. Para saber en qu orden se realizan las operaciones es necesario definir unas reglas
de precedencia y asociatividad. La tabla siguiente resume las reglas de precedencia y asociatividad de los
principales operadores en el lenguaje C. Los operadores que estn en la misma lnea tienen la misma
precedencia, y las filas estn en orden de precedencia decreciente.

Operador

Asociatividad

! ++ -- - (cambio de signo)

derecha a izquierda

* / %

izquierda a derecha

+ - (diferencia)

izquierda a derecha

< <= > >=

izquierda a derecha

== !=

izquierda a derecha

&&

izquierda a derecha

||

izquierda a derecha

Por supuesto, el orden de evaluacin puede modificarse por medio de parntesis, pues siempre se evalan
primero las operaciones encerradas en los parntesis ms interiores. En general, es recomendable el uso de
los parntesis para remarcar y documentar el orden de las operaciones.
Conversiones explcitas e implcitas de tipo. Existen conversiones automticas (implcitas) de cada uno de los
tipos al siguiente en la sucesin: char, int, long, float, double. Como en Java, una operacin que involucre
dos tipos diferentes de los anteriores se hace en dos pasos: en primer lugar se convierten ambos tipos al
mayor (en el orden anterior) y posteriormente se hace la operacin correspondiente sobre los valores de los
operandos.
Si se quiere hacer una conversin de tipo de uno mayor a otro menor hace falta usar el operador de casting
que tiene la misma forma que en Java y las mismas consecuencias.
Funciones predefinidas. En las expresiones tambin se pueden incluir llamadas a funciones, bien definidas
por el programador, bien existentes en las libreras de funciones predefinidas proporcionadas con el

11

12

Fundamentos de Programacin

compilador de C. Ejemplos de funciones proporcionadas por el compilador son las funciones matemticas o
funciones de conversin de tipos.
Las funciones matemticas usuales vienen proporcionadas en la librera math.h. Algunas de ellas son:
int abs(int num);
int rand(void);
double log(double x);
double log10(double x);
double sin(double x);
double cos(double x);
double pow(double x, double y);
double exp(double x);
double sqrt(double x);

//
//
//
//
//
//
//
//
//

valor absoluto
nmero entero aleatorio entre 0 y RAND_MAX
logaritmo neperiano
logaritmo decimal
seno, el ngulo debe estar expresado en radianes
coseno, el ngulo debe estar expresado en radianes
x elevado a y
e elevado a x
raz cuadrada

Adems se proporcionan un conjunto de funciones para convertir cadenas de caracteres con un formato
dado a valores de los tipos bsicos. Vienen en stdlib.h y algunas de ellas son:
int atoi(const char * s);
long atol(const char * s);
double atof(const char * s);

//convierte la parte inicial de s a un entero


//convierte la parte inicial de s a un long
//convierte la parte inicial de s a un double

2.3. Punteros
El concepto de puntero no existe directamente en Java aunque todos los objetos (de Java) estn
implementados usndolos. Un puntero es una variable capaz de almacenar direcciones de memoria y se usa
para sealar dnde hay guardada una informacin. Una variable puede ser declarada de tipo puntero a un
tipo T. Esto se consigue posponiendo * al tipo T. El tipo puntero a T se declara como T *.
Ejemplos:
int *pint;
float *pf;

En el ejemplo anterior hemos declarado la variable pint de tipo puntero a int y pf de tipo puntero a float. Eso
quiere decir que los valores de pint sern direcciones de memoria adecuadas para sealar la direccin donde
se ubica un entero. Igualmente ocurre con pf pero respecto a un float.
En general, si tenemos un tipo T, entonces T* ser el tipo puntero a T.
Para los punteros los operadores disponibles son: * y &.
El operador & se aplica a una variable de tipo T y devuelve un valor de tipo T * (la direccin donde se
encuentra ubicada en la memoria la variable).
El operador * se aplica sobre una variable de tipo T * y devuelve un valor de tipo T (el valor contenido en la
memoria sealada por el puntero).
Al operador & se le denomina obtencin de la direccin y al operador * obtencin del contenido.

12. Introduccin al Lenguaje C

Ejemplo:
Sean dos variables enteras i y j, un puntero a entero p y un puntero a entero p2 inicializado con la direccin
de j:
int
int
int
i =
p =
j =

i, j;
* p;
// p puede guardar la direccin de una variable entera como i,j
* p2 = &j; // p2 se inicializa guardando la direccin de j
15;
&i;
// p guarda la direccin de la variable i, apunta a i
*p +7;
// j pasa a valer 7 + lo que guarda lo apuntado por p, esto es, 22

3. Bloques y sentencias de control


Un bloque es una secuencia de declaraciones y sentencias delimitadas por { }. Las declaraciones deben ir al
comienzo del bloque y tienen como mbito hasta el final del mismo.
Una sentencia puede ser una sentencia bsica, una sentencia de control o un bloque tal como se ha definido
antes. Las sentencias bsicas son expresiones terminadas en punto y coma (;).
Las sentencias de control permiten modificar y controlar el flujo secuencial de ejecucin de los programas y
se clasifican en:
Selectivas: para bifurcar el flujo de ejecucin.
Repetitivas: para establecer bucles iterativos de ejecucin.
Las sentencias de control selectivas son similares a las de Java, y permiten evaluar una condicin y segn el
resultado de la misma ejecutar un conjunto determinado de sentencias. Igual que en Java, en C se dispone
de la sentencia if y de la sentencia switch, cuya sintaxis se muestra ms abajo. Los corchetes indican que esa
parte de la sentencia es opcional, es decir, puede aparecer o no.
Al igual que vimos en Java, la sentencia if evala una condicin (una expresin booleana). Si la condicin se
evala a cierto, se ejecuta el bloque de sentencias asociado al if (sentencias_1), y si se evala a falso, se
ejecuta el bloque de sentencias asociado a else (sentencias_2). Como puede verse, el bloque else es
opcional, as que si tenemos un if que no tiene bloque else, con una condicin que se evala a falso, no se
ejecutar ninguna sentencia.
if (condicion) {
sentencias_1
} [else {
sentencias_2
}]

La sentencia switch evala la expresion, que debe ser obligatoriamente de tipo int o char. Si el valor de la
expresin coincide con el valor de una de las expresiones constantes de los case, se empiezan a ejecutar las
sentencias que haya hasta el final del bloque switch o hasta que se encuentre un break. Si el valor de la

13

14

Fundamentos de Programacin

expresion no coincide con ninguno de los valores de las expresiones constantes de los bloques case,
entonces se ejecuta el bloque default, si es que hay. Note que tanto el bloque default como las sentencias
break al final de cada case son opcionales.
switch (expresion) {
case expresion_constante_1:
sentencias_1;
[break;]
case expresion_constante_2:
sentencias_2;
[break;]

case expresion_constante_n:
sentencias_n;
[break;]
[default:
sentencias_m;]
}

Las sentencias de control repetitivas permiten ejecutar reiteradamente un conjunto determinado de


sentencias, mientras cierta condicin evale a cierto (distinto de cero).
Veremos dos sentencias de control repetititvas: while y for, cuyo funcionamiento es similar al de Java.
while (condicion) {
sentencias
}
for (inicializacin; condicin; incremento){
sentencias
}

C no incluye el for-extendido, pero se puede simular con un for clsico. A su vez cualquier sentencia for
podemos convertirla en una sentencia while. La transformacin es de la forma:
for (inicializacin; condicin; incremento) {
sentencias
}

inicializacin;
while (condicin) {
sentencias;
incremento;
}

4. Funciones para trabajar con la entrada y salida estndar


No hay palabras reservadas del lenguaje que realicen tareas de lectura y escritura, sino que todas estas
operaciones estn suministradas por la biblioteca stdio.h, que contiene un conjunto de funciones de
entrada/salida.
Entrada y salida de caracteres
La funcin getchar lee un carcter del teclado y devuelve su valor cuando se pulsa la tecla de retorno de

12. Introduccin al Lenguaje C

carro. La funcin putchar escribe un carcter en la pantalla. Por ejemplo, siendo ch una variable de tipo char,
el siguiente fragmento de cdigo
ch = getchar ();
putchar (ch);

lee un carcter de la entrada estndar y lo asigna a la variable ch. Despus escribe el mismo carcter en la
salida estndar.
Entrada y salida con formato
La funcin printf. La funcin printf permite escribir una lista de datos de acuerdo con un formato
preestablecido. Acepta diferentes tipos de argumentos: carcter, valor numrico entero o real, o una cadena
de caracteres, y los escribe segn un formato especificado sobre la salida estndar. El formato de la funcin
printf es:
printf ("formato", arg1, arg2, ..., argn);

donde los argi pueden ser constantes, variables o expresiones en general, y formato es una cadena de
caracteres en la cual se pueden encontrar dos clases de datos: un mensaje o texto a escribir literalmente, y
los smbolos especificadores del formato con el cual se van a escribir las variables dadas como argumentos.
Por ejemplo,
printf ("Esto es un mensaje\n");

Escribe la cadena Esto es un mensaje seguida de un retorno de lnea (debido al '\n'). Los especificadores de
formato deben ir precedidos del carcter %. Algunos de ellos son:
%c
%d
%ld
%f
%lf
%s

Carcter (char)
Nmero entero (int)
Nmero entero largo (long)
Nmero real (float)
Nmero real (double)
Cadena de caracteres

Por cada argumento a imprimir debe existir un especificador de formato, que indica el formato en el cual se
va a mostrar el dato. Por ejemplo, siendo letra una variable de tipo char con el valor 'A', la instruccin
printf ("El cdigo ASCII de %c es %d", letra, letra);

escribira por la salida estndar


El cdigo ASCII de A es 65

mostrndose el mismo dato con dos formatos distintos: como carcter (%c) y como entero (%d). Obsrvese
que hay dos especificadores de formato y dos argumentos (aunque en este caso sean el mismo).

15

16

Fundamentos de Programacin

Otros ejemplos de uso de printf son:


printf ("\nEl cuadrado de %f vale %f", x, x*x);
printf ("\nLa edad de %s es %d aos", "Juan", edad);
printf ("\nSeno(%lf) = %lf\n", x, sin(x));

La funcin printf puede emplearse sin argumentos, en cuyo caso slo se imprimen los caracteres presentes
en la cadena de formato. Entre el smbolo % y el carcter que especifica la notacin a emplear se pueden
insertar ciertos caracteres opcionales. Son los siguientes:

El signo menos (-) para que el dato se ajuste por la izquierda, en lugar de hacerlo por la derecha, que
es lo establecido a falta de especificacin explcita.
Un nmero que indica la longitud mnima en caracteres que tiene el campo donde se imprimir el
dato correspondiente. Los espacios juegan el papel de caracteres de relleno.
Un punto decimal (.) seguido de una cifra que indica el nmero de dgitos despus del punto decimal
de un dato flotante, o el nmero mnimo de dgitos para un entero, o el nmero mximo de
caracteres de una cadena que sern impresos.

Por ejemplo:

%6d imprime un nmero entero (int) alineado por la derecha y en un campo de al menos seis
caracteres.
%-10s imprime una serie de caracteres alineados por la izquierda y asegurando una longitud mnima
de 10 caracteres.
%.4f imprime un nmero real (float) en coma flotante con un mximo de 4 cifras significativas en la
parte fraccionaria.

La funcin scanf. La funcin scanf permite leer valores desde la entrada estndar (teclado) y almacenarlos en
las variables que se especifican como argumentos. stas deben ir normalmente precedidas por el smbolo &.
El smbolo & es un operador unario que significa direccin de. La sintaxis de scanf es:
scanf ("formato", arg1, arg2, ..., argn);

donde debe haber tantos especificadores en la cadena de formato como variables en la lista de argumentos.
Por ejemplo,
scanf ("%d%lf", &n, &x);

para leer un valor n de tipo int y un valor x de tipo double. Estos valores se introducirn desde la entrada
estndar separndolos por espacios o retornos de carro.
En la cadena de formato aparecen especificadores de formato, que son los mismos que se han visto para
printf pero, a diferencia de lo que ocurre con ste, nunca deben aparecer caracteres que no sean formatos.

12. Introduccin al Lenguaje C

5. Tablas, cadenas de caracteres y estructuras


5.1. Tablas (arrays)
El concepto de tabla es equivalente al visto en Java. Una tabla es un conjunto de datos (llamados elementos),
con las siguientes propiedades:
Todos son del mismo tipo (int, char, float, etc.)
Se accede a cada uno de ellos mediante un ndice.
Declaracin e inicializacin de tablas: Las tablas se declaran indicado el tipo de los elementos, su nombre, y
la dimensin entre corchetes. La dimensin es el nmero de elementos que como mximo puede almacenar
la tabla. Una tabla puede tener ms de una dimesin. Una tabla con ms de una dimensin es similar a una
matriz. Cuando se declara una tabla, es obligatorio definir al menos una dimensin, bien sea de forma
explcita (mediante una constante que indique el tamao), bien de forma implcita (enumerando los
elementos que contendr la tabla). La sintaxis general para definir una tabla de una dimensin, de dos
dimensiones, y con una dimensin implcita se muestra a continuacin:
tipo nombre [dim];
tipo nombre [dim1][dim2];
tipo nombre[] = {v1, v2, ..., vn};

Ejemplos de declaracion de tablas son los siguientes:


int v [10];
char palabra [TAM_CADENA];
int a[] = {2, -3, 7};

La variable v es una tabla de 10 enteros. La variable palabra es una tabla que tiene tantos caracteres como
indique la constante TAM_CADENA. La variable a es una tabla de 3 enteros.
Asociado a una tabla vamos a definir dos conceptos que no existen en C, pero que es conveniente usarlos
para hacer una programacin ms segura.

Tamao de una tabla: es el nmero de elementos que tiene. El tamao de una tabla no se puede
modificar. Cada vez que declaremos una tabla declararemos una constante que guardar el tamao de la
tabla. La constante tendr como identificador TAM_NOMBRE, donde NOMBRE es el identificador de la
tabla.
Longitud: es el nmero de elementos tiles de la tabla. Esta longitud s puede variar. En muchos
programas en C usaremos tablas que no estn completamente llenas. En este caso declararemos una
variable con identificador nombreLength que guarde el nmero de elementos tiles. Debe cumplirse que
nombreLength <= TAM_NOMBRE y ambas son mayores o iguales a cero.

Declaracin e inicializacin de los elementos de una tabla: cuando declaramos una tabla se reserva memoria
para ubicar cada uno de sus elementos. Pero estos elementos no estn inicializados y por lo tanto si los
consultamos obtenemos, en general, un valor no definido. Igual que para las dems variables, los elementos
de una tabla deben de ser inicializados antes de ser consultados. Mediante la sentencia T b[] = {v1,v2,,vn}

17

18

Fundamentos de Programacin

es posible declarar la tabla b, de tipo T y tamao n, e inicializar sus elementos con los valores indicados entre
llaves {}. El primer valor, v1, quedar ubicado en la casilla de ndice 0 y as sucesivamente.
Acceso a los elementos de una tabla: se realiza mediante el operador corchete ([]), y un nmero entero que
representa un ndice. Si i es un ndice, entonces se debe cumplir 0 <= i < TAM_NOMBRE y si la tabla no est
completamente llena entonces 0 <= i < nombreLength. Si no se cumplen esas restricciones los programas
que construyamos funcionarn mal y el error ser difcil de detectar.
Modificacin de los elementos de una tabla: se realiza usando nmeros enteros como ndices dentro del
operador [], como para la consulta, pero ubicando la expresin en la parte izquierda de un operador de
asignacin.
Ejemplos:
#define TAM_V 10
int v[TAM_V];
int a[] = {2, -3, 7};
int aTam = 3;
a[2] = a[1] + 2;
// la tabla a ha quedado modificada a {2, -3, -1}
v[4] = v[3];
// incorrecto: la casilla v[3] se est usando antes de inicializarse
v[14] = 12;
// incorrecto pero no es detectado por el compilador

En el ejemplo anterior se declara la tabla v pero no se inicializan sus elementos. La tabla a es declarada e
inicializada.
Un buen programa (y por tanto un buen programador) debe definir previamente la constante de la
dimensin del array y un tipo que permita trabajar con la tabla, de forma que, cada vez que vayamos a
trabajar con una tabla, procederemos declarando la constante y el tipo para manejar el array en el
correspondiente archivo .h, de la siguiente forma:
#define TAM_VECTOR3D 3

typedef int Vector3D[TAM_VECTOR3D];

Una variable de tipo Vector3D se puede inicializar igual que cualquier tabla, por ejemplo:
void main (void){
Vector3D punto3D = {1.1, 3.2, -4.5};

Tablas y Punteros: aritmtica de punteros


Existen equivalencias claras entre el tipo puntero a T y tabla de T. El nombre de una tabla, tomado
aisladamente, es la direccin donde comienza la tabla. Es una constante que no se puede modificar y
equivalente a un puntero al elemento que est en la posicin cero. Veamos algunas equivalencias entre
tablas y punteros. Sean las variables v y p declaradas de la forma siguiente para cualquier tipo T:

12. Introduccin al Lenguaje C

#define TAM_V 20
T v[TAM_V];
T * p = v;

Entonces existen las siguientes equivalencias:


v
&v[i]
p+i
p[i]
v[i]

&v[0]
v+i
v+i
v[i]
*(p+i)

v[i]

*(v+i)

v equivale a la direccin del primer elemento del vector


La direccin del elemento i del vector equivale al puntero v desplazado i posiciones.
El puntero p desplazado i posiciones equivale al puntero v desplazado i posiciones.
Accecer al elemento i a partir de p equivale a acceder al elemento i a partir de v.
Acceder al elemento i de v equivale a acceder al contenido al que apunta p desplazado i
posiciones.
Acceder al elemento i de v equivale a acceder al contenido al que apunta v desplazado i
posiciones.

Como vemos, el nombre de una tabla es esencialmente un puntero, pero constante. Es decir, no puede ser
colocado a la izquierda de un operador de asignacin. Por otra parte, a cualquier puntero es posible sumarle
un entero i (tambin restarle). Esa operacin nos da otro puntero que seala a la casilla i de una tabla. Estas
operaciones se denominan aritmtica de punteros.
El operador [], denominado operador de indexacin, puede colocarse detrs de un nombre de tabla o de un
puntero. En general si p es un puntero, lo que incluye al identificador de una tabla, entonces p[i] es
equivalente a *(p+i) para cualquier i. Ambas expresiones pueden ser usadas indistintamente a la derecha de
un operador de asignacin, para la consulta del contenido del elemento i, o a la izquierda del mismo, para la
modificacin del elemento i.
5.2. Cadenas de caracteres
El lenguaje C no tiene definido un tipo equivalente al tipo String de Java para almacenar cadenas de
caracteres. En C, una cadena de caracteres es una tabla de char donde los elementos tiles van desde la
casilla 0 hasta la que contenga el carcter `\0`. Este carcter se conoce como carcter de fin de cadena. Las
funciones sobre cadenas de caracteres funcionan mal si usamos cadenas sin el carcter final `\0`. Las
constantes de tipo cadena son secuencias de caracteres entre comillas. En el fichero string.h se definen las
funciones sobre cadenas proporcionadas en la librera estndar de C.
Definimos los tipos Cadena y PChar tal como vemos abajo. El tipo PChar es equivalente a char * y, por lo
tanto, al ser declarado no reserva espacio para los caracteres. El tipo Cadena, por el contrario, es una tabla
de caracteres de tamao TAM_CADENA.
#define TAM_CADENA 256
typedef char Cadena[TAM_CADENA];
typedef char * PChar;

Estas declaraciones las incluimos en el fichero tipos.h junto con otros tipos que puedan ser de inters como
el tipo boolean visto ms arriba.

19

20

Fundamentos de Programacin

Los prototipos de las funciones de manejo de cadenas de caracteres estn en string.h. Las ms importantes
son las siguientes:
int strlen (const char * s);
char * strchr(const char * s, char c);
char * strstr(const char * s1, const char * s2);
char * strcpy (char * s1, const char * s2);
int strcmp(const char * s1, const char * s2) ;
char * strcat(char * s1, const char * s2);

Como puede observar, algunos de los parmetros de estas funciones van precedidos por la palabra
reservada const. Esto indica que estos parmetros son parmetros de entrada, mientras que los que no
llevan son de salida. Una explicacin ms detallada de estas cuestiones se ve en el apartado Funciones y
procedimientos: paso de parmetros. La semntica de las funciones anteriores es la siguiente:
strlen
strchr
strstr
strcpy
strcmp
strcat

Calcula la longitud de la cadena s. La longitud de una cadena se mide hasta que se


encuentra el carcter \0.
Busca la primera posicin del carcter c en la cadena s y devuelve un puntero al mismo o
NULL si no lo encuentra.
Busca la cadena s2 en s1. Devuelve un puntero a la primera posicin de la cadena de
caracteres s2 (excluyendo el carcter nulo) dentro de s1 o NULL si no la encuentra.
Copia s2 en s1 y devuelve un puntero a s1.
Devuelve un entero negativo, cero o positivo segn que s1 sea menor, igual o mayor que
s2 en el orden lexicogrfico.
Concatena s2 detrs de s1 y devuelve un puntero a s1.

A la hora de usar estas funciones hay que hacer algunas consideraciones. En las funciones anteriores los
parmetros formales con la etiqueta const son parmetros de entrada y no van a ser modificados. Los que
no tienen la etiqueta const s sern modificados. As ocurre con s1 en strcpy y strcat. Como s1 va a ser
modificado, hay que tener en cuenta que debe apuntar a una zona de memoria, previamente reservada, con
tamao suficiente. En el caso de strcpy para ubicar la cadena s2 (junto con el carcter final \0) y en el caso
de strcat para ubicar a s1 seguida de s2.
Finalmente, recordemos algunos detalles importantes de implementacina la hora de trabajar con cadenas:
Las cadenas en C acaban siempre con el carcter \0.
El nmero de caracteres tiles de la cadena es el devuelto por strlen, pero la cadena necesita, al
menos, un carcter ms de memoria para ubicar el \0 final. Por lo tanto, para una cadena s dada, el
tamao de la tabla de caracteres donde se ubique la cadena debe cumplir que TAM_CADENA >
strlen(s).
Algunos ejemplos del uso de cadenas de caracteres son:
int i1, i2;
Cadena s1 = Hola;
Cadena s2 = Mundo;
PChar s3;
i1 = strlen(s1);

12. Introduccin al Lenguaje C

s3 = strcat(s1,s2);
i2 = strlen(s3);

El resultado para i1 es 4 y para i2 es 10. Hemos tenido en cuenta que los tamaos de las tablas de caracteres
(256) donde se ubican s1, s2 (antes y despus de la concatenacin) cumplen la restriccin anterior.
Por otra parte, hemos de tener en cuenta que el tipo Cadena define una tabla de caracteres cuyo
identificador, como en todas las tablas, es un puntero constante y, por lo tanto, no puede estar en la parte
izquierda de una asignacin. As, la sentencia siguiente sera incorrecta:
s1 = strcat(s1,s2);

//incorrecto: s1 es un puntero constante y no puede estar


// en la izquierda de una asignacin

Tambin hemos de tener en cuenta que una variable de tipo PChar puede ser inicializada con la direccin de
una cadena constante pero no puede modificarla.
PChar nn1 = "Nuevo Mundo";
Cadena s1 = Hola; // La cadena constante se copia en la memoria de s1
nn1[3] = '5';
// produce un error porque intenta modificar la cadena constante
s1[3] = '5';
// correcto

5.3. Estructuras y punteros a estructuras


Una estructura es un agregado de datos. Cada dato se llama campo y tiene las siguientes caractersticas:
Cada campo puede ser de distinto tipo (int, char, float, etc.).
Cada campo debe tener un identificador distinto.
Declaracin e inicializacin de estructuras: una estructura se declara con la palabra reservada struct.
Normalmente trabajaremos con struct definiendo un tipo nuevo mediante typedef, de la siguiente manera:
typedef struct {
T1 c1;
T2 c2;
...
Tn cn;
} Tr;
typedef Tr * PTr;

Una variable de un tipo construido mediante un struct puede inicializarse con un conjunto de valores para
los campos, separados por comas y delimitados por llaves:
Tr r = {v1, v2, ..., vn};
PTr pr = &r;

Un ejemplo de declaracin de una estructura es:


typedef struct {
double x;
double y;

21

22

Fundamentos de Programacin

} Punto;
typedef Punto * PPunto;
Punto p = {2.0,3.1};
PPunto pp = &p;

Arriba definimos el tipo Punto a partir de un struct y el tipo PPunto como un puntero a la estructura Punto.
Tambin se muestra la forma de inicializar variables de estos tipos.
Operadores de acceso a campos: hay disponibles dos operadores para acceder a los campos de un tipo struct
o puntero a struct. Son los operadores punto ( . ) y flecha (->), respectivamente. El primero se usa para
acceder a los campos de una variable de tipo struct. El segundo se usa para acceder a los campos de una
variable de tipo puntero a struct. Si tenemos la declaracin de los tipos Punto y PPunto vista arriba y las
declaraciones de las variables p y pp, el acceso a los campos se har tal como sigue:

Operador Punto: acceso a travs de variable de tipo struct: p.x


Operador Flecha: acceso a travs de puntero a struct: pp->x o tambin (*pp).x

Es decir, si tenemos una variable de tipo puntero a struct y queremos acceder a un campo, usamos el
operador flecha (->). Si la variable es de tipo struct usamos el operador punto (.).
Las expresiones construidas con estos operadores (. y ->) tienen el tipo del campo correspondiente y pueden
ser colocadas a la derecha o a la izquierda de un operador de asignacin. Si se colocan a la derecha, estamos
consultando el valor del campo. Si se colocan a la izquierda, estamos modificando su valor.
Ejemplos de uso de estos operadores son:
pp->x = pp->y+18.0;
(*pp).x = (*pp).y+18.0;

o equivalentemente

6. Funciones y procedimientos: paso de parmetros


Todo programa en C est construido en base a funciones. Las funciones permiten estructurar la codificacin
de los programas reduciendo su complejidad y, como consecuencia, mejorando su desarrollo. En el apartado
Estructura de un programa en C, se ha visto cmo se estructura un programa en un solo archivo .c. Sin
embargo, esta estructuracin no es la que se encuentra normalmente en cualquier programa en C.
Habitualmente, se tiene en un archivo .h la declaracin de tipos y prototipos de funciones, en un archivo .c la
implementacin de las funciones, y en un archivo main.c el programa principal en el que se invocan a las
funciones o se realizan las pruebas.
Declaracin de prototipos de funciones
Igual que las variables tienen un tipo, las funciones tienen un tipo asociado, su prototipo, cabecera o
signatura. Es conveniente estructurar el cdigo agrupando los prototipos de las funciones en un fichero con
extensin .h. El cdigo asociado (cuerpo de las funciones) se incluye en el fichero del mismo nombre con

12. Introduccin al Lenguaje C

extensin .c. Usualmente, dentro de la cultura del C, a las funciones que devuelven void se les llama
procedimientos.
Las funciones permiten la reutilizacin de cdigo. Las funciones junto con su agrupacin en ficheros son los
mecanismos de modularizacin del cdigo en C. Son mecanismos primitivos, si los comparamos con los
disponibles en Java: interfaces, clases y paquetes.
Ejemplos de prototipos de funciones son:
double getXPunto(const Punto p);
void setXPunto(Punto p, double x);
double getYPunto(const Punto p);
void setYPunto(Punto p, double y);

La estructura del cuerpo de una funcin EXIGE declarar las variables al principio como sigue:
Tr nombre (T1 e1, ..., Tn en) {
Declaracin de variables locales
Sentencias
return r;
// no hay return si la funcin devuelve void.
}

Un programa en C se compone de un conjunto de ficheros con extensin .h y otro conjunto con extensin .c.
Los primeros son ficheros de declaraciones e incluyen lneas de #include (para incluir otros ficheros .h), lneas
#define (que definen macros en general y constantes en particular), declaraciones de tipos (mediante
typedef) y prototipos de funciones. Los ficheros .c contienen lneas #include (para inclusin de ficheros .h) y
cdigo de funciones (cabecera ms cdigo).
Los ficheros con extensin .h suelen tener una estructura particular para facilitar su uso. As el fichero tipos.h
tiene la estructura:
#ifndef TIPOS_H_
#define TIPOS_H_
typedef enum{falso,cierto} boolean;
#endif /* TIPOS_H_ */

El objetivo es definir una variable similar al nombre del fichero, en este caso TIPOS_H_, que nos sirve para
conseguir que el fichero se incluya una sola vez. Esto se consigue por el funcionamiento de las clusulas del
preprocesador #ifndef, #define, #endif. La primera decide si se ha definido antes la variable. Si no se ha
definido, expande el fichero hasta #endif. La primera lnea define la variable que no estaba definida. Si ya
est definida, porque el fichero se haba incluido previamente en otro lugar, el preprocesador se salta todo
el contenido del fichero hasta #endif.
Un programa en C es, por lo tanto, un conjunto de funciones. Como no existe sobrecarga todas deben tener
nombres diferentes. De todas ellas, hay una nica funcin distinguida cuyo nombre es main. La llamada a
esta funcin es el comienzo del programa.

23

24

Fundamentos de Programacin

La llamada a una funcin es como en Java salvo que en C no se invoca sobre ningn objeto. Igualmente la
invocacin de funcin puede formar una sentencia bsica (si la funcin devuelve void) o formar parte de una
expresin si devuelve un valor. El concepto de parmetros formales y parmetros reales es igual que en Java.
Ejemplos:
double x;
Punto pd = {3.0,4.5};
PPunto p = &pd;

x = getXPunto(p);
setYPunto(p,3.0);

Paso de parmetros: C vs. Java


El paso de parmetros en C es como en Java: se copia el valor de los parmetros reales en los parmetros
formales y se ejecuta el cuerpo del mtodo invocado. Al terminar, si existe la sentencia return, se devuelve el
valor de la expresin correspondiente. Es lo que se denomina paso de parmetros por valor. En Java
distinguamos dos tipos de parmetros: parmetros de entrada y parmetros de entrada/salida. Los mismos
conceptos existen en C, pero ahora debemos identificar con claridad qu parmetros son de un tipo y de
otro.
De manera simple podemos decir que los parmetros cuyo tipo es T * (puntero a un tipo T) son parmetros
de entrada/salida. El resto de parmetros son de entrada. Es decir, son parmetros de entrada aquellos que
son de uno de los tipos bsicos (char, int, float, ), de tipo enum y de tipo struct. Son parmetros de
entrada/salida los que son punteros a algunos de los tipos anteriores.
Veamos con algunos ejemplos por qu los parmetros de tipo puntero son de entrada/salida.
La funcin mediaAritmetica, cuya definicin es la siguiente, tiene tres parmetros de entrada que son de
tipos bsicos. La funcin intercambio tiene dos parmetros de entrada/salida.
double mediaAritmetica (int a, int b, int c) {
a = a + b + c;
return (a / 3.0);
}
void intercambio (int *p1, int *p2) {
int tmp;
tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}

Si el archivo ejemplosES.h contiene los prototipos de los mtodos mediaAritmetica e intercambio, un


ejemplo de funcin main donde se hacen invocaciones a estos mtodos es la siguiente:
#include <stdio.h>
#include ejemplosES.h
void main (void) {

12. Introduccin al Lenguaje C

int x = 5, y = 8, z = 10;
double r;
intercambio (&x, &y);
printf(%d %d\n,x,y);
r = mediaAritmetica(x,y,z);
printf(%d %f\n,x,r);
}

Podemos comprobar el que valor de x e y ha cambiado despus de la llamada a la funcin intercambio en el


ejemplo anterior. Vemos que como parmetros reales pasamos punteros a las correspondientes variables. A
esta tcnica (declarar el parmetro formal de tipo T *, pasar como parmetro real un puntero a una variable
dada y, posiblemente, modificar en el cuerpo de la funcin el contenido apuntado por el puntero) se le
denomina paso de parmetros por referencia. Es la tcnica adecuada en C para disponer de parmetros de
entrada/salida.
Sin embargo, cuando llamamos a la funcin mediaAritmetica la variable x no cambia (aunque en el cuerpo de
la funcin el correspondiente parmetro formal s es modificado) porque es un parmetro de entrada.
Los parmetros formales pueden llevar el calificador const, lo que indica que el parmetro formal
correspondiente es constante y no puede ser modificado dentro del cuerpo de la funcin. Es decir, no puede
aparecer a la izquierda de un operador de asignacin. Esto es til para declarar que una tabla no puede ser
modificada (y, de esa forma, convertirla en un parmetro de entrada). En general, es recomendable
etiquetar los parmetros de entrada con el calificador const.
void prueba_array(const VectorEntero);
void prueba_array(const VectorEntero t) {

En este caso, el compilador nos avisara de que estamos intentando modificar un valor declarado constante
cuando compila la sentencia t[0]++ en en cuerpo del mtodo prueba_array.

7. Funciones de tratamiento de ficheros de texto


En C se dispone de un conjunto de funciones para mostrar resultados en la consola, ubicarlos en una cadena
o en un fichero. Igualmente existen otras para leer de la consola, de una cadena de caracteres o de un
fichero. Al conjunto de todas ellas las denominamos funciones de entrada salida con formato. Su funcin es
convertir cadenas de caracteres en secuencias de valores de otros tipos (int, float, ..) o viceversa, secuencias
de valores en una cadena de caracteres.
Un fichero se representa en un programa en C por el tipo FILE *. Abrir un fichero se hace con la funcin
fopen cuyo prototipo es:
FILE * fopen( const char * nombreFichero, const char * modo);

25

26

Fundamentos de Programacin

La funcin fopen conecta una variable de tipo fichero con el archivo correspondiente en el sistema
operativo. Asimismo, debe indicar si el fichero se abre en modo lectura (para obtener datos de l) o en modo
escritura (para guardar datos). Por tanto, la funcin fopen recibe dos argumentos de tipo cadena de
caracteres. El primero es el nombre del archivo en el sistema de archivos, incluyendo si fuera necesario la
ruta. El segundo argumento es el modo de apertura. En este tema slo vamos a estudiar los tipos de lectura
r, escritura w o aadir a1. La funcin fopen devuelve una variable de tipo FILE * que es la variable que
se conecta con el archivo cuyo nombre es el primer argumento. Si el fichero nombreFichero no existe en el
sistema de fichero la funcin anterior devuelve NULL. Veamos algunos ejemplos de apertura de ficheros:
fich
fich
fich
fich

=
=
=
=

fopen("datos.txt","r");
fopen("resultados.dat", "w");
fopen(".\\Debug\\datos.dat","r");
fopen("..\\..\\datos.dat","a");

En el primer ejemplo la variable fich representa al archivo datos.txt, que se abre en modo lectura, es decir,
para extraer informacin de l. Cuando se abre un fichero en modo r el fichero debe existir previamente
en el sistema de archivos; si no la variable fich tomar el valor NULL. En este primer caso, el argumento con
el nombre del archivo no lleva ruta; por tanto, el archivo deber estar en la misma carpeta (o directorio) que
el fichero fuente .c que contiene la sentencia.
En el segundo ejemplo, el archivo resultados.dat se abre para escritura, de forma que si no existe, se crea, y
si existiera, se borra y se crea nuevo. Igual que en el caso anterior, al no contener ruta la cadena del primer
argumento, el archivo se crea en la misma carpeta en la que est el archivo fuente.
En el tercer ejemplo, el archivo datos.dat debe estar en una carpeta de nombre Debug situada en el
directorio de trabajo. Como la apertura es en modo lectura, el archivo debe existir.
Finalmente, en el ltimo ejemplo, el archivo datos.dat se sita dos carpetas por arriba del directorio de
trabajo. El archivo se abre para aadir, por tanto, se escribir a continuacin de la ltima lnea. Si el archivo
no existiera se creara en blanco.
Ntese que aunque el modo de apertura slo es un carcter (a, w r), se escribe entre dobles comillas
porque el compilador espera una cadena de caracteres, no un tipo char.
Una vez que se termina de trabajar con un fichero, es importante cerrarlo. Para cerrar un fichero la
sentencia es nica independientemente del modo de apertura.
int fclose(FILE *fp);

La funcin fclose recibe como argumento la variable de tipo FILE *, y desconecta el archivo fsico de la
variable. Es importante cerrar el fichero, sobre todo cuando se ha abierto en modo escritura o aadir porque

Estos no son los nicos modos de apertura. En C tambin estn los modos r+, w+ y a+ que permiten realizar en
un mismo fichero lectura y escritura. Adems de que son muy engorrosos de utilizacin, tienen poca utilidad en
ficheros de texto.

12. Introduccin al Lenguaje C

si no se hace, podra no guardarse en el archivo correspondiente toda la informacin escrita. Un ejemplo de


uso de la funcin fclose:
fclose (fich);

Para saber si hemos alcanzado el fin de fichero usamos la funcin:


int feof(FILE *fp);

Salida con formato: printf, sprintf, fprintf


La funcin printf se vi con detalle en el apartado Funciones para trabajar con la entrada y salida estndar,
as que en este apartado nos centramos en sprintf y fprintf.
De manera completamente similar a printf, podemos ubicar el resultado en una cadena que se da como
parmetro en vez de en la salida estndar mediante la funcin sprintf, cuyo formato es el siguiente (donde s
es una cadena de caracteres):
sprintf (s,formato, arg1, arg2, , argn);

Igualmente se puede enviar el resultado a un fichero mediante la funcin fprintf, cuyo formato es el
siguiente:
fprintf (f,formato, arg1, arg2, , argn);

En este caso el parmetro f es del tipo FILE *.


De la misma forma que ocurre con printf, hay una funcin similar a puts para escribir en un fichero, la
funcin fputs. Son las funciones: puts, fputs, cuyas signaturas son:
int puts(const char *s);
int fputs(const char * s, FILE * f);

Ambas escriben una lnea (en la consola o en el fichero f) y retornan un valor positivo si no ha habido error.
Entrada con formato: scanf, sscanf, fscanf
Las funciones de entrada hacen el trabajo inverso a las de salida: convertir una cadena, procedente de la
consola, de una cadena dada o de un fichero, en una secuencia de valores cuyos tipos y estructura est
especificada por un formato. La funcin scanf permite leer valores desde la entrada estndar y almacenarlos
en las variables que se especifican como argumentos, y se vi en el apartado Funciones para trabajar con la
entrada y salida estndar. Las funciones sscanf y fscanf hacen lo mismo, pero en lugar de tomar como origen
la consola, lo toman de una cadena de caracteres dada o de un fichero. El formato de estas funciones es el
siguiente:
scanf ("formato", arg1, arg2, ..., argn);
sscanf(s, "formato", arg1, arg2, ..., argn);
fscanf(f, "formato", arg1, arg2, ..., argn);

27

28

Fundamentos de Programacin

Note que s es una cadena de caracteres, y f una variable de tipo FILE *.


De forma similar a puts, existe una funcin similar a gets (fgets), que permite leer lneas enteras desde un
fichero. El prototipo de estas funciones es el siguiente:
char * gets(char *s);
char * fgets(char * s, int n, FILE * f);

La funcin fgets lee un mximo de n-1 caracteres o hasta que encuentra un fin de lnea del fichero f,
poniendo el resultado en la cadena s. El puntero s debe sealar a una zona con suficiente memoria reservada
para ubicar la lnea leda. Regresa un puntero a la cadena leda o NULL si ha encontrado el fin de fichero.
Similarmente funciona gets pero leyendo una lnea de la consola.
Comprobacin de apertura de un fichero
Una vez invocada la funcin fopen con el argumento r, lo primero que se debe hacer es comprobar si la
apertura se ha realizado correctamente, es decir, si la variable fichero tiene valor null o no. Un valor de null
en una variable de tipo FILE * despus de la apertura para lectura indica que el fichero no existe en la
carpeta donde se le esperaba. Si es en modo escritura, el valor de null indicara disco lleno o protegido
contra escritura.
Por tanto, cada vez que trabajemos con un fichero, es necesario comprobar que la variable fichero tiene un
valor vlido, mediante una sentencia if, de la siguiente forma:
f=fopen(nomfich,"r"); //nomfich de tipo array de char o Cadena
if (f==NULL) {
printf("El fichero %s no existe", nomfich);
}else {
// tratamiento del fichero
}

Lectura de datos de un fichero


La forma ms simple de leer datos de un fichero de texto es mediante la funcin fscanf, que se ha visto
anteriormente, aunque existen tambin otras posibilidades para leer desde fichero de texto, como son las
funciones fgets para leer cadenas de caracteres que incluyan blancos y fgetc para leer variables de tipo char.
En general, hay que tener en cuenta que no es adecuado mezclar en la lectura de un fichero de texto datos
de distinto tipo y desde luego dificulta mucho la operativa si los datos se separan por comas u otro tipo de
caracteres especiales distintos de blancos y tabuladores.
Ejemplos de lectura de datos de ficheros son los siguientes:
Ejemplo 1:
Supongamos que tenemos un fichero de texto con la siguiente estructura:
6

12. Introduccin al Lenguaje C

23.4 32.3 -8.7 65.3 -28.7 43.5

Es decir, en primer lugar, hay un nmero entero y despus, tantos valores reales como indique el primer
nmero. Se desea construir una funcin que reciba como argumento de entrada una cadena de caracteres
con el nombre de un fichero y devuelva como salida un array de reales con los valores contenidos en la
segunda lnea del fichero de texto, y en el nombre de la funcin debe devolver el tamao real del array, esto
es el valor de la primera lnea. Su cdigo sera:
int lecturaFichero(const Cadena nomfich, TablaReales v, int tamTablaReales) {
FILE* f;
int numelem = -1, i;
f = fopen(nomfich,"r");
if(f==NULL) {
printf("El fichero %s no existe", nomfich);
}else {
fscanf(f,"%d",&numelem);
if (numelem > tamTablaReales) {
printf(El numero de elementos es mayor que el tamao de la tabla);
} else {
for(i=0; i<numelem && ! feof(f); i++){
fscanf(f,"%f",&v[i]);
}//end-for
}//end-else
}//end-else
return numelem;
}

Ntese cmo las invocaciones a fscanf son similares a si quisiramos leer desde teclado con la funcin scanf.
Esto es, el formato de las variables a leer es %d para int y %f para float. Igualmente es necesario un &
delante de las variables a leer y por eso se escribe &numelem y &v[i].
Ejemplo 2:
Supongamos tenemos un fichero de texto como el del Ejemplo 1, pero sin el primer nmero entero, sino
solamente con un nmero indeterminado de valores reales. Queremos construir una funcin que reciba una
cadena de caracteres con el nombre de un fichero y devuelva un array con todos los valores reales ledos del
fichero. Como es habitual, la funcin deber devolver el nmero de elementos que hay en el array.
int lectura (const Cadena nomFich, TablaReales v, int tamTablaReales) {
FILE *f;
int i = 0;
float x;
f = fopen(nomFich,"r");
if(f==NULL)
printf("El fichero no existe");
else{
fscanf(f,"%f",&x);
while (!feof(f) && i < tamTablaReales){
v[i] = x;
i++;
fscanf(f,"%f",&x);
}

29

30

Fundamentos de Programacin

fclose(f);
}
return i;
}

Ntese como hay una lectura antes del bucle while. Si el fichero estuviera vaco, esta lectura activara la
funcin feof, que devolvera cierto y, entonces, el bucle no se ejecutara ni una sola vez, devolviendo i con un
valor cero. Si el fichero contiene algn elemento, entonces la primera lectura guarda en x el valor ledo, feof
devuelve falso y, como la condicin del while est puesta con el operador lgico No, entonces !feof(f)
devuelve cierto y el flujo del programa entrara en el bucle (ya que i es menor que el tamao de la tabla).
Note que en la condicin de while, adems de comprobar que no se ha llegado al final del fichero, tambin
se comprueba que hay espacio reservado para almacenar el elemento ledo del fichero, gracias a la
condicin i<tamTablaReales. Dentro del bucle el valor x ledo fuera se asignara a la primera posicin del
vector v (i est inicializada a 0), se incrementara el contador i en uno y se volvera a leer la misma variable x,
de forma que si el fichero tena ms de un valor, volvera a la condicin del while que seguira siendo cierta,
la guardara en la siguiente posicin del array y as sucesivamente. Cuando se lee el ltimo dato, todo
continua igual, esto es, la condicin sigue siendo cierta, se guarda en v, se incrementa la i, pero cuando se va
a volver a leer, se lee la marca de fin de fichero. En este caso, feof devuelve cierto.

8. Ejercicios propuestos
BLOQUE 1 Definiciones de constantes, tipos y variables. Funciones. Estructura de un programa. Punteros
Ejercicio 1
Defina las siguientes constantes:
a)
b)
c)
d)
e)
f)

Una constante entera EOF con valor -1.


Una constante entera MAXIMO con valor 99.
Dos constantes enteras CIERTO y FALSO, con valores 1 y 0, respectivamente.
Una constante de tipo carcter ULTIMA_LETRA con valor Z.
Una constante real PI con valor 3.14159.
Una cadena constante MENSAJE con valor "Error en la entrada de datos".

Ejercicio 2
Defina los siguientes tipos de datos:
a)
b)
c)
d)
e)
f)
g)
h)

Un tipo Edad que represente la edad de una persona.


Un tipo Dni que represente el dni de una persona.
Un tipo Vocal que represente el conjunto de las cinco vocales.
Un tipo DiaSemana que represente los siete das de la semana.
Un tipo Mes que represente los doce meses del ao.
Un tipo PInt que represente un puntero a entero.
Un tipo PEdad que represente un puntero a Edad.
Un tipo PMes que represente un puntero a mes.

12. Introduccin al Lenguaje C

Ejercicio 3
Defina las siguientes variables:
a)
b)
c)
d)
e)
f)
g)
h)
i)
j)
k)
l)

Dos variables carcter c1 y c2 con valores iniciales A y B, respectivamente.


Dos variables enteras i, j.
Una variable real d.
Una variable encontrado de tipo lgico con valor inicial falso.
Una variable mayoria_de_edad de tipo Edad con valor inicial 18.
Una variable dia de tipo DiaSemana.
Una variable mes_de_nacimiento de tipo Mes.
Una variable pi de tipo puntero a entero.
Una variable pedad de tipo puntero a Edad.
Una variable pedad2 de tipo PEdad.
Una variable pmes de tipo puntero a Mes.
Una variable pmes2 de tipo PMes.

Ejercicio 4
Implemente las siguientes funciones:
a)

Una funcin que dado un nmero entero, devuelva cierto si es par. Para probarla escriba una funcin main que
muestre por la salida estndar un mensaje indicando si un nmero es par o impar.

b) Una funcin que dado un nmero real que representa el radio del crculo, devuelva su rea. Pruebe que la funcin
est bien implementada usando una funcin main. Defina el valor de como una constante.
c)

Una funcin que calcule el factorial de un nmero. Pruebe la funcin factorial en una funcin main.

d) Una funcin que dados tres enteros que representan las horas, minutos y segundos de un instante de tiempo,
devuelva el nmero de segundos transcurridos desde las cero horas hasta dicho instante de tiempo. Utilice la
frmula:
segundos_transcurridos = horas * 3600 + minutos * 60 + segundos
Pruebe que la funcin est bien implementada en una funcin main.
e)

Una funcin que dada una nota expresada en forma numrica devuelva uno de los siguientes valores, definidos en
un enumerado: SUSPENSO, APROBADO, NOTABLE, SOBRESALIENTE, VALOR_INCORRECTO. La correspondencia de
los valores numricos es la siguiente: 0 nota < 5 = SUSPENSO; 5 nota < 7 = APROBADO; 7 nota < 9 = NOTABLE;
y 9 nota 10 = SOBRESALIENTE. Cualquier otro valor numrico se corresponder con VALOR INCORRECTO.
Pruebe la funcin en un main.

f)

Una funcin que dado un carcter, indique su tipo mediante un enumerado. El enumerado podr tomar los
valores: MAYUSCULA (de la 'A' a la 'Z'), MINUSCULA (de la 'a' a la 'z'), DIGITO (del '0' al '9'), OTRO. Pruebe la funcin
en un main.

g)

Una funcin que devuelva cierto si un nmero es mltiplo de otro. Pruebe la funcin en una funcin main.

BLOQUE 2 Lectura y Escritura. Cadenas. Arrays


Ejercicio 5
Modifique las pruebas de los apartados del Ejercicio 4 para que se soliciten los datos necesarios por la entrada
estndar.

31

32

Fundamentos de Programacin

Ejercicio 6
En un archivo cadenas.c escriba las siguientes funciones:
a) Una funcin que dado un carcter devuelva cierto si dicho carcter es una vocal.
b) Una funcin que dada una cadena de caracteres devuelva el nmero de vocales que hay en la cadena.
c)

Una funcin que devuelva cierto si una palabra es un palndromo. Las palabras palndromos son aquellas que
se leen igual de izquierda a derecha que de derecha a izquierda. Por ejemplo, ana o reconocer seran
palndromos.

d) Una funcin que dado un vector de cadenas de caracteres y una cadena, devuelva cierto si la cadena est
incluida en el vector.
Escriba tambin los ficheros de cabecera (.h) que considere necesarios, as como, un fichero main.c en el que incluya
una funcin main para probar las funciones anteriores.

Ejercicio 7
Implemente una funcin que dado un array de enteros y la longitud del mismo, permita mediante parmetros de
entrada/salida el clculo a la vez de la suma, el mximo, el mnimo y la media de los valores de un array de enteros
dado. El prototipo de la funcin es:
void calculaSumMaxMinMed(const Vector, int, IntP, IntP, IntP, IntP, DoubleP);
Realice tambin las definiciones de los tipos Vector, IntP y DoubleP.

Ejercicio 8
Implemente la funcin con prototipo:
void leerDatos(Vector a, int aTam, IntP aLength);
donde a es el array a inicializar, aTam es el tamao mximo del array y aLength es el nmero real de valores que tiene
el array. Realice tambin un programa donde se utilice la funcin anterior para leer los valores del array desde la
entrada estndar.

BLOQUE 3 Struct. Paso de parmetros. Lectura de ficheros.


Ejercicio 9
Realice los siguientes apartados para poder trabajar con el tipo Punto en C:
a) Escriba un fichero de cabecera punto.h con las definiciones necesarias para trabajar con el tipo Punto.
b) Defina en el mismo fichero un tipo Poligono como un array de tipo Punto.
c)

Aada la definicin de un tipo enumerado que contenga los nombres de los cuatro cuadrantes y la palabra Ejes
para aquellos puntos que estn sobre los ejes.

d) Aada las definiciones de las siguientes funciones para el tipo Punto:


i.
double distanciaAlOrigen(Punto p);
ii.
Punto masCercanoAlOrigen(const Poligono pol, int polLength);
iii.
Cuadrante cuadrante(Punto p);

12. Introduccin al Lenguaje C

iv.
v.
vi.

Punto sumaPuntos(Punto p1, Punto p2);


Punto leePunto();
void leePoligono(Poligono pol, IntP polLength);

e) Escriba el fichero punto.c con el cdigo necesario.


f)

Escriba un fichero pruebaPunto.c que contenga un mtodo main donde se invoquen todos los mtodos
anteriores y se impriman los resultados en pantalla.

g)

Intente imprimir por pantalla el resultado de invocar el mtodo cuadrante. Qu especificador de formato
habr que usar?

h) Implemente un nuevo mtodo que devuelva una cadena de texto a partir de un parmetro de tipo Cuadrante,
con el siguiente prototipo:
void obtenerCadenaCuadrante (Cuadrante c, Cadena cad);

Ejercicio 10
Realice los siguientes apartados para poder trabajar con el tipo Album en C:
a)

Escriba en un fichero album.h las definiciones de tipos y estructuras necesarias para trabajar con los siguientes
tipos:
i. Cancion: ttulo, intrprete, duracin, ao
ii. Album: nombre, gnero musical, array de canciones
Teniendo en cuenta que:
iii. Un lbum tendr un mximo de 100 canciones.
iv. El gnero musical de un lbum debe ser uno de los siguientes: pop, rock, jazz, salsa, flamenco.

b) Defina tambin el tipo AlbumP como un tipo puntero del tipo Album.
c)

Aada al fichero album.h las declaraciones de los siguientes mtodos:


i. leeCancion. Lee la informacin de una cancin por teclado.
ii. leeAlbum. Lee desde teclado la informacin de un lbum.
iii. duracionTotal. Calcula la duracin total de todas las canciones de un lbum.
iv. masAntigua. Devuelve la cancin ms antigua de un lbum.
v. numeroDeCanciones. Devuelve el nmero de canciones de un intrprete determinado en un lbum.
vi. muestraCanciones. Muestra por pantalla la informacin de todas las canciones de un lbum, cada cancin
en una lnea.
vii. anyadeCancion. Aade una nueva cancin a un lbum. En caso de que el lbum est lleno se devolver el
valor -1. En otro caso devolver 0.
viii. subAlbum. Devuelve un album con aquellas canciones correspondientes a un ao determinado.

d) Escriba en un fichero album.c las implementaciones de todos los mtodos anteriores.


e)

Escriba un fichero pruebaAlbum.c que contenga un mtodo main donde se invoquen todos los mtodos anteriores
y se impriman los resultados en pantalla.

BLOQUE 4 Problemas de exmenes (bloques 1, 2 y 3).


Ejercicio 11
a) Escriba una sola sentencia para leer desde teclado los valores de varias variables de los siguientes tipos: una
cadena de caracteres, un entero largo y un carcter. Defina las variables de los tipos adecuados.

33

34

Fundamentos de Programacin

b) Defina un tipo para almacenar un punto en el plano.


c)

Defina un tipo para almacenar los puntos que conforman los vrtices de un polgono de a lo sumo 20 vrtices.

d) Escriba slo el prototipo de dos funciones distintas tal que cada una de ellas modifique las dos coordenadas de
un punto con dos valores que se pasan como argumentos. En una versin el punto modificado se devolver
como valor de retorno y en la otra versin el punto ser pasado como argumento o parmetro de
entrada/salida. Suponiendo definido el punto p, haga una invocacin a cada una de las dos posibilidades
cambiando el punto p al origen de coordenadas.
e) Escriba el cdigo de una funcin leePunto para leer desde teclado las coordenadas de un punto y devolverlo
como argumento de salida.
f)

Usando la funcin anterior escriba el cdigo de una funcin leePoligono que lea los vrtices de un polgono. El
nmero de vrtices se leer tambin por teclado en la misma funcin.

g)

Escriba un programa principal para probar leePoligono, mostrando el conjunto de vrtices ledos por pantalla
con el siguiente formato:
Las coordenadas del vrtice 1 son (3.2,4.7)
Las coordenadas del vrtice 2 son (-1.2,3.6)

Ejercicio 12
a) Defina los siguientes tipos:
i.
Un tipo que represente un valor lgico.
ii.
Un tipo que represente un jugador de baloncesto, cuyas propiedades son:
- Nombre, de tipo cadena de caracteres.
- Dorsal, de tipo entero.
- Posicin, de tipo enumerado con los valores BASE, ESCOLTA, ALERO, PIVOT, ALA-PIVOT.
- Promedio de Rebotes, de tipo real.
- Promedio de Puntos, de tipo real.
Si para el tipo jugador de baloncesto necesita algn tipo auxiliar, defnalo tambin.
iii.
Un tipo que represente un puntero a un jugador
iv.
Un tipo que represente un array de jugadores que tenga como mximo 50 jugadores.
b) Escriba una funcin que pida los datos de un jugador por la consola, y devuelva el jugador en un parmetro de
salida.
c)

Escriba slo el prototipo de un mtodo que sirva para leer un array de Jugadores por consola.

d) Un mtodo que dado un array de jugadores y un entero que representa la longitud de ese array, muestre por
consola el contenido de ese array con el siguiente formato:
Pau Gasol, 16, ALA-PIVOT, 11.3 Rebotes, 18.3 Puntos
Marc Gasol, 33, PIVOT, 9.3 Rebotes, 14.6 Puntos

e) Escriba una funcin main en la que declare un array de jugadores, y usando las funciones definidas en los
apartados anteriores pida por consola los datos de los jugadores, los almacene en el array y los muestre por
consola.

Ejercicio 13
a)

Defina las siguientes constantes:


MAXCAR de valor 256
MAXJUG de valor 20
NUMEQUIPOS de valor 4

12. Introduccin al Lenguaje C

b) Defina los siguientes tipos:


-

c)

Cadena como un array de MAXCAR elementos de tipo carcter.


ArrayCad como un array de MAXJUG elementos de tipo Cadena.
Equipo como un tipo que permita almacenar los siguientes campos para un equipo de ftbol: nombre,
puntos, goles a favor, goles en contra y un array con los nombres de los jugadores. El nmero de
jugadores depender de cada equipo, aunque nunca podr ser superior a MAXJUG.
Grupo como un array de MAXJUG elementos de tipo Equipo.

Escriba la cabecera de un mtodo que permita modificar los goles a favor, goles en contra y puntos de un
equipo. Realice una invocacin a dicho mtodo a partir de una variable de tipo Equipo y tres variables de tipo
int.

d) Implemente un mtodo que permita leer desde la entrada estndar un array de Cadena con los nombres de
los jugadores y devolverlo como parmetro de salida. Su cabecera debe ser: void leeJugadores(...). Utilice el
tipo ArrayCad del apartado primero, y tenga en cuenta que el mximo nmero de jugadores para un equipo
ser MAXJUG.
e) Implemente un mtodo que permita leer desde la entrada estndar un Equipo y lo devuelva como parmetro
de salida. Su cabecera debe ser: void leeEquipo(). Utilice para su implementacin el mtodo anterior y el tipo
Equipo.

Ejercicio 14
a) Defina un tipo Producto con las siguientes propiedades: identificador, de tipo cadena; nombre, de tipo cadena;
precio, de tipo real; unidades, de tipo entero; stock_minimo, de tipo entero. Defina tambin los siguientes
tipos: un tipo puntero a Producto y un tipo vector de Producto capaz de almacenar un nmero de productos
determinado por una constante. Defina los tipos auxiliares que sean necesarios.
b) Implemente una funcin que lea desde teclado los datos necesarios para un Producto.Una funcin que, a partir
del nombre de un fichero de texto, lea los datos necesarios para cargarlos en un vector de productos. El
formato de las lneas del fichero ser similar al del ejercicio 1 (sustituyendo las comas por blancos). La funcin
devolver un entero con el nmero de productos ledos o -1 si no pudo abrir el fichero.
c)

Implemente una funcin que devuelva el valor comercial (nmero de unidades multiplicado por el precio) de
todos los productos de un array.

d) Escriba slo el prototipo de una funcin que, dado un vector de productos, devuelva otro con todos los
productos cuyo nmero de unidades es menor al stock mnimo.
e) Escriba slo el prototipo de una funcin que, dado un array de productos, devuelva el de mayor precio y su
posicin.
f)

Para cada una de las funciones anteriores (tanto si se solicita el cdigo completo como slo el prototipo)
escriba una invocacin a la misma en un programa principal suponiendo definidas las siguientes variables:
VectorProducto v1, v2, v3;
Producto p1, p2, p3;
int a, b, c;
double x, y, z;
Cadena s1, s2, s3;

Ejercicio 15
a)

Escriba el contenido de persona.h. En l se tiene que definir:


- El tipo Cadena como un array de caracteres de un tamao determinado por una constante.

35

36

Fundamentos de Programacin

El tipo Persona, (nombre, apellido y edad).


El tipo VectorPersonas como un array de Persona un tamao determinado por una constante.

b) Escriba una funcin que reciba el nombre de un fichero que contiene los datos de una persona en cada lnea
separados por espacios (suponemos que en los nombres y apellidos no hay espacios) y que devuelva un vector
con los datos de esas personas y el nmero de lneas ledas, o -1 si no se pudo abrir el fichero.
c)

Escriba una funcin que lea desde teclado una Persona.

d) Escriba una funcin que dado un VectorPersonas y un entero d, devuelva las personas de edad mayor o igual a
d.
e) Escriba una funcin que dado un VectorPersonas devuelva la Persona de mayor edad. Si hay varias empatadas
a mayor edad deber devolver la primera de ellas.

Ejercicio 16
a)

Escriba el contenido de un fichero episodio.h en el que se incluya la definicin de los siguientes tipos:
- Un tipo Logico.
- Un tipo Cadena, de tamao determinado por una constante.
- El tipo Episodio con las siguientes propiedades: nomenclatura, de tipo Cadena; ttulo, de tipo Cadena;
subtitulado, de tipo Logico.
- El tipo EpisodioP como un puntero a Episodio.
- El tipo VectorEpisodio como un array de Episodio de un tamao determinado por una constante.

b) Escriba una funcin que reciba un VectorEpisodio, el nmero real de episodios que tiene el vector y un nombre
de fichero y escriba en ese fichero el contenido del vector con el formato nomenclatura-titulo-carcter, donde
carcter ser V si el episodio est subtitulado, y F en caso contrario.
c)

Escriba una funcin que lea por teclado los datos de un episodio y devuelva el episodio ledo.

d) Suponiendo definida una funcin que lee los datos de un conjunto de episodios por teclado y los almacena en
un vector de episodios, escriba el cdigo de una funcin main para leer por teclado un conjunto de episodios y
almacenarlos en un fichero llamado episodios.txt utilizando una de las funciones creadas anteriormente. La
cabecera de la funcin para leer los datos es: void leeEpisodios(VectorEpisodio , int *);
e) Escriba una funcin que dado un VectorEpisodio, devuelva cuntos episodios tienen subttulos.

Ejercicio 17
a)

Escriba el contenido de un fichero servicio.h en el que se incluya la definicin de los siguientes tipos:
- Un tipo Cadena, de tamao determinado por una constante previamente definida con valor 256.
- El tipo Servicio, con las siguientes propiedades:nombre, de tipo Cadena; categora, de tipo Cadena;
minAsistentes de tipo enterp; temporada, array de dos dimensiones de tipo entero
- El tipo ServicioP como un puntero a Servicio.
- El tipo VectorServicio como un array de Servicio de un tamao determinado por una constante
previamente definida con valor 100.
- El tipo Menu, con las siguientes propiedades: nombre, de tipo Cadena; numServicios, de tipo entero;
servicios, de tipo VectorServicio.
- El tipo MenuP como un puntero a Menu.

b) Escriba una funcin que lea por teclado los datos de un servicio y lo devuelva como parmetro de salida.
c)

Escriba una funcin que lea por teclado los datos de un men y lo devuelva como parmetro de salida.

d) Escriba una funcin main que lea por teclado un men y muestre en pantalla el nombre de cada servicio.
e) Escriba una funcin que dado un men devuelva el servicio ms caro como parmetro de salida.

También podría gustarte