c arrays matrix dynamic-allocation

Asignación dinámica de una matriz desconocida en C



arrays matrix (2)

Necesito tomar un archivo ingresado por el usuario y multiplicarlo por otro archivo. Eso es lo que sé hacer.

El problema es que un archivo es una matriz y el otro es una matriz.

Necesito escanear en la primera línea de la matriz para encontrar el tamaño de la matriz y luego necesito asignar dinámicamente la matriz y la matriz de los archivos.

Esto es lo que tengo hasta ahora:

#include <stdio.h> #include <stdlib.h> #include <math.h> #include <string.h> int main() { int row1, col1; //These values need to be pulled from the first file// char filename1[100]; //Setting the file name for entry and setting the limit to 100// FILE* fp1; //FILE must be set as a pointer (FILE must also be capitalized)// printf("Enter file name including file extension: /n"); //This will pull in the name entered by the user// scanf("%s", filename1); //Scans in the name of the first file// fp1 = fopen(filename1, "r"); //This will open the file as entered by the user// if (fp1 == NULL) { printf("/nError, file not found/n"); exit(0); } //This is for the first file// char filename2[100]; //Setting the file name for entry and setting the limit to 100// FILE* fp2; //FILE must be set as a pointer (FILE must also be capitalized)// printf("Enter file name including file extension: /n"); //This will pull in the name entered by the user// scanf("%s", filename2); //Scans in the name of the first file// fp2 = fopen(filename2, "r"); //This will open the file as entered by the user// if (fp2 == NULL) { printf("/nError, file not found/n"); exit(0); } //This is for the second file// //**I need to now dynamically allocate the input files**// return 0; }

También lamento que parezca que me fui después de publicar mi pregunta, ya que algunos miembros han compartido los comentarios diciendo que estaba pescando códigos. No soy; Simplemente no me di cuenta de lo activa que es esta comunidad. Gracias por el aporte hasta el momento.

Aquí está la captura de pantalla de todo lo que tengo hasta ahora, incluidos los archivos que se van a leer.

Gracias por las sugerencias Pude descubrir la función "fgets" y la usé para extraer el tamaño de la matriz desde el primer archivo. Después de tener eso, asignar dinámicamente eso fue fácil.


Mi recomendación es considerar que su matriz tiene algún tipo de datos abstractos que desea implementar.

Una forma común podría ser utilizar una matriz de punteros (a matrices que representan filas de su matriz). Pero siento que es confuso e ineficiente.

Entonces, ¿cuáles son las operaciones que desea en sus matrices?

  • crear una matriz de dimensiones dadas

  • destruir una matriz creada previamente

  • acceder a algún elemento en una matriz dada con índices de fila y columna dados

  • cambiar el valor de un elemento en una matriz dada con índices de fila y columna dados

  • etc ....

Por cierto, puede tener varias variantes de ellos. Por ejemplo, podría hacer una comprobación de errores (por ejemplo, rechazar un índice negativo) o podría tener funciones inseguras (pero un poco más rápidas) capaces de un comportamiento indefinido (y esto es muy scary ). Por supuesto, podría definir más operaciones (utilizando otras), por ejemplo, multiplicación de matrices, etc.

Debe enumerar, en papel o pizarra, todas las operaciones que desee en sus matrices y explicarlas en su documentación (o sus comentarios). En la práctica, puede tener muchas docenas, o incluso cientos, de operaciones en su tipo de datos abstractos. Documente también lo que sucede en casos de error.

Por lo general, recomiendo mantener las dimensiones con la matriz (a menos que sepa que parte de la dimensión es constante). Una forma común de implementar tipos de datos abstractos en C es encapsularlos en alguna struct y usar punteros para estos.

Por lo tanto, sugiero usar un miembro de matriz flexible (como el último elemento de su struct ). Aquí está mi estructura matrix_st :

