Problema programa en C

EnDeEsgue

Pues bien, resulta que en Ingenieria tecnica en informatica de sistemas en la Universidad de Barcelona el primer año solo hemos hecho java y de golpe nos han pedido hacer un programa en C el cual se trata de poder crear y eliminar matrices y hacer operaciones con ellas, inicializarlas, etc.., y mi compañero de grupo y yo nos estamos comiendo la olla con las estructuras....

La cuestion es crear una estructura de tipo matriz y otra que sea el conjunto de todas las matrices...

Hemos puesto esto pero el compilador nos da mil fallos y no conseguimos solucionarlo:

struct matriz {
int columnas;
int filas;
float contenido[columnas][filas];
}matriz;

struct conjuntomatrices {
int numeromatriz, n_total;
struct matriz lista[];
};

El compilador que usamos es el Dev-cpp, por si sirve de algo xD

Si alquien pudiera darme aunke sea ALGUNA pista para poder sacar las estructuras correctamente porfavor..

Saludos

Edit: Aparte de todo esto, que compilador es el mejor para trabajar en C?(En Windows)

X

hm... hay ke ir a clase EnDeESgue.

raul84

struct matriz {
int columnas;
int filas;
float contenido[columnas][filas];
}matriz;

En los corchetes de float contenido eso está mal. No puedes utilizar las variables columnas y filas ahi.
Puedes usar el #define

Ej:

#define columnas valor
#define filas valor

EnDeEsgue

#3 lo primero de todo thx por contestar :)

luego.., el problema esta en ke la dimension (es decir, el valor de columnas y el valor de filas) lo pasa el usuario por teclado a la hora de crear la matriz y yo tenia entendido ke el define era para declarar constantes..

Si consigues que me salga te hago un altar xD

cabron

Pues hombre, lo que pides es que te enseñemos asignación dinámica, y yo personalmente casi que no te voy a escribir un tutorial...

En Internet que tiene que haber millones, busca por "asignación dinámica de memoria" o como usar malloc() y free()

Eso sí, antes asegurate de que comprendes bien los punteros o no te enterarás de mucho.

LOc0

Edit: Aparte de todo esto, que compilador es el mejor para trabajar en C?(En Windows)

Yo uso Dev-Cpp (gcc), pero me ha dado problemas "raros" con la asignación dinámica (en concreto con la función realloc).

El mismo código que compilado con GCC daba errores de memoria, con LCC-WIN iba perfectamente.

Salu2 ;)

IS4kO

#6 cualquiera de borland

Feliz 2006

javithelong

Vamos a ver como lo hacemos :P

Primero, en tu código, falta un typedef, antes del struct matriz, y no puedes poner el mismo nombre arriba y abajo, me explico

struct matriz {
int columnas;
int filas;
float contenido[columnas][filas];
}matriz;

typedef struct tag_matriz {
int columnas;
int filas;
float contenido[columnas][filas];
} matriz;

Segundo, no puedes poner asi las columnas y las filas para la variable contenido. Puesto que son numeros que no conoces de antemano y pueden ser variables, tendrás que hacerlo con memoria dinámica. Segun tu mensaje, parece que el numero de matrices es también variable, en ese caso lo mismo te digo con la estructura "conjuntomatrices". Te recomiendo un cambio radical, aunque requiere saber usar punteros :P

Si no os exigen mucha calidad de código, podeis usar máximos, y "moveros" por la matriz usando los dos enteros "columnas y filas". Si es el 1º programa, no creo que os digan nada, voy a ver si me explico como:

#define MAX_FILAS 50 //Aqui cualquier numero
#define MAX_COLS 50 //lo mismo
#define MAX_MATRICES 20 //idem

typedef struct tag_matriz {
int filas, columnas;
float contenido[MAX_FILAS][MAX_COLS];
} tipoMatriz;

typedef struct tag_conjunto {
int num_matrices;
tipoMatriz matriz[MAX_MATRICES];
}

