PDA

Visualizza la versione completa : [C++] Problema con la lettura di una matrice da file


DaemonDestroyer
10-06-2014, 11:44
Ciao a tutti, sono nuovo del forum! Vorrei chiedere aiuto a voi esperti circa un programma che non riesco a fare. Devo leggere una matrice da file di testo e poi trovarne il punto di sella. Sul punto di sella non ci sono problemi, so come si fa, il problema è leggere la matrice da file e soprattutto il riempimento delle righe e delle colonne... è una matrice quadrata 4x4. L'input da file di testo è questo:
4
2 17 19 22
3 20 7 9
25 23 32 40
13 21 27 39

Tuttavia non so come fargli leggere solamente il primo numero come riempimento delle righe e delle colonne. Vi posto quello che ho fatto fino ad ora, ma funziona solo se l'input è questo:

2 17 19 22
3 20 7 9
25 23 32 40
13 21 27 39


Ecco il programma (così funziona, ma va completato e non so come! Grazie a chiunque mi darà una mano):



#include <iostream>
#include <fstream>
#include <cstdlib>
#include <stdlib.h>
#define R 4
#define C 4




using namespace std;


void leggomat() {


int mat[R][C];


// legge dati
ifstream dati("mat.txt");
int r = 0;
while(!dati.eof())
{
dati >> mat[r][0] >> mat[r][1] >> mat[r][2] >> mat[r][3];
r++;
}
dati.close();


// visualizza dati
int i;
for(i=0; i<r; i++)
cout << mat[i][0] << " " << mat[i][1] << " " << mat[i][2] << " "<< mat [i] [3] << endl;

}


int main () {

leggomat();


return 0; }

oregon
10-06-2014, 12:00
Prima del while scrivi

dati >> riempimento;

e poi usa la variabile riempimento per allocare dinamicamente l'array.

DaemonDestroyer
10-06-2014, 12:20
Ciao oregon, grazie per la risposta. Quindi devo dichiarare un intero (riempimento), e una volta fatto questo qual'è il procedimento? Scusami, ma sono un neofita della programmazione... grazie per il Tuo tempo

oregon
10-06-2014, 12:21
Non di "tipo" riempimento (non esiste un tipo simile) ma un intero che chiami come vuoi (riempimento era solo un esempio di nome).

E poi devi allocare dinamicamente l'array con la funzione malloc ... l'hai mai usata?

DaemonDestroyer
10-06-2014, 12:30
Si ha ragione, mi sono espresso male, ho modificato il messaggio.
Ecco è questo il problema, l'allocazione dinamica con malloc... pur avendo visto diversi esempi sul libro e su internet non mi è proprio chiaro come essa funzioni, e da dove devo partire innanzitutto!

Scara95
10-06-2014, 12:51
Si ha ragione, mi sono espresso male, ho modificato il messaggio.
Ecco è questo il problema, l'allocazione dinamica con malloc... pur avendo visto diversi esempi sul libro e su internet non mi è proprio chiaro come essa funzioni, e da dove devo partire innanzitutto!
In C++ puoi anche usare new e delete (o new[] e delete[]).

In ogni caso malloc ritorna un puntatore a un blocco di memoria che ha dimensione in bytes pari all'unico argomento della funzione:
void *p_blocco = malloc(n);
p_blocco è un puntatore a un blocco di memoria di n bytes.
Per essere utile tuttavia bisogna fare alcune considerazioni:

sizeof ritorna le dimensioni in bytes dell'argomento:
ad esempio sizeof(char) ritornerà sempre 1, sizeof(type *) ritorna le dimensioni in bytes di un puntatore (8 su 64bit, 4 su 32bit, 2 su 16bit)

dunque sizeof(tipo) ti da il numero di byte di un elemento, moltiplichi questo per il numero degli elementi e ottieni il numero di byte del blocco.

per utilizzare il blocco alla fine ti serve un cast al puntatore di tipo.

Ad esempio per allocare un array di interi di n elementi servirà
int *array = (int *)malloc( sizeof(int) * n );

Ti allego la soluzione dell'esercizio che è un esempio di allocazione dinamica:
#include <iostream>
#include <fstream>

//necessario se usi malloc e free, non necessario altrimenti
#include <cstdlib>

using namespace std;

