PDA

Ver la versión completa : [Ayuda] Ejercicio básico c++



The_Punisher
27/10/2009, 11:24
Hola famigos y famigas!!!!!

Creo que se me ha podrido el cerebro y no recuerdo porque el compilador me escupe este error: [Warning] passing arg 2 of `FiltroFIR' from incompatible pointer type

El código es este,


#define TAMVECTOR 20
#define ORDENFILTRO 5
int Leerdato() ;
void Desplazavector(int *vector, int tam);
void Inicializavector (int *vector, int tam) ;
float FiltroFIR (int *u, int *b, int orden) ;

int Leerdato()
{
static int numero=1;
return numero++;
}

void Desplazavector(int *vector, int tam)
{
int i;
for (i=tam-1;i>0;i--)
vector[i]=vector[i-1];
}

void Inicializavector (int *vector, int tam)

{
int i;
for (i=0;i<tam;i++)
vector[i]=0;
}

float FiltroFIR (int *u, int *b, int orden)

{
int suma, i;
suma=0;
for (i=0;i<orden;i++)
suma=suma+u[i]*b[i];
return suma;
}




int main()

{
float coeficientes_filtro[]={0.2,0.2,0.2,0.2,0.2};
int senal[TAMVECTOR];
int filtrada[TAMVECTOR];
int dato;
Inicializavector(senal,TAMVECTOR);
Inicializavector(filtrada,TAMVECTOR);

dato=Leerdato();
Desplazavector(senal,TAMVECTOR);
senal[0]=dato;
filtrada[TAMVECTOR]=FiltroFIR(senal,coeficientes_filtro,ORDENFILTRO);
Anadedato(filtrada,TAMVECTOR,dato);
return;
}

A ver si me echaí una mano mientras voy definiendo la función Anadedato, graciasssssssss

xzakox
27/10/2009, 11:30
Por lo que veo nada, es un Warning, se queja porque no es lo mismo un int* que un float[] ;-)
(defines la función asi, float FiltroFIR (int *u, int *b, int orden) y le pasas un array de floats, coeficientes_filtro).

Soltfern
27/10/2009, 11:32
¿ coeficientes_filtro es un vector y en la función FiltroFIR no trabaja como tal ?

The_Punisher
27/10/2009, 11:37
buffff parezco tontito pero es qe nunca trabaje con arras y me pierdo xD el objetivo de la práctica es este, a er si asi nos entemdemos mejor.

Leer un nuevo dato cada vez que se llama a Leerdato, que serían números consecutivos (1,2,3,4,...)
Añadir el nuevo dato a la señal
Calcular la media de los últimos (orden) datos de la señal
Añadir el nuevo dato a la señal filltrada
Funcionar de forma indenida

Soltfern
27/10/2009, 11:57
¿Pero no es lo que te hemos dicho?

xzakox
27/10/2009, 11:57
indenida? xD

The_Punisher
27/10/2009, 11:58
Si entiendo el problema. pero no veo donde tengo que hacer la modifcacion, en la declaracion de la funcion? o donde?

Soltfern
27/10/2009, 12:01
En la declaración de la funión, claro. La función se cree que le vas a pasar int por referencia, y le estás pasando un vector de float

Ñuño Martínez
27/10/2009, 12:08
Esto nunca pasaría con Object Pascal. 8^V

Ahora en serio: procura utilizar el mismo tipo cuando hagas asignaciones y pases valores como parámetro. Para evitar los avisos, utiliza moldes. Además, así compruebas si realmente quieres hacer lo que quieres hacer. Por ejemplo, intentar hacer pasar un flota[] por un *int pues como que me rechina un poco, incluso utilizando moldes.

The_Punisher
28/10/2009, 10:25
Bueno estoy a medio camino, algo es algo xD

He hecho un programa que hace las cosas que me piden lo cual está genial jajajaja pero tengo un pero bastante gordo, tengo que hacerlo con punteros y no tengo ni idea de punteros, entonces, como es la manera mas fácil de pasar mi código, que tiene unos vecotres que ralentizan la ejecución del programa, a uno con punteros que haga mas ligero el trabajo.


#define TAMVECTOR 20
#define ORDENFILTRO 5

int Leerdato() ;
void Anadedato(float vector[],int tam, float dato);
void Desplazavector(float vector[], int tam);
float Filtromedia (float vector[], int tam, int orden);
void Inicializavector (float vector[], int tam);

int Leerdato() {
static int numero=1;
return numero++;
}


void Anadedato(float vector[],int tam, float dato) {
Desplazavector(vector,tam);
vector[tam-1]=dato;
}

void Desplazavector(float vector[], int tam) {
int i;
for (i=0;i<tam-1;i++)
vector[i]=vector[i+1];
}

float Filtromedia (float vector[], int tam, int orden) {
float media=0.0;
int i;
for (i=tam-1;i>tam-1-orden;i--)
media=media+vector[i];
return media/orden;
}

void Inicializavector (float vector[], int tam) {
int i;
for (i=0;i<tam;i++)
vector[i]=0;
}

int main() {
int dato;
float media;
float senal[TAMVECTOR];
float filtrada[TAMVECTOR];
Inicializavector(senal,TAMVECTOR);
Inicializavector(filtrada,TAMVECTOR);
while(1){
dato=Leerdato();
Anadedato(senal,TAMVECTOR,dato);
media=Filtromedia(senal,TAMVECTOR,ORDENFILTRO);
Anadedato(filtrada,TAMVECTOR,media);
}
return 0;
}

Gracias famigos!

Ñuño Martínez
28/10/2009, 10:38
Si no tienes ni idea de punteros, mal lo tienes. :rolleyes:

Mira: un puntero es una variable que contiene una dirección de memoria: punto. Cuando le pones el asterisco delante, le estás diciendo al compilador que quieres obtener o modificar el dato que hay en dicha posición de memoria.


int Variable, *Puntero;

Variable = 0;

/* Hacemos que Puntero almacene la posición de memoria de la Variable. */
Puntero = &Variable;

/* Guardamos "7" en la posición de memoria a la que apunta Puntero. */
*Puntero = 7;

/* Variable contiene "7" porque hemos cambiado su posición de memoria. */
printf ("%d\n", Variable);


Cuando a un puntero le sumas o restas un número, estás cambiando la posición de memoria. El "problema" es que si sumas uno a un puntero, este no pasa a apuntar al octeto (byte) siguiente, sino que en realidad se le suma tantos octetos como el tamaño del tipo de puntero. A ver si lo explico en el próximo código:


int List[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, *Punt;

/* Hacemos que Punt apunte al primer elemento de List. */
Punt = &(List[0]); /* Redundante, pero más claro. ;) */

/* Si sumamos uno a Punt, entonces apuntará al siguiente elemento. */
Punt ++;
*Punt = 20;
for (Cnt=0; Cnt<10; ++Cnt)
printf ("%d = %d\n", Cnt, List[Cnt]);
/* Por tanto, podemos recorrer toda la lista utilizando el puntero.
Fíjate que la condición final es encontrar una posición de memoria que contenga el valor "9". */
for (Punt=&(List[0]); *Punt!=9; ++Punt)
printf ("%d\n", *Punt);


Et voilá! Creo que esto lo cubre todo, o casi. :)

Me falta una cosa: en algunos sitios utilizan las listas como si fueran punteros. Sí, se puede, pero no es recomendable, precisamente porque es confuso. Lo mejor es utilizar las listas como listas siempre.

The_Punisher
28/10/2009, 10:40
uooooo, gracias por la explicacion, creo que con el ejemplo he visto el cielo y la tierra!!!!

O sea ya no me hace falta saber el tamaño del vector, puesto que no corro riesgo de equivocarme, salvo que yo me confunda y apunte a una direccion que no existe, ¿me equivoco? Asi me puedo ahorrar todos esos bucles recorriendo el vector entero ¿no?

GRACIAS

Soltfern
28/10/2009, 10:43
Lo que necesitas es básicamente pasar de tener vectores a punteros. El puntero te indicará en qué posición de memoria está el primer valor de tu vector, y luego irá recorriendo las posiciones siguientes para tomar los valores.

Digamos que si usas los vectores, le pasas toda la información de golpe, y si usas un puntero, le pasas simplemente la dirección del primer elemento del vector, y va leyendo consecutivamente para sacar todos los valores.

EDIT: Me salté los 2 post anteriores, si xD

The_Punisher
28/10/2009, 11:02
Bueno ya casi lo tengo pero me tira 3 warnings por algo que ya me explicasteis pero no acabo de ver claro os pongo el code, los errores y lo que pienso que puede ser.


#define TAMVECTOR 20
#define ORDENFILTRO 5
int Leerdato() ;
void Desplazavector(int *vector, int tam);
void Inicializavector (int *vector, int tam) ;
void Anadedato(float *vector, int tam, float dato);
float Filtromedia (float *vector, int tam, int orden);

int Leerdato()
{
static int numero=1;
return numero++;
}
void Anadedato(float *vector,int tam, float dato) {
Desplazavector(vector,tam);
vector[tam-1]=dato;
}

void Desplazavector(int *vector, int tam)
{
int i;
for (i=tam-1;i>0;i--)
vector[i]=vector[i-1];
}

void Inicializavector (int *vector, int tam)

{
int i;
for (i=0;i<tam;i++)
vector[i]=0;
}

float Filtromedia (float *vector, int tam, int orden)

{
float media=0.0;
int i;
for (i=tam-1;i>tam-1-orden;i--)
media=media+vector[i];
return media/orden;
}


int main()

{
int dato;
float media;
float senal[TAMVECTOR];
float filtrada[TAMVECTOR];
Inicializavector(senal,TAMVECTOR);
Inicializavector(filtrada,TAMVECTOR);
while(1)

{
dato=Leerdato();
Anadedato(senal,TAMVECTOR,dato);
media=Filtromedia(senal,TAMVECTOR,ORDENFILTRO);
Anadedato(filtrada,TAMVECTOR,media);
}
return 0;

}



In function `Anadedato':
15[Warning] passing arg 1 of `Desplazavector' from incompatible pointer type

In function `main':
52 [Warning] passing arg 1 of `Inicializavector' from incompatible pointer type
53 [Warning] passing arg 1 of `Inicializavector' from incompatible pointer type