struct matrix_st { unsigned m_h, m_w; // height and width of matrix double m_v[]; // values inside the matrixes, there are m_h*m_w of them };

así que mi tipo de datos abstractos es solo punteros a

typedef struct matrix_st Matrix;

Aquí están las declaraciones de las funciones que implementan mi tipo de datos abstractos:

Matrix* matrix_create(unsigned height, unsigned width); void matrix_destroy(Matrix*mat); double matrix_access(Matrix*mat, unsigned i, unsigned j); void matrix_change_element(Matrix*mat, unsigned i, unsigned j,double v);

Aquí hay algunas implementaciones (dado que no quiero tratar con matrices patológicamente enormes, defino alguna dimensión máxima; ¡los recursos informáticos siempre son finitos!):

#define MATRIX_MAXDIM 10000000 /* ten millions */ Matrix* matrix_create(unsigned height, unsigned width) { if (height>MATRIX_MAXDIM || width>MATRIX_MAXDIM) { fprintf(stderr, "too huge matrix height=%u width=%u/n", height, width); exit(EXIT_FAILURE); }; Matrix* res = calloc(1, sizeof(Matrix) + height*width*sizeof(double)); if (!res) { perror("matrix calloc"); exit(EXIT_FAILURE); }; res->m_h = height; res->m_w = width; return res; } // end matrix_create

Estoy usando calloc no malloc porque realmente quiero un poco de memoria cero ed. Entonces la matriz devuelta contiene todos los ceros. Por cierto, en algunas computadoras (no la mía, una PC / Linux / Debian / x86-64 de escritorio) la height*width*sizeof(double) podría desbordarse.

Aquí está la función para acceder a algún elemento. Hace alguna comprobación de errores.

double matrix_access(Matrix*mat, unsigned i, unsigned j) { if (!mat) { fprintf(stderr, "no matrix to access/n"); exit(EXIT_FAILURE; }; unsigned h = mat->m_h; unsigned w = mat->m_w; if (i >= h || j >= w) { fprintf(stderr, "out-of-bound matrix access/n"); exit(EXIT_FAILURE); }; return mat->m_v [i*h + j]; }

Como solo hice un calloc la destrucción es simple de codificar:

void matrix_destroy(Matrix*mat) { if (!mat) { fprintf(stderr, "no matrix to destroy/n"); exit(EXIT_FAILURE); }; assert (mat->m_h < MATRIX_MAXDIM); assert (mat->m_w < MATRIX_MAXDIM); free (mat); }

Las declaraciones de afirmación son en principio inútiles (verifican algo que siempre debe ser cierto). Pero me encanta la programación defensiva (esto me ayudaría a detectar errores en otros lugares haciendo un mal uso de Matrix ). Podrían deshabilitarse (leer assert(3) ) en el momento de la compilación.

Por cierto, podría declarar estas funciones como en inline o en inline static inline (y definirlas en algún archivo de encabezado incluido). Es probable que un compilador optimizador produzca código eficiente (por ejemplo, compilar with gcc -O2 -Wall -march=native cuando se realiza una evaluación comparativa).

Como está leyendo una matriz de algún archivo, debe definir su formato de archivo (usando, en su documentación, alguna notación EBNF para describir la sintaxis en ese archivo es útil) y podría definir e implementar una función de lectura y crear una matriz a partir de algún identificador de archivo abierto.

La codificación de las otras funciones se deja como ejercicio para el lector.

No olvide compilar with todas las advertencias e información de depuración, así que gcc -Wall -Wextra -g con GCC . Use el depurador gdb (y también valgrind para buscar pérdidas de memoria ). Lea la documentation de cada función utilizada (por ejemplo, su código no verifica el recuento de retorno de scanf pero realmente debería). Ejecute varios casos de prueba . Intenta convencerte de que tu código es bueno (probando partes de él). Quizás use algún analizador de código fuente estático (por ejemplo, Frama-C , que quiere anotaciones adicionales en ACSL ). Si necesita benchmark su programa, active las optimizaciones en tiempo de compilación (por ejemplo, pasando -O2 -march=native a gcc ....).

En un comentario de código estás preguntando:

// I need to now dynamically allocate the input files

No asigna files entrada (el sistema operativo los está administrando), asigna alguna zona de memoria . Lea acerca de la asignación de memoria dinámica C. Tenga en cuenta que la asignación de memoria puede fallar (por ejemplo, como se documenta en malloc(3) ), porque su espacio de direcciones virtuales no puede crecer indefinidamente.

Por cierto, la pila de llamadas está limitada (generalmente a un megabyte o algunos de ellos en computadoras de escritorio), por lo que generalmente desea evitar grandes variables automáticas , por lo que esa es otra buena razón para evitar colocar matrices en su marco de llamadas y preferir dinámicas asignación de memoria para ellos.


No veo dónde realmente lee los recuentos de filas / columnas, pero una vez que los tiene, la asignación es simple:

int (*matrix)[columnCount] = malloc(rowCount*sizeof(*matrix));

Eso es. Esto declara que la matrix es una *matrix puntero *matrix a una matriz de enteros columnCount . Los paréntesis son necesarios porque int* matrix[...] declararía una matriz de punteros en su lugar. El malloc() asigna espacio para rowCount tales matrices, brindándole la matriz 2D completa en una sola pieza de memoria. El acceso es como para cualquier matriz 2D:

for(int y = 0; y < rowCount; y++) { for(int x = 0; x < columnCount; x++) { matrix[y][x] = 42; } }

La desasignación es tan simple como la asignación:

free(matrix);