Sei sulla pagina 1di 21

Vectores Programacin en C

VECTORES

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 1


Prof. lvaro Snchez Miralles

Vectores Programacin en C

Objetivos
Manipular mediante programa estructuras de tipo vector
Facilitar el paso del vector matemtico que el alumno
conoce a su programacin
Creacin
Uso
Uso de recursos de forma dinmica
Desmitificar el uso de punteros
Reglas y utilidades para aislar los posibles problemas que pueden
dar los punteros.

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 2


Prof. lvaro Snchez Miralles
Vectores Programacin en C

Para qu sirven los vectores en programacin?


Manejar informacin del
mismo de tipo, de igual forma
como se maneja un vector en OJO! Inicio de ndice
matemticas.
Vector de enteros.
Vector de char.
Ctricos
Vector de modelos de coches.
Vector de tipos de frutas. Naranja 0
Cmo se define un vector? Limn 1
Nombre del vector.
Lima 2
Elementos del vector.
Tipo de los elementos del
vector. Cada elemento del Frutas
vector debe ser suficiente para
almacenar el tipo.
ndice para moverse dentro del
vector y ver lo que hay en Ctricos[1] Limn
cada elemento.
Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 3
Prof. lvaro Snchez Miralles

Vectores Programacin en C

Cmo almacenar un vector en el ordenador?


MEMORIA
Posiciones contiguas de memoria V1
Cada elemento del vector ocupa 1 o 0 1000 03
varios bytes dependiendo del tipo. V1: vector de 1 1001 ff
La direccin donde comienza el vector 4 elementos
2 1002 20
en memoria equivale al nombre del de tamao
vector. 1 byte 3 1003 31
Se necesita un mecanismo automtico V2
1004 30
para ir de un elemento a otro mediante
el ndice de forma cmoda. 0 1005 01
V2: vector de
La memoria es en s un vector: 3 elementos 1006 10
La direccin es el ndice para acceder 1
de tamao
1007 02
a cada elemento 2 bytes
El elemento es cada posicin de 1008 30
2
memoria.
1009 41
El valor de cada elemento es un byte.
Todo lenguaje de programacin V1[1] ff
100a 23
tiene un mecanismo para soportar
V2[2] 3041
vectores.
Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 4
Prof. lvaro Snchez Miralles
Vectores Programacin en C

Cmo definir y utilizar vectores en C?


Vectores estticos:
mecanismo directo soportado double md[3];
por el lenguaje. OJO! Inicio
Fcil de utilizar. md[0]=2.3; en cero
Problema: se debe conocer md[1]=-3.4;
cuando se programa el nmero md[2]=5.6;
de elementos del vector.
Tamao fijo
Vectores dinmicos: Elementos de un vector en
mecanismo indirecto basado C: direccin de comienzo,
en el uso de punteros y tipo de los elementos y
reserva de memoria dinmica nmero de elementos
para los elementos del vector.
Ms complejo
No se necesita conocer a priori
el nmero de elementos del
vector. Los vectores se crean
a la medida del problema.
Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 5
Prof. lvaro Snchez Miralles

Vectores Programacin en C

Introduccin a los vectores estticos


DECLARACIN: un vector
con 5 elementos de tipo entero

void prueba(void) Memoria


{
int mi[5]; ff 00
int i; mi[0]
e0 00
44 00
for (i=0;i<5;i++){ mi[1]
55 01
mi[i]=i;
21 00
} mi[2]
0a 02
}
00 00
mi[3]
01 03
USO: cada elemento del vector 90 00
es una variable de tipo entero mi[4]
11 04
que se selecciona a travs de [ ]

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 6


Prof. lvaro Snchez Miralles
Vectores Programacin en C

Vectores estticos: Declaracin Es una constante


cuyo valor es
tipo nombre[tamao]; una direccin!
nombre es una constante de tipo tipo *
nombre se forma a partir de:
El prefijo m para indicar vector reservado estticamente.
El prefijo correspondiente al tipo (i,d,c,l,...). Caso s.
Funcin que desempea el vector. Se recomienda utilizar
la declaracin con tamao
Inicializacin explcito
tipo nombre[tamao]={ele0,ele1,...,eletamao-1};
tipo nombre[]={ele0,ele1,...,eletamao-1};
int mi[10]; /*Vector de 10 enteros*/
double md[5]; /*Vector de 5 doubles*/
char mc[10]; /*Vector de 10 char*/
int miConta[5]={1,1,1,1,1}; /*Se sabe el tamao*/
int miCeros[]={0,0,0,0,0}; /*Hay que contar para saber el
tamao que utilizar el compilador*/
Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 7
Prof. lvaro Snchez Miralles

