Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: MartNahuel95 en 8 Junio 2016, 15:37 pm



Título: Proyecto en Dev C++ (Arreglo de dimensión variable en archivo .h")
Publicado por: MartNahuel95 en 8 Junio 2016, 15:37 pm
Buenas, tengo un problema en un proyecto que estoy compilando "Cálculos Estadísticos".
Se supone que el usuario debe poder ingresar la cantidad de elementos que quiere guardar en un vector (Longitud del arreglo). Para luego ponerse a cargar los
elementos.
 
Mi proyecto consta de tres archivos:

"main.cpp": Aquí iría mi menú, con una instrucción "Switch" el
usuario elegiría lo que quiere calcular.

"Calculos_estadisticos.h": Aquí deberia "Declarar mi arreglo de ( L ) dimension" y en una estructura crear mis funciones con el arreglo declarado como argumento de cada una.

"Calculos_estadisticos.cpp": Aquí iría la programación de las funciones, llamadas desde el arreglo.

Lo que ocurre es que si no declaro mi arreglo en el .h con una dimensión preestablecida, obviamente me dice que no está declarado.

Ya hice un proyecto anterior, "Calculos_Vectoriales" pero en ese caso tenía que declarar un vector de una dimensión fija L=3. Lo declaré de la siguiente forma
Código:
#pragma once

const int D=3;
typedef int vector3D[D];

typedef struct vector_estr{
void carga_vector(vector3D V);
double angulo(vector3D A,vector3D B);
double proyeccion(vector3D A,vector3D B);
void punto_medio(vector3D A,vector3D B);
void perpendicular(vector3D A,vector3D B);
void verif_perpendicularidad(vector3D A,vector3D B);
void verif_paralelismo(vector3D A,vector3D B);

private:
int prod_punto(vector3D A, vector3D B);
double modulo(vector3D V);
int vector_vacio(vector3D V);
void imprimir_vector(vector3D V);
};

Necesito hacer lo mismo para mi nuevo proyecto "Calculos_estadisticos" pero no puedo definir el arreglo de dimensión variable.

Agradecería Muchísimo una ayuda con esto!! Desde ya muchas gracias.


Título: Re: Proyecto en Dev C++ (Arreglo de dimensión variable en archivo .h")
Publicado por: AlbertoBSD en 9 Junio 2016, 02:01 am
Para que sea de longitud variable necesitas memoria dinamica.

Se declara un apuntador ej..
Código
  1. int *a =NULL;
  2. a= calloc(sizeof(int),N); // N elementos int

N puede ingresarlo el usuario en tiempo de ejecucion.

Si tienss duddas sobre memoria dinamica

iBf7AThP1w8

O sobre arreglos de longitud variable
pw7hzCserBw

En mi firma esta mi canal de youtube.


Título: Re: Proyecto en Dev C++ (Arreglo de dimensión variable en archivo .h")
Publicado por: MartNahuel95 en 9 Junio 2016, 02:58 am
Agradezco muchísimo su respuesta en serio, pero de igual manera no entiendo aún cómo hacerlo,
¿en qué archivo debo codificar el ejemplo anterior que me dio?

En el "main.cpp"; en la instrucción "switch" que corresponde a (Cargar el arreglo):
Debo pedir al usuario la cantidad de elementos que desea cargar.

Mi problema es que si no declaro la variable "arreglo" en el Calculos_estadisticos.h no puedo argumentar las funciones dentro de mi estructura.

Este sería mi archivo "main.cpp"

Código:
#include<stdio.h>
#include<ctype.h>
#include<windows.h>
#include "Calculos_estadisticos.h"

void menu(){
printf("\n\n\t\t\tC%clculos Estad%csticos.",160,161);
printf("\n\n\t1)Ingrese el tama%co y datos del arreglo   [C]",164);
printf("\n\t2)Media del arreglo                       [M]");
printf("\n\t3)Varianza del arreglo                    [V]");
printf("\n\t4)Desviaci%cn estandar del arreglo         [D]",162);
printf("\n\t5)Salir                                   [S]");
printf("\n\n\t\tIngrese una opci%cn v%clida [C-M-V-D-S]\n",162,160);
printf("\n\tOpci%cn: ",162);
}

int main(){
menu();
char op;
do{
scanf("%c",&op);
op=toupper(op);
switch(op){
case 'C':
int N;
int *a=NULL;
printf("Ingrese la cantidad de numeros del que estará compuesto el arreglo:");
scanf("%d",&N);
a=calloc(sizeof(int),N);

break;
case 'M':

break;
case 'V':

break;
case 'D':

break;
}
}while(toupper(op)!='S');
}

Este mi archivo "Calculos_vectoriales.h"
Código:
#pragma once

typedef int arreglo[*a];

typedef struct funciones{
  void carga_arreglo(arreglo V);
double media(arreglo V);
  double varianza(arreglo V);
  double desv_est(arreglo V);
 
 
 };

Por último iría mi "Calculos_estadisticos.cpp"

Código:
#include<stdio.h>
#include<math.h>
#include "Calculos_estadisticos.h"


En el que aún no tengo nada


Título: Re: Proyecto en Dev C++ (Arreglo de dimensión variable en archivo .h")
Publicado por: AlbertoBSD en 9 Junio 2016, 03:56 am
Esque realmente no se que quieres hacer.

Según tu codigo:

Código
  1. typedef int vector3D[D];

Vector 3D es un arreglo de 3 enteros.

Entonces no se por que lo quieres hacer dinamico.

Código
  1. int *vectorN;
  2. vectorN = calloc(sizeof(int),10); // vector de 10 elementos
  3.  

Aqui el detalle que tienes, es que se necesita inicializar cada vez que uses uno nuevo.

Saludos!!


Título: Re: Proyecto en Dev C++ (Arreglo de dimensión variable en archivo .h")
Publicado por: class_OpenGL en 9 Junio 2016, 07:02 am
Si lo que quieres hacer es declarar un tipo de variable que almacene un vector de n elementos, podrías crear la siguiente estructura:

Código
  1. typedef struct {
  2.    int *elementos; // Este puntero apuntará al primer byte del vector
  3.    unsigned int n; // Esta variable almacenará cuantas dimensiones tiene el vector
  4. } vectorN;

Entonces, una vez tenemos esa estructura, cuando obtengamos del usuario las dimensiones que quiere para su vector, solamente rellenamos la estructura:

Código
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3.  
  4. int main() {
  5.    vectorN vector = {NULL, 0};
  6.  
  7.    fprintf(stdout, "Introduzca las dimensiones que quiera para su vector: ");
  8.    fscanf(stdin, "%u", &vector.n);
  9.    vector.elementos = calloc(vector.n, sizeof(int));
  10.  
  11.    return 0; // No olvides liberar la memoria cuando termines!
  12. }

También podrías crear una función que te haga el trabajo:
Código
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3.  
  4. void init_vectorN(vectorN *vector, unsigned int n);
  5.  
  6. int main() {
  7.    vectorN vecto = {NULL, 0};
  8.    unsigned int n;
  9.  
  10.    fprintf(stdout, "Introduzca las dimensiones que quiera para su vector: ");
  11.    fscanf(stdin, "%u", &n);
  12.    init_vectorN(&vector, n);
  13.  
  14.    return 0;
  15. }
  16.  
  17. void init_vectorN(vectorN *vector, unsigned int n) {
  18.    vector.n = n;
  19.    vector.elementos = calloc(n, sizeof(int));
  20. }


Título: Re: Proyecto en Dev C++ (Arreglo de dimensión variable en archivo .h")
Publicado por: MartNahuel95 en 9 Junio 2016, 16:08 pm
Código
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3.  
  4. int main() {
  5.    vectorN vector = {NULL, 0};
  6.  
  7.    fprintf(stdout, "Introduzca las dimensiones que quiera para su vector: ");
  8.    fscanf(stdin, "%u", &vector.n);
  9.    vector.elementos = calloc(vector.n, sizeof(int));
  10.  
  11.    return 0; // No olvides liberar la memoria cuando termines!
  12. }

En esta parte, vector.elementos = calloc(vector.n, sizeof(int)); por qué es necesario que ante-puesto a calloc se escriba (int*)?? Lo digo porque al usarlo así como usted escribió se produjeron errores. Luego leí ejemplos en Internet y siempre anteponen eso.

De por sí, creo que por el momento su respuesta me está ayudando mucho, le agradezco


Título: Re: Proyecto en Dev C++ (Arreglo de dimensión variable en archivo .h")
Publicado por: MartNahuel95 en 9 Junio 2016, 16:32 pm
Por el momento tengo esto:

En el main.cpp:

Código:
case 'C':
printf("Introduzca la dimensión de su conjunto de valores:");
scanf("%d",&arreglo.n);
arreglo.elementos=(int*)calloc(arreglo.n, sizeof(int));


break;

En Calculos_estadisticos.h:

Código:
#pragma once


typedef struct vectorN{
int *elementos;
        int n;
};

typedef struct funciones{
  void carga_arreglo(vectorN V);
double media(vectorN V);
  double varianza(vectorN V);
  double desv_est(vectorN V);
 
 
 };

y ahora creando mi Calculos_estadisticos.cpp:

Código:
#include<stdio.h>
#include<math.h>
#include "Calculos_estadisticos.h"

void funciones::carga_arreglo(vectorN V){
int z=vectorN.n;
for(int i=0;i<z;i++){
scanf("%d",&vectorN.elementos);
}
}

cuando quiero guardar en z el valor de la (cantidad de elementos cargados por el usuario) me da error.


Título: Re: Proyecto en Dev C++ (Arreglo de dimensión variable en archivo .h")
Publicado por: class_OpenGL en 9 Junio 2016, 17:27 pm
Claro. Estás trabajando en C++. En C++, el casteo de tipos es más estricto. Mientras que en C ese código no produciría errores, en C++ tienes que castear el retorno de la función (tienes que poner int * porque calloc retorna el tipo void *).

Básicamente, C++ es más estricto en esas situaciones


Título: Re: Proyecto en Dev C++ (Arreglo de dimensión variable en archivo .h")
Publicado por: AlbertoBSD en 9 Junio 2016, 18:30 pm
segun veo si tiene el (int *) Junto al calloc.

Creo que el error va por el lado de la funcion
Código
  1. #include<stdio.h>
  2. #include<math.h>
  3. #include "Calculos_estadisticos.h"
  4.  
  5. void funciones::carga_arreglo(vectorN V){
  6. int z=vectorN.n;
  7. for(int i=0;i<z;i++){
  8. scanf("%d",&vectorN.elementos);
  9. }
  10. }

Donde vectorN es el tipo de dato la variable es V

Deberia de ser asi:

Código
  1. #include<stdio.h>
  2. #include<math.h>
  3. #include "Calculos_estadisticos.h"
  4.  
  5. void funciones::carga_arreglo(vectorN V){
  6. int z=V.n;
  7. for(int i=0;i<z;i++){
  8. scanf("%d",&vectorN.elementos);
  9. }
  10. }


No he compilado el codigo pero deberia de ser ese el problema.

Saludos.


Título: Re: Proyecto en Dev C++ (Arreglo de dimensión variable en archivo .h")
Publicado por: class_OpenGL en 9 Junio 2016, 18:44 pm
Cita de: AlbertoBSD
segun veo si tiene el (int *) Junto al calloc.

Creo que se refería al fragmento de código que proporcioné. Puse en código pensando en C, porque no caí en la cuenta de que el usuario está trabajando en C++. Entonces, antes de la función calloc yo tendría que haber puesto (int *)


Título: Re: Proyecto en Dev C++ (Arreglo de dimensión variable en archivo .h")
Publicado por: MartNahuel95 en 9 Junio 2016, 21:28 pm
Si AlbertoBSD, ese era el problema, no me había dado cuenta de eso, gracias.

Ahora tengo un nuevo inconveniente en el "main.cpp", al momento de llamar a mi función creada.

A mi estructura del arreglo dinámico la renombré así:
Código:
vectorN arreglo={NULL,0};

Código:
switch(op){
case 'C':
printf("Introduzca la dimension de su conjunto de valores:");
scanf("%d",&arreglo.n);
arreglo.elementos=(int*)calloc(arreglo.n, sizeof(int));

funciones.carga_arreglo(/*Cuál sería el argumento aquí*/);

break;


Título: Re: Proyecto en Dev C++ (Arreglo de dimensión variable en archivo .h")
Publicado por: class_OpenGL en 9 Junio 2016, 21:42 pm
Si nos guiamos por el ejemplo dado por AlbertoBSD, el argumento sería el vector. Es decir, puedes hacer esto:
Código
  1. funciones.carga_arreglo(arreglo);

Solo quería aclarar que creo que hay algunos pequeños errores en el código de AlbertoBSD. Creo que este sería el código bueno (puede que me equivoque):

Código
  1. #include<stdio.h>
  2. #include<math.h>
  3. #include "Calculos_estadisticos.h"
  4.  
  5. void funciones::carga_arreglo(vectorN &V) {// Si no lo pasas por referencia, no afectará al vector.
  6.    int z = V.n; // Aquí antes estaba vectorN.n, pero lo que quieres hacer es acceder al miembro de 'V'
  7.    for(int i=0; i<z; i++){
  8.        scanf("%d",&vectorN.elementos[i]); // Aquí tienes que poner los corchetes para acceder a cada elemento
  9.    }
  10. }


Título: Re: Proyecto en Dev C++ (Arreglo de dimensión variable en archivo .h")
Publicado por: MartNahuel95 en 9 Junio 2016, 21:58 pm
Cierto, me faltó tambien el [sub i]
También veo que tengo un error aquí:

Código:
for(int i=0; i<z; i++){
        scanf("%d",&vectorN.elementos[i]);
    }

Donde está "vectorN" debe también ser cambiado por "V"

Una vez solucionado esto, sigo teniendo un problema al llamar a mi función:

Código:
funciones.carga_arreglo(arreglo);


main.cpp [Error] expected unqualified-id before '.' token


Título: Re: Proyecto en Dev C++ (Arreglo de dimensión variable en archivo .h")
Publicado por: class_OpenGL en 9 Junio 2016, 22:16 pm
No me fijé en eso antes. Si quieres acceder a las funciones de una estructura de forma estática, primero, en la estructura, tienes que definirlas como estáticas:

Código
  1. struct funciones {
  2.    static void carga_arreglo(arreglo V);
  3.    static double media(arreglo V);
  4.    static double varianza(arreglo V);
  5.    static double desv_est(arreglo V);
  6. };

Definirlas de forma estática le dice al compilador que esos métodos (funciones dentro de una clase/estructura) no modificarán ningún miembro del objeto.

Una vez declaras las funciones como estáticas, puedes usarlas así:

Código
  1. funciones::carga_arreglo(arreglo);


Título: Re: Proyecto en Dev C++ (Arreglo de dimensión variable en archivo .h")
Publicado por: MartNahuel95 en 10 Junio 2016, 02:48 am
Tengo que agradecer en serio a los dos, A class_OpenGL y a AlbertoBSD. En serio Muchas Gracias.

Ahora que ya solucioné mi problema con la carga del arreglo puedo terminar de crear las funciones restantes.

Una última pregunta, ¿dónde libero la memoria?.
Al liberar la memoria se elimina lo que se haya guardado en el vector no?


Título: Re: Proyecto en Dev C++ (Arreglo de dimensión variable en archivo .h")
Publicado por: AlbertoBSD en 10 Junio 2016, 02:54 am
Una última pregunta, ¿dónde libero la memoria?.
Al liberar la memoria se elimina lo que se haya guardado en el vector no?

Liberar memoria solo marca el espacio como disponible para que sea usado por otra parte del programa.

El contenido no es borrado.

Tienes que liberarla en una sección del codigo donde de ahi en adelante estes totalmente segura de que no volveras a acceder a esos elementos

En codigos pequeños es generalemente al finalizar el programa. En codigos mas grandes hay que tomar el criterio que te comente.

Saludos


Título: Re: Proyecto en Dev C++ (Arreglo de dimensión variable en archivo .h")
Publicado por: MartNahuel95 en 10 Junio 2016, 03:00 am
Genial!!

Muchas Gracias.

Saludos.


Título: Re: Proyecto en Dev C++ (Arreglo de dimensión variable en archivo .h")
Publicado por: MartNahuel95 en 10 Junio 2016, 03:31 am
Me surgió un nuevo inconveniente. Creé una función para corroborar que el usuario en tiempo de ejecución no calcule por ejemplo la media antes de cargar elementos al arreglo:

Código:
int funciones::vector_vacio(vector_n V){
int z=V.n;
double suma=0;
for(int i=0;i<z;i++){
suma=suma+V.elementos[i];
}
if(suma != 0){
return 1;
}else{
return 0;
}
}

Pero cuando lo quiero aplicar a la función para hallar la media:

Código:
double funciones::media(vector_n V){
if(vector_vacio(vector_n V)==1){
int z=V.n;
double suma=0;
double media=0;
for(int i=0;i<z;i++){
suma=suma+(V.elementos[i]);
}
media=suma/z;
return media;
}else{
printf("Cargue elementos a su arreglo!!");
                return 0;
}
}

Me marca error en el argumento de vector_vacio

In static member function 'static double funciones::media(vector_n)':
[Error] expected primary-expression before 'V'

Cuando creí que todo andaba bien, apareció esto jaja, lo siento.



Título: Re: Proyecto en Dev C++ (Arreglo de dimensión variable en archivo .h")
Publicado por: class_OpenGL en 10 Junio 2016, 05:46 am
La función 'vacío' se puede hacer más sencilla:

Código
  1. bool funciones::vector_vacio(vector_n V){
  2.    for(int i = 0; i < V.n; i++) {
  3.        if(0 != V.elementos[i])
  4.            return false;
  5.    }
  6.  
  7.    return true;
  8. }

A parte de eso, en la función 'media' hay varios errores:

Código
  1. double funciones::media(vector_n V){
  2.    double resultado = 0.0;
  3.    int i;
  4.  
  5.    for(i = 0; i < V.n; i++)
  6.        resultado += V.elements[i];
  7.  
  8.    if(0 == V.n) {// Damos el error
  9.        printf(stdout, "Error. Se ha intentado calcular la media de un conjunto vacío.\n");
  10.        return 0.0;
  11.    } else {
  12.        return resultado / (double)V.n;
  13.    }
  14. }


Título: Re: Proyecto en Dev C++ (Arreglo de dimensión variable en archivo .h")
Publicado por: AlbertoBSD en 10 Junio 2016, 05:47 am
Tu primera funcion, que pasa si el usuario agrega puros 00000000000

En resultado de la suma
siempre sera 0..

Lo mejor es validar si el varlor de n es distindo de 0 si lo es, quiere decir que el arreglo no esta vacio.

Seria:

Código
  1. int funciones::vector_vacio(vector_n V){
  2. return !V.n;
  3. }

Lo anterior se lee como "Regresa la negacion de V.n, (Si es distinto de 0 regresa 0 [falso], si es 0 regresa 1 [Verdadero])"

Sobre el error que te aparece la verdad no tengo ni idea de que sea, prueba este codigo y si te sale error nos dices.

Saludos.