Sto implementando l'algoritmo del simplesso duale per un esame universitario, e per inizializzare il problema leggo un file .dat con tutti i dati tramite fscanf(). Tra questi sono presenti anche il numero di vincoli (che indico con "m") e delle variabili (che indico "n").
Per inizializzare la matrice mxn chiamo la funzione malloc() per allocare lo spazio richiesto.
Dopo aver inizializzato gli elementi della matrice, l'algoritmo richiede eventualmente (non sto a spiegarvi il motivo visto che non è inerente al problema) di aggiungere ulteriori righe e colonne. Per farlo chiamo la funzione realloc() (dopo aver aumentato m ed n del numero di righe e di colonne rispettivamente richiesti).
A questo punto provo a inizializzare i nuovi elementi inseriti, ma all'ultima riga (i = m) mi dà segmentation fault. Ho debuggato per un'ora e sono sicuro al 100% che l'errore proviene dal realloc(), ma non capisco perchè. Probabilmente sto gestendo male i puntatori. Vi incollo il codice:
codice:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Costanti
#define MAX_FILENAME_LENGTH 30 // Lunghezza massima nome del file
#define M 1000000000 // Valore di M (per il vincolo artificiale)
#define PRECISIONE 0.0000001 // Precisione per diminuire gli errori nei confronti
// Prototipi funzioni
int read_file_and_init(const char *filename, double **Mat, int *m, int *n, int **Segni);
// Funzione main()
int main()
{
// Variabili locali
double **Mat; // Tableau del problema
int **Segni; // Segno dei vincoli
long **Stato; // Stato delle variabili
long **Base; // Variabili in base
int m, n; // Numero di condizioni e di variabili
char filename[MAX_FILENAME_LENGTH]; // Nome del file di input
int found = 0; // Verrà settata a 1 se il file di input esiste
int num_slack = 0; // Numero di variabili slack
int va = 0; // "Booleano" per sapere se dobbiamo inserire il vincolo artificiale
int i, j; // Per cicli
// Mostriamo questo messaggio
printf("Questa applicazione permette di applicare il metodo del Simplesso Duale alle istanze passate in input.\n");
// Cicliamo finchè non troviamo il file di input
do {
// Chiediamo all'utente il nome del file
printf("\nInserisci il nome del file di input: ");
scanf("%s", filename);
// Controlliamo la lunghezza del nome del file
if(strlen(filename) > MAX_FILENAME_LENGTH)
{
printf("Il nome del file supera la lunghezza massima consentita!\n");
continue;
}
// Tentiamo di aprire il file
found = read_file_and_init(filename, &Mat, &m, &n, &Segni);
if(!found) printf("File non trovato!\n");
} while(!found);
// Contiamo il numero di variabili slack da aggiungere
for (i = 1; i <= m; ++i)
{
if(Segni[i] == 1 || Segni[i] == -1) ++num_slack;
}
// Controlliamo se dobbiamo aggiungere il vincolo artificiale
for (j = 1; j <= n; ++j)
{
if(Mat[0][j] > 0) // Se troviamo un zj - cj > 0, allora dobbiamo aggiungere il vincolo
{
++num_slack;
va = 1;
break;
}
}
// Memorizziamo le nuove dimensioni del tableau
if(va) ++m;
n += num_slack;
// Inizializziamo il resto del tableau se abbiamo trasformato in forma standard e/o aggiunto il v.a.
if(va || num_slack > 0)
{
// Allochiamo un nuovo blocco di memoria
Mat = realloc(Mat, (m+1) * sizeof(double*));
for (i = 0; i <= m; ++i) Mat[i] = realloc(Mat[i], (n+1) * sizeof(double*));
// Azzeriamo i nuovi coefficienti
for(i = 1; i <= m; ++i)
{
for(j = 1; j <= n; ++j)
{
if(i == m || j > (n - num_slack))
{
Quando assegna Mat[m][j] = 0.0 dà segfault
Mat[i][j] = 0.0; // Azzeriamo solo la riga del v.a. e/o le colonne delle variabili slack
}
}
}
}
system("pause");
return 0;
}
// Funzione che preleva l'input dai file e inizializza il problema
int read_file_and_init(const char *filename, double **Mat, int *m, int *n, int **Segni)
{
// Variabili locali
FILE *fdata; // Stream di lettura
int i, j, k; // Per cicli
double **tmpMat, **tmpSegni; // Tableau e versi temporanei
double cc; // Variabile costi
long no; // Numero di coefficienti non-zero della j-esima colonna
long rr; // Indice di riga del corrente coefficiente non-zero
// Apriamo il file di input in lettura
fdata = fopen(filename, "r");
// Controlliamo che il file esista, in caso contrario ritorniamo
if(fdata == NULL) return 0;
// Leggiamo il numero di righe e di colonne
fscanf(fdata,"%d %d", n, m);
// Allochiamo il tableau con le relative dimensioni
tmpMat = (double*) malloc((*m+1) * sizeof(double*));
for (i = 0; i <= (*m); ++i) tmpMat[i] = (double*) malloc((*n+1) * sizeof(double));
// Allochiamo l'array dei versi
tmpSegni = (double*) malloc((*m) * sizeof(double*));
// Inizializziamo il tableau
for(i = 0; i <= (*m); ++i)
{
for(j = 0; j <= (*n); ++j)
{
tmpMat[i][j] = 0.0;
}
}
// Leggiamo il vettore dei termini noti
for(i = 1; i <= (*m); ++i)
{
fscanf(fdata, "%lf", &(tmpMat[i][0]));
}
// Leggiamo il vettore dei versi delle condizioni
for (i = 1; i <= (*m); ++i)
{
fscanf(fdata, "%d", &(tmpSegni[i]));
}
// Leggiamo la matrice dei coefficienti
for (j = 1; j <= (*n); ++j)
{
// Leggiamo il costo della j-esima colonna
fscanf(fdata, "%lf", &cc);
tmpMat[0][j] = -cc;
// Leggiamo il numero di coefficienti non-zero della j-esima colonna
fscanf(fdata, "%d", &no);
// Leggiamo i coefficienti non-zero della j-esima colonna
for (k = 1; k <= no; ++k)
{
fscanf(fdata, "%d", &rr); // Reperiamo l'indice di riga
fscanf(fdata, "%lf", &(tmpMat[rr][j])); // Memorizziamo il coefficiente
}
}
// Chiudiamo il file
fclose(fdata);
// Memorizziamo nelle variabili originali
*Mat = tmpMat;
*Segni = tmpSegni;
// Ritorniamo
return 1;
}