Vectores Programacin en C

Vectores estticos: Uso y funcionamiento


Slo se puede acceder desde nombre[0] hasta
nombre[tamao-1]. for (i=0;i<tamao;i++){
Operar(nombre[i]);
}
nombre no es una variable.
nombre[i] son las variables. HORROR!!

nombre no es un l-value. nombre=12

Se crean y destruyen de forma automtica.


void prueba(void)
{
int mi[10]; Se crean 10 variables de tipo entero
int i;

for (i=0;i<10;i++){
mi[i]=i;
}
} Se destruyen las 10 variables

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 8


Prof. lvaro Snchez Miralles
Vectores Programacin en C

Cadenas de caracteres ASCII


Caso especial de manejo de un vector de char.
Almacenar y manipular cadenas de caracteres ASCII de
diferente tamao sobre un vector de longitud fija.
El \0 indica cuando se acaba la cadena de caracteres
dentro del vector.
La longitud del vector debe ser suficiente para albergar las
cadenas de caracteres (incluido el \0) a manipular.
M M
Se crea un vector de 6 char automticamente
A A
main() {
char s[6]={'M','a','r','i','a','\0'}; R R
printf(1 %s\n",s);
1 Maria I \0
s[3]='\0';
2 Mar
printf(2 %s\n",s); A A
}
\0 \0
Se destruyen las 6 variables char automticamente
Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 9
Prof. lvaro Snchez Miralles

Vectores Programacin en C

Declaracin de cadenas de caracteres ASCII


Declaracin: char snombre[tamao];
El prefijo s indica que es vector de caracteres destinado a albergar
cadenas de caracteres ASCII terminadas en \0.
El tamao mximo de la cadena de caracteres no puede superar
tamao-1, para incluir al final el \0.
Se recomienda utilizar
mc significa slo vector de caracteres. la declaracin con tamao
Inicializacin: explcito
Tamao explcito:
char sApellido[10]={R;o,a,\0};

char sApellido[10]=Roa;

Tamao implcito:
char sApellido[]=Roa; /* Vector de 4 char */

!No recomendada! Hay que contar


los caracteres y sumar 1
Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 10
Prof. lvaro Snchez Miralles
Vectores Programacin en C

Errores tpicos con cadenas de caracteres ASCII


Intentar asignar un valor a una constante.
Tamao insuficiente.

main() {
char s[6];

s=Hola; /*FALLO -> ES UNA CONSTANTE */

s[0]=H; /*CORRECTO -> ES UNA VARIABLE */


s[1]=\0;

strcpy(s,Manolo); /* TAMAO INSUFICIENTE */


}

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 11


Prof. lvaro Snchez Miralles

Vectores Programacin en C

Antes de hablar de vectores dinmicos: Punteros


Variable que almacena la direccin de otra variable
El operador & calcula la direccin de una variable
Declaracin: tipo *nombre;
nombre es una variable que almacena una direccin que apunta a
otra variable de tipo tipo
nombre se forma a partir de:
El prefijo p para indicar puntero o variable que almacena direcciones.
El prefijo correspondiente al tipo de la variable a la que apunta
(i,d,c,l,v,pv...). Caso s: significa que apunta a una cadena de
caracteres gestionada como cadena ASCII (con \0 al final).
Funcin que desempea el puntero.
Uso como una variable normal sometida a la aritmtica de
direcciones.
Uso para acceder a la variable a la que apunta:
dereferenciando a travs del operador *
Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 12
Prof. lvaro Snchez Miralles
Vectores Programacin en C

Ejemplo con punteros


12
1000 0
2 -3
main() i
3 1000 1001 2
{
4 1000
int i;
5 2000 1002 2
int *pi; /*Puntero a entero*/
1003 2
i=2; 1004
printf("1 %d\n",i);
2000 00
pi=&i; /*pi apunta a i*/
*pi=-3; /*pi modifica el valor de i*/ 2001 00
printf("2 %d\n",i); pi
2002 10
printf("3 %p\n",&i); 2003 00
printf("4 %p\n",pi); Al dereferenciar pi
printf("5 %p\n",&pi); obtenemos la variable i.
} *pi=-3 significa escribir
en la posicin indicada por pi
segn el tipo especificado
(int para este caso).

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 13


Prof. lvaro Snchez Miralles

Vectores Programacin en C

Ejemplo de declaracin de punteros

int *pi; /*Puntero a variable de tipo entero*/


/*Variable que almacena la direccin de otra*/
/*variable de tipo entero*/
double *pd; /*Puntero a variable de tipo double*/
/*Variable que almacena la direccin de otra*/
/*de tipo double*/
int **ppi; /*Puntero a variable de tipo puntero*/
/*que apunta a entero*/
/*Variable que almacena la direccin de otra*/
/*variable que a su vez almacena la*/
/*direccin de otra variable de tipo entero*/
void **ppv; /*Puntero a puntero que apunta*/
/*a void (a ningn tipo concreto)*/
/*Variable que almacena la direccin de otra*/
/*variable que almacena simplemente una*/
/*direccin*/

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 14


Prof. lvaro Snchez Miralles
Vectores Programacin en C

Uso del puntero para acceder a variables


individuales
Declarar un puntero del mismo tipo que la variable.
Calcular la direccin de la variable y asignarla al puntero.
Dereferenciar el puntero (*nombre) para acceder a la
posicin de la variable y asignarle un valor. En C no hay paso
Utilidad: por referencia: siempre
es por valor
Modificar variables externas a una funcin.
El puntero permite en las funciones el mecanismo de paso por
referencia. Sigue siendo un paso por valor, porque se pasa la
direccin de la variable a modificar.

int i; /*Variable de tipo entero*/


int *pi; /*Puntero a variable de tipo entero*/
pi=&i; /*Direccin de i es asignada a pi*/
*pi=4; /*pi[0] tambin es vlido*/

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 15


Prof. lvaro Snchez Miralles

Vectores Programacin en C

Ejemplo de puntero con variables individuales

#include <stdio.h>

void Modifica(double *pd);


1 -1.2
main() 2 3.8
{
double d;

d=-1.2;
printf("%g\n",d);
Modifica(&d);
printf("%g\n",d); Se calcula la direccin de la variable d
}

void Modifica(double *pd)


{ La funcin recibe la direccin de la
*pd=*pd + 5; variable a modificar en el
} puntero pd

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 16


Prof. lvaro Snchez Miralles
Vectores Programacin en C

Uso del puntero para acceder a vectores


Declarar un puntero del mismo tipo que los elementos del
vector.
Calcular la direccin donde se inicia el vector y asignarla al
puntero.
Moverse con [] a travs de los elementos del vector: p[i].
Alternativa *(p+i) ([] es otro mecanismo de
dereferenciar)
Si se quiere obtener la direccin de cada elemento del vector
a travs de p: &(p[i])
Alternativa p+i
Utilidad:Manejo de vectores tanto estticos como dinmicos.
int mi[5]; /*Vector de 5 enteros*/
int *pi; /*Puntero a variable de tipo entero*/
pi=mi; /*Direccin mi es asignada a pi*/
pi[2]=4;

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 17


Prof. lvaro Snchez Miralles

Vectores Programacin en C

Ejemplo de puntero con vectores: leer valores


#include <stdio.h>

void ImpVector(double *pd, int nEle);

main () pd[0]= 2.3


{ pd[1]= -1.8
double md[3]={2.3,-1.8,4.5}; pd[2]= 4.5

ImpVector(md,3);
return 0; Por qu no se
} calcula la direccin
de md?
void ImpVector(double *pd, int nEle)
{
int i;

for (i=0;i<nEle;i++) {
printf("pd[%d]= %g\n",i,pd[i]);
}
}
Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 18
Prof. lvaro Snchez Miralles
Vectores Programacin en C

Ejemplo de puntero con vectores: cambiar valores


#include <stdio.h>
void LeeVector(double *pd, int nEle);
void ImpVector(double *pd, int nEle);
main () 2.3
{ 4.2
double md[3]; -1.8
pd[0]= 2.3
LeeVector(md,3); pd[1]= 4.2
ImpVector(md,3); pd[2]= -1.8
return 0;
}
void LeeVector(double *pd, int nEle)
{ Hay que pasar a fscanf la
int i; direccin de la variable donde
depositar el valor a leer
for (i=0;i<nEle;i++) { (pd+i tambin es correcto)
fscanf(stdin,"%lf",&pd[i]);
}
}
Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 19
Prof. lvaro Snchez Miralles

Vectores Programacin en C

Errores tpicos con los punteros y vectores


double *pdActualiza();
1 00000000
main () 2 0012FF68
{ pd[0]= 1.2
double *pd=NULL; pd[1]= -2.3
pd[2]= -1.4
printf("1 %p\n",pd); 3 0012FF68
pd=pdActualiza(); pd[0]= 0
printf("3 %p\n",pd); pd[1]= 2.64195e-308
ImpVector(pd,3); HORROR!! pd[2]= 1.78731e-307
return 0; Dnde estn los
} md es un
elementos del vector md?
variable
double *pdActualiza()
LOCAL
{
double md[3]={1.2,-2.3,-1.4};
double *pd=md;
printf("2 %p\n",pd);
ImpVector(pd,3);
return pd;
}
Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 20
Prof. lvaro Snchez Miralles
Vectores Programacin en C

Punteros y cadenas de caracteres


char *NombreCorr1();
char *NombreCorr2();
char *NombreIncorr(); Es correcto 1
main() { /* Falta incluir stdio.h y stdlib.h */ Es correcto 2
printf("%s\n",NombreCorr1()); X&
printf("%s\n",NombreCorr2());
printf("%s\n",NombreIncorr());
}
char *NombreCorr1(){
return "Es correcto 1"; Cadena de caracteres constante. Se crea
}
al principio del programa y slo se
char *NombreCorr2(){ destruye al final. Cuando se evala el
char *ps; resultado es la direccin de comienzo de
ps="Es correcto 2";
dicha cadena en memoria.
return ps;
}
char *NombreIncorr(){ Cadena de caracteres local a la funcin. Se
char s[20]="Es correcto 2"; crea al inicio de la funcin y se inicializa
char *ps=s; segn la cadena descrita. Se destruye al
return ps; terminar de ejecutarse la funcin
}

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 21


Prof. lvaro Snchez Miralles

Vectores Programacin en C

Funciones de la librera string.h


char* strcpy(char* destino, char* origen)
char* strcat(char* destino, char* origen)
int strcmp(char* , char*)
unsigned inf strlen(char*)
#include string.h

char szFrase[10] = "Inicio"; 1 Ini


char szCopiaFrase[10]; 2 IniInicio
char *pcCopiaFrase; 36
4 Inicio
strcpy(pcCopiaFrase,szFrase); // Error 50
pcCopiaFrase = strncpy(szCopiaFrase,szFrase,3);
printf("1 %s\n",szCopiaFrase);
6 InicioInicio
strcat(pcCopiaFrase, szFrase);
printf("2 %s\n",szCopiaFrase);
printf("3 %d\n", strlen(szFrase));
strcpy(szCopiaFrase,szFrase);
printf("4 %s\n",szCopiaFrase);
printf("5 %d\n", strcmp(szFrase,szCopiaFrase));
strcat(szFrase, szCopiaFrase); // Error
printf("6 %s\n",szFrase);

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 22


Prof. lvaro Snchez Miralles
Vectores Programacin en C

Por qu se necesitan vectores creados de forma


dinmica?
Hasta que no se inicia la
ejecucin del programa no se
sabe la dimensin del vector.
Caso tpico: funcin que lee
un vector desde un fichero. Fichero vector.txt
Hasta que el programa no abra 3 2.3 -4.5 2.03
el fichero no se puede conocer
el nmero de elementos que
contiene.
Se podra resolver
reservando un vector esttico
de dimensin suficiente: Dimensin Elementos
No siempre es fcil conocer la del vector del vector
mxima dimensin.
En la mayora de los casos es
un despilfarro de memoria

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 23


Prof. lvaro Snchez Miralles

Vectores Programacin en C

Cmo se puede crear un vector dinmicamente?


Reservando memoria que sea
contigua.
Debe ser suficiente para albergar pd
todos los elementos del vector. PROGRAMA
El tamao de cada elemento se
conoce a travs del tipo.
Manejarla a travs de una variable
que maneje direcciones: HEAP
PUNTERO.
Esta memoria suele estar en el
espacio de heap.
Las variables locales, y por tanto los
vectores estticos, estn en el stack. STACK
El mecanismo de reserva de
memoria se basa generalmente en
funciones que hacen llamadas al
Sistema Operativo.
Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 24
Prof. lvaro Snchez Miralles
Vectores Programacin en C

Vectores dinmicos en C
Se manejan a travs de punteros (tambin los estticos).
Antes de utilizar los elementos del vector hay que reservar
memoria suficiente
El puntero es quin almacena la direccin ms baja del vector en
memoria (direccin inicial).
Funcin calloc o similar para reservar memoria.
Se accede a los elementos del vector dereferenciando el
puntero (igual que los estticos)
0 a (nmero de elementos del vector -1)
Cuando no se necesita el vector, se libera la memoria
reservada para dicho vector
Funcin free o similar. La direccin de inicio
del vector en memoria
se debe mantener hasta
el final

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 25


Prof. lvaro Snchez Miralles

Vectores Programacin en C

Ejemplo muy bsico de vector dinmico


#include <stdio.h>
#include <stdlib.h> 1. Crear un vector para albergar
la direccin de inicio del vector
main ()
{
2. Reservar memoria suficiente.
double *pd;
Tamao =
int i;
Nmero de elementos * tamao elemento
pd=(double *)calloc(3,sizeof(double));
pd[0]=2.3;
pd[1]=-1.4; 3. Manejar a travs del puntero como
pd[2]=3.0; los vectores estticos

for (i=0;i<3;i++) 0 2.3


printf("%d %g",i,pd[i]); 1 -1.4
23
free(pd);
return 0;
} 4. Liberar cuando no se necesita
Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 26
Prof. lvaro Snchez Miralles
Vectores Programacin en C

Errores tpicos con los vectores dinmicos (I)


Creer que si se declara el puntero, ya se ha reservado
memoria para el vector.
HORROR!!
Dnde est almacenado
main () 2.3 o -1.4?
{
double *pd; Se ha colgado el
int i; ordenador!!

pd[0]=2.3;
pd[1]=-1.4;
pd[2]=3.0;

for (i=0;i<3;i++)
printf("%d %g",i,pd[i]);

return 0;
}

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 27


Prof. lvaro Snchez Miralles

Vectores Programacin en C

Errores tpicos con los vectores dinmicos (II)


Para qu liberar memoria si mi ordenador tiene 128
Mbytes de RAM?.
HORROR!!
Qu ha pasado con la memoria?
Espacio de memoria Yo slo he reservado memoria
insuficiente: para una matriz de 1000x1000
cierre aplicaciones 50 veces y siempre la he liberado

ANDA!!
Dnde est free?

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 28


Prof. lvaro Snchez Miralles
Vectores Programacin en C

Errores tpicos con los vectores dinmicos (III)


Modificar el puntero que contiene la direccin de inicio del
vector dinmico.
Para liberar la memoria hay que pasar la misma direccin de inicio.
A travs de ella el Sistema Operativo sabe qu trozo de memoria
liberar.
PROFESOR, esto NO FUNCIONA
main (){ He incluido free y sigo con
double *pd; el mensaje de no hay memoria
int i;
pd=(double *)calloc(2,sizeof(double));
pd[0]=2.3;
pd[1]=-1.4;
for (i=0;i<3;i++) {
printf("%d %g",i,*pd);
pd++;
}
free(pd);
}
Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 29
Prof. lvaro Snchez Miralles

Vectores Programacin en C

Ejemplo: biblioteca para manejar vectores de doubles


vector.h + vector.c
Funciones:
double *pdVectordAlea(int nEle);
Generar un vector de nmeros aleatorios entre 0 y 1.
void VectordImp(FILE *pfic,int nEle,double *pd);
Imprimir un vector.
double *pdVectordLee(FILE *pfic,int *pnEle);
Leer un vector desde un fichero.
double dVectordMedia(int nEle, double *pd);
Convenio:
nEle: nmero de elementos del vector
pd: Puntero al vector de doubles.
pfic: Puntero a la estructura de control del fichero.
Vector nulo: nEle =0 y pd =NULL.
Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 30
Prof. lvaro Snchez Miralles
Vectores Programacin en C

Convenio para leer e imprimir vectores


Primero aparece el nmero de elementos y a continuacin
los valores de cada elemento, todo separado por espacios.
Pantalla
Fichero vector.txt
3 2.3 -4.5 2.03
3 2.3 -4.5 2.03

Caso de vector nulo


Pantalla
Fichero vector.txt
0
0

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 31


Prof. lvaro Snchez Miralles

Vectores Programacin en C

double *pdVectordAlea(int nEle)


{ GENERAR VECTOR
int i; DE NUMEROS
double *pd; ALEATORIOS [0,1]

if (nEle<=0)
return NULL;

if ((pd=(double *)calloc(nEle,sizeof(double)))==NULL) {
fprintf(stderr,"Error de sistema: no hay memoria\n");
exit(1);
}
/* Generacin nmero aleatorios */
for (i=0;i<nEle;i++) {
pd[i]=((double)rand())/RAND_MAX;
}

return pd;
}

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 32


Prof. lvaro Snchez Miralles
Vectores Programacin en C
double *pdVectordLee(FILE *pfic,int *pnEle){
int i; LEER VECTOR
double *pd;
if (fscanf(pfic,"%d",pnEle)==EOF) { /* Fichero vacio */
fprintf(stdout,"Datos incorrectos\n");
*pnEle=0; Pseudocdigo:
return NULL;
}
if (*pnEle<0) {
1. Leer tamao del vector
fprintf(stdout,"Datos incorrectos\n"); 2. Reservar memoria
*pnEle=0; 3. Leer elementos del vector
}
return NULL;
4. Devolver puntero al vector
5. En caso de error devolver
if (*pnEle==0) /* Vector nulo */
return NULL; vector nulo.
if ((pd=(double *)calloc(*pnEle,sizeof(double)))==NULL) {
fprintf(stderr,"Error de sistema: no hay memoria");
exit(1);
}
for (i=0;i<*pnEle;i++) { /* Lectura elementos del vector */
if (fscanf(pfic,"%lf",&pd[i])==EOF) {
fprintf(stdout,"Datos incorrectos\n");
}
}
lf para double en fscanf y similares
return pd;
}
f para double en fprintf y similares

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 33


Prof. lvaro Snchez Miralles

Vectores Programacin en C

void VectordImp(FILE *pfic, int nEle, const double *pd){


int i;
fprintf(pfic,"%d ",nEle); IMPRIMIR VECTOR
for (i=0;i<nEle;i++) {
fprintf(pfic,"%f ",pd[i]);
}
} f para double en fprintf y similares
lf para double en fscanf y similares
double dVectordMedia(int nEle, double *pd){
double dSuma;
int i;
if (nEle<=0) CALCULAR MEDIA DE UN
return 0.0; VECTOR
dSuma=0.0;
for (i=0;i<nEle;i++)
dSuma+=pd[i];
return dSuma/nEle;
}

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 34


Prof. lvaro Snchez Miralles
Vectores Programacin en C
Programa de prueba para la biblioteca de vectores:
int nEle=2;
double *pd; Falta main() por razones
FILE *pfic;
de espacio
pd=pdVectordAlea(nEle);
VectordImp(stdout,nEle,pd);
fprintf(stdout," Media: %lf\n",dVectordMedia(nEle,pd));

if ((pfic=fopen("vector.vec","w"))==NULL) {
fprintf(stdout,"No se puede abrir vector.vec\n");
} else {
VectordImp(pfic,nEle,pd);
fclose(pfic);
Fichero que se abre correctamente,
} fichero que se cierra cuando se
free(pd); utiliza
if ((pfic=fopen("vector.vec","r"))==NULL) {
fprintf(stdout,"No se puede abrir vector.vec\n");
} else {
pd=pdVectordLee(pfic,&nEle);
fclose(pfic);
2 0.010559 0.003967 Media: 0.007263
VectordImp(stdout,nEle,pd); 2 0.010559 0.003967
}
free(pd);
Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 35
Prof. lvaro Snchez Miralles

Vectores Programacin en C

Versin avanzada con gestin de memoria dinmica


Mdulo mem (mem.h + mem.cpp) para evitar problemas con la
memoria dinmica:
Liberar memoria que se haya reservado.
Evitar los continuos chequeos de error cada vez que se reserva
memoria.
Contabilidad de la memoria reservada.
Funciones:
void MemReserva(int nObj,int size,void **ppv);
Reserva memoria (sustituye a calloc).
void MemLibera(int *pnObj,int size,void **ppv);
Libera memoria (sustituye a free).
long int MemConsulta(void);
Consulta tamao de la memoria reservada.
void MemIni(void);
Inicializa el contador de memoria reservada a 0.

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 36


Prof. lvaro Snchez Miralles
Vectores Programacin en C

Uso de mem
Todos los punteros que van a guardar una direccin de
inicio de un vector, y despus van a ser utilizados para
liberarlo, se inicializan a NULL.
Asociado a cada puntero del tipo anterior siempre hay una
variable que dice cuantos elementos se han reservado.
Al inicio del programa, siempre se llama a MemIni para
poner el contador de memoria a 0.
Al final del programa, siempre se llama a MemConsulta
para comprobar que se ha liberado toda la memoria.
Centraliza el control de los posibles errores de sistema al
reservar memoria y los de programacin.

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 37


Prof. lvaro Snchez Miralles

Vectores Programacin en C

Ejemplo con mem Memoria inicial: 0


Memoria actual: 40
Memoria actual: 0
#include "mem.h"

main()
{
int nEle;
double *pd=NULL; 1. Inicializar el mdulo mem a 0

MemIni();
fprintf(stdout,"Memoria inicial: %ld\n",MemConsulta());
2. Reservar cuando es necesario
nEle=5;
MemReserva(nEle,sizeof(double),(void **)&pd);
fprintf(stdout,"Memoria actual: %ld\n",MemConsulta());

MemLibera(&nEle,sizeof(double),(void **)&pd);
3. Liberar
fprintf(stdout,"Memoria actual: %ld\n",MemConsulta());
}
4. Consultar que todo ha sido liberado
Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 38
Prof. lvaro Snchez Miralles
Vectores Programacin en C

static long int lMemoria; CONTABILIDAD MEMORIA


void MemIni(void){
INICIALIZAR
lMemoria=0;
}

void MemReserva(int nObj, int size, void **ppv){


RESERVAR
MEMORIA
if ((*ppv!=NULL)||(nObj<0)||(size<=0)){
fprintf(stdout,"Error de programacin en MemReserva\n");
exit(1);
}
Error de
programacin
if ((*ppv=calloc(nObj,size))==NULL){
fprintf(stderr,"Error de sistema: no hay memoria\n");
exit(1);
}
Error de sistema
lMemoria+=(nObj*size);
}

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 39


Prof. lvaro Snchez Miralles

Vectores Programacin en C

void MemLibera(int *pnObj, int size, void **ppv){


if ((*pnObj<0)||(size<=0)) {
fprintf(stdout,"Error de programacin en MemLibera\n");
exit(1);
} Error de
programacin
if (*ppv!=NULL) {
free(*ppv);
*ppv=NULL;
}
LIBERAR MEMORIA
lMemoria-=((*pnObj)*size);
*pnObj=0;
}

long int MemConsulta(void){


return lMemoria;
}

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 40


Prof. lvaro Snchez Miralles
Vectores Programacin en C

Ordenacin de vectores
void* qsort(void* Vector, unsigned int TamanoVector, unsigned
int TamanoElem, int (*cmp)(const void *, const void* ))
#include <string.h>
#include <stdio.h>
hola
#include <stdlib.h>
adios
int ComparaCadena(const void* sz1, const void* sz2){ comida
return(strcmp((char*)sz1,(char*)sz2));} ---------------
adios
int main(){ comida
char pszPalabras[3][10]; hola
strcpy(pszPalabras[0],"hola");
strcpy(pszPalabras[1],"adios");
strcpy(pszPalabras[2],"comida");
for (int i = 0; i<3; i++)
printf("%s\n",pszPalabras[i]);
qsort(pszPalabras,3,10,ComparaCadena);
printf("----------\n");
for (int i = 0; i<3; i++)
printf("%s\n",pszPalabras[i]);}

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 41


Prof. lvaro Snchez Miralles

Vectores Programacin en C

Puntos a discutir
double *pdVectordAlea(int nEle); Debe reservar
memoria o le debemos pasar un puntero apuntando a un
vector ya reservado?
Evita mem el problema de salirse fuera de la memoria
asignada?

Con mem reprogramar vector.h

Discutir un vector de punteros a cadenas de caracteres


Ejemplo: vector de palabras.

Prof. Jos A. Rodrguez Mondjar UPCO ICAI Departamento de Electrnica y Automtica 42


Prof. lvaro Snchez Miralles