Esto creo que deberia solucionaros muuucho trabajo. De todas formas, si os hacen tener la memoria dinámica, avisa, y pongo algo mas mejor. Saludos

Atoll

Aprovecha estos momentos que te brindamos en MV para repasar tus apuntes de programación y enterarte de lo que son malloc y free.

...

...

...

...

...

Nos gusta la asignación dinámica de memoria... ¿qué pasa?

Antena MV, felices fiestas.

EnDeEsgue

Saludos a todos de nuevo. Nuestros objetivos principales para el proyecto son:

  • Creacion de una estructura matriz de tamaño variable.
  • Creacion de una estructura conjuto de matrices que contendra un array de tamaño variable que contendra todas las matrices i el numero total que tenemos.

Hemos buscado informacion sobre las estructuras dinamicas y hemos encontrado un codigo para la creacion de una matriz con su funcion y demas. Nuestra estructura conjunto matrices sigue estando mal pero aqui os adjuntamos el codigo primordial haber si os situamos mejor y recibimos mejor vuestra ayuda.


Estructuras


struct mat {
float *datos;
int columnas,filas;
};

typedef struct mat *MATRIZ;

struct conjuntomatrices {
int n_items;
MATRIZ lista[30];
}conjuntom;

conjuntom.n_items = 0;


Funciones


MATRIZ creamatriz (int x,int y) {
MATRIZ temp;

temp = (MATRIZ) malloc (sizeof(struct mat));
temp->columnas = x;
temp->filas = y;
temp->datos = (float ) malloc (sizeof(float)x*y);
return temp;
}

void agregarmatriz(MATRIZ nueva) {
conjuntomatrices.lista[conjuntomatrices.n_items] = nueva;
conjuntomatrices.n_items++;
return;

}


Programa Principal


int fil=0, colum=0;
MATRIZ a;

printf("Introduce el numero de columnas: ");
colum = scanf("%i", &colum);
printf("Introduce el numero de filas: ");
fil = scanf("%i", &fil);
a = creamatriz(colum,fil);
agregarmatriz(a);


Como podeis ver en el programa principal queremos crear una funcion que pase una matriz a un metodo con agregarmatriz y se añada al array dinamico lista[] de tipo matriz de la estructura conjuntomatrices. N_items nos dira el numero de matrices que tenemos en el array.

Gracias por vuestros aportes, esto es lo basico que nuestro programa tendria que hacer, ya que luego tenemos que rellenar las matrices y hacer operaciones con ellas.

Seguimos mirando la funcion de agregarmatriz que esta como el culo. Cualquier informacion que nos faciliteis nos sirve de mucho.

Gracias a todos por adelantado :)

guner

Tiene que ser C o C++?

EnDeEsgue

#11 tiene ke ser C xD

Para simplificar, hemos decicido ke vamos a poner un maximo de matrices posibles para introducir, asi ke usaremos un array y punto porq si nos tenemos ke poner con listas ya si ke la liamos parda xD

Saludos

LOc0

Mira a ver si te va esto:

ACTUALIZADO4: (Diversas modificaciones y corregida (esperemos que esta vez sí xD) la liberación de memoria)
ACTUALIZADO3: (corregida la reserva de memoria y la liberación)
ACTUALIZADO2: (las matrices se rellenan con floats pseudo-aleatorios)
ACTUALIZADO: (Corregida la liberación de memoria)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

typedef struct mat {
float ** datos;
int columnas, filas;
} MATRIZ;

typedef struct conjuntomatrices {
int n_items;
MATRIZ ** lista;
} CONJUNTOM;

void creamatriz(MATRIZ, int, int);
void agregarmatriz(CONJUNTOM
, MATRIZ*);

