Assegnazione di Dynamica di una matrice sconosciuta in C

Ho bisogno di prendere un file che viene immesso dall’utente e moltiplicarlo per un altro file. Quel che so come fare.

Il problema è che un file è un array e l’altro è una matrice.

Ho bisogno di scansionare la prima riga della matrice per trovare la dimensione della matrice e quindi ho bisogno di allocare dynamicmente la matrice e la matrice dai file.

Questo è quello che ho finora:

#include  #include  #include  #include  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; } 

Mi dispiace anche per il fatto che ho appena lasciato la mia domanda dopo aver postato la mia domanda come alcuni membri hanno condiviso nei commenti dicendo che ero il codice della pesca. Non sono; Non mi rendevo conto di quanto sia triggers questa comunità. Grazie per l’input finora.

Ecco lo screenshot di tutto ciò che ho finora incluso i file che verranno letti.

Grazie per i suggerimenti. Sono stato in grado di capire la funzione “fgets” e l’ho usata per inserire la dimensione della matrice dal primo file. Dopo averlo fatto, allocare dynamicmente è stato facile.

La mia raccomandazione è di considerare la matrice come un tipo di dati astratti che si desidera implementare.

Un modo comune potrebbe essere quello di utilizzare una matrice di puntatori (agli array che rappresentano le righe della matrice). Ma sento che è confuso e inefficiente.

Quindi quali sono le operazioni che vuoi sulle tue matrici?

  • creare una matrice di dimensioni date

  • distruggere una matrice precedentemente creata

  • accedere ad alcuni elementi in una data matrice con determinati indici di righe e colonne

  • cambia il valore di un elemento in una data matrice con determinati indici di righe e colonne

  • eccetera….

A proposito, potresti avere diverse varianti di loro. Ad esempio, è ansible eseguire il controllo degli errori (ad esempio, rifiutare un indice negativo) oppure si potrebbero avere funzioni non sicure (ma leggermente più veloci) in grado di comportamento non definito (e questo è molto spaventoso ). Ovviamente potresti definire più operazioni (usando altre), ad esempio moltiplicazione di matrici, ecc.

Dovresti elencare – su carta o cartone – tutte le operazioni che vuoi sulle tue matrici e spiegarle nella tua documentazione (o nei tuoi commenti). In pratica potresti avere molte dozzine o anche centinaia di operazioni sul tuo tipo di dati astratti. Documenta anche cosa succede nei casi di errore.

Di solito raccomando di mantenere le dimensioni con la matrice (a meno che tu non sappia che alcune delle dimensioni sono una costante). Un modo comune di implementare i tipi di dati astratti in C è incapsularli in alcune struct e utilizzare i puntatori a questi.

Quindi suggerisco di usare un membro di array flessibile (come l’ ultimo elemento della tua struct ). Ecco la mia struttura 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 }; 

quindi il mio tipo di dati astratti è solo un suggerimento

  typedef struct matrix_st Matrix; 

Ecco le dichiarazioni delle funzioni che implementano il mio tipo di dati astratti:

  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); 

Ecco alcune implementazioni (dal momento che non voglio trattare con matrici patologicamente grandi, definisco alcune dimensioni massime, le risorse del computer sono sempre limitate!):

  #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 

Sto usando calloc non malloc perché voglio davvero una memoria zero-ed. Quindi la matrice restituita contiene tutti gli zeri. BTW su alcuni computer (non il mio, un desktop PC / Linux / Debian / x86-64) l’ height*width*sizeof(double) potrebbe traboccare.

Ecco la funzione per accedere ad alcuni elementi. Fa qualche controllo degli errori.

 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]; } 

Poiché ho creato un solo calloc la distruzione è semplice da codificare:

  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); } 

Le asserzioni sono in linea di principio inutili (controllano qualcosa che dovrebbe sempre essere vero). Adoro la programmazione difensiva (questo mi aiuterebbe a cogliere bug in altri posti che usano male Matrix ). Potrebbero essere disabilitati (leggi assert (3) ) al momento della compilazione.

A proposito, potresti dichiarare queste funzioni come inline o static inline (e definirle in qualche file header incluso). Un compilatore ottimizzante è in grado di produrre codice efficiente (ad es. gcc -O2 -Wall -march=native con gcc -O2 -Wall -march=native durante il benchmarking).

Poiché stai leggendo una matrice da un file, devi definire il tuo formato di file (usando, nella tua documentazione, alcune notazioni EBNF per descrivere la syntax in quel file è utile) e potresti definire e implementare una funzione che legge e crea una matrice da qualche handle di file aperto.


La codifica delle altre funzioni è lasciata come esercizio al lettore.

Non dimenticare di compilare tutti gli avvisi e le informazioni di debug, quindi gcc -Wall -Wextra -g con GCC . Usa il debugger gdb (e anche valgrind per cercare perdite di memoria ). Leggi la documentazione di ogni funzione usata (ad esempio il tuo codice non controlla il conteggio di ritorno di scanf ma dovrebbe davvero). Esegui diversi test case . Cerca di convincerti che il tuo codice è buono (provando parti di esso). Forse usate qualche analizzatore di codice sorgente statico (es. Frama-C , che vuole annotazioni extra in ACSL ). Se è necessario eseguire il benchmark del programma, abilitare le ottimizzazioni in fase di compilazione (ad esempio passando -O2 -march=native su gcc ....).


In un commento sul codice che stai chiedendo:

  // I need to now dynamically allocate the input files 

Non si assegnano i file di input (il sistema operativo li sta gestendo), si allocano alcune zone di memoria . Leggi informazioni sull'allocazione della memoria dynamic C. Si noti che l'allocazione della memoria può fallire (ad esempio, come documentato in malloc (3) ), perché lo spazio di indirizzamento virtuale non può crescere indefinitamente.

BTW, lo stack di chiamate è limitato (in genere a un megabyte o alcuni di essi su computer desktop), quindi in genere si desidera evitare grandi variabili automatiche , quindi questo è un altro buon motivo per evitare di inserire le matrici nel frame della chiamata e preferire la dynamic allocazione di memoria per loro.

Non vedo dove si leggano effettivamente i conteggi riga / colonna, ma una volta ottenuti, l’allocazione è semplice:

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

Questo è tutto. Ciò dichiara che la matrix è una *matrix puntatore a un array di interi columnCount . Le parentesi sono necessarie perché int* matrix[...] dichiarerebbe invece una matrice di puntatori. Il malloc() alloca lo spazio per rowCount tali matrici, fornendo la matrice 2D completa in un unico pezzo di memoria. L’accesso è come per qualsiasi array 2D:

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

La deallocazione è semplice quanto l'assegnazione:

 free(matrix);