Está en la página 1de 238

Introduccin al lenguaje C

Marta Zorrilla
Universidad de Cantabria

Marta Zorrilla Universidad de Cantabria

Introduccin al C

Objetivos:

Presentar la historia del lenguaje C y sus


caractersticas principales.
Presentar la estructura de un programa en C
mediante ejemplos sencillos.

Contenidos:

1. La historia del C.
2. Caractersticas.
3. Mi primer programa en C.
2

Marta Zorrilla Universidad de Cantabria

Historia del C

Muchas ideas provienen de BCPL (Martin Richards, 1967) y de B (Ken


Thompson, 1970).
C fue diseado originalmente en 1972 para el SO UNIX en el DEC PDP-11 por
Dennis Ritchie en los Laboratorios Bell.
Primer Libro de referencia de C: The C Programming Language (1978) de
Brian Kernighan y Dennis Ritchie.
En los 80, gran parte de la programacin se realiza en C.
En 1983 aparece C++ (orientado a objetos).
En 1989 aparece el estndar ANSI C.
En 1990 aparece el estndar ISO C (actual estndar de C). WG14 se
convierte en el comit oficial del estndar ISO C.
En dcada de los 90, WG14 trabaja en el estndar C9X/C99 que resuelve
problemas de fiabilidad del ANSI C, amplia su funcionalidad con nuevos tipos
de dato, funciones matemticas, arrays irrestringidos, etc.
3

Marta Zorrilla Universidad de Cantabria

Caractersticas del C

Lenguaje de programacin de propsito general, muy adecuado para


programacin de sistemas (unix fue escrito en C).
Lenguaje relativamente pequeo: solo ofrece sentencias de control
sencillas y funciones.
La E/S no forma parte del lenguaje, sino que se proporciona a travs
de una biblioteca de funciones.
Permite la agrupacin de instrucciones. Programacin estructurada.
Permite la separacin de un programa en mdulos que admiten
compilacin independiente. Diseo modular.
Programas portables.

Marta Zorrilla Universidad de Cantabria

Inconvenientes del C

No es un lenguaje fuertemente tipado.


Es bastante permisivo con la conversin de datos.
Sin una programacin metdica puede ser propenso a errores
difciles de encontrar.
La versatilidad de C permite crear programas difciles de leer.
#define _ -F<00||--F-OO--;
int F=00,OO=00;
main(){F_OO();printf("%1.3f\n",4.*-F/OO/OO);}F_OO()
{..}

Marta Zorrilla Universidad de Cantabria

Primer programa en C
/* Ejemplo 1. Programa DOCENA.C */
#include <stdio.h>
main ()
{
int docena;
docena = 12;
printf ("Una docena son %d unidades\n", docena);
}

Marta Zorrilla Universidad de Cantabria