void main() {
int fil=0, colum=0, conta=0, conta_filas, conta_columnas, num, aux;
MATRIZ * a;
CONJUNTOM conjunto;
conjunto.n_items=0;
conjunto.lista = NULL;

printf("\nCuantas matrices vas a introducir? ->");
scanf("%d", &num);


/* Reservamos memoria para el array de MATRIZ /
conjunto.lista=malloc(num
sizeof(MATRIZ));

while(conta < num) {
printf("\n\nMATRIZ #%d\n", conta+1);
printf("Introduce el numero de filas: ");
scanf("%d", &fil);
printf("Introduce el numero de columnas: ");
scanf("%d", &colum);


/* Reservamos memoria para la matriz a (temporal) */
a = malloc(sizeof(MATRIZ));


creamatriz(a, fil, colum);
   
srand(time(NULL));
   
for(conta_filas=0; conta_filas<fil; conta_filas++)
    for(conta_columnas=0; conta_columnas<colum; conta_columnas++)
        a->datos[conta_filas][conta_columnas] = ((float)rand())/100;
 
agregarmatriz(&conjunto, a);
   
printf("\n");
   
for(conta_filas=0; conta_filas<conjunto.lista[conjunto.n_items-1]->filas; conta_filas++) {
  for(conta_columnas=0; conta_columnas<conjunto.lista[conjunto.n_items-1]->columnas; conta_columnas++)
      printf("%12.1f", conjunto.lista[conjunto.n_items-1]->datos[conta_filas][conta_columnas]);
  printf("\n");
}
   
conta++;

}


//Liberamos la memoria reservada
for(aux=0; aux<conjunto.n_items; aux++) {


/* Free de los datos de la matriz */
for(conta_filas=0; conta_filas<conjunto.lista[aux]->filas; conta_filas++)
free(conjunto.lista[aux]->datos[conta_filas]);


free(conjunto.lista[aux]->datos);

/* Free de la MATRIZ */
free(conjunto.lista[aux]);

}


/* Free del array de MATRIZ */
free(conjunto.lista);



}