Bueno realmente creo que esas dos funciones estan mal hechas, pero no se muy bien como reescribirlas para que funcionen con punteros

Ñuño Martínez
28/10/2009, 11:07
Pues sí, más o menos. Por cierto, que también puedes hacer algo como esto:


int Lista[10], *Punt, Cnt;

*Punt = &(Lista[0]);

for (Cnt=0; Cnt<10; ++Cnt)
*(Punt + Cnt); /* Esto es como hacer "Lista[Cnt]" o "Punt[Cnt]". */


Con esto y lo que ha escrito Softerm debería bastarte.

< - >
Para llamar a "Inicializavector" mejor así:


Inicializavector (&(senal[0]), TAMVECTOR);

Creo que con eso te quita el warning.

Soltfern
28/10/2009, 11:09
Si que necesitas saber el tamaño que vas a utilizar (a no ser que programes para que pueda ir aumentando su tamaño a medida que lo necesite), porque el puntero que crees debe apuntar al primer elemento del vector, y para recorrer el vector necesitas saber cuan grande es.

Digamos que tendrías algo así para definir un vector:



double (*vector)[20]; /*crea un puntero a un array de números de tipo double, de tamaño 20. Apunta al primer número del array, es decir, a vector[0]. Si al puntero le sumas un entero, apunta a otro número del array*/

int i=5;
double a=*(vector+i) /*a=vector[5]*/

hardyx
28/10/2009, 16:22
Las funciones InicializaVector() y DesplazaVector() te dan error porque tratan vectores de enteros y le estás endiñando un vector de floats. Tienes que cambiar las funciones para usar floats.

Además no le veo sentido a la función DesplazaVector() para añadir un dato, no te va a funcionar de esa manera. Lo más sencillo es tener un índice inicializado a cero con el siguiente elemento a añadir. Y en AnadeDato haces esto:


vector[indice]=dato;
indice++;

Para hacerlo con punteros y que vaya más rápido no es suficiente con cambiar las cabeceras. Los índices implican usar instrucciones indirectas de la CPU y son más lentos. Tienes que cambiar también el proceso de los datos con punteros en vez de con índices. De esta forma:


// así se hace con índices
void Inicializavector (float vector[], int tam)
{
for (int i=0; i<tam; i++)
vector[i] = 0;
}

// así se hace con punteros
void Inicializavector (float *vector, int tam)
{
for (int i=0; i<tam; i++, vector++)
*vector = 0;
}

Notas:
vector++, incrementa el puntero al siguiente elemento del vector.
*vector = 0, asigna cero al contenido del puntero (elemento)