Segundo programa en C
/* Ejemplo 1. Programa saludo.c*/
#include <stdio.h>
#define MENSAJE alumnos
/*prototipo funciones*/
int imprimir_saludo (char * destino);
int main (void)
{
int error=0;
error=imprimir_saludo (MENSAJE);
return(0);
}
int imprimir_saludo (char * destino)
{
printf (hola %s \n", destino);
return(0);
}
7

Marta Zorrilla Universidad de Cantabria

Crear, compilar y ejecutar un


programa C

Crear un fichero con extensin .c con un editor de texto


Mandato de compilacin bsico:
cc ejemplo.c
- Genera el cdigo objeto ejemplo.o
- Genera el ejecutable a.out
- El programa se ejecuta tecleando a.out

El mandato cc -c ejemplo.c genera el fichero objeto


ejemplo.o
El mandato cc ejemplo.o -o ejemplo genera el
ejecutable ejemplo
- El programa se ejecuta tecleando ejemplo.
8

Marta Zorrilla Universidad de Cantabria

Modelo de compilacin C

Marta Zorrilla Universidad de Cantabria

Entorno desarrollo IDE

10

Ejercicio

Marta Zorrilla Universidad de Cantabria


Sean dos cuadrados de lados L1 y L2 inscritos uno en
otro. Calcula el rea de la zona comprendida entre
ambos, utilizando para ello una funcin (que se llamar
AreaCuadrado) que devuelve el rea de un cuadrado
cuyo lado se pasa como argumento

#include <stdio.h>
int cuadrado (int);
int main (void)
{
int lado2, lado1;
printf ("dame lado del cuadrado 1:");
scanf( "%d",&lado1);
printf ("dame lado del cuadrado 2:");
scanf(" %d",&lado2);
printf ("El resultado de la diferencia es %d", cuadrado(lado1)-cuadrado(lado2));
return(0);
}
int cuadrado (int lado)
{
return(lado*lado);
}

11

Elementos de un programa
en C

12

Marta Zorrilla Universidad de Cantabria

Elementos de un programa C

Objetivos:

Mostrar la utilidad de documentar el cdigo utilizando los


comentarios.
Explicar los conceptos de variable y tipo de dato.
Conocer los identificadores vlidos y tipos de constantes.
Ensear las instrucciones de lectura y escritura junto con el formato
de los datos.

Contenidos:
1. Comentarios
2. Identificadores y palabras reservadas
3. Constantes
4. Variables y tipos de dato
5. Escritura de datos con printf()
6. Lectura de datos con scanf()
13

Marta Zorrilla Universidad de Cantabria

Elementos de un programa C

Bsicamente el C est compuesto por los


siguientes elementos:
Comentarios
Identificadores
Palabras reservadas
Variables y tipos de datos
Constantes
Operadores
14

Marta Zorrilla Universidad de Cantabria

Comentarios

Sirven para incrementar la legibilidad de los programas.


No se pueden anidar. Dentro de un comentario no puede
aparecer el smbolo /*

/* Este es un comentario que


ocupa ms de una lnea */
// Este comentario ocupa una sola lnea

15

Marta Zorrilla Universidad de Cantabria

Identificador

Nombre que se asigna a los distintos elementos del


programa (variables, funciones,).
Identificadores NO vlidos:

Empezar por
Empezar por un nmero
Utilizar la "

Ejemplos vlidos:
numero
area_circulo
valor_1
16

Marta Zorrilla Universidad de Cantabria

Palabras reservadas
auto
break
case
char
const
continue
default

do
double
else
enum
extern
float

for
goto
if
int
long
register

return
short
sizeof
static
struct
switch

typedef
union
unsigned
void
volatile
while

Es preciso insistir en que C hace distincin entre maysculas y minsculas.


Por lo tanto, la palabra reservada for no puede escribirse como FOR,
pues el compilador no la reconoce como una instruccin,
sino que la interpreta como un nombre de variable.
17

Marta Zorrilla Universidad de Cantabria

Variables

Identificador utilizado para representar un


cierto tipo de informacin.
Cada variable es de un tipo de dato
determinado.
Una variable puede almacenar diferentes
valores en distintas partes del programa.

18

Marta Zorrilla Universidad de Cantabria

Tipos de datos bsicos


TIPO

PALABRA
RESERVADA

TAMAO EN
BYTES

sin valor

void

carcter

char

int

coma flotante (simple


precisin)

float

coma flotante (doble


precisin)

double

entero

19

Marta Zorrilla Universidad de Cantabria

Tipos de datos. Modificadores


Modificadores

Tipo
char
int

short
long

Rango

Ocupa

unsigned

0 a 255

1 byte

signed

-128 a 127

1 byte

unsigned

0 a 65.535

2 bytes

signed

-32.768 a 32.767

2 bytes

unsigned

0 a 4.294.967.295

4 bytes

signed

-2.147.483.648 a 2.147.483.647 4 bytes

float

3,4*10-38 a 3,4*10+38

4 bytes

double

1,7*10-308 a 1,7*10+308

8 bytes

3,4*10-4932 a 1,1*10+4932

10 bytes

long

El tipo de dato int coincide con el tamao de palabra del procesador,


generalmente 4 bytes
20

Marta Zorrilla Universidad de Cantabria

Declaracin de variables

Una declaracin asocia un tipo de datos determinado a una o


ms variables.

El formato de una declaracin es:


tipo_de_dato var1, var2, ..., varN;

Ejemplos:

int a, b, c;
float numero_1, numero_2;
char letra;
unsigned long entero;

Deben declararse todas las variables antes de su uso.

Deben asignarse a las variables nombres significativos.


int temperatura;
int k;

21

Marta Zorrilla Universidad de Cantabria

Tipos definidos

Permite dar nuevo nombre a tipos de datos que ya existen,


siendo estos ms acordes con aquello que representan.

Sintaxis:
typedef tipo_basico nombre;

Declaracin :
typedef float Kg;
typedef float Mts;

Y su uso al declarar variables:


Kg peso;
Mts longitud;
22

Marta Zorrilla Universidad de Cantabria

La funcin printf()

Permite imprimir informacin por la salida


estndar (pantalla)

Formato:
printf(formato, argumentos);

Ejemplos:

printf("Hola mundo\n");
printf("El numero 28 es %d\n", 28);
printf("Imprimir %c %d %f\n", 'a', 28, 3.0e+8);
23

Marta Zorrilla Universidad de Cantabria

La funcin printf() (y 2)

Formatos.
TIPO DE
ARGUMENTO
Numrico

Carcter
Punteros

CARCTER
DE FORMATO
%d
%i
%o
%u
%x
%X
%f
%e
%g
%E
%G
%c
%s
%%
%n
%p

FORMATO DE
SALIDA
signed decimal int
signed decimal int
unsigned octal int
unsigned decimal int
unsigned hexadecimal int (con a, ..., f)
unsigned hexadecimal int (con A, ..., F)
[-]dddd.dddd
[-]d.dddd o bien e[+/-]ddd
el ms corto de %e y %f
[-]d.dddd o bien E[+/-]ddd
el ms corto de %E y %f
carcter simple
cadena de caracteres
el carcter %
se refieren a punteros y se
estudiarn en el Captulo 14
7
24

Marta Zorrilla Universidad de Cantabria

La funcin printf() (y 3)

Secuencias de escape.
CARCTER BARRA

SIGNIFICADO

\a

Alarma (Beep)

\b

Retroceso (BS)

\t

Tabulador Horizontal (HT)

\n

Nueva Lnea (LF)

\v

Tabulador Vertical (VT)

\f

Nueva Pgina (FF)

\r

Retorno

\"

Comillas dobles

\'

Comilla simple

\\

Barra invertida

25

Marta Zorrilla Universidad de Cantabria

La funcin printf (y 4)

Especificadores de ancho de campo:

printf("Numero entero = %5d \n", 28);


produce la salida:
Numero entero = 28
printf("Numero real = %5.4f \n", 28.2);
produce la salida:
Numero real = 28.2000

26

Marta Zorrilla Universidad de Cantabria

Funcin scanf()

Permite leer datos del usuario.


La funcin devuelve el nmero de datos que se han
ledo bien.
No va texto
Formato:

scanf(formato, argumentos);

Especificadores de formato igual que printf().

Ejemplos:

scanf("%f", &numero);
&
scanf("%c\n", &letra);
scanf("%f %d %c", &real, &entero, &letra);
scanf("%ld", &entero_largo);
no &
scanf("%s", cadena);

27

Marta Zorrilla Universidad de Cantabria

Funcin scanf() (y 2)

Ejemplo: lee un nmero entero y lo eleva al


cuadrado:
#include <stdio.h>
void main()
{

Comenzar
ESCRIBIR
Dame numero
LEER
numero

cuadrado=numero * numero

int numero;
int cuadrado;
ESCRIBIR
numero y cuadrado
printf("Introduzca un numero:");
scanf("%d", &numero);
FIN
cuadrado = numero * numero;
printf("El cuadrado de %d es %d\n", numero,cuadrado);
28

Marta Zorrilla Universidad de Cantabria

Constantes simblicas

Para evitar el uso de valores constantes dentro


del cdigo, se definen las constantes simblicas
Suele escribirse en maysculas.
#define
#define
#define
#define

PI 3.141593
CIERTO 1
FALSO 0
AMIGA "Marta"

no acaba en ;

29

Marta Zorrilla Universidad de Cantabria

Constantes o literales

Caracteres:

Valores enteros:

Ejemplos: "Marta ", " barco"

Notacin decimal: 987


Notacin hexadecimal: 0x25 0X25
Notacin octal: 034
Enteros sin signo: 485U
Enteros de tipo long: 485L
Enteros sin signo de tipo long: 485UL
Valores negativos (signo menos): -987

Valores reales (coma flotante):

Ejemplos: 12, 14, 8., .34


Notacin exponencial: .2e+9, 1.04E-12
Valores negativos (signo menos): -12 -2e+9
30

Marta Zorrilla Universidad de Cantabria

Ejemplo.

Programa que lee el radio de un crculo y calcula su rea

#include <stdio.h>
#define PI 3.141593
void main()
{
float radio;
float area;
printf("Introduzca el radio: ");
scanf("%f", &radio);
area = PI * radio * radio;
printf("El area del circulo es %5.4f \n", area);
}

Comenzar
PI =3.141593
ESCRIBIR
Dame radio
LEER radio

area = PI * radio * radio

ESCRIBIR
area

FIN

31

Marta Zorrilla Universidad de Cantabria

Ejercicios

Encuentra errores
include studio.h
/* Programa que dice cuntos das hay en una semana /*
main {}
(
int d
d := 7;
print (Hay d das en una semana);

32

Marta Zorrilla Universidad de Cantabria

Ejercicios

Indica cul sera la salida de cada uno de los


siguientes grupos de sentencias:

a) printf ("Historias de cronopios y famas.");


printf ("Autor: Julio Cortzar");
b) printf ("Cuntas lneas \nocupa esto?");
c) printf ("Estamos \naprendiendo /naprogramar en C");
d) int num;
num = 2;
printf ("%d + %d = %d", num, num, num + num);

33

Operadores y expresiones

34

Marta Zorrilla Universidad de Cantabria

Operadores y expresiones

Objetivos:

Mostrar el concepto de expresin, operador y sentencia.


Mostrar el repertorio de operadores de C y el orden de precedencia.

Contenidos:
1. Expresiones y sentencias
2. Operador asignacin. Conversin de tipos
3. Operadores aritmticos
4. Operadores relacionales
5. Operadores lgicos
6. Operadores de asignacin compuestos
7. Precedencia
35

Marta Zorrilla Universidad de Cantabria

Expresiones y sentencias

Sentencia: especifica una accin a realizar

printf()

Expresin: secuencia de operadores y operandos que


especifican un valor

Ej.

Ej.

4+5

Una expresin se convierte en una sentencia cuando va seguida de


un punto y coma. Cuando un grupo de sentencias se encierran entre
llaves { }, forman un bloque, sintcticamente equivalente a una
sentencia.
36

Marta Zorrilla Universidad de Cantabria

Operador de asignacin

Forma general: identificador = expresin ;


Ejemplos:
a = 3;
area = lado * lado;

El operador de asignacin = y el de igualdad ==

Asignaciones mltiples:
id_1 = id_2 = ... = expresin

Las asignaciones se efectan de derecha a izquierda.


En i = j = 5
1. A j se le asigna 5
2. A i se le asigna el valor de j
37

Marta Zorrilla Universidad de Cantabria

Reglas de asignacin

Si los dos operandos en una sentencia de asignacin son de tipos


distintos, entonces el valor del operando de la derecha ser
automticamente convertido al tipo del operando de la izquierda.
Adems:

1. Un valor en coma flotante se puede truncar si se asigna a una variable


de tipo entero.
2. Un valor de doble precisin puede redondearse si se asigna a una
variable de coma flotante de simple precisin.
3. Una cantidad entera puede alterarse si se asigna a una variable de tipo
entero corto o a una variable de tipo carcter.

Es importante en C utilizar de forma correcta la conversin de tipos.

38

Marta Zorrilla Universidad de Cantabria

Conversin de tipos
(tipo de dato) expresin
int x;
x = 5;
y = x / 2;

el valor asignado a la variable y ser 2, pues / realiza una divisin entera.


int x;
x = 5;
y = (float) x / 2;

Ahora, la variable y almacena el valor 2.5.


int x;
x = 5;
y = (float) (x / 2);

no se asigna a y el valor 2.5, sino 2, ya que los parntesis que envuelven a la expresin
x / 2 hacen que primero se efecte la divisin entera y luego la conversin a flotante

39

Marta Zorrilla Universidad de Cantabria

Operadores aritmticos
Divisin entera ( / ): divisin de una cantidad entera por otra se desprecia la parte
decimal del cociente.
El operador % requiere que los dos operandos sean enteros.
La mayora de las versiones de C asignan al resto el mismo signo del primer operando.
Valores negativos con el signo OPERADOR
UNARIOS

BINARIOS

DESCRIPCIN
Cambio de signo

--

Decremento

++

Incremento

Resta

Suma

Producto

Divisin

Resto de divisin entera

40

Marta Zorrilla Universidad de Cantabria

Ejemplo
int x, y;
x = 9;
y = 2;

la operacin x / y devuelve el valor 4, mientras que la


operacin x % y devuelve 1. Sin embargo, despus de las
sentencias
float x;
int y;
x = 9.0;
y = 2;
la operacin x / y devuelve 4.5, no pudindose aplicar, en este
caso, el operador % puesto que uno de los operandos no es
entero.
41

Marta Zorrilla Universidad de Cantabria

Operadores incremento, decremento

La expresin

es equivalente a

i++;
++i;
i--;
--i;

i
i
i
i

=
=
=
=

i
i
i
i

+ 1;
+ 1;
- 1;
- 1;

Si el operador sigue al operando el valor del operando se modificar despus


de su utilizacin. Si el operador precede al operando el valor del operando se
modificar antes de su utilizacin.
Ejemplo: si a = 1
printf("a
printf("a
printf("a
printf("a

=
=
=
=

%d
%d
%d
%d

\n",
\n",
\n",
\n",

Imprime:
a);
++a);
a++);
a);

a
a
a
a

=
=
=
=

1
2
2
3
42

Marta Zorrilla Universidad de Cantabria

Operadores relacionales
Se utilizan para formar expresiones lgicas.
El resultado es un valor entero que puede ser:
cierto, se representa con un 1
falso, se representa con un 0
BINARIOS

Ejemplo 1: Si a = 1 y b = 2
Expresin
a<b
a>b
(a + b) ! = 3
a == b
a == 1

Valor
1
0
0
0
1

Interpretacin
cierto
falso
falso
falso
cierto

OPERADOR

DESCRIPCIN

>

Mayor que

>=

Mayor o igual que

<

Menor que

<=

Menor o igual que

==

Igual que

!=

Diferente que

43

Marta Zorrilla Universidad de Cantabria

Operadores lgicos
Actan sobre operandos que son a su vez expresiones lgicas que se
interpretan como:
cierto, cualquier valor distinto de 0
falso, el valor 0
Tabla de verdad
a

!a

a && b

a || b

OPERADOR DESCRIPCIN
UNARIOS
BINARIOS

!
&&
||

not
and
or

44

Marta Zorrilla Universidad de Cantabria

Ejemplo

&& y || se evalan de izquierda a derecha.


! se evala de derecha a izquierda.

Ejemplos:

si a = 7 y b = 3

Expresin
(a + b) < 10
!((a + b) < 10)
(a ! = 2) || ((a +b) <= 10)
(a > 4) && (b < 5)

Valor
0
1
1
1

Interpretacin
falso
cierto
cierto
cierto

45

Operadores de asignacin
compuestos
Marta Zorrilla Universidad de Cantabria

El operador de asignacin se puede combinar con otros


operadores como *, /, %, +, -, <<, >>, &, |, ^ para
operaciones acumulativas
es equivalente a
m *= 5;

m = m * 5;

m += b;

m = m + b;

m += y - 3;

m = m + y - 3;

m - = (y = 5);

m = m - (y = 5);

46

Marta Zorrilla Universidad de Cantabria

Precedencia
Evaluacin a
igual nivel de
prioridad

Nivel de
prioridad

Operadores

()

[]

->

++

--

<<

<

==

&

10

11

&&

12

||

13

?:

14

operadores de asignacin

15

(cast)

* & sizeof

>>
<=

>

>=

!=

47

Marta Zorrilla Universidad de Cantabria

Ejercicios

Indica cules de los siguientes identificadores no son correctos y por


qu.
a)
e)

contador
dias2

b) CONTADOR c) _hola
d) hola_
f) 2dias
g) Suma_Total h) Suma-Total

Sean x, y, z, u, v y t, variables que contienen, respectivamente, los


valores 2, 3, 4, 5, 6 y 7, qu almacenarn despus de ejecutar las
siguientes sentencias?
x++;
y = ++z;
t = - -v;
v = x + (y *= 3) / 2;
u = x + y / 2;
48

Marta Zorrilla Universidad de Cantabria

Ejemplo
Programa que convierte grados Fahrenheit a grados centgrados.
C = (5/9) * (F - 32)
#include <stdio.h>
void main()
{
float centigrados;
float fahrenheit;

printf("Introduzca una temperatura en grados fahrenheit: ");


scanf("%f", &fahrenheit);
centigrados = 5.0/9 * (fahrenheit - 32);
printf("%f grados fahrenheit = %f grados centigrados \n", fahrenheit, centigrados);

49

Marta Zorrilla Universidad de Cantabria

ERRORES COMUNES

Olvidar que el resultado de dividir dos enteros es entero


Realizar divisin por cero
Olvidar la prioridad de los operadores
Errores en la conversin de tipos
Confundir el operador de igualdad y el de asignacin

50

Funciones

51

Marta Zorrilla Universidad de Cantabria

Introduccin a funciones

Objetivos:

Introducir al alumno en el diseo estructurado.


Presentar el concepto de funcin.
Mostrar la definicin y declaracin de funciones en C.

Contenidos:

1. Introduccin al diseo estructurado. Concepto de funcin


2. Definicin de funciones
o Argumentos
o Valor de retorno
o Llamada a funcin

3. Declaracin de funciones. Prototipos


4. Ejemplos

52

Marta Zorrilla Universidad de Cantabria

Introduccin

Una funcin es un segmento de programa que realiza una


determinada tarea.

Todo programa C consta de una o ms funciones.

Una de estas funciones se debe llamar main()

Todo programa comienza su ejecucin en la funcin main()

El uso de funciones permite la descomposicin y desarrollo


modular. Permite dividir un programa en componentes ms
pequeos. reutilizacin

53

Marta Zorrilla Universidad de Cantabria

Definicin de una funcin


tipo nombre_func (tipo1 arg1, ..., tipoN argN)
{
/* CUERPO DE LA FUNCION */
}

Los argumentos se denominan parmetros formales.


La funcin devuelve un valor de tipo de dato tipo

Si se omite tipo se considera que devuelve un int


Si no devuelve ningn tipo void
Si no tiene argumentos void

void explicacion(void)

Entre llaves se encuentra el cuerpo de la funcin (igual que main()).


La sentencia return finaliza la ejecucin y devuelve un valor a la funcin que
realiz la llamada.
return(expresion);

En C no se pueden anidar funciones

54

Marta Zorrilla Universidad de Cantabria

Declaracin de funciones:
prototipos

No es obligatorio pero si aconsejable.


Permite la comprobacin de errores entre las llamadas a
una funcin y la definicin de la funcin correspondiente.

tipo nombre_func (tipo1 arg1, ..., tipoN argN);

55

Marta Zorrilla Universidad de Cantabria

Llamadas a funciones

Para llamar a una funcin se especifica su nombre y la lista de argumentos


sin poner el tipo de dato.

nombre_func (var1,var2,,varN);

Parmetros formales: los que aparecen en la definicin de la funcin.


Parmetros reales: los que se pasan en la llamada a la funcin.
En una llamada habr un argumento real por cada argumento formal,
respetando el orden de la declaracin.
Los parmetros reales pueden ser:

Constantes.
Variables simples.
Expresiones complejas.

Deben ser del mismo tipo de datos que el argumento formal


correspondiente.
Cuando se pasa un valor a una funcin se copia el argumento real en el
argumento formal.

56

Marta Zorrilla Universidad de Cantabria

Paso de parmetros por valor

En las llamadas por valor se hace una copia del valor del
argumento en el parmetro formal.
La funcin opera internamente con estos ltimos.
Como las variables locales a una funcin (y los parmetros
formales lo son) se crean al entrar a la funcin y se
destruyen al salir de ella, cualquier cambio realizado por la
funcin en los parmetros formales no tiene ningn efecto
sobre los argumentos.

57

Marta Zorrilla Universidad de Cantabria

Ejemplo
Programa que calcula el mximo de dos nmeros.

58

Marta Zorrilla Universidad de Cantabria

Ejemplo:

Funcin que calcula x elevado a y (con y entero)

#include <math.h>
float potencia (float x, int y); /* prototipo */
float potencia (float x, int y) /* definicin */
{
int i;
float prod = 1;
prod = pow(x,y);
return(prod);
}
59

Marta Zorrilla Universidad de Cantabria

Ejemplo 3

Programa que indica si un nmero es cuadrado perfecto.

#include <stdio.h>
#include <math.h>
#define TRUE 1
#define FALSE 0
void explicacion(void);
int cuadrado_perfecto(int x);
void main()
{
int n, perfecto;
explicacion();
scanf("%d", &n);
perfecto = cuadrado_perfecto(n);
if (perfecto)
printf("%d es cuadrado perfecto.\n", n);
else
printf("%d no es cuadrado perfecto.\n", n);
}

60

Marta Zorrilla Universidad de Cantabria

Ejemplo 3 - Continuacin
void explicacion(void)
{
printf("Este programa dice si un numero ");
printf("es cuadrado perfecto \n");
printf("Introduzca un numero: );
}
int cuadrado_perfecto(int x)
{
int raiz;
int perfecto;
raiz = (int) sqrt(x);

if (x == raiz * raiz)
perfecto = TRUE; /* cuadrado perfecto */
else
perfecto = FALSE; /* no es cuadrado perfecto */
return(perfecto);
61

Marta Zorrilla Universidad de Cantabria

Paso de parmetros por


referencia

Hasta ahora las funciones solo devolvan un valor, pero qu pasa si


tienen que devolver ms?

En este caso, se requiere pasar parmetros por referencia

La declaracin de una funcin en este caso sera


void nombreFunc (tipo in1, ..., tipo inN, tipo *out1, tipo *outN)
{
/* CUERPO DE LA FUNCION */
}

La llamada a la funcin
nombre_func (in1, ..., inN, &out1, , &outN);
62

Marta Zorrilla Universidad de Cantabria

Paso de parmetros por


referencia (II)

En este tipo de llamadas los argumentos contienen direcciones de


variables.

Dentro de la funcin la direccin se utiliza para acceder al argumento


real.

En las llamadas por referencia cualquier cambio en la funcin tiene


efecto sobre la variable cuya direccin se pas en el argumento. No
hay un proceso de creacin/destruccin de esa direccin.
Aunque en C todas las llamadas a funciones se hacen por valor,
pueden simularse llamadas por referencia utilizando los operadores &
(direccin) y * (en la direccin).
Mediante & podemos pasar direcciones de variables en lugar de
valores, y trabajar internamente en la funcin con los contenidos,
mediante el operador *.
63

Marta Zorrilla Universidad de Cantabria

Ejemplo 3 con parmetros por


referencia
void explicacion ( int *numero)
{
printf("Este programa dice si un numero ");
printf("es cuadrado perfecto \n");
printf("Introduzca un numero: );
scanf("%d", *&n);
}
void main()
{
int n, perfecto;
explicacion(&n);
perfecto = cuadrado_perfecto(n);
..
}

64

Marta Zorrilla Universidad de Cantabria

Ejercicio 4

Programa que calcula la hipotenusa de un


tringulo rectngulo.
h = (a2 + b2)
Pasos a seguir:

1. Leer a y b funcin leer


2. Calcular h segn la frmula dada definimos
una funcin hipotenusa
3. Imprimir el valor de h usar printf().
65

Marta Zorrilla Universidad de Cantabria

Solucin
#include <stdio.h>
#include <math.h>
void hipotenusa(float a, float b, float *h)
{
*h = sqrt(pow(a,2) + pow(b, 2));
}

void main()
{
float a, b, h;
leer (&a,&b);
hipotenusa(a,b,&h);
printf("La hipotenusa es %f\n", h);
}

void leer (float *a, float *b)


{
printf("Dame valores a y b:\n");
scanf("%f %f", *&a, *&b);
}
66

Marta Zorrilla Universidad de Cantabria

Recapitulacin

Antes de escribir un programa:

Leerlo detenidamente
Hacer pseudocdigo o diagrama de flujo
Decidir divisin en funciones
Determinar parmetros de entrada y salida
Desde main() invocar a las funciones

67

Sentencias de control

68

Marta Zorrilla Universidad de Cantabria

Estructuras de control

Objetivos:

Introducir los tres tipos bsicos de sentencias de control: secuencia,


seleccin e iteracin.
Explicar la sintaxis y la semntica de las sentencias de control
dedicadas a definir estructuras de seleccin.

Contenidos:
1. Tipos de estructuras
2. Estructuras condicionales
o Instruccin if - else
o Instruccin switch

3. Instruccin break

69

Marta Zorrilla Universidad de Cantabria

Tipos de estructuras

Secuencia: ejecucin
sucesiva de dos o ms
operaciones.
Seleccin: se realiza
una u otra operacin,
dependiendo de una
condicin.
Iteracin: repeticin de
una operacin mientras
se cumpla una
condicin.
70

Marta Zorrilla Universidad de Cantabria

If - else
if (expresin) sentencia;
o bien
if (expresin) sentencia;
else sentencia;

71

Marta Zorrilla Universidad de Cantabria

Ejemplo if - else

Programa que lee un nmero y dice si es par o impar.

#include <stdio.h>
main()
{
int numero;
/* Leer el numero */
printf("Introduzca un numero: ");
scanf("%d", &numero);
if ((numero % 2) == 0)
printf("El numero %d es par.\n", numero);
else
printf("El numero %d es impar.\n", numero);
}
72

Marta Zorrilla Universidad de Cantabria

Operador condicional

Se utiliza para sentencias if-else simples


y=(x>9 ? 100 : 200);
if (x > 9) {
y=100;
}
else {
y=200;

LO MISMO

}
73

Marta Zorrilla Universidad de Cantabria

switch

Tipo entero o letra

switch (variable) {
case cte1: sentencia;
break;
case cte2: sentencia;
break;
...
...
default: sentencia;
}
74

Marta Zorrilla Universidad de Cantabria

Ejemplo switch
#include <stdio.h>
void main()
{
char letra;
printf("Introduzca una letra: ");
scanf("%c", &letra);
switch(letra)
{
case 'a':
case 'A':
printf("Vocal %c\n", letra);
break;
case 'e':
case 'E':
printf("Vocal %c\n", letra);
break;

case 'i':
case 'I':
printf("Vocal %c\n", letra);
break;
case 'o':
case 'O':
printf("Vocal %c\n", letra);
break;
case 'u':
case 'U':
printf("Vocal %c\n", letra);
break;
default:
printf("Consonante %c\n",
letra);

75

Marta Zorrilla Universidad de Cantabria

Bucles

Objetivos:

Explicar la sintaxis y la semntica de las sentencias de control


dedicadas a definir estructuras de iteracin.
Mostrar patrones habituales de concatenacin de sentencias de
control con vistas a su utilizacin en el seno de un programa real.

Contenidos:
1. Bucles
a. Instruccin for
b. Instruccin while
c. Instruccin do - while

2. Instrucciones break y continue


3. Bucles anidados
76

Marta Zorrilla Universidad de Cantabria

Instruccin for
for (inicializacin; condicin; incremento)
sentencia;

Inicializacin: se inicializa algn parmetro que controla la repeticin


del bucle.
Condicin: es una condicin que debe ser cierta para que se ejecute
sentencia.
Incremento: se utiliza para modificar el valor del parmetro.
El bucle se repite mientras condicin no sea cero (falso).
Si sentencia es compuesta se encierra entre { }
incializacin e incremento se pueden omitir.
Si se omite condicin se asumir el valor permanente de 1 (cierto) y el
bucle se ejecutar de forma indefinida.
77

Marta Zorrilla Universidad de Cantabria

Ejemplo for

Programa que imprime los 100 primeros nmeros

#include <stdio.h>
void main()
{
int numero;
for (numero=0; numero <100; numero++)
printf("%d\n", numero);
}

78

Marta Zorrilla Universidad de Cantabria

Instruccin while
while (expresin)
sentencia;

sentencia se ejecutar mientras el valor de expresin


sea verdadero (distinto de 0).
Primero se evala expresin.
Lo normal es que sentencia incluya algn elemento
que altere el valor de expresin, proporcionando la
condicin de salida del bucle.
Si la sentencia es compuesta se encierra entre { }
79

Marta Zorrilla Universidad de Cantabria

Ejemplo while

lee un nmero N y calcula 1 + 2 + 3 + + N

#include <stdio.h>
void main()
{
int N;
int suma = 0;
/* leer el numero N */
printf("N: ");
scanf("%d", &N);
while (N > 0)
{
suma = suma + N;
N = N - 1; /* equivalente a N-- */
}
printf("1 + 2 +...+ N = %d\n", suma);
}
80

Marta Zorrilla Universidad de Cantabria

do - while
do
sentencia;
while (expresin);

sentencia se ejecutar mientras el valor de expresin sea verdadero


(distinto de 0).
sentencia siempre se ejecuta al menos una vez (diferente a while).
Lo normal es que sentencia incluya algn elemento que altere el
valor de expresin, proporcionando la condicin de salida del bucle.
Si la sentencia es compuesta se encierra entre { }
Para la mayora de las aplicaciones es mejor y ms natural
comprobar la condicin antes de ejecutar el bucle (while).
81

Marta Zorrilla Universidad de Cantabria

Ejemplo do -while

Programa que lee de forma repetida un nmero e indica si es par o


impar. El programa se repite mientras el nmero sea distinto de cero.

#include <stdio.h>
void main()
{
int numero;
do
{
/* se lee el numero */
printf("Introduzca un numero: ");
scanf("%d", &numero);
if ((numero % 2) == 0)
printf("El numero %d es par.\n", numero);
else
printf("El numero %d es par.\n", numero);
}
while (numero != 0)
}

82

Marta Zorrilla Universidad de Cantabria

Bucles anidados

Los bucles se pueden anidar pero es importante estructurarlos de forma correcta.


Ejemplo: Calcular 1 + 2 + N mientras N sea distinto de 0.

#include <stdio.h>
main()
{
int N, suma, j;
do
{

/* leer el numero N */
printf("Introduzca N: ");
scanf("%d", &N);
suma = 0;
for (j = 0; j <= N; j++)
/* bucle anidado */
suma = suma + j;
printf("1 + 2 + ... + N = %d\n", suma);
} while (N > 0);
/* fin del bucle do */

83

Marta Zorrilla Universidad de Cantabria

Instruccin break

Se utiliza para terminar la ejecucin de bucles o salir de una


sentencia switch.

Es necesaria en la sentencia switch para transferir el control fuera de


la misma.

En caso de bucles anidados, el control se transfiere fuera de la


sentencia ms interna en la que se encuentre, pero no fuera de las
externas.

No es aconsejable el uso de esta sentencia en bucles pues es


contrario a la programacin estructurada.

Puede ser til cuando se detectan errores o condiciones anormales.


84

Ej.

#include <stdio.h>
Marta Zorrilla Universidad de Cantabria
void main()
{
int opcion;
printf ("1 - Mensaje pantalla \n");
printf ("2 - salir \n");
printf (" cualquier carcter, no hace nada\n");
printf("Elija la opcin: ");
scanf("%d", &opcion);
while (opcion)
{
switch(opcion)
{
case 1:
printf("Hola, selecciono opcion %d\n" , opcion);
break;
case 2:
printf ("Adios \n");
return;
break;
default:
printf("Seleccion invalida. Intentelo de nuevo\n");
}
printf("Elija la opcion: ");
scanf("%d", &opcion);
}
}

85

Marta Zorrilla Universidad de Cantabria

Sentencia continue

Esta sentencia se utiliza en los bucles for,


while y do/while.
Cuando se ejecuta, fuerza un nuevo ciclo del
bucle, saltndose cualquier sentencia
posterior.

86

Marta Zorrilla Universidad de Cantabria

Ejemplo continue
#include <stdio.h>
#include <conio.h>
void main ()
{
int n;
int positivos = 0;
do {

printf ("\n Teclea un nmero (-99 finaliza): ");


scanf ("%d", &n);
if (n <= 0) continue;
positivos++;
} while (n != -99);
printf ("\n Has tecleado %d nmeros positivos", positivos);
La sentencia positivos++ slo se ejecuta cuando n es un nmero
positivo. Si n es negativo o vale 0, se ejecuta continue que fuerza una
87
nueva evaluacin de la condicin de salida del bucle.

Marta Zorrilla Universidad de Cantabria

Tabla de comparativas
Valores
iniciales,
operaciones
previas

Cond. para
seguir
repitiendo

Cuando se
comprueba

for

1 campo

2 campo

Antes de cada 3 campo


vuelta

si

while

Hay que ponerlo


fuera, antes del
ciclo

En el while entre
parntesis

Antes de cada Dentro del ciclo


vuelta
despus de las
instrucciones a
repetir

No

do
while

Hay que ponerlo


fuera, antes del
ciclo

En el while entre
parntesis

Despus de
cada vuelta

no

Cambios que
hay que hacer

Dentro del ciclo


despus de las
instrucciones a
repetir

pueden
quedar
campos
vacos?

88

Marta Zorrilla Universidad de Cantabria

Ejercicios
Escriba un programa
que calcule xn, siendo
x y n dos nmeros que
se introducen por
teclado

#include <stdio.h>
void main()
{
int n,x,i;
float potencia=1;
printf("Dame x y n \n: ");
scanf("%d %d", &x, &n);
for (i=0; i<n ; i++) {
potencia=potencia * x;
}
printf("El resultado es: %f\n", potencia);
}
89

Marta Zorrilla Universidad de Cantabria


Escriba un
programa que calcule e imprima la
suma de los pares y de los impares comprendidos
entre dos valores que se piden por teclado (x y n)

#include <stdio.h>
void leer (int *a, int *b)
{
do{
printf("Solicito dos numeros a<b \n");
printf("Dame a y b \n: ");
scanf("%d %d", *&a , *&b);
} while (a>b);
}

void main()
{
int n,x;
leer (&x,&n);
calcula(x,n);
}

void calcula (int x, int n)


{
int i, int par=0, impar=0;
for (i=x; i<=n; i++ ) {
if ((i%2)==0) par+=i;
else impar+=i;
}
printf("El resultado suma par: %d e impar: %d \n", par, impar);
}

90

Marta Zorrilla Universidad de Cantabria

Ejemplo - funciones y bucles


#include <stdio.h>
mensaje ()
{
printf ("\nTeclee un nmero (0 finaliza): ");
}
int lee_numero ()
{
int n;
scanf ("%d", &n);
return n;
}
cuadrado (int x)
{
printf ("\nEl cuadrado es %d", x * x);
}
void main ()
{
int t;
for (mensaje (); t = lee_numero (); cuadrado (t));
}

91

Recursividad

92

Marta Zorrilla Universidad de Cantabria

Recursividad

Objetivos:

Repaso: paso de parmetros por valor y por referencia a


una funcin.
Mostrar la capacidad de la recursin y las funciones
recursivas.

Contenidos:
1.Paso de parmetros a una funcin
2.Recursividad
93

Marta Zorrilla Universidad de Cantabria

Paso de parmetros por valor

En las llamadas por valor se hace una copia del valor del
argumento en el parmetro formal.
La funcin opera internamente con estos ltimos.
Como las variables locales a una funcin (y los parmetros
formales lo son) se crean al entrar a la funcin y se
destruyen al salir de ella, cualquier cambio realizado por la
funcin en los parmetros formales no tiene ningn efecto
sobre los argumentos.

94

Marta Zorrilla Universidad de Cantabria

Ejemplo

95

Marta Zorrilla Universidad de Cantabria

Paso de parmetros por


referencia

En este tipo de llamadas los argumentos contienen direcciones de


variables.

Dentro de la funcin la direccin se utiliza para acceder al argumento


real.

En las llamadas por referencia cualquier cambio en la funcin tiene


efecto sobre la variable cuya direccin se pas en el argumento. No
hay un proceso de creacin/destruccin de esa direccin.
Aunque en C todas las llamadas a funciones se hacen por valor,
pueden simularse llamadas por referencia utilizando los operadores &
(direccin) y * (en la direccin).
Mediante & podemos pasar direcciones de variables en lugar de
valores, y trabajar internamente en la funcin con los contenidos,
mediante el operador *.
96

Marta Zorrilla Universidad de Cantabria

Ejemplo

x, y punteros

#include <stdio.h>
void funcion(int *a, int *b); /* prototipo */
main()
{
int x = 2;
int y = 5;
printf("Antes x = %d, y = %d\n", x, y);
funcion(&x, &y);
printf("Despues x = %d, y = %d\n", x, y);
}
void funcion(int *a, int *b)
{
*a = 0;
*b = 0;
printf("Dentro *a = %d, *b = %d\n", *a, *b);
return;
}
97

Marta Zorrilla Universidad de Cantabria

Ejemplo

Funcin que intercambia el valor de dos variables.

#include <stdio.h>
void swap_ref (int *a, int *b); /* prototipo */
void main()
{
int x = 2;
int y = 5;
printf("Antes x = %d, y = %d\n", x, y);
swap(&x, &y);
printf("Despues x = %d, y = %d\n", x, y);
}
void swap_ref (int *a, int *b)
{
int temp;
temp = *b;
*b = *a;
*a = temp;
}
98

Marta Zorrilla Universidad de Cantabria

Recursividad

Una funcin se llama a s misma de forma


repetida hasta que se cumpla alguna condicin.

Ejemplo: el factorial de un nmero:


long int factorial(int n)
{
if (n <= 1)
return(1);
else
return(n * factorial(n-1));
}
99

Marta Zorrilla Universidad de Cantabria

Ejemplo torres de Hanoi


#include <stdio.h>
void transferir( int n, char desde, char hacia, char temp);
void main()
{
int n;
printf ("Bienvenido a las torres de Hanoi \n");
printf ("Cuntos discos?\n");
scanf("%d", &n);
transferir(n,'I','D','C');
}

Izquierda

Centro

Derecha

100

Marta Zorrilla Universidad de Cantabria

Ejemplo torres de Hanoi (y 2)


void transferir(int n, char desde, char hacia, char temp)
{
/* transferir n discos de un pivote a otro*/
/* n = numero de discos
desde = origen
hacia = destino
temp = almacenamiento temporal */
if (n>0)
{
transferir (n-1, desde, temp, hacia);
printf ("mover disco %d desde %c hasta %c\n", n, desde, hacia);
transferir (n-1, temp, hacia,desde);
}
return;
}

101

Arrays (listas y tablas)

102

Marta Zorrilla Universidad de Cantabria

Arrays (listas y tablas)

Objetivos:

Introducir el concepto de tipo de dato estructurado.


Mostrar la representacin de datos mediante arrays unidimensionales y
multidimensionales.
Conocer la representacin de cadenas de caracteres y las funciones de manipulacin.

Contenidos:
1. Arrays
o
o
o
o

Declaracin
Subndices
Almacenamiento en memoria
Tamao de los arrays

2. Inicializacin de un array
3. Array de caracteres y cadenas de texto
4. Arrays multidimensionales

103

Marta Zorrilla Universidad de Cantabria

Listas

Conjunto de datos del mismo tipo a los que se da un nombre comn


y a los que se accede a travs de un ndice
tipo_dato variable_lista[num_elementos];
int numeros[20];
float temperaturas[100];

En un vector de N elementos, el primero se referencia con el ndice 0


y el ltimo con el ndice N-1
Inicializacin
int numeros[2]={0,1}
int numeros[]={0,1} el compilador asume array de 2 elementos

El procesamiento se debe hacer elemento a elemento


104

Marta Zorrilla Universidad de Cantabria

Listas

cmo se utilizan?

Usar un elemento de la lista


variable_lista[posicion];

Empieza en 0

temperaturas[10];

Pasar a funciones

en la declaracin

void nombreFuncion (int variable)

en la llamada a la funcin

nombreFuncion (variable_lista[posicion])
105

Marta Zorrilla Universidad de Cantabria

Listas de nmeros

cmo se utilizan?

Usar toda la lista. Podemos:

Copiar una lista en otra

memcpy (listadestino,listaorigen,tamao)

Pasar la lista a una funcin

Sean de entrada o
salida, no requieren *

void nombreFuncion (int nombreLista[TAMAO])


nombreFuncion ( nombreLista );

Ojo, corchetes
106

Marta Zorrilla Universidad de Cantabria

Listas de nmeros

cmo se utilizan?

Usar toda la lista. Podemos:

Pasar la lista a una funcin de tamao ajustado

void nombreFuncion (int tamano, int nombreLista[tamano])


nombreFuncion ( tamano, nombreLista );

Se debe declarar la lista dentro de un bloque


Antes debe ser conocida la variable tamano
La lista slo es conocida dentro del bloque
107

Marta Zorrilla Universidad de Cantabria

Ejemplo lista tamao fijo


#include <stdio.h>
#define TAM_VECTOR 10
void leer (int vector_a[TAM_VECTOR])
{
int j; /* variable utilizada como indice */
for (j = 0; j < TAM_VECTOR; j++)
{
printf("Elemento %d: ", j);
scanf("%d", &vector_a[j]);
}
}
void copiar (int vector_a[TAM_VECTOR], int
vector_b[TAM_VECTOR])
{
int j;
for (j = 0; j < TAM_VECTOR; j++)
vector_b[j] = vector_a[j];
}

void escribir (int vector[TAM_VECTOR])


{
int j;
for (j = 0; j < TAM_VECTOR; j++)
printf("El elemento %d es %d \n", j, vector[j]);
}
void main()
{
int vector_a[TAM_VECTOR];
int vector_b[TAM_VECTOR];
leer ( vector_a);
copiar (vector_a, vector_b);
escribir (vector_b);
}

108

Marta Zorrilla Universidad de Cantabria

Ejemplo lista tamao variable


#include <stdio.h>
void leer (int cuantos, float lista[cuantos])
{
int i;
printf ("teclealos :\n");
for (i=0 ; i< cuantos ; i++)
{
scanf("%f", &lista[i]);
}
}
void pintar(int cuantos, float lista[cuantos])
{
int i;
for (i=0 ; i< cuantos ; i++)
{
printf("%i\n", lista[i]);
}
}

void main()
{
int cuantos;
printf ("dame cuantos \t");
scanf("%i", &cuantos);
{
float lista[cuantos];

leer(cuantos,lista);
pintar (cuantos, lista);
}

109

Marta Zorrilla Universidad de Cantabria

Ordenacin elementos de lista


#include <stdio.h>
#include <stdlib.h>
int comparar (int *num1, int *num2)
return ((*num1)-(*num2));
}

void main()
{
int cuantos;
printf ("dame cuantos \t");
scanf("%i", &cuantos);
{
float lista[cuantos];
leer(cuantos,lista);
qsort(lista,cuantos, sizeof(lista[0],comparar);
pintar (cuantos, lista);
}
}

110

Marta Zorrilla Universidad de Cantabria

La funcin sizeof()

Devuelve el tamao en bytes que ocupa un tipo o


variable en memoria.

#include <stdio.h>
main()
{
char cadena[10];
printf("un int ocupa %d bytes\n", sizeof(int));
printf("un char ocupa %d bytes\n", sizeof(char));
printf("un float ocupa %d bytes\n", sizeof(float));
printf("un double ocupa %d bytes\n", sizeof(double));
printf(" cadena ocupa %d bytes\n", sizeof(cadena));

}
111

Algoritmos de ordenacin y
bsqueda
Transparencias en pdf aparte

112

Marta Zorrilla Universidad de Cantabria

Cadenas de caracteres

Un caso particular de lista es la cadena de caracteres. Se declara:


char nombre[num_car];

y permite almacenar num_car-1 caracteres y el carcter nulo '\0' de terminacin.


char frase[21];

es apta para almacenar 20 caracteres y el nulo.

C permite la inicializacin de cadenas de caracteres en la declaracin, mediante


sentencias del tipo
char cadena[ ] = "Esto es una cadena de caracteres";

en la que no es necesario aadir el nulo final ni indicar el tamao, pues lo hace


automticamente el compilador.

Generalmente se utiliza tamao por exceso, no se suele preguntar al usuario cuntos


caracteres va a introducir
113

Marta Zorrilla Universidad de Cantabria

Cadenas de caracteres

Cmo se utilizan?

Usar un elemento de la lista. Igual que lista de nmeros.


Usar toda la lista. Hay diferencias:
Leer una lista de letras con una sola instruccin
scanf (%s, palabra)
coge hasta espacio o fin de lnea
scanf (%[^\n], frase)
coge hasta fin de lnea

Escribir una lista de letras


printf (%s, palabra)

Copiar una lista de letras <string.h>


strcpy (str_destino, str_origen)

114

Marta Zorrilla Universidad de Cantabria

biblioteca estndar string.h


char *strcat (char *cad1, const char *cad2) Concatena cad2 a cad1 devolviendo la
direccin de cad1. Elimina el nulo de terminacin de cad1 inicial.
char *strcpy (char *cad1, const char *cad2) Copia la cadena cad2 en cad1,
sobreescribindola. Devuelve la direccin de cad1. El tamao de
cad1 debe ser suficiente para albergar a cad2.
int strlen (const char *cad)
Devuelve el nmero de caracteres que almacena cad
(sin contar el nulo final).
int isalnum (int ch)
Devuelve 1 si ch es alfanumrico (letra del alfabeto o dgito) y 0
en caso contrario.
int isalpha (int ch)
Devuelve 1 si ch es una letra del alfabeto y 0 en caso contrario.
int isdigit (int ch)
Devuelve 1 si ch es un dgito del 0 al 9, y 0 en caso contrario.
int islower (int ch)
Devuelve 1 si ch es un letra minscula y 0 en caso contrario.
int isupper (int ch)
Devuelve 1 si ch es una letra mayscula y 0 en caso contrario.
int tolower (int ch)
Devuelve el carcter ch en minscula. Si ch no es una letra
mayscula la funcin devuelve ch sin modificacin.
int toupper (int ch)
Devuelve el carcter ch en mayscula. Si ch no es una letra
minscula la funcin devuelve ch sin modificacin.
115

Marta Zorrilla Universidad de Cantabria

Ejemplo: lectura y escritura de cadenas de


caracteres
#include <stdio.h>
#define TAM_CADENA 80
main()
{
char cadena[TAM_CADENA];
printf("Introduzca una cadena: ");
scanf("%s", cadena);
printf("La cadena es %s\n", cadena);
}

no requiere
&

scanf deja de buscar cuando encuentra un blanco si se


introduce Hola a todos, solo se leer Hola.
No es necesario el operador de direccin (&) ya que cadena
representa de forma automtica la direccin de comienzo.
116

Marta Zorrilla Universidad de Cantabria

Ejemplo: lectura y escritura de cadenas


de caracteres (y 2)

La funcin gets lee una lnea completa hasta que encuentre el retorno
de carro incluyendo los blancos.
La funcin puts escribe una cadena de caracteres junto con un salto de
lnea.
#include <stdio.h>
#define TAM_LINEA 80
main()
{
char linea[TAM_LINEA];
printf("Introduzca una linea: \n");
gets(linea);
puts("La linea es");
puts(linea);
}
Son equivalentes:
puts("La linea es:");

printf("La linea es: \n");

117

Marta Zorrilla Universidad de Cantabria

Ej.

Programa que lee una palabra y la escribe al revs

#include <stdio.h>
#include <string.h>
#define MAXLETRAS 20
void leer (char palabra[MAXLETRAS])
{
printf ("\nTeclee una cadena de caracteres: ");
scanf(%s, palabra);
}
void escribir (char palabra[MAXLETRAS])
{
int primera=0, ultima=0, i;
ultima=strlen(palabra)-1;

for (i=ultima; i>=primera; i--)


printf(%c,palabra[i]);

void main (void)


{
char palabra[MAXLETRAS];
leer(palabra);
escribir(palabra);
}

118

Marta Zorrilla Universidad de Cantabria

Ej.

El programa siguiente hace uso de alguna de las funciones


anteriores para examinar una cadena de caracteres y
convertir las minsculas a maysculas y viceversa. Adems
cuenta cuntos caracteres son dgitos numricos.

#include <stdio.h>
#include <string.h>
#define MAXLETRAS 100
void leer (char cadena [MAXLETRAS])
{
printf ("\nTeclee una cadena de caracteres: ");
gets (cadena);
}
void escribir (char cadena[MAXLETRAS])
{
int i, contador=0;
for (i = 0; i <= strlen (cadena); i++) {
if (isupper (cadena[i])) cadena[i] = tolower (cadena[i]);
else if (islower (cadena[i])) cadena[i] = toupper (cadena[i]);
else if (isdigit (cadena[i])) contador++;
}
printf ("\nLa cadena tiene %d dgitos numricos\n", contador);
puts (cadena);
}
void main (void)
{
char frase[MAXLETRAS];
leer(frase);
escribir(frase);
}

119

Marta Zorrilla Universidad de Cantabria

Vectores multidimensionales

Un vector multidimensional se declara:


tipo_dato vector[exp1] [exp2] ... [expN];

Matrices o vectores de 2 dimensiones:


int matriz[20][30];
define una matriz de 20 filas por 30 columnas.

Generalmente se declaran por exceso.

La numeracin comienza en 0.
120

Marta Zorrilla Universidad de Cantabria

Tablas

Cmo se utilizan?

Usar un elemento de la tabla


tabla[fila][columna]

Pasar un elemento a una funcin.

llamada
nombreFuncion (arg1,.., nombretabla[fila][columna])
declaracin
void nombreFuncion (tipo arg1,, tipo variablesimple)

Usar una columna de la tabla: NO SE PUEDE EN C


121

Marta Zorrilla Universidad de Cantabria

Tablas

Usar un vector de la tabla como argumento a una funcin:


tabla[fila]

declaracin
void nombreFuncion (tipo arg1,, tipo lista[COLUMNAS])
llamada
nombreFuncion (arg1,.., nombretabla[fila]);

Usar una tabla completa

Copiar
memcpy(destino, origen,tamao)
Ej: memcpy ( clientes2, clientes1, sizeof(int)*filas*columnas)
Parmetro de una funcin

Declaracin de funcin

void nombreFuncion (tipo arg1,, tipo tabla[FILAS][COLUMNAS])

Llamada a una funcin

nombreFuncion (arg1,, tabla)

122

Marta Zorrilla Universidad de Cantabria

Ejemplo

Leer dos matrices de


dimensiones indicadas por el
usuario y escribir su suma

#include <stdio.h>
void sumar(int filas, int columnas, float tabla1[filas][columnas], float tabla2[filas][columnas])
{
int i,j, acumulador=0;
for (i=0;i<filas;i++)
{
for (j=0;j<columnas;j++)
{
printf("%f \t", tabla1[i][j]+tabla2[i][j]);
}
printf("\n");
}
}

void main()
{
int filas, columnas;
printf("dame filas y columnas: \n");
scanf("%i %i", &filas, &columnas);

void leer(int filas, int columnas, float tabla[filas][columnas])


{
{
float tabla1[filas][columnas], tabla2[filas][columnas];
int i,j;
printf("dame tabla:\n");
leer(filas,columnas, tabla1);
leer(filas,columnas, tabla2);
for (i=0;i<filas;i++)
sumar(filas, columnas,tabla1, tabla2);
{
}
for (j=0;j<columnas;j++)
{
}
scanf("%f", &tabla[i][j]);
}
}
}
123

Marta Zorrilla Universidad de Cantabria

Ejemplo

Funcin que calcula el producto de dos matrices cuadradas.

void multiplicar(float a[DIM][DIM], float b[DIM][DIM], float c[DIM][DIM])


{
int i, j, k;
for(i = 0; i < DIM; i++)
for(j = 0; j < DIM; j++)
{
c[i][j] = 0.0;
for(k = 0; k < DIM; k++)
c[i][j] += a[i][k] * b[k][j];
}
}
124

Marta Zorrilla Universidad de Cantabria

Ej.:

Leer lista de palabras y contar el n de veces que est


una palabra que solicita el usuario

#include <stdio.h>
#include <string.h>
#define MAX 30 /*incluye el fin de lnea*/

void main()
{
int numpal;
void leer(int numpal, int columnas, char tabla[numpal][MAX], char pal[MAX]) printf("dame n palabras: \n");
{
scanf("%i", &numpal);
int i;
printf("dame palabras:\n");
{
char tabla[numpal][MAX], pal[MAX];
for (i=0;i<numpal;i++)
{
leer(numpal, tabla, pal);
scanf("%s",tabla[i]);
calcular(numpal,tabla,pal);
}
}
printf("dame palabra a buscar:\n");
}
scanf("%s",pal);
}
void calcular(int numpal, int columnas, char tabla[numpal][MAX], char pal[MAX])
{

int i,suma=0;
for (i=0;i<numpal;i++)
{
if (strcmp(listapal[i],pal)==0)
{
suma ++;
}
}
printf(la palabra buscada %s, aparece %d veces\,pal, suma);
}

125

Estructuras y uniones

126

Marta Zorrilla Universidad de Cantabria

Estructuras y uniones

Objetivos:

Conocer la posibilidad de definir tipos de datos estructurados con campos


heterogneos mediante el uso de estructuras.
Explicar la posibilidad de combinar tipos de datos estructurados.
Mostrar los tipos union.

Contenidos:

1. Estructuras
2.
3.
4.
5.

o Concepto de campo
o Declaracin e inicializacin

Acceso a estructuras
Declaracin typedef
Combinacin de datos estructurados
Campos variables con el uso de union

127

Marta Zorrilla Universidad de Cantabria

Estructuras

Es una estructura de datos compuesta de elementos individuales que


pueden ser de distinto tipo.
Cada uno de los elementos de una estructura se denomina miembro.
Declaracin de una estructura:
struct nombre_estructura
{
tipoDato1 miembro_1;
tipoDato2 miembro_2;
.
.
tipoDatoN miembro_N;
};

Los miembros pueden ser de cualquier tipo excepto void


128

Marta Zorrilla Universidad de Cantabria

Ejemplo

Declaracin de una estructura denominada CD.


struct CD
{
char titulo[100];
char artista[50];
int num_canciones;
int anio;
Euros precio;
};
Declaracin de una variable denominada cd1 de tipo struct CD.
struct cd1 CD;
Se pueden copiar estructuras, pero NO comparar:
struct CD cd1,cd2;
cd2 = cd1;
129

Marta Zorrilla Universidad de Cantabria

Inicializacin de una estructura

Dos formas:

En la declaracin:
struct CD
{
char titulo[100];
char artista[50];
int num_canciones;
int anio;
Euros precio;
} cd1= {Un sueo de verano,Miguel Rios,1989,10};

En el programa:
struct CD cd1;
strcpy(cd1.titulo, Un sueo de verano");
strcpy(cd1.artista, Miguel Rios");
cd1.num_canciones = 2;
c1.anio = 1989;

130

Marta Zorrilla Universidad de Cantabria

Acceso a una estructura

Los miembros de una estructura se procesan individualmente.


Para hacer referencia a un miembro determinado, se utiliza el operador
. si la variable es de tipo estructura
variable_estructura.miembro

O, se utiliza el operador -> si la variable es de tipo puntero a estructura


variable_estructura->miembro

Ejemplo: imprimir la fecha de hoy


struct fecha {
int dia, mes, anio;
};
struct fecha hoy;
struct fecha *ayer;
printf("%d: %d: %d\n", hoy.dia,hoy.mes, hoy.anno);
printf("%d: %d: %d\n", ayer->dia, ayer-> mes, ayer-> anno);

131

Marta Zorrilla Universidad de Cantabria

Ejemplo
#include <stdio.h>
struct fecha
{
int dia;
int mes;
int anno;
};
struct cuenta
{
int cuenta_no;
char nombre[80];
float saldo;
struct fecha ultimo_pago;
};
132

Marta Zorrilla Universidad de Cantabria

Ejemplo (y 2)
main()
{
struct cuenta c1, c2;
/* rellena la estructura c1 */
c1.cuenta_no = 2;
strcpy(c1.nombre, "Pepe");
c1.saldo = 100000;
c1.ultimo_pago.dia = 12;
c1.ultimo_pago.mes = 5;
c1.ultimo_pago.anno = 1997;
/* asignacion de estructuras */
c2 = c1;
printf("No. Cuenta %d \n", c2.cuenta_no);
printf("Nombre %s \n", c2.nombre);
printf("Saldo %f \n", c2.saldo);
printf("Fecha de ultimo pago: %d:%d:%d \n", c2.ultimo_pago.dia,
c2.ultimo_pago.mes, c2.ultimo_pago.anno);
}

133

Marta Zorrilla Universidad de Cantabria

Combinacin de datos estructurados:


vector de estructuras
#include <stdio.h>
#include <string.h>
#define NUMCAJAS 3

Programa que permita introducir las


piezas de un almacn (tipo, nombre,
nro, precio) e imprimirlas
Caja N
caja ...
Caja 1

typedef struct
{
char pieza[20];
/* Tipo de pieza.
*/
int cantidad;
/* Nmero de piezas.
*/
float precio_unitario; /* Precio de cada pieza.
*/
char existe;
/* Comprobar si el registro existe. */
} registro_piezas;
134

Marta Zorrilla Universidad de Cantabria

main()
{
registro_piezas cajas[NUMCAJAS];
int registro=0;
int i;
do
{
/* Leer el nombre de la pieza. */
printf("Nombre de la pieza => ");
scanf("%s", cajas[registro].pieza);
/* Leer el nmero de piezas. */
printf("Numero de piezas => ");
scanf("%d", &cajas[registro].cantidad);
/* Leer el precio de cada pieza. */
printf("Precio de cada pieza => ");
scanf("%f", &cajas[registro].precio_unitario);
/* Indicar que el registro tiene datos, V */
cajas[registro].existe = 'V';
registro ++;
} while (registro < NUMCAJAS);

135

Marta Zorrilla Universidad de Cantabria

Cont.
/* Imprimir la informacin. */
for(registro = 0; registro < NUMCAJAS; registro++)
{
if(cajas[registro].existe == 'V')
{
printf("La caja %d contiene:\n", registro + 1);
printf("Pieza => %s\n", cajas[registro].pieza);
printf("Cantidad => %d\n",
cajas[registro].cantidad);
printf("Precio unitario => $%f\n",
cajas[registro].precio_unitario);
}
} /* Fin for. */
} /*fin main*/
136

Marta Zorrilla Universidad de Cantabria

Paso de estructuras a funciones

Una funcin puede devolver una estructura.


Se pueden pasar miembros individuales y estructuras
completas a una funcin. Si la estructura es grande, el
tiempo para copiar un estructura (paso por valor) es
prohibitivo, por eso se aconseja pasarlo por referencia.
Paso de miembros individuales
struct punto
{
float x;
float y;
};

void imprime_x (float x)


{
printf ("el valor de x %f", x);
}
/*llamada a funcin*/
imprime_x (p1.x);

137

Marta Zorrilla Universidad de Cantabria

Paso de estructuras a funciones por


valor
Ej.: leer y escribir una fecha.

struct fecha leer_fecha(void)


{
struct fecha f;
printf("Dia: ");
scanf("%d", &(f.dia));
printf("Mes: ");
scanf("%d", &(f.mes));
printf("Anno: ");
scanf("%d", &(f.anno));
return(f);

#include <stdio.h>
struct fecha
{
int dia;
int mes;
int anno;
};
void imprimir_fecha(struct fecha f)
{
printf("Dia: %d\n", f.dia);
printf("Mes: %d\n", f.mes);
printf("Anno: %d\n", f.anno);
return;
}

}
main()
{
struct fecha fecha_de_hoy;
fecha_de_hoy = leer_fecha();
imprimir_fecha(fecha_de_hoy);
138
}

Marta Zorrilla Universidad de Cantabria

Paso de estructuras a funciones por


referencia
void leer_punto(struct punto *p);
void imprimir_punto(struct punto p);
struct punto
{
float x;
float y;
};
main()
{
struct punto p1;

void leer_punto(struct punto *p)


{
printf("x = ");
scanf("%f", &(p->x));
printf("y = ");
scanf("%f", &(p->y));
}
void imprimir_punto(struct punto p)
{
printf("x = %f\n", p.x);
printf("y = %f\n", p.y);
}

leer_punto(&p1);
imprimir_punto(p1);
}

139

Marta Zorrilla Universidad de Cantabria

Uniones

Una union contiene miembros cuyos tipos de datos pueden ser


diferentes (igual que las estructuras).
Su declaracin es similar a las estructuras:
union nombre_estructura
{
tipoDato1 miembro_1;
tipoDato2 miembro_2;
.
.
tipoDatoN miembro_N;
};

Todos los miembros que componen la union comparten la misma


zona de memoria ahorro de memoria.
Una variable de tipo union slo almacena el valor de uno de sus
miembros.
140

Marta Zorrilla Universidad de Cantabria

Ejemplo
#include <stdio.h>
#include <stdlib.h>
union numero
{
int entero;
float real;
};
main()
{
union numero num;
/* leer un entero e imprimirlo */
printf("Entero: ");
scanf("%d", &(num.entero));
printf("El entero es %d\n", num.entero);
/* leer un real e imprimirlo */
printf("Real: ");
scanf("%f", &(num.real));
printf("El entero es %f\n", num.real);
}

3
entero
real

141

Marta Zorrilla Universidad de Cantabria

Combinacin de datos estructurados:


vector de estructuras y union
struct ALUMNO {
char grupo[15];
int asignat;
char repite;
};
struct PROFESOR {
char nrp[16];
char cargo[21];
};
union AL_PR {
struct ALUMNO al;
struct PROFESOR pr;
};

Persona n
Persona ...
Persona 1

struct DATOS {
char tipo;
char nombre[40];
int edad;
char direccion[40];
char telefono[15];
union AL_PR ambos;
} personal[100];

142

Marta Zorrilla Universidad de Cantabria

El siguiente segmento de programa


muestra los datos de la matriz personal.
for (i = 0; i < 100; i++) {
printf ("\nNombre: %s", personal[i].nombre);
printf ("\nEdad: %d", personal[i].edad);
printf ("\nDireccin: %s", personal[i].direccion);
printf ("\nTelfono: %s", personal[i].telefono);
if (personal[i].tipo == 'A') {
printf ("\nALUMNO");
printf ("\nGrupo: %s", personal[i].ambos.al.grupo);
printf ("\nN de Asignaturas: %d", personal[i].ambos.al.asignat);
printf ("\nRepite: %d", personal[i].ambos.al.repite); }
else {
printf ("\nPROFESOR");
printf ("\nN.R.P.: %s", personal[i].ambos.pr.nrp);
printf ("\nCargo: %s", personal[i].ambos.pr.cargo);
}
143
}

Marta Zorrilla Universidad de Cantabria

Tipos enumerados

Un tipo enumerado es similar a las estructuras.


Sus miembros son constantes de tipo int.
Es til definir nuevos literales para

Asociar un nombre a un valor numrico


Limitar los valores que puede tomar una variable entera
Hacer el cdigo ms legible

Definicin:
enum nombre {m1, m2, ..., mN};

Ejemplo:
enum color {negro, blanco, rojo};
144

Marta Zorrilla Universidad de Cantabria

Ejemplo
#include <stdio.h>
enum semaforo {rojo, amarillo, verde};
main()
{
enum estado semaforo;
for(estado =rojo; estado <=verde; estado ++)
switch(estado )
{
case rojo:
printf(Parar, sino multa\n");
break;
case amarillo:
printf(Parar si no tienes vehculo encima\n");
break;
case verde:
printf(Circular\n");
break;
}
}

145

Definicin de tipos de datos


(typedef)
Marta Zorrilla Universidad de Cantabria

Permite dar nuevo nombre a tipos de datos que ya existen:


typedef tipoDato nuevo_tipo;

Ejemplos:
typedef char letra;
letra c;
typedef struct{
int dia;
int mes;
int anio;
} FECHA;
FECHA a;

146

Marta Zorrilla Universidad de Cantabria

Combinacin de typedef y enum

Usando typedef y enum se pueden definir tipos que slo pueden


tomar ciertos valores
Ej. tipo booleano en C
typedef enum {false, true} boolean;
...
boolean f=false;
...
if(f)
printf("f es verdadero\n");
else
printf("f es falso\n");
...
f=45; /* Error, no debera tomar ese valor */
147

Ficheros
Marta Zorrilla

148

Marta Zorrilla Universidad de Cantabria

Ficheros

Objetivos:

Presentar el tipo de dato FILE y los tipos de fichero.


Explicar las instrucciones para abrir, cerrar y gestionar ficheros.
Capacitar al alumno a trabajar con ficheros de texto y binarios.

Contenidos:

1. Concepto de ficheros y sus tipos


2. Declaracin de una variable tipo fichero
3. Operaciones con ficheros:

o Abrir y cerrar ficheros


o Control de errores y fin de fichero
o Lectura/escritura de ficheros de texto: caracteres, cadenas de
caracteres y con formato
o Lectura/escritura de ficheros binarios
o Acceso directo a informacin de archivos
149

Marta Zorrilla Universidad de Cantabria

Canales y ficheros

El sistema de E/S del ANSI C proporciona un intermediario entre el


programa y el dispositivo al que se accede (pantalla, cinta, disco,...).
Este intermediario se llama canal o flujo (stream) y es un buffer
independiente del dispositivo al que se conecte.
Existen dos tipos de canales:

Canales de texto: Son secuencias de caracteres. Dependiendo del


entorno puede haber conversiones de caracteres (LF CR + LF). Esto
hace que el nmero de caracteres escritos/ledos en un canal pueda no
coincidir con el nmero de caracteres escritos/ledos en el dispositivo.
Canales binarios: Son secuencias de bytes. A diferencia de los canales de
texto, en los canales binarios la correspondencia de caracteres en el
canal y en el dispositivo es 1 a 1, es decir, no hay conversiones.

150

Marta Zorrilla Universidad de Cantabria

Canales y ficheros ( y 2)

Hay 3 canales que se abren siempre que comienza un programa C:

stdin
stdout
stderr
(ANSI)

Canal estndar de entrada. Por defecto el teclado. (ANSI)


Canal estndar de salida. Por defecto la pantalla. (ANSI)
Canal estndar de salida de errores. Por defecto la pantalla.

Un canal se asocia a un archivo cuando se abre o se crea ste para lo cual se


utilizan funciones de la biblioteca stdio.h.
Tambin incluye funciones para realizar las operaciones de lectura/escritura
as como para desasociar un canal de un archivo (operacin de cierre).

151

Marta Zorrilla Universidad de Cantabria

Apertura de un archivo

Para abrir un archivo:


desc = fopen(nombre_archivo, modo)

donde desc, el descriptor, se declara como:


FILE *desc;

y modo especifica la forma de apertura del archivo.


si fopen devuelve NULL, el fichero no se pudo abrir.
152

Marta Zorrilla Universidad de Cantabria

Parmetros para abrir un fichero


DESCRIPCIN
MODO
r

Abre un fichero slo para lectura. Si el fichero no existe fopen() devuelve


un puntero nulo y se genera un error.

Crea un nuevo fichero para escritura. Si ya existe un fichero con este


nombre, se sobreescribe, perdindose el contenido anterior.

Abre o crea un fichero para aadir. Si el fichero existe, se abre apuntando


al final del mismo. Si no existe se crea uno nuevo.

r+

Abre un fichero para leer y escribir. Si el fichero no existe fopen()


devuelve un puntero nulo y se genera un error. Si existe, pueden
realizarse sobre l operaciones de lectura y de escritura.
Crea un nuevo fichero para leer y escribir. Si ya existe un fichero con este
nombre, se sobreescribe, perdindose el contenido anterior. Sobre el
archivo pueden realizarse operaciones de lectura y de escritura.

w+

a+

Abre o crea un fichero para leer y aadir. Si el fichero ya existe se abre


apuntando al final del mismo. Si no existe se crea un fichero nuevo.

Modo TEXTO: aadir letra t. Ej: si modo es rt, se est abriendo el fichero en modo texto slo para lectura
Modo BINARIO: aadir letra b. Ej: modo es w+b se abrir o crear un fichero en modo binario para lectura y escritura153

Marta Zorrilla Universidad de Cantabria

Cierre de un fichero

Para cerrar un fichero y liberar el canal previamente


asociado con fopen(), se debe usar la funcin fclose()
int fclose (FILE *canal);

Esta funcin devuelve 0 si la operacin de cierre ha


tenido xito, y distinto de 0 en caso de error.

154

Marta Zorrilla Universidad de Cantabria

Ejemplo
#include <stdio.h>
main()
{
FILE *desc;
desc = fopen("ejemplo.txt", w");
if (desc == NULL)
{
printf("Error, no se puede abrir el archivo \n");
}
else
{
/* se procesa el archivo */
/* al final se cierra */
fclose(desc);
}
exit(0);
}

155

Marta Zorrilla Universidad de Cantabria

Control de errores

Cada vez que se realiza una operacin de lectura o de


escritura sobre un fichero debemos comprobar si se ha
producido algn error. Para ello disponemos de la funcin
ferror()
int ferror (FILE *canal);

Esta funcin devuelve 0 si la ltima operacin sobre el


fichero se ha realizado con xito.

156

Marta Zorrilla Universidad de Cantabria

Final de fichero

Cada vez que se realiza una operacin de lectura sobre un fichero, el


indicador de posicin del fichero se actualiza.
Es necesario, pues, controlar la condicin de fin de fichero. Por ello,
debemos saber que cuando se intentan realizar lecturas ms all del
fin de fichero, el carcter ledo es siempre EOF. Sin embargo en los
canales binarios un dato puede tener el valor EOF sin ser la marca
de fin de fichero. Es aconsejable, por ello, examinar la condicin de
fin de fichero mediante la funcin feof()

int feof (FILE *canal);

Esta funcin devuelve un valor diferente de cero cuando se detecta


el fin de fichero.
157

Marta Zorrilla Universidad de Cantabria

Ficheros de texto

Se trata de archivos cuyo contenidos son caracteres en


formato ASCII, por tanto, son legibles y editables por
cualquier editor de texto. Usualmente tienen la extensin
txt.
Para abrir un archivo en modo texto se debe emplear el
modificador t en el modo de apertura del archivo.
Existen dos formas de tratar ficheros de texto:

Carcter a carcter (fgetc y fputc)


Cadenas de caracteres (fgets y fputs)
Con formato (fprintf y fscanf)

158

Marta Zorrilla Universidad de Cantabria

Funciones de manejo carcter a carcter

Lectura:
int fgetc(FILE *fich)
Lee un carcter del archivo (EOF si estamos al final del
mismo)

Escritura:
int fputc(char c, FILE *fich)
Escribe el carcter c en el archivo. Si es correcto devuelve
el mismo carcter y si no EOF.
159

Marta Zorrilla Universidad de Cantabria

Ejemplo

Ejemplo que realiza la lectura de un archivo carcter a carcter


empleando un buffer:

char buffer[255], lineas[100][80], c;


int n, t;
FILE *entrada;
entrada = fopen(ejemplo.txt, rt);
while (!feof(entrada)) {
t = 0;
do {
c = fgetc(entrada);
buffer[t] = c;
t++;
} while (c!=EOF && c!=\n); //fin de fichero o de lnea
strcpy(lineas[n], buffer);
n++;
}
fclose(salida);

160

Marta Zorrilla Universidad de Cantabria

Funciones de manejo cadenas de


caracteres

Lectura:
char *fgets(const char *s, int n, FILE *fich)
Lee n-1 caracteres o hasta carcter de fin de lnea (que tambin se almacena
en s). Si no se produce error, la funcin devuelve un puntero a char; en caso
contrario, devuelve un puntero nulo.

Escritura:
int fputs(char *s, FILE *fich)
Escribe la cadena s en el archivo. Si es correcto devuelve un valor no
negativo y si no EOF. No copia el carcter nulo ni aade el carcter de fin
de lnea.
161

Marta Zorrilla Universidad de Cantabria

Ejemplo
#include <stdio.h>
int main(void)
{
FILE *fent;
FILE *fsal;
char car[120];
int res = 0;
char * ret;
/* Apertura del archivo de entrada */
fent = fopen("./entrada.txt", "r");
if (fent == NULL)
{
fprintf(stderr, "Error abriendo entrada.txt \n");
return(0);
}
/* Apertura, con creacin si no existe, del archivo de salida */
fsal = fopen("./salida.txt", "w");
if (fsal == NULL)
{
fprintf(stderr, "Error creando salida.txt \n");
fclose(fent);
return(0);
}

162

Marta Zorrilla Universidad de Cantabria

Ejemplo (y 2)
/* Bucle de lectura y escritura con lneas */
do
{
/* Lectura de la lnea siguiente */
ret = fgets(car, 110, fent);
if ( car == NULL)
fprintf(stderr, "Error al leer \n");
else
fprintf(stdin, "Longitud linea leida: %d \n", strlen(car));
/* Escritura de la lnea */
if (ret != NULL) {
res = fputs(car, fsal);
if (res == EOF)
fprintf(stderr, "Error al escribir %s \n", car);
}
} while (ret != NULL);
/* Cierre de los streams de entrada y de salida */
fclose(fent);
fclose(fsal);
return(0);
}

163

Marta Zorrilla Universidad de Cantabria

Funciones de manejo con formato

Lectura:
int fscanf(FILE *fich, char *formato, arg1,arg2,argN)
Su uso es el mismo que scanf pero con la salvedad de que lee desde
un archivo, en vez desde el teclado.

Escritura:
int fprintf(FILE *fich, char *formato, arg1,arg2,argN)
Su uso es igual al de printf pero con la salvedad de que escribe en
un archivo en vez de en la pantalla.

164

Marta Zorrilla Universidad de Cantabria

Ejemplo

Veamos un ejemplo para escribir una cadena de


caracteres en un fichero:
char cadena[255];
FILE *salida;

salida = fopen(salida.txt, wt);


strcpy(cadena, Prueba de escritura);
fprintf(salida,%s,cadena);
fclose(salida);

165

Marta Zorrilla Universidad de Cantabria

Ficheros binarios

Son archivos cuyo contenido son caracteres en formato binario,


por tanto NO son legibles ni editables. Para asegurarnos que la
apertura de un archivo se hace en modo binario se debe emplear
el modificador b en el modo de apertura del archivo. Si no
ponemos nada se asume el modo binario por defecto.
Las funciones bsicas de escritura y lectura asociadas a este
modo son: fwrite y fread.
Generalmente se utilizan para leer estructuras

166

Marta Zorrilla Universidad de Cantabria

Escribir a fichero binario

Escritura
int fwrite(void *datos, int tam, int ndatos, FILE *fich);

Devuelve:
Nmero de elementos (no bytes) escritos en el archivo.
Parmetros:
*ptr = puntero al origen de los datos.
tam = tamao de cada elemento.
ndatos = nmero de elementos.
*fich = puntero a FILE (archivo donde escribir).
167

Marta Zorrilla Universidad de Cantabria

Ejemplo
FILE *archivo;
int valor;
Tficha ficha;
int n;

archivo=fopen(c:\archivo.dat,w);
n = fwrite(&valor, sizeof(int), 1, archivo);
if (n!=1) printf(Error: escritura incompleta.);
n = fwrite(&ficha, sizeof(TFicha), 1, archivo);
if (n!=1) printf(Error: escritura incompleta.);

168

Marta Zorrilla Universidad de Cantabria

Lectura de fichero binario

Sintaxis:
int fread(void *datos, int tam, int ndatos, FILE *fich);

Devuelve el nmero de elementos (no bytes) ledos del archivo.

Parmetros:
*ptr = puntero al destino de los datos.
tam = tamao de cada elemento.
ndatos = nmero de elementos.
*fich = puntero a FILE (archivo de donde leer).

169

Marta Zorrilla Universidad de Cantabria

Ejemplo
TFicha fichas[100];
int nfichas;
FILE *agenda;
nfichas =0;
agenda = fopen(agenda.dat, rb);
while (!feof(agenda)) {
fread(&fichas[nfichas], sizeof(TFicha), 1, agenda);
nfichas ++;
}
fclose(agenda);
170

Marta Zorrilla Universidad de Cantabria

Ejemplo agenda

El registro de ese archivo constar de los siguientes campos:


Nombre
Domicilio
Poblacin
Provincia
Telfono

40 caracteres
40 caracteres
25 caracteres
15 caracteres
10 caracteres

El programa crea el fichero llamado LISTIN.TEL con los datos


suministrados por el usuario

171

Marta Zorrilla Universidad de Cantabria

Ejemplo
#include <stdio.h>
typedef struct {
char nom[41];
char dom[41];
char pob[26];
char pro[16];
char tel[11];
} REG;
void main (void)
{
FILE *f;
REG var;
if (!(f = fopen ("LISTIN.TEL", "wb"))) {
perror ("LISTIN.TEL");
return;
}
printf ("Nombre: ");
gets (var.nom);

172

Marta Zorrilla Universidad de Cantabria

Ejemplo (y 2)
while (var.nom[0]) {
printf ("\nDomicilio: ");
gets (var.dom);
printf ("\nPoblacin: ");
gets (var.pob);
printf ("\nProvincia: ");
gets (var.pro);
printf ("\nTelfono: ");
gets (var.tel);
fwrite (&var, sizeof (var), 1, f);
if (ferror (f)) {
puts ("No se ha almacenado la informacin");
getch ();
}
printf ("Nombre: ");
gets (var.nom);

}
fclose (f);

173

Marta Zorrilla Universidad de Cantabria

Ejemplo: Lectura en bloques


#include <stdio.h>
typedef struct {
char nom[41];
char dom[41];
char pob[26];
char pro[16];
char tel[11];
} REG;
void main (void)
{
FILE *f;
REG var[4];
int i, n;
if (!(f = fopen ("LISTIN.TEL", "rb"))) {
perror ("LISTIN.TEL");
exit (1);
}
do {
n = fread (var, sizeof (REG), 4, f);
for (i = 0; i < n; i++) printf ("\n%-41s %s", var[i].nom, var[i].tel);
puts ("\nPulse una tecla ...");
getch ();
} while (!feof (f));
fclose (f);
}

174

Marta Zorrilla Universidad de Cantabria

Acceso directo

El acceso directo a un archivo, se realiza con la ayuda de la


funcin fseek() que permite situar el indicador de posicin del
archivo en cualquier lugar del mismo.
int fseek (FILE *canal, long nbytes, int origen);

Esta funcin sita el indicador de posicin del fichero nbytes


contados a partir de origen.
La funcin devuelve 0 cuando ha tenido xito. En caso contrario
devuelve un valor diferente de 0.
Esta funcin simplemente maneja el indicador de posicin del
fichero, pero no realiza ninguna operacin de lectura o
escritura. Por ello, despus de usar fseek() debe ejecutarse
una funcin de lectura o escritura.
175

Marta Zorrilla Universidad de Cantabria

Acceso directo (y 2)
int fseek (FILE *canal, long nbytes, int origen);

Los valores posibles del parmetro origen y sus macros asociadas


ORIGEN

VALOR

MACRO

Principio del fichero

SEEK_SET

Posicin actual

SEEK_CUR

Fin del fichero

SEEK_END

176

Marta Zorrilla Universidad de Cantabria

Ejemplo:

Se crea un archivo llamado FRASE.TXT con una cadena de

caracteres. Posteriormente lee un carcter de la cadena cuya posicin se teclea.


#include <stdio.h>
#include <string.h>
void main (void)
{
FILE *f;
int nbyte, st;
char frase[80], caracter;
if (!(f = fopen ("FRASE.TXT", "w+t"))) {
perror ("FRASE.TXT");
return;
}

printf ("Teclee frase: ");


gets (frase);
fwrite (frase, strlen (frase) + 1, 1, f);
printf ("\nLeer carcter n: ");
scanf ("%d", &nbyte);
st = fseek (f, nbyte, SEEK_SET);
if (st) puts ("Error de posicionamiento");
else {
caracter = getc (f);
if (caracter != EOF) printf ("\nEl carcter es: %c", caracter);
else puts ("Se sobrepas el fin de fichero");
}
fclose (f);

177

Marta Zorrilla Universidad de Cantabria

Ejemplo:

programa escribe registros ayudndose de fseek()

#include <stdio.h>
typedef struct {
char nombre[40];
int edad;
float altura;
} REGISTRO;
void main (void)
{
FILE *f1;
REGISTRO mireg;
int num;
long int puntero;
if (!(f1 = fopen ("REGISTRO.DAT", "r+b"))) {
puts ("Error de apertura");
return;
}
printf ("Escribir registro n: ");
scanf ("%d", &num);

178

Marta Zorrilla Universidad de Cantabria

Ejemplo:

programa escribe registros ayudndose de fseek()

(y2)

while (num > 0) {


getchar ();
printf ("Nombre: ");
gets (mireg.nombre);
printf ("Edad: ");
scanf ("%d", &mireg.edad);
printf ("Altura: ");
scanf ("%f", &mireg.altura);
puntero = (num - 1) * sizeof (REGISTRO);
if (fseek (f1, puntero, SEEK_SET)) puts ("Error de posicionamiento");
else {
fwrite (&mireg, sizeof (mireg), 1, f1);
if (ferror (f1)) {
puts ("ERROR de escritura");
getch ();
}
}
printf ("Escribir registro n: ");
scanf ("%d", &num);
}
fclose (f1);
}
179

Programacin modular
Tema 13

180

Marta Zorrilla Universidad de Cantabria

Tema 13

Objetivos:

Explicar el mbito de las variables del programa.


Familiarizar al alumno con la creacin de programas
modularizados y la creacin de libreras de funciones propias.

Contenidos:
1. Variables globales y locales
2. Variables estticas
3. El preprocesador C: #include y #define.
4. Programas modulares
5. Bibliotecas de funciones

181

Marta Zorrilla Universidad de Cantabria

mbito de las variables y tipos de


almacenamiento

Existen dos formas de caracterizar una variable:

El tipo de dato se refiere al tipo de informacin que representa la


variable (int, char, . . . ).
El tipo de almacenamiento se refiere a su permanencia y a su mbito.
El mbito de una variable es la porcin del programa en la cual se
reconoce la variable.
Segn el mbito, las variables pueden ser:

Por su tipo de dato


Por su tipo de almacenamiento

Variables locales.
Variables globales.

Segn el tipo, las variables pueden ser:

Variables
Variables
Variables
Variables

automticas.
estticas.
externas.
de tipo registro.

182

Marta Zorrilla Universidad de Cantabria

Variables globales

Se declaran fuera de las funciones y antes de su uso.


Pueden ser accedidas desde cualquier funcin.

#include <stdio.h>
void funcion1(void);
int a = 1000; /* variable global */
main()
{
int b = 2; /* variable local */
funcion1();
printf("a = %d, b = %d \n", a, b);
}
void funcion1(void)
{
int c = 4; /* variable local */
printf("a = %d, c = %d \n", a, c);
return;
}
183

Marta Zorrilla Universidad de Cantabria

Variables globales (y 2)

Mantienen los valores que se les asignan en las funciones.


Es mejor hacer uso de variables locales para evitar efectos secundarios
o laterales.

#include <stdio.h>
void funcion1(void);
int a=10; /* variable global */
main()
{
printf("Antes a = %d\n", a);
funcion1();
printf("Despues a = %d\n", a);
}
void funcion1(void)
{
a = 1000;
return;
}
184

Marta Zorrilla Universidad de Cantabria

Variables locales

Las variables locales que se definen en las funciones.


Su mbito es local.
Su vida se restringe al tiempo en el que esta activa la funcin.
Los parmetros formales se tratan como variables automticas.
Se pueden especificar con la palabra reservada auto aunque no
es necesario.
#include <stdio.h>
main()
{
auto int valor; /* equivalente a int valor */
valor = 5;
printf("El valor es %d\n", valor);
}
185

Marta Zorrilla Universidad de Cantabria

Variables estticas

Su mbito es local a la funcin.


Su vida coincide con la del programa retienen sus valores durante toda la vida del
programa.
Se especifican con static.
#include <stdio.h>
void funcion(void);
main()
{
funcion();
funcion();
funcion();
}
void funcion(void)
{
static int veces = 0;
veces = veces + 1;
printf("Se ha llamado %d veces a funcion\n", veces);
}

186

Marta Zorrilla Universidad de Cantabria

Variables de tipo registro

Informan al compilador que el programador desea que la variable


se almacene en un lugar de rpido acceso, generalmente en
registros.
Si no existen registros disponibles se almacenar en memoria.
Se especifican con register
#include <stdio.h>
main()
{
register int j;
for (j = 0; j < 10; j++)
printf("Contador = %d\n", j);
}

187

Marta Zorrilla Universidad de Cantabria

Variables de tipo externas

Variables globales.
Hay que distinguir entre definicin y declaracin de variable
externa.
La definicin se escribe de la misma forma que las variables
normales y reserva espacio para la misma en memoria.
Una declaracin no reserva espacio de almacenamiento se
especifica con extern.
Se emplean cuando un programa consta de varios mdulos. En uno
de ellos se define la variable. En los dems se declara (extern)

188

Marta Zorrilla Universidad de Cantabria

Ejemplo

Modulo principal (main.c)

#include <stdio.h>
extern int valor; /* se declara */
void funcion(void);
main()
{
funcion();
printf("Valor = %d\n", valor);
}

- Se compila por separado:


gcc -c -Wall
main.c
gcc -c -Wall
aux.c
- Se obtienen dos mdulos
objetos: main.o y aux.o.
- El ejecutable (prog) se genera:
gcc main.o aux.o -o prog

Modulo auxiliar (aux.c)

int valor; /* se define la variable */


void funcion(void)
{
valor = 10;
}

189

Marta Zorrilla Universidad de Cantabria

Recomendaciones

Evitar el uso de variables globales.


Mantener las variables lo ms locales que se
pueda.
Cuando se precise hacer accesible el valor de una
variable a una funcin, se pasar como
argumento.

190

Marta Zorrilla Universidad de Cantabria

Macros

Una macro es un identificador equivalente a una expresin,


sentencia o grupo de sentencias.

#include <stdio.h>
#define maximo(a,b) ((a > b) ? a : b)
main()
{
int x, y;
int max;
printf("Introduzca dos numeros: ");
scanf("%d %d", &x, &y);
max = maximo(x,y); /* uso de la macro */
printf("El maximo es %d\n", max);
}
191

Marta Zorrilla Universidad de Cantabria

Macros (y 2)

No puede haber blancos entre el identificador y el


parntesis izquierdo.
Una macro no es una llamada a funcin.
El preprocesador sustituye todas las referencias a la
macro que aparezcan dentro de un programa antes
de realizar la compilacin:

No se produce llamada a funcin mayor velocidad.


Se repite el cdigo en cada uso de la macro mayor cdigo
objeto.

192

Marta Zorrilla Universidad de Cantabria

Directiva #include

Indica al preprocesador que incluya un archivo fuente


nom_fich. El formato es:
#include "nom_fich"
o bien,
#include <nom_fich>

El uso de comillas dobles " " o ngulos < > indica dnde debe
buscar el preprocesador el fichero nom_fich.

comillas dobles " " : en el directorio de trabajo o en el camino


absoluto que se especifique en la sentencia include
ngulos < >: en los directorios donde se encuentran las bibliotecas
que proporciona el compilador
193

Marta Zorrilla Universidad de Cantabria

Archivos de cabecera (.h)

Permiten modularizar el cdigo y favorecer la ocultacin de


informacin.
Puede contener:

Definiciones de macros #define MIL 1000


Declaraciones de variables extern int dia;
Declaraciones de funciones extern void f(void);
Otras directivas de inclusin #include a.h
Comentarios
Definiciones de tipos de dato (typedef)

Nunca debe tener:

Definiciones de variables int dia;


Definiciones de funciones void f(void);
194

Marta Zorrilla Universidad de Cantabria

Compilacin prog. varios mdulos


preprocesador
leyOhm.h

prog_ppal.c

leyOhm.c

leyOhm.h

compilador

leyOhm.o

Inclusin del
archivo leyOhm.c

prog_ppal.c
prog_ppal.o

enlazador

prog_ppal.exe
195

Marta Zorrilla Universidad de Cantabria

La biblioteca de funciones
LENGUAJE

ARCHIVO
DE CABECERA

DESCRIPCIN

ALLOC.H

Define funciones de asignacin dinmica de memoria

ANSI C

ASSERT.H

Declara la macro de depuracin assert

C++

BCD.H

Define la clase bcd

BIOS.H

Define funciones utilizadas en rutinas de ROM-BIOS

C++

COMPLEX.H

Define las funciones matemticas complejas

C++

CONIO.H

Define varias funciones utilizadas en las llamadas a rutinas de E/S por consola
en DOS

ANSI C

CTYPE.H

Contiene informacin utilizada por las macros de conversin y clasificacin de


caracteres

DIR.H

Contiene definiciones para trabajar con directorios.

DOS.H

Declara constantes y da las declaraciones necesarias para llamadas


especficas del 8086 y del DOS

ERRNO.H

Declara mnemnicos constantes para cdigos de error

FCNTL.H

Declara constantes simblicas utilizadas en conexiones con la biblioteca de


rutinas open()

FLOAT.H

Contiene parmetros para rutinas de coma flotante

ANSI C

ANSI.C

196

Marta Zorrilla Universidad de Cantabria

La biblioteca de funciones
LENGUAJE

ARCHIVO
DE CABECERA

DESCRIPCIN

C++

FSTREAM.H

Define los flujos de C++ que soportan E/S de archivos

C++

GENERIC.H

Contiene macros para declaraciones de clase genricas

C++

GRAPHICS.H

Define prototipos para las funciones grficas

IO.H

Declaraciones de rutinas de E/S tipo UNIX

C++

IOMANIP.H

Define los gestores de flujos de E/S de C++ y contiene macros para creacin de
gestores de parmetros

C++

IOSTREAM.H

Define rutinas bsicas de flujo de E/S de C++ (v2.0)

ANSI C

LIMITS.H

Parmetros y constantes sobre la capacidad del sistema

ANSI C

LOCALE.H

Define funciones sobre el pas e idioma

ANSI C

MATH.H

Define prototipos para las funciones matemticas

MEM.H

Define las funciones de gestin de memoria

PROCESS.H

Contiene estructuras y declaraciones para las funciones spawn(), exec()

SETJMP.H

Declaraciones para dar soporte a saltos no locales

SHARE.H

Parmetros utilizados en funciones que utilizan arhivos-compartidos

SIGNAL.H

Declara constantes y declaraciones para utilizarlos en funciones signal() y


197
raise()

ANSI C

ANSI C

Marta Zorrilla Universidad de Cantabria

La biblioteca de funciones
LENGUAJE

ARCHIVO
DE CABECERA

DESCRIPCIN

ANSI C

STDARG.H

Soporte para aceptar un nmero variable de argumentos

ANSI C

STDDEF.H

Declara varios tipos de datos y macros de uso comn

ANSI C

STDIO.H

Declara tipos y macros para E/S estndar

C++

STDIOSTR.H

Declara las clases de flujo para utilizar con estructuras del archivo stdio.h

ANSI C

STDLIB.H

Define algunas de las rutinas comnmente utilizadas

C++

STREAM.H

Define las clases de flujo de C++ para utilizarlas con arrays de bytes en
memoria

ANSI C

STRING.H

Define varias rutinas de manipulacin de cadenas y de memoria

SYS\STAT.H

Declara constantes simblicas utilizadas para abrir y crear archivos

SYS\TIMEB.H

Define la funcin ftime() y la estructura timeb

C++

SYS\TYPES.H

Define el tipo time_t

ANSI C

TIME.H

Estructuras y prototipos para funciones de tiempo

VALUES.H

Declara constantes dependientes de la mquina

198

Punteros y arrays
Tema 14

199

Marta Zorrilla Universidad de Cantabria

Punteros y arrays

Objetivos:

Introducir el concepto de puntero.


Introducir el concepto de tipo de dato estructurado.
Mostrar la representacin de datos mediante arrays unidimensionales y
multidimensionales.
Conocer la representacin de cadenas de caracteres y las funciones de manipulacin.

Contenidos:
1. Punteros

o Declaracin
o Operadores

2. Arrays
o
o
o
o

Declaracin
Subndices
Almacenamiento en memoria
Tamao de los arrays

3. Inicializacin de un array
4. Array de caracteres y cadenas de texto
5. Arrays multidimensionales
200

Marta Zorrilla Universidad de Cantabria

Punteros

Un puntero es una variable que contiene una


direccin de memoria. Por ejemplo, la
direccin de otra variable .

201

Marta Zorrilla Universidad de Cantabria

Punteros (y 2)

Las variables puntero se declaran de la siguiente forma:


tipo *nombre;

siendo nombre el identificador de la variable puntero, y tipo el


tipo de variable a la que apunta. Por ejemplo:
char *m;
int *n;
float *p;

En estas declaraciones, las variables m, n y p son punteros que


apuntan, respectivamente, a datos de tipo char, int y float.

202

Marta Zorrilla Universidad de Cantabria

Punteros (y 3)

Los operadores de punteros son:

&
*

direccin de
en la direccin de

El operador * slo se puede aplicar a punteros

Las operaciones permitidas con punteros son:

Asignacin
Incremento / Decremento
Suma / Resta
Comparacin
203

Marta Zorrilla Universidad de Cantabria

Asignacin punteros

Dadas las declaraciones


float x;
float *p, *q;

la forma de asignar a p y q la direccin de x es:


p = &x;
q = &x;

Ahora p y q almacenan la misma direccin de memoria: la de la


variable x. El mismo efecto se consigue con la asignacin
directa entre punteros:
p = &x;
q = p;
No es correcta una sentencia como
p = x;

204

Marta Zorrilla Universidad de Cantabria

Ejemplo
#include <stdio.h>
main()
{
int x; /* variable entera */
int y; /* variable entera */
int *px; /* variable puntero a entero */

int x;
int y;
int *px;
1

(&x) 1000

(&x) 1200
x = 5;
px = &x; /* asigna a px la direccion de x */
y = *px; /* asigna a y el contenido de la
direccion almacenada en px */
(&px) 3000
printf("x = %d\n", x);
printf("y = %d\n", y);
printf("*px = %d\n", *px);
}

px=&x;
3

x=5;

y=*px;
2

100
0

205

Marta Zorrilla Universidad de Cantabria

Ejercicio

Dado el siguiente fragmento de cdigo:

float n1;
float n2;
float *p1;
float *p2;
n1 = 4.0;
p1 = &n1;
p2 = p1;
n2 = *p2;
n1 = *p1 + *p2;
Cunto vale n1 y n2?
206

Marta Zorrilla Universidad de Cantabria

Incremento / Decremento

Los operadores ++ y -- actan de modo diferente segn el tipo


apuntado por el puntero.

Si p es un puntero a caracteres (char *p) la operacin p++


incrementa el valor de p en 1.

Si embargo, si p es un puntero a enteros (int *p), la misma


operacin p++ incrementa el valor de p en 2 para que apunte
al siguiente elemento, pues el tipo int ocupa dos bytes.

Del mismo modo, para el tipo float la operacin p++


incrementa el valor de p en 4.

Lo dicho para el operador ++ se cumple exactamente igual,


pero decrementando, para el operador --.
207

Marta Zorrilla Universidad de Cantabria

Suma / Resta

Ocurre exactamente lo mismo que con las operaciones de


incremento y decremento. Si p es un puntero, la operacin
p = p + 5;
hace que p apunte 5 elementos ms all del actual.
Si p estaba definido como un puntero a caracteres, se
incrementar su valor en 5, pero si estaba definido como
un puntero a enteros, se incrementar en 10.

208

Marta Zorrilla Universidad de Cantabria

Comparacin

Pueden compararse punteros del mismo modo que


cualquier otra variable, teniendo siempre presente que
se comparan direcciones y NO contenidos.
int *p, *q;
if (p == q) puts ("p y q apuntan a la misma
posicin de memoria");

209

Marta Zorrilla Universidad de Cantabria

Puntero NULL

Cuando se asigna 0 a un puntero, este no apunta a ningn objeto o


funcin.
La constante simblica NULL definida en stdio.h tiene el valor 0 y
representa el puntero nulo.
Es una buena tcnica de programacin asegurarse de que todos los
punteros toman el valor NULL cuando no apuntan a ningn objeto o
funcin.
int *p = NULL;
Para ver si un puntero no apunta a ningn objeto o funcin:
if (p == NULL)
printf("El puntero es nulo\n");
else
printf("El contenido de *p es\n", *p);
210

Marta Zorrilla Universidad de Cantabria

Arrays

Conjunto de datos del mismo tipo a los que se da un nombre comn


y a los que se accede a travs de un ndice
tipo_dato variable_array[num_elem];
int numeros[20];
float temperaturas[100];

En un vector de N elementos, el primero se referencia con el ndice 0


y el ltimo con el ndice N-1
Inicializacin
int numeros[2]={0,1}
int numeros[]={0,1} el compilador asume array de 2 elementos

El procesamiento se debe hacer elemento a elemento


211

Marta Zorrilla Universidad de Cantabria

Ejemplo arrays
#include <stdio.h>
#define TAM_VECTOR 10
main()
{
int vector_a[TAM_VECTOR];
int vector_b[TAM_VECTOR];
int j; /* variable utilizada como indice */
/* leer el vector a */
for (j = 0; j < TAM_VECTOR; j++)
{
printf("Elemento %d: ", j);
scanf("%d", &vector_a[j]);
}
/* copiar el vector */
for (j = 0; j < TAM_VECTOR; j++)
vector_b[j] = vector_a[j];
/* escribir el vector b */
for (j = 0; j < TAM_VECTOR; j++)
printf("El elemento %d es %d \n", j, vector_b[j]);
}

212

Marta Zorrilla Universidad de Cantabria

Cadenas de caracteres

Un caso particular de vector es la cadena de caracteres. Se declara:


char nombre[num_car];

y permite almacenar num_car-1 caracteres y el carcter nulo '\0' de


terminacin.
char frase[21];

es apta para almacenar 20 caracteres y el nulo.

C permite la inicializacin de cadenas de caracteres en la declaracin,


mediante sentencias del tipo
char cadena[ ] = "Esto es una cadena de caracteres";

en la que no es necesario aadir el nulo final ni indicar el tamao, pues


lo hace automticamente el compilador.
213

Marta Zorrilla Universidad de Cantabria

Cadenas de caracteres

Una forma de asignar un valor a una cadena es la siguiente:


char cadena[10];
strcpy(cadena, "Hola");

214

Marta Zorrilla Universidad de Cantabria

biblioteca estndar string.h


char *strcat (char *cad1, const char *cad2) Concatena cad2 a cad1 devolviendo la
direccin de cad1. Elimina el nulo de terminacin de cad1 inicial.
char *strcpy (char *cad1, const char *cad2) Copia la cadena cad2 en cad1,
sobreescribindola. Devuelve la direccin de cad1. El tamao de
cad1 debe ser suficiente para albergar a cad2.
int strlen (const char *cad)
Devuelve el nmero de caracteres que almacena cad
(sin contar el nulo final).
int isalnum (int ch)
Devuelve 1 si ch es alfanumrico (letra del alfabeto o dgito) y 0
en caso contrario.
int isalpha (int ch)
Devuelve 1 si ch es una letra del alfabeto y 0 en caso contrario.
int isdigit (int ch)
Devuelve 1 si ch es un dgito del 0 al 9, y 0 en caso contrario.
int islower (int ch)
Devuelve 1 si ch es un letra minscula y 0 en caso contrario.
int isupper (int ch)
Devuelve 1 si ch es una letra mayscula y 0 en caso contrario.
int tolower (int ch)
Devuelve el carcter ch en minscula. Si ch no es una letra
mayscula la funcin devuelve ch sin modificacin.
int toupper (int ch)
Devuelve el carcter ch en mayscula. Si ch no es una letra
minscula la funcin devuelve ch sin modificacin.
215

Marta Zorrilla Universidad de Cantabria

Lectura y escritura de cadenas de caracteres


#include <stdio.h>
#define TAM_CADENA 80
main()
{
char cadena[TAM_CADENA];
printf("Introduzca una cadena: ");
scanf("%s", cadena);
printf("La cadena es %s\n", cadena);
}

scanf deja de buscar cuando encuentra un blanco si se


introduce Hola a todos, solo se leer Hola.
No es necesario el operador de direccin (&) ya que cadena
representa de forma automtica la direccin de comienzo.
216

Marta Zorrilla Universidad de Cantabria

Lectura y escritura de cadenas de


caracteres (y 2)

La funcin gets lee una lnea completa hasta que encuentre el retorno de carro
incluyendo los blancos.
La funcin puts escribe una cadena de caracteres junto con un salto de lnea.
#include <stdio.h>
#define TAM_LINEA 80
main()
{
char linea[TAM_LINEA];
printf("Introduzca una linea: \n");
gets(linea);
puts("La linea es");
puts(linea);
}
puts("La linea es:");

es equivalente a:
printf("La linea es: \n");

217

Marta Zorrilla Universidad de Cantabria

Ejemplo

El programa siguiente hace uso de alguna de las funciones anteriores para examinar una
cadena de caracteres y convertir las minsculas a maysculas y viceversa. Adems cuenta
cuntos caracteres son dgitos numricos.

#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <ctype.h>
void main (void)
{
char cadena[100];
int contador = 0;
register int i;
clrscr ();
printf ("\nTeclee una cadena de caracteres: ");
gets (cadena);
for (i = 0; i <= strlen (cadena); i++) {
if (isupper (cadena[i])) cadena[i] = tolower (cadena[i]);
else if (islower (cadena[i])) cadena[i] = toupper (cadena[i]);
else if (isdigit (cadena[i])) contador++;
}
printf ("\nLa cadena tiene %d dgitos numricos\n", contador);
puts (cadena);
}

218

Marta Zorrilla Universidad de Cantabria

La funcin sizeof()

Devuelve el tamao en bytes que ocupa un tipo o


variable en memoria.

#include <stdio.h>
main()
{
char cadena[10];
printf("un int ocupa %d bytes\n", sizeof(int));
printf("un char ocupa %d bytes\n", sizeof(char));
printf("un float ocupa %d bytes\n", sizeof(float));
printf("un double ocupa %d bytes\n", sizeof(double));
printf(" cadena ocupa %d bytes\n", sizeof(cadena));

}
219

Marta Zorrilla Universidad de Cantabria

Vectores multidimensionales

Un vector multidimensional se declara:


tipo_dato vector[exp1] [exp2] ... [expN];

Matrices o vectores de 2 dimensiones:


int matriz[20][30];

define una matriz de 20 filas por 30 columnas.


El elemento de la fila i columna j es matriz[i][j]

220

Marta Zorrilla Universidad de Cantabria

Ejemplo

Funcin que calcula el producto de dos matrices cuadradas.

void multiplicar(float a[][DIMENSION], float b[][DIMENSION], float c[][DIMENSION])


{
int i, j, k;
for(i = 0; i < DIMENSION; i++)
for(j = 0; j < DIMENSION; j++)
{
c[i][j] = 0.0;
for(k = 0; k < DIMENSION; k++)
c[i][j] += a[i][k] * b[k][j];
}
return;
}
221

Funciones y argumentos de
tipo puntero
Tema 16

222

Marta Zorrilla Universidad de Cantabria

Tema 16

Objetivos:

Mostrar el paso de estructuras y arrays a funciones, enfatizando la


conveniencia de realizarlo por referencia.
Indicar cmo se pasan parmetros al programa principal.

Contenidos:

1. Matrices como argumentos de funciones


2. Estructuras como argumentos de funciones
3. Argumentos de la funcin main()

223

Marta Zorrilla Universidad de Cantabria

Paso de vectores a funciones

Un vector se pasa a una funcin especificando su nombre sin corchetes.


El nombre representa la direccin del primer elemento del vector los vectores se
pasan por referencia y se pueden modificar en las funciones.
El argumento formal correspondiente al vector se escribe con un par de corchetes
cuadrados vacos. El tamao no se especifica.
Programa que calcula la media de los componentes de un vector.
#include <stdio.h>
#define MAX_TAM 4
void leer_vector(int vector[]);
int media_vector(int vector[]);
main()
{
int v_numeros[MAX_TAM];
int media;
leer_vector(v_numeros);
media = media_vector(v_numeros);
printf("La media es %d\n", media);
}
224

Marta Zorrilla Universidad de Cantabria

Paso de vectores a funciones (y2)


void leer_vector(int vector[])
{
int j;
for(j=0; j<MAX_TAM; j++)
{
printf("Elemento %d: ", j);
scanf("%d", &vector[j]);
}
return;
}
int media_vector(int vector[])
{
int j;
int media = 0;
for(j=0; j<MAX_TAM; j++)
media = media + vector[j];
return(media/MAX_TAM);
}
225

Marta Zorrilla Universidad de Cantabria

Punteros y vectores

El nombre del vector representa la direccin del primer elemento


del vector
float vector[MAX_TAM];
vector == &vector[0]

El nombre del vector es realmente un puntero al primer elemento


del vector
&x[0]
&x[1]
&x[2]
&x[i]

x
(x+1)
(x+2)
(x+i)

Es decir, &x[i] y (x+i) representan la direccin del i-esimo elemento


del vector x x[i] y *(x+i) representan el contenido del i-esimo
elemento del vector x.

226

Marta Zorrilla Universidad de Cantabria

Punteros y vectores (y 2)

Cuando un vector se define como un puntero no se le pueden


asignar valores ya que un puntero no reserva espacio en memoria.
float x[10] define un vector compuesto por 10 nmeros reales
reserva espacio para los elementos.
float *x declara un puntero a float. Si se quiere que float x se
comporte como un vector habr que reservar memoria para los
10 elementos:
x = (float *) malloc(10 * sizeof(float));
malloc(nb) (stdlib.h) reserva un bloque de memoria de nb bytes.
Para liberar la memoria asignada se utiliza free() (stdlib.h)
free(x);
El uso de punteros permite definir vectores de forma dinmica.

227

Marta Zorrilla Universidad de Cantabria

Ejemplo.

Programa que calcula la media de un


vector de tamao especificado de forma dinmica.
#include <stdio.h>
#include <stdlib.h>
void leer_vector(int vector[], int dim);
int media_vector(int vector[], int dim);
main()
{
int *v_numeros;
int dimension;
int media;
printf("Dimension del vector: ");
scanf("%d", &dimension);
v_numeros = (int *) malloc(dimension*sizeof(int));
leer_vector(v_numeros, dimension);
media = media_vector(v_numeros, dimension);
printf("La media es %d\n", media);
free(v_numeros);
}

228

Marta Zorrilla Universidad de Cantabria

Ejemplo.

Programa que calcula la media de un


vector de tamao especificado de forma dinmica. (y 2)
void leer_vector(int vector[], int dim)
{
int j;
for(j=0; j<dim; j++)
{
printf("Elemento %d: ", j);
scanf("%d", &vector[j]);
}
return;
}
int media_vector(int vector[], int dim)
{
int j;
int media = 0;
for(j=0; j<dim; j++)
media = media + vector[j];
return(media/dim);
}

229

Marta Zorrilla Universidad de Cantabria

Vectores y cadenas de caracteres

Una cadena de caracteres es un vector de caracteres cada elemento del


vector almacena un carcter.
Ejemplo: Funcin que copia una cadena en otra:
void copiar(char *destino, char *fuente)
{
while (*fuente != '\0')
{
*destino = *fuente;
destino++;
fuente++ ;
}
*destino = '\0';
return;
}
230

Marta Zorrilla Universidad de Cantabria

Punteros a estructuras

Igual que con el resto de variables.


struct punto
{
float x;
float y;
};
main()
{
struct punto punto_1;
struct punto *punto_2;
punto_1.x = 2.0;
punto_1.y = 4.0;
punto_2 = &punto_1;
printf("x = %f \n", punto_2->x);
printf("y = %f \n", punto_2->y);
}
231 ->
En una variable de tipo puntero a estructura los miembros se acceden con

Marta Zorrilla Universidad de Cantabria

Paso de estructuras a funciones (ej. por valor)

Se pueden pasar miembros individuales y estructuras


completas.Por valor o por referencia.
Una funcin puede devolver una estructura.
Ejemplo: leer y escribir una fecha.
void imprimir_fecha(struct fecha f)
{
printf("Dia: %d\n", f.dia);
printf("Mes: %d\n", f.mes);
printf("Anno: %d\n", f.anno);
return;
}
232

Marta Zorrilla Universidad de Cantabria

Paso de estructuras a funciones (y 2)


struct fecha leer_fecha(void)
{
struct fecha f;
printf("Dia: ");
scanf("%d", &(f.dia));
printf("Mes: ");
scanf("%d", &(f.mes));
printf("Anno: ");
scanf("%d", &(f.anno));
return(f);
}
main()
{
struct fecha fecha_de_hoy;
fecha_de_hoy = leer_fecha();
imprimir_fecha(fecha_de_hoy);
}

233

Marta Zorrilla Universidad de Cantabria

Paso de estructuras a funciones (ej. por


referencia)
void leer_punto(struct punto *p);
void imprimir_punto(struct punto p);
main()
{
struct punto *p1;
p1 = (struct punto *)malloc(sizeof(struct punto));
leer_punto(p1);
imprimir_punto(*p1);
free(p1);

}
234

Marta Zorrilla Universidad de Cantabria

Paso de estructuras a funciones (ej. por


referencia) (y 2)
void leer_punto(struct punto *p)
{
printf("x = ");
scanf("%f", &(p->x));
printf("y = ");
scanf("%f", &(p->y));

}
void imprimir_punto(struct punto p)
{
printf("x = %f\n", p.x);
printf("y = %f\n", p.y);
}
235

Marta Zorrilla Universidad de Cantabria

Argumentos de la funcin main()

Ejecutar un programa con parmetros


entrada (en lnea de comandos)

de

main (int argc, char *argv[ ])


argc: Entero que indica el nmero de parmetros tecleados (incluye
el nombre del programa).
argv[ ]: Matriz de cadenas de caracteres. Cada uno de los elementos
argv[i] es una cadena que almacena un argumento.

236

Marta Zorrilla Universidad de Cantabria

Argumentos de la funcin main()


La variable argc vale 1 como mnimo, puesto que se cuenta el
nombre del programa. Los parmetros se identifican mediante argv
de la siguiente manera:
argv[0]
argv[1]
argv[2]
...
...
argv[argc]

cadena que almacena el nombre del programa.


cadena que almacena el primer parmetro.
cadena que almacena el segundo parmetro.

vale cero (En realidad es un puntero nulo).

Para que los argumentos sean tratados como diferentes tienen que
ir separados por uno o varios espacios blancos
237

Marta Zorrilla Universidad de Cantabria

Ejemplo

Programa que lista los parmetros, si los hay, de la lnea de rdenes.

#include <stdio.h>
void main (int argc, char *argv[ ])
{
register int i;
printf ("\nNombre del programa: %s", argv[0]);
if (argc == 1) printf ("\nNo se han introducido parmetros");
else {
printf ("\nParmetros en la lnea de rdenes: ");
for (i = 1; i < argc; i++) printf ("\n%d: %s", i, argv[i]);
}
}

238

También podría gustarte