int **readMat(int**&m, size_t& size, ifstream& in) {
in >> size;
m = new int *[size];
for(int i = 0; i < size; ++i)
m[i] = new int[size];
for(int i = 0; i < size; ++i)
for(int j = 0; j < size; ++j)
in >> m[i][j];
return m;
}

int **readMat1(int **&m, size_t& size, ifstream &in) {
in >> size;
m = (int **)malloc(sizeof(int *) * size);
for(int i = 0; i < size; ++i)
m[i] = (int *)malloc(sizeof(int) * size);
for(int i = 0; i < size; ++i)
for(int j = 0; j < size; ++j)
in >> m[i][j];
return m;
}

void freeMat(int **&m, size_t size) {
for(int i = 0; i < size; ++i)
delete[] m[i];
delete[] m;
}

void freeMat1(int **&m, size_t size) {
for(int i = 0; i < size; ++i)
free(m[i]);
free(m);
}

int main(void) {
ifstream in("input.txt");
size_t size;
int **m;
readMat1(m, size, in);
for(int i = 0; i < size; ++i) {
for(int j = 0; j < size; ++j)
cout << m[i][j] << '\t';
cout << endl;
}
freeMat1(m, size);
return 0;
}

Scara95
10-06-2014, 12:54
Da notare infine che puoi allocare un unico blocco di memoria e calcolare gli indici. Prova a pensare tu come.

DaemonDestroyer
10-06-2014, 15:59
Grazie mille Scara, la tua risposta è stata più che soddisfacente! Finalmente le idee mi sono già più chiare, e finalmente ho capito, grazie al cast di cui mi hai parlato, a cosa erano dovuti quegli errori che spesso mi dava Dev c++. Analizzerò per bene il programma che mi hai fornito e tenterò di rifarlo da solo, proverò altresì ad allocare un unico blocco di memoria. Se dovessi riuscirci posterò il mio risultato qui!

Scara95
10-06-2014, 16:05
Nessun problema. Nota che io ti ho offerto 2 coppie di funzioni in ogni caso: una usa malloc e free, l'altra new e delete.
Se c'è qualcosa che non capisci chiedi pure (:
:ciauz:

DaemonDestroyer
11-06-2014, 09:43
Nessun problema. Nota che io ti ho offerto 2 coppie di funzioni in ogni caso: una usa malloc e free, l'altra new e delete.
Se c'è qualcosa che non capisci chiedi pure (:
:ciauz:
Ciao scara! Il tuo programma funziona correttamente, ho preferito utilizzare le funzioni con new int e delete che, a mio parere, sono più semplici da ricordare e da scrivere. Ho continuato il programma, ora è a buon punto, ho aggiunto una funzione che mi calcola l'indice minimo nelle colonne, te lo faccio vedere




#include <iostream>
#include <fstream>
#include <cstdlib>


using namespace std;


int **readMat(int**&m, size_t& size)
{
ifstream in("mat.txt");
in >> size;
m = new int *[size];
for(int i = 0; i < size; ++i)
m[i] = new int[size];
for(int i = 0; i < size; ++i)
for(int j = 0; j < size; ++j)
in >> m[i][j];
return m;
}


void freeMat(int **&m, size_t size) {
for(int i = 0; i < size; ++i)
delete[] m[i];
delete[] m;
}


int calc_ind_min(int **&m,int size,int r)
{
int min=m[r][0];
int i,indmin=0;
for (i=0;i<size;i++)
{
if (m[r][i]<min)
{
min=m[r][i];
indmin=i;
}
}
cout<<indmin;
return indmin;
}


int main(void) {
size_t size;
int **m;
readMat(m, size);
for(int i = 0; i < size; ++i) {
for(int j = 0; j < size; ++j)
cout << m[i][j] << '\t';
cout << endl;
}
int r;
for(r=0;r<size;r++)
{
calc_ind_min(m,size,r);
}
freeMat(m, size);
return 0;
}



Però ti vorrei chiedere alcune cose. Nel programma mi è quasi tutto chiaro, devo solo capire, qual'è precisamente la funzione di new int? La funzione di delete è quella di liberare la memoria altrimenti si appesantisce il sistema, ma new int, prima di size nella prima funzione, a che serve precisamente?
E poi, size_t che tipo è? Ha la stessa funzione di unsigned int? Grazie per il tuo tempo!!

Loading