void creamatriz (MATRIZ * a, int y, int x) {
int aux;
a->filas = y;
a->columnas = x;

/* Reservamos memoria para los datos de la matriz temporal a /
a->datos=malloc(y
sizeof(float*));

for(aux=0; aux < y; aux++)
a->datos[aux]=malloc(x*sizeof(float));
}

void agregarmatriz(CONJUNTOM * conjunto, MATRIZ * a) {
conjunto->lista[conjunto->n_items] = a;
conjunto->n_items++;
}
[/i]

Salu2 ;)

B

Con C++ es más guay. ¡Vivan los constructores y destructores!

javithelong

No he leido el codigo de #13, pero viendo tu código, te falta crearte el conjuntomatrices, y pasarselo como parámetro a la funcion agregamatriz

EDIT: Mirando el codigo de #13, tiene buena pinta... ¿getch es ansi? ¿no esta en una librería en plan conio.h? Creo que no es ansi, tonces no lo recomiendo, pero vamos, el getch ahi no vale para na :P

EDIT2: Me he estado mirando el codigo de #13 mas a fondo, tiene un par de fallos.

No tienes que liberar a.datos (aparte de que datos es un doble puntero, y dejas la memoria mal liberada, jodes la matriz, porque tienes la referencia a la matriz que acabas de agregar al conjunto)

Antes de terminar el programa (despues de hacer tus operaciones y mostrar lo que sea por pantalla, o lo que tengas que hacer) tienes que liberar bien todo, esto es, liberar cada una de las y de los datos, liberar las x y también liberar cada matriz.

Y esto ya en cuanto a programación en general (mejor calidad de codigo):

El getch ese no vale pa na ahi, mas mejor si lo quitas.

No hagais funciones void, devolver siempre un int, aunque devuelvas siempre lo mismo y no lo quieras para nada.

Usa returns para volver de las funciones (te quitas warnings que no quedan bonitos).

En agregar matriz, has puesto una direccion de memoria (pasas un puntero a matriz) que no es necesaria, aunque NO esta mal. Simplemente trabajas con un puntero que no necesitas, solo es poner mas * y mas -> de forma innecesaria, pero vamos, que esta bien también.

Nunca está de mas hacer control de errores por si fallan los mallocs, los scanf y demas.

Y ya como pijerio máximo, no leas de teclado con scanf, falla por todos lados (si pides un entero, y te meten una b, te explota todo). Mejor leer con fgets de stdin (teclado) y luego hacer sscanf sobre la variable donde hayas leido el fgets, al tipo que necesites (%d o lo que sea).

No se me ocurre nada mas, si algo falla, volveré :P. Saludos

L

Buenas soy el compi de EndeEsgue, su ultimo post le pase yo todo dado que estaba registrado desde hace poco y no podia escribir hasta superar las 12 horas jeje.

Agradezco todas las aportaciones que nos estais brindando desinteresadamente por amor al C jeje.

  • Decir que ara mismo estamos probando el codigo de Loco y adaptandolo a nuestro programa.

  • javithelong, gracias por intentar optimizar el codigo de Loco pero podrias escribir el codigo igual que ha hecho el?

Hemos trabajado mucho con java a nivel de clases y metodos pero no con C y nos cuesta entender aveces lo que quereis exponer y mejorar, por eso si lo haceis mediante codigo podemos probarlo y entenderos mejor a la vez.

Gracias y feliz 2006 a todos!!!

LOc0

#15

Corregido el tema de la liberación de memoria y el getch() (me gusta conio.h, lo siento xD).
Lo del scanf lo he hecho porque ha dicho que es noob en C y tp quería complicar en exceso la lectura de datos.

En la función crearmatriz uso un puntero a la matriz porque la paso por referencia.

En cuanto al void-int para las funciones, a mi me enseñaron que cuando no hace falta devolver nada no se devuelve y ya ta ;) (Para algo existe el tipo void, aunque no sea ANSI C puro ;) )

#16
Prueba el código actualizado y a ver qué pasa.

Salu2 y suerte!

PD: Llevas razón, pero al menos en mi caso tenía un rato libre y para mi es un hobby (a la vez que repaso cosas que vi hace ya bastante tiempo)
||
||
\/

cabron

Ante todo dejar claro que no critico a nadie, cada uno es libre de hacer lo que quiera con su tiempo libre, solo estoy dando una opinión.

Me parece fatal la postura de que estáis manteniendo pidiendo que os escriban el código, sobre todo en #16 donde directamente le dices a otro que por que no te escribe algo de código en lugar de solo hablar.

Una cosa es escribir algo de código para aclarar una idea, y otra pedir que os hagan vuestro trabajo... Creo que con la información que se os ha dado tenéis de sobra para trabajar vosotros mismos, y pienso que es lo que deberías de hacer, ahora bien, si preferis pedir que os lo hagan y alguien está dispuesto a haceroslo, pues como ya dije, cada uno es libre de gastar su tiempo en lo que quiera.

L

Saludos de nuevo.

Siento mucho si alguien se a ofendido como es el caso de cabron. Responder que el programa que por ejemplo loco nos esta facilitando no es ni mucho menos lo que se nos pide en esta maldita practica.

Todos los que an respondido contribuyendo con codigo y demas para nada nos estan haciendo los deberes. No estan facilitando el codigo basico para poder crear matrices y demas.

Creo que he sido bastante agradecido en otros mensajes tanto yo como mi compañero y vuelvo a decir que si alguien se ha ofendido pos que lo sentimos.


Preguntando a Loco y quien quiera responder :)

  • Utilizo Dev-cpp y por probar tu codigo me encuentro con bastantes errores a la hora de compilar como las llaves de los bucles y algun otro mu raro pero gracias por todo!

Como bien e dicho cogemos el codigo y lo adaptanmos a nuestro programa, porque lo que queremos es crear una matriz nueva cuando se quiera y rellenarla cuando se quiera (vaya tela es lo que se nos pide).

  • Podrias darnos unas ideas de como se destruye una matriz aplicado a tu codigo? Como si fuera un tipo funcion o lo que se te ocurra para entenderlo.

Gracias a ti y los demas que como bien e dixo ayudan desinteresadamente por amor al C. (Loco ya lo a confesado xD)

cabron

No no, no me ha ofendido ni nada, precisamente intente dejar claro en el post que no tengo nada en contra de lo que estáis haciendo, simplemente era una opinión nada más.

Como ya dije antes, solo con aprender a utilizar malloc() y free() tenéis el camino abierto para resolver esto vosotros mismos. No me molesta para nada que hagáis estas preguntas, pero sinceramente creo que sacariais más provecho aprendiendo a utilizar malloc() y free() vosotros mismos y preguntando las dudas que os surjan, que directamente pidiendo partes de código ya hechas.

Por cierto, veo en vuestro código que cada vez que usáis malloc() haceis un cast:

temp = b[/b] malloc (sizeof(struct mat));

temp->datos = (float ) malloc (sizeof(float)x*y);

malloc() devuelve un puntero de tipo void, y se puede asingar directamente a cualquier puntero, no es necesario hacer una conversión de tipos (en C++ sí es necesario, en C no).

LOc0

#19

LO he compilado con Dev-Cpp 4.9.9.2 y va sin problemas:
Compilador: Default compiler
Ejecutando gcc.exe...
gcc.exe "D:\Mis cosas\dina_mat.c" -o "D:\Mis cosas\dina_mat.exe" -I"C:\Dev-Cpp\include" -L"C:\Dev-Cpp\lib"
D:\Mis cosas\dina_mat.c: In function `main':

D:\Mis cosas\dina_mat.c:23: warning: return type of 'main' is not `int'

Ejecución Terminada
Compilación Concluida con Éxito

En el código que os puse de muestra se crean matrices y se rellenan en un bucle. Simplemente haced lo que está dentro del bucle while() cuando lo necesitéis y ya ta. Eso sí, al final del todo del main liberad la memoria como os he puesto tb en el ejemplo.

Salu2 ;)

javithelong

Releido el ejemplo editado, parece que ya va todo bien (tampoco lo he probado, solo lo he leido por encima :P)

Un par de comentarios na mas, nada importante :

A los del problema, estoy con Cabron, no es bueno que os den código ya hecho, y que lo adapteis a vuestro problema, es mejor que lo vayais pariendo vosotros. La programación no se aprende leyendo programas dabuti hechos por otros, muy a mi pesar; aqui se aprende currando, y dejandose los cuernos contra el monitor para encontrar los putos fallos.

Cabron, emplear castings en el malloc es una práctica bastante útil, obviamente no es necesaria (ningún casting es necesario, pues en realidad un casting no es nada), pero, primero, te quitas warnings, y segundo, ayuda a la depuracion del código (hablo de C, no se nada de C++, igual en C++ los castings si hacen algo)

Loco, ya vi que pasabas la matriz como referencia, decia, que no hace falta que la pases como referencia, puedes pasarla directamente por valor, pues es una estructura, y podrás modificar el valor de sus campos (vamos, me parece ^^) si pones matriz.datos en lugar de matriz->datos, todo irá guay :P (ya te dije, lo que tu hiciste esta bien)

Conio no es ansi, y deberias aprender a no usarla :P (todo lo no-ansi, se puede hacer con código ansi)

No se me ocurre que mas poner, asi que me voy a dormir, que ya son horas... si es que tienen razón, los informáticos somos como las putas... trabajamos en horarios extraños, y lo hacemos gratis a parientes y amigos ^. Saludos

L

Saludos de nuevo!! tamos probando el codigo de loko que por lo visto esta funcionando de luxe :)

Me pregunto si sabriais decirnos como generar un float aleatorio. Lo probe con randomize() y luego la funcion random y tal pero no me coge la libreria stdlib.h cuando en otro compilador borland c si...
Que se os ocurre para hacer el random?

Gracias de nuevo

LOc0

La función rand() de stdlib.h os valdría para eso (Tb os hace falta incluir time.h para la semilla).

float aleatorio;

srand(time(NULL)); //Normalmente se usa como semilla el timestamp

aleatorio=((float)rand())/100; //Esto te genera un float pseudo-aleatorio

Salu2 ;)

L

Fantastico random!! ara me pondre a añadirlo.

Respecto a tu super programa...
Si pones a crear una matriz con:
3 filas x 2 columnas
4 filas x 3 columnas

.... y asi succesivamente porqué falla y peta el program?

Merci por dedicarle tanto.

Edit: Tendre que buscarme otro random ya que alomejor tarda mucho en cambiar el time y para cada matriz me llena con el bucle el mismo numero. Puede ser que exista una con el clock del sistema o algo asi y dentro de un bucle pequeño de tiempo a cambiar?

LOc0

#25

time(NULL) varía cada segundo, que normalmente es suficiente... Busca en Google otras semillas para la función rand()

En cuanto a lo que comentas es cierto. Me he puesto a debuggear y ya sé dónde falla pero no entiendo por qué. Voy a mirarlo un ratillo más hasta la cena. Ahora te cuento.

EDITADO: NO entiendo por qué falla, lo siento :( :(

Salu2 ;)

cabron

javithelong: Hombre, que yo recuerde ( a lo mejor me equivoco) con malloc nunca te dará ningún Warning, ya que por definición, un puntero void se puede asingar a un puntero de cualquier tipo, pero puede que esté confundido.

Y sobre lo de que el código sea más claro, a mi me parece mejor utilizar nombre de variables, por ejemplo, para un puntero integer utilizas el prefijo pi, algo así:

piMiVariable = malloc ( sizeof(int) );

De todas formas, es lo de menos, no creo que haya una forma mejor que otra, supongo que será cuestión de gustos.

Edit: Lo acabo de probar, y efectivamente no te da ningún warning el compilador si no haces un cast al puntero que devuelve malloc.

L

Saludos de nuevo. Llevamos viento en popa esta practica sobre el 70 % o algo mas :D y todo es gracias a vosotros gente!

Una nueva cuestion a surguido en nuestro programa. Estamos intentando simplemente destruir una matriz que elijamos con este codigo un poco variado de Loco pero el mismo vaya.


printf("Total de matrices: %i\n\n",conjunto.n_items);
printf("Introduce el num. de la matriz que quieres:");
scanf("%i",&elec);

for(conta_columnas=0; conta_columnas<conjunto.lista[elec-1].columnas; conta_columnas++)
free(conjunto.lista[elec-1].datos[conta_columnas]);

           free(conjunto.lista[elec-1].datos);

Nuestra duda surge en que luego hacemos el listado de las matrices y nos aparecen datos sin liberarse. Creo entender por dato liberado el que su valor sea un 0.0

Por ejemplo normalmente si creamos una matriz 3x3 con el codigo de arriba solo liberamos la primera columna. Con otra matriz se libera solo las dos primeras filas de 3 que tiene, cosas asi mu raras jeje

Seguro que se liberan todos los datos correctamente de una matriz con ese codigo?

Gracias de nuevo!!

LOc0

Bueno, pues parece que ya he dado con el problema. Estaba en la función AGREGAMATRIZ() Resulta que estaba reservando la memoria al revés confundiendo filas con columnas. Lo he cambiado (y tb la parte de la liberación) y parece que va bien. Tienes el código actualizado arriba.

Salu2 ;)

L

Buenos dias a toda nuestra comunidad de C :)
He probado tus nuevos cambios y ya no peta si entras una matriz de:
3filas x 2 columnas, 4 filas x 3 columnas... increible gracias!!!

No obstante el tema de la liberacion nos sigue pasando que una vez destruida una matriz o como tu mismo lo as hecho con el bucle de destruirlas todas, sin liberar el array final, pues siguen quedando valores que no son 0.0 al hacer un listado de lo que hay. Nu sabemos que puede ser.

PD: Seria un honor que te pudieramos enviar por pm nuestro codigo despues de tanta ayuda que nos estas dando una vez acabado todo claro _

Usuarios habituales