|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Member
Iscritto dal: Jul 2006
Messaggi: 64
|
[C++] Caricare dati float da txt
Ciao a tutti, chissà quante volte vi è stata fatta questa domanda, cercando in giro ho trovato più proposte con le quali però nascono ulteriori problemi che non sò risolvere.
il file txt dal quale devo leggere è composto da una serie di colonne con numeri in forma esponenziale (es: 1.03948e+12), vorrei leggere il file txt e disporre dei dati sottoforma di array. Essendo totalmente inetto in c++ |
|
|
|
|
|
#2 | |
|
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
Quote:
ti chiedo qualche informazione sul formato del file: - I numeri come sono separati? Virgola, spazio, punto e virgola? - La prima riga contiene contiene informazioni sulla dimensione della matrice(numero di righe e colonne) o parte subito dai dati? |
|
|
|
|
|
|
#3 |
|
Member
Iscritto dal: Jul 2006
Messaggi: 64
|
si, i numeri sono separati, sono del tipo in allegato, il numero di colonne dovrebbe essere di 365 (lettura di un laser a scansione) con separazione per mezzo di spazi, e non vi sono informazioni sulle dimensioni, che però rimane costante.
Grazie per l'interessamento |
|
|
|
|
|
#4 |
|
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
Il programma seguente implementa un automa a stati finiti che legge il file di testo e restituisce il risultato in una struttura che contiene, come campi, l'array, il numero di righe e il numero di colonne.
Con questo file: Codice:
2.025e+12 3.125e-15 2.125e-5 1.0125e-10 2.031e+10 5.12548e-12 Codice:
array[0][0] -> 2.025e+012 array[1][2] -> 5.12548e-012 Codice:
#include <iostream>
using namespace std;
#define BUFFER_SIZE 4096
typedef struct tagArray
{
size_t rows;
size_t cols;
double **m;
} Array;
typedef enum tagStati
{
S_ERROR = -1, S0 = 0, S1, S2, S3, S4, S5, S6, S7, S8, S9
} Stati;
Stati DFA(const char *szFileName, Array *pArray)
{
Stati stato = S0;
FILE *fp;
unsigned char buffer[BUFFER_SIZE];
int numblocks;
int numread;
unsigned char c;
int k, x, j;
int riga, colonna;
char szNum[256];
double num;
bool bCountCols = true;
unsigned char byteCR = 0xD; // Carriage Return
unsigned char byteLF = 0xA; // Line Feed
pArray->rows = 0;
pArray->cols = 0;
fp = fopen(szFileName, "rb"); // Warning C4996 -> Usare fopen_s
if ( fp == NULL )
{
cout << "Errore nell'apertura del file " << szFileName << endl;
return S_ERROR;
}
if ( fseek(fp, 0, SEEK_END) )
return S_ERROR;
numblocks = ftell(fp)/BUFFER_SIZE;
if ( numblocks == 0 )
{
numblocks = 1;
}
else
{
if ( ftell(fp) % BUFFER_SIZE != 0 )
numblocks++;
}
fseek(fp, 0, SEEK_SET);
while ( 1 )
{
k = 0;
numread = fread(buffer, 1, BUFFER_SIZE, fp);
if ( numread == 0 )
break;
for ( k = 0; k < numread; k++ )
{
if ( *(buffer + k) == byteLF )
{
pArray->rows++;
bCountCols = false;
}
else if ( bCountCols && *(buffer + k) != ' ' )
{
pArray->cols++;
while ( *(buffer + k) != ' ' )
{
k++;
if ( k == numread )
break;
if ( *(buffer + k) == byteLF )
{
pArray->rows++;
bCountCols = false;
break;
}
}
}
}
if ( numread < BUFFER_SIZE )
break;
}
if ( fseek(fp, -1, SEEK_END) )
return S_ERROR;
fread(buffer, 1, 1, fp);
if ( *buffer != byteLF )
pArray->rows++;
pArray->m = new double*[pArray->rows];
if ( pArray->m )
{
for ( size_t row(0); row != pArray->rows; ++row )
{
pArray->m[row] = new double[pArray->cols];
if ( !pArray->m[row] )
{
cout << "Memoria insufficiente." << endl;
fclose(fp);
return S_ERROR;
}
}
}
else
{
cout << "Memoria insufficiente." << endl;
fclose(fp);
return S_ERROR;
}
fseek(fp, 0, SEEK_SET);
numread = fread(buffer, 1, BUFFER_SIZE, fp);
riga = colonna = 0;
num = 0;
x = k = j = 0;
while ( x < numblocks )
{
c = *(buffer + k++);
if ( c == byteCR )
{
if ( k >= numread )
{
numread = fread(buffer, 1, BUFFER_SIZE, fp);
k = 0;
x++;
}
c = *(buffer + k++);
}
switch (stato)
{
case S0:
j = 0;
if ( c == '-' || c == '+' )
{
szNum[j++] = c;
stato = S1;
}
else if ( c >= '0' && c <= '9' )
{
szNum[j++] = c;
stato = S2;
}
else if ( c == '.' )
{
szNum[j++] = c;
stato = S3;
}
else
{
cout << "Errore: stato S0 << riga " << riga << " colonna " << colonna << endl;
fclose(fp);
return S_ERROR;
}
break;
case S1:
if ( c >= '0' && c <= '9' )
{
szNum[j++] = c;
stato = S2;
}
else if ( c == '.' )
{
szNum[j++] = c;
stato = S3;
}
else
{
cout << "Errore: stato S1 riga " << riga << " colonna " << colonna << endl;
fclose(fp);
return S_ERROR;
}
break;
case S2:
if ( c >= '0' && c <= '9' )
{
szNum[j++] = c;
}
else if ( c == '.' )
{
szNum[j++] = c;
stato = S4;
}
else if ( c == 'E' || c == 'e' )
{
szNum[j++] = c;
stato = S5;
}
else if ( c == ' ' || c == byteLF )
{
szNum[j] = '\0';
pArray->m[riga][colonna] = atof(szNum);
if ( c == byteLF )
{
riga++;
colonna = 0;
}
else
{
colonna++;
}
stato = S0;
}
else
{
cout << "Errore: stato S2 riga " << riga << " colonna " << colonna << endl;
fclose(fp);
return S_ERROR;
}
break;
case S3:
if ( c >= '0' && c <= '9' )
{
szNum[j++] = c;
stato = S6;
}
else
{
cout << "Errore: stato S3 riga " << riga << " colonna " << colonna << endl;
fclose(fp);
return S_ERROR;
}
break;
case S4:
if ( c >= '0' && c <= '9' )
{
szNum[j++] = c;
stato = S6;
}
else if ( c == 'E' || c == 'e' )
{
szNum[j++] = c;
stato = S7;
}
else if ( c == ' ' || c == byteLF )
{
szNum[j] = '\0';
pArray->m[riga][colonna] = atof(szNum);
if ( c == byteLF )
{
riga++;
colonna = 0;
}
else
{
colonna++;
}
stato = S0;
}
else
{
cout << "Errore: stato S4 riga " << riga << " colonna " << colonna << endl;
fclose(fp);
return S_ERROR;
}
break;
case S5:
if ( c >= '0' && c <= '9' )
{
szNum[j++] = c;
stato = S9;
}
else if ( c == '-' || c == '+' )
{
szNum[j++] = c;
stato = S8;
}
else
{
cout << "Errore: stato S5 riga " << riga << " colonna " << colonna << endl;
fclose(fp);
return S_ERROR;
}
break;
case S6:
if ( c >= '0' && c <= '9' )
{
szNum[j++] = c;
stato = S6;
}
else if ( c == 'E' || c == 'e' )
{
szNum[j++] = c;
stato = S7;
}
else if ( c == ' ' || c == byteLF )
{
szNum[j] = '\0';
pArray->m[riga][colonna] = atof(szNum);
if ( c == byteLF )
{
riga++;
colonna = 0;
}
else
{
colonna++;
}
stato = S0;
}
else
{
cout << "Errore: stato S6 riga " << riga << " colonna " << colonna << endl;
fclose(fp);
return S_ERROR;
}
break;
case S7:
if ( c >= '0' && c <= '9' )
{
szNum[j++] = c;
stato = S9;
}
else if ( c == '-' || c == '+' )
{
szNum[j++] = c;
stato = S8;
}
else
{
cout << "Errore: stato S7 riga " << riga << " colonna " << colonna << endl;
fclose(fp);
return S_ERROR;
}
break;
case S8:
case S9:
if ( c >= '0' && c <= '9' )
{
szNum[j++] = c;
stato = S9;
}
else if ( c == ' ' || c == byteLF )
{
szNum[j] = '\0';
pArray->m[riga][colonna] = atof(szNum);
if ( c == byteLF )
{
riga++;
colonna = 0;
}
else
{
colonna++;
}
stato = S0;
}
else
{
cout << "Errore: stato S9 riga " << riga << " colonna " << colonna << endl;
fclose(fp);
return S_ERROR;
}
break;
}
if ( k >= numread )
{
numread = fread(buffer, 1, BUFFER_SIZE, fp);
k = 0;
x++;
}
}
fclose(fp);
if ( stato == S2 || stato == S4 || stato == S6 || stato == S9 )
{
szNum[j] = '\0';
pArray->m[riga][colonna] = atof(szNum);
}
return stato;
}
int main()
{
Stati stato;
Array myArray;
char *szFileName = "prova.txt";
stato = DFA(szFileName, &myArray);
if ( stato == S0 || stato == S2 || stato == S4 || stato == S6 || stato == S9 )
{
// stampa il primo elemento dell'array(riga 0, colonna 0)
cout << endl << "array[0][0] -> " << myArray.m[0][0] << endl;
// stampa l'ultimo elemento(ultima riga, ultima colonna)
cout << "array[" << myArray.rows - 1 << "][" << myArray.cols - 1 << "] -> " << myArray.m[myArray.rows - 1][myArray.cols - 1] << endl;
for ( size_t row(0); row != myArray.rows; ++row )
delete [] myArray.m[row];
delete [] myArray.m;
}
else
{
cout << "L'automa ha restituito un errore. Stato " << stato << endl;
}
return 0;
}
Ultima modifica di Vincenzo1968 : 12-09-2008 alle 02:25. |
|
|
|
|
|
#5 |
|
Member
Iscritto dal: Jul 2006
Messaggi: 64
|
Grazie mille, adesso lo provo.
Spero che non sei stato sveglio fino alle 2 per me! |
|
|
|
|
|
#6 | |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
Quote:
![]() e occhio, ci sta pure il commento (C++ - like) che ti avvisa che a quella linea il compilatore ti da' il warning C4996 ![]() ti offendi se ti dico che si risolveva tutto con molto meno? Codice:
#include <iostream>
#include <fstream>
#include <list>
using namespace std;
struct Vector
{
float x;
float y;
float z;
};
istream &operator >> (istream &source, Vector &v)
{
return source >> v.x >> v.y >> v.z;
}
ostream &operator << (ostream &sink, const Vector &v)
{
return sink << v.x << ", " << v.y << ", " << v.z << endl;
}
int main()
{
ifstream source("input.txt", ifstream::in);
if (!source.good())
{
return 1;
}
list<Vector> vectors;
while (!source.eof())
{
Vector v;
source >> v;
vectors.push_back(v);
}
for (list<Vector>::iterator i = vectors.begin(); i != vectors.end(); i++)
{
cout << *i;
}
return 0;
}
|
|
|
|
|
|
|
#7 | |
|
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
Quote:
La tua implementazione è una porcata dal punto di vista delle prestazioni. Vogliamo provare a confrontare i tempi su file di grosse dimensioni? |
|
|
|
|
|
|
#8 |
|
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
Se modifico il file di esempio da cosi:
Codice:
2.025e+12 3.125e-15 2.125e-5 1.0125e-10 2.031e+10 5.12548e-12 Codice:
2.025e+12 3.125e-15 2.125e-5 1.0125e-10 2.ciao 5.12548e-12 Errore stato S4 riga 1 colonna 1 La tua breve(nonché intelligente) applicazione, si blocca |
|
|
|
|
|
#9 |
|
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
Ho preso i tempi di esecuzione:
La tua versione, pur non eseguendo nessun lavoro di gestione degli errori, è più lenta della mia. I file di test li ho creati con questo codice: Codice:
void CreaDoubleFile()
{
FILE *fp;
int i, j;
int n1, n2;
char szNum[256];
fp = fopen("test.txt", "w+");
srand((unsigned)time(NULL));
for ( i = 0; i < 100000; i++ )
{
for ( j = 0; j < 365; j++ )
{
n1 = rand();
n2 = rand();
itoa(n1, szNum, 10);
strcat(szNum, ".1e-5");
fwrite(szNum, strlen(szNum), 1, fp);
if ( j < 364 )
fwrite(" ", 1, 1, fp);
}
fwrite("\n", 1, 1, fp);
//printf("record n. %d\n", i);
}
fclose(fp);
}
Il secondo contiene 100.000 righe e 365 colonne. 83 secondi contro 35. Preferisco reinventare l'acqua calda e avere codice efficiente, e dal punto di vista delle prestazioni, e da quello delle funzionalità(gestione degli errori), piuttosto che scrivere due righe di codice per avere programmi... come definirli? Porcate? |
|
|
|
|
|
#10 |
|
Senior Member
Iscritto dal: May 2005
Messaggi: 564
|
Ti si legge “” dal path...
Ultima modifica di slartibartfast : 13-09-2008 alle 01:50. |
|
|
|
|
|
#11 |
|
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
|
|
|
|
|
|
#12 |
|
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
E per fortuna c'è anche chi la pensa diversamente sulle 'porcate' che scrivo:
http://www.democritos.it:8888/O-sesame/chngview?cn=6026 Ultima modifica di cionci : 13-09-2008 alle 09:38. |
|
|
|
|
|
#13 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Vincenzo1968: tolgo le due mail, il mittente, che specifico non è alcun utente del forum, non ti ha certo autorizzato a pubblicare i suoi dati personali.
Inoltre Vincenzo1968 ti prendi una sospensione di 3 gg per il "coglione" nel path. 71104: continui a rivolgerti agli altri utenti come se fossero tuoi compagni di merende, non lo sono, ricordati che comportamenti di questo tipo non saranno oltremodo tollerati in tutto il forum. 1 giorno di sospensione Ultima modifica di cionci : 13-09-2008 alle 09:38. |
|
|
|
|
|
#14 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Tornando alla questione iniziale, il linguaggio richiesto era il C++ e non il C e le prestazioni non sono tutto, anzi, nel 90% dei casi non sono niente.
|
|
|
|
|
|
#15 |
|
Member
Iscritto dal: Jul 2006
Messaggi: 64
|
Pensavo anche io inizialmente che un programma così non lungo (data la mia inesperienza) fosse estremamente lento, ma invece è molto veloce, e questo è ben accetto sopratutto in previsioni di applicazioni real-time.
Se mi permetti invece, volevo domandarti dove era possibile eliminare dal programma la segnalazione di errore relativo a come sono separati i dati, poichè mi sono accorto che il file di txt molto spesso separa con caratteri diversi dal solo spazio (doppio spazio, carattere di rientro(quello vicino a q sulla tastiera, non mi ricordo il nome)). Grazie ancora!! |
|
|
|
|
|
#16 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
In C++ lo farei così:
Codice:
struct Data
{
float x;
float y;
float z;
};
int parseLine(string line, Data &d)
{
istringstream iss(line);
iss >> d.x >> d.y >> d.z;
return iss.fail();
}
int main()
{
ifstream inputFile("nomefile");
while(1)
{
string line;
getline(inputFile, line);
if(inputFile.fail())
break;
vector<Data> v;
Data d;
if(parseLine(line, d))
{
cout << "Malformed line" << endl;
break;
}
v.push_back(d);
}
return 0;
}
Per i tab e i doppi spazi non ti devi preoccupare, almeno nel mio caso li salta tutti. |
|
|
|
|
|
#17 | |
|
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
Quote:
vero è che li salta tutti, i tab e gli spazi, ma salta anche, per ogni riga, le restanti 362 colonne Mattia ha specificato che le colonne dovrebbero essere 365 Il mio automa, le colonne le calcola al volo(basandosi sulla prima riga) e crea un array bidimensionale adeguato. Col vostro programma che bisogna fare? Utilizzare una struttura con 365 campi? E se debbo leggere in sequenza più file, ognuno dei quali con un numero di colonne diverso? Mi permetto di suggerire l'uso di un vettore di vettori dimensionato in modo dinamico. Ecco un esempio: Codice:
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <time.h>
using namespace std;
template <typename T>
class MyArray
{
public:
MyArray()
{
m_righe = 0;
m_colonne = 0;
}
MyArray(int righe, int colonne) : myArray(righe, vector<T>(colonne))
{
m_righe = righe;
m_colonne = colonne;
}
vector<T> & operator[](int i)
{
return myArray[i];
}
const vector<T> & operator[] (int i) const
{
return myArray[i];
}
void resize(int righe, int colonne)
{
myArray.resize(righe);
for( int i = 0; i < righe; ++i )
myArray[i].resize(colonne);
}
private:
vector<vector<T>> myArray;
int m_righe;
int m_colonne;
};
int parseLine(string line, MyArray<double> &d, int riga, int numcols)
{
istringstream iss(line);
for ( int i = 0; i < numcols; i++ )
iss >> d[riga][i];
return iss.fail();
}
void GetSizes(const char *szFileName, int &righe, int &colonne)
{
string line;
ifstream inputFile(szFileName);
righe = colonne = 0;
getline(inputFile, line);
if(inputFile.fail())
return;
int k = 0;
while ( line[k] != '\0' )
{
if ( line[k] == ' ' || line[k] == '\t' )
colonne++;
k++;
}
righe = 1;
while(1)
{
getline(inputFile, line);
if(inputFile.fail())
break;
righe++;
}
if ( colonne > 0 )
colonne++;
}
int main()
{
int righe, colonne;
char *szFileName = "C:\\Temp\\test3.txt";
clock_t c_start, c_end;
c_start = clock();
GetSizes(szFileName, righe, colonne);
MyArray<double> v(righe, colonne);
ifstream inputFile(szFileName);
int riga = 0;
while(1)
{
string line;
getline(inputFile, line);
if(inputFile.fail())
break;
if( parseLine(line, v, riga, colonne) )
{
cout << "Malformed line" << endl;
break;
}
riga++;
}
c_end = clock();
cout << endl;
cout << "v[0][0] -> " << v[0][0] << endl;
cout << "v[" << righe - 1 << "][" << colonne - 1 << "] -> " << v[righe - 1][colonne - 1] << endl;
printf("\nTempo impiegato -> %5.5f secondi\n", (double)(c_end - c_start) / CLOCKS_PER_SEC);
return 0;
}
Questo è il risultato sul file di 100.000 righe e 365 colonne: Il codice che ho scritto(il primo, quello con l'automa) è in C++. Utilizzo le funzioni del C per la gestione dei file, solo perchè queste sono più efficienti degli fstream del C++. Ti posso citare una mezza dozzina di libri al riguardo o, se preferisci, posso postare il risultato di vari test che ho effettuato sulla mia macchina. Infine, non ti sembra troppo generica la tua gestione degli errori? L'automa riporta la riga e la colonna dove l'errore s'è verificato. Il tuo programma se ne esce con un messaggio generico. Pensa se un compilatore, quando trova un errore, riporta il seguente messaggio all'utente: C'è un errore nel codice senza indicare il file e la presunta riga Posto il codice modificato in modo da tenere conto sia degli spazi multipli che dei caratteri di tabulazione: Codice:
#include <iostream>
#include <time.h>
using namespace std;
#define BUFFER_SIZE 4096
typedef struct tagArray
{
size_t rows;
size_t cols;
double **m;
} Array;
typedef enum tagStati
{
S_ERROR = -1, S0 = 0, S1, S2, S3, S4, S5, S6, S7, S8, S9
} Stati;
Stati DFA(const char *szFileName, Array *pArray)
{
Stati stato = S0;
FILE *fp;
unsigned char buffer[BUFFER_SIZE];
int numblocks;
int numread;
unsigned char c;
int k, x, j;
int riga, colonna;
char szNum[256];
double num;
bool bCountCols = true;
unsigned char byteCR = 0xD; // Carriage Return
unsigned char byteLF = 0xA; // Line Feed
pArray->rows = 0;
pArray->cols = 0;
fp = fopen(szFileName, "rb"); // Warning C4996 -> Usare fopen_s
if ( fp == NULL )
{
cout << "Errore nell'apertura del file " << szFileName << endl;
return S_ERROR;
}
if ( fseek(fp, 0, SEEK_END) )
return S_ERROR;
numblocks = ftell(fp)/BUFFER_SIZE;
if ( numblocks == 0 )
{
numblocks = 1;
}
else
{
if ( ftell(fp) % BUFFER_SIZE != 0 )
numblocks++;
}
fseek(fp, 0, SEEK_SET);
while ( 1 )
{
k = 0;
numread = fread(buffer, 1, BUFFER_SIZE, fp);
if ( numread == 0 )
break;
for ( k = 0; k < numread; k++ )
{
if ( *(buffer + k) == byteLF )
{
pArray->rows++;
bCountCols = false;
}
else if ( bCountCols && *(buffer + k) != ' ' )
{
pArray->cols++;
while ( *(buffer + k) != ' ' )
{
k++;
if ( k == numread )
break;
if ( *(buffer + k) == byteLF )
{
pArray->rows++;
bCountCols = false;
break;
}
}
}
}
if ( numread < BUFFER_SIZE )
break;
}
if ( fseek(fp, -1, SEEK_END) )
return S_ERROR;
fread(buffer, 1, 1, fp);
if ( *buffer != byteLF )
pArray->rows++;
pArray->m = new double*[pArray->rows];
if ( pArray->m )
{
for ( size_t row(0); row != pArray->rows; ++row )
{
pArray->m[row] = new double[pArray->cols];
if ( !pArray->m[row] )
{
cout << "Memoria insufficiente." << endl;
fclose(fp);
return S_ERROR;
}
}
}
else
{
cout << "Memoria insufficiente." << endl;
fclose(fp);
return S_ERROR;
}
fseek(fp, 0, SEEK_SET);
numread = fread(buffer, 1, BUFFER_SIZE, fp);
riga = colonna = 0;
num = 0;
x = k = j = 0;
while ( x < numblocks )
{
c = *(buffer + k++);
if ( c == byteCR )
{
if ( k >= numread )
{
numread = fread(buffer, 1, BUFFER_SIZE, fp);
k = 0;
x++;
}
c = *(buffer + k++);
}
switch (stato)
{
case S0:
j = 0;
if ( c == '-' || c == '+' )
{
szNum[j++] = c;
stato = S1;
}
else if ( c >= '0' && c <= '9' )
{
szNum[j++] = c;
stato = S2;
}
else if ( c == '.' )
{
szNum[j++] = c;
stato = S3;
}
else if ( c == ' ' || c == '\t' )
{
while ( c == ' ' || c == '\t' )
{
c = *(buffer + k++);
if ( k >= numread )
break;
}
k--;
}
else
{
cout << "Errore: stato S0 << riga " << riga << " colonna " << colonna << endl;
fclose(fp);
return S_ERROR;
}
break;
case S1:
if ( c >= '0' && c <= '9' )
{
szNum[j++] = c;
stato = S2;
}
else if ( c == '.' )
{
szNum[j++] = c;
stato = S3;
}
else
{
cout << "Errore: stato S1 riga " << riga << " colonna " << colonna << endl;
fclose(fp);
return S_ERROR;
}
break;
case S2:
if ( c >= '0' && c <= '9' )
{
szNum[j++] = c;
}
else if ( c == '.' )
{
szNum[j++] = c;
stato = S4;
}
else if ( c == 'E' || c == 'e' )
{
szNum[j++] = c;
stato = S5;
}
else if ( c == ' ' || c == '\t' || c == byteLF )
{
szNum[j] = '\0';
pArray->m[riga][colonna] = atof(szNum);
if ( c == byteLF )
{
riga++;
colonna = 0;
}
else
{
colonna++;
}
stato = S0;
}
else
{
cout << "Errore: stato S2 riga " << riga << " colonna " << colonna << endl;
fclose(fp);
return S_ERROR;
}
break;
case S3:
if ( c >= '0' && c <= '9' )
{
szNum[j++] = c;
stato = S6;
}
else
{
cout << "Errore: stato S3 riga " << riga << " colonna " << colonna << endl;
fclose(fp);
return S_ERROR;
}
break;
case S4:
if ( c >= '0' && c <= '9' )
{
szNum[j++] = c;
stato = S6;
}
else if ( c == 'E' || c == 'e' )
{
szNum[j++] = c;
stato = S7;
}
else if ( c == ' ' || c == '\t' || c == byteLF )
{
szNum[j] = '\0';
pArray->m[riga][colonna] = atof(szNum);
if ( c == byteLF )
{
riga++;
colonna = 0;
}
else
{
colonna++;
}
stato = S0;
}
else
{
cout << "Errore: stato S4 riga " << riga << " colonna " << colonna << endl;
fclose(fp);
return S_ERROR;
}
break;
case S5:
if ( c >= '0' && c <= '9' )
{
szNum[j++] = c;
stato = S9;
}
else if ( c == '-' || c == '+' )
{
szNum[j++] = c;
stato = S8;
}
else
{
cout << "Errore: stato S5 riga " << riga << " colonna " << colonna << endl;
fclose(fp);
return S_ERROR;
}
break;
case S6:
if ( c >= '0' && c <= '9' )
{
szNum[j++] = c;
stato = S6;
}
else if ( c == 'E' || c == 'e' )
{
szNum[j++] = c;
stato = S7;
}
else if ( c == ' ' || c == '\t' || c == byteLF )
{
szNum[j] = '\0';
pArray->m[riga][colonna] = atof(szNum);
if ( c == byteLF )
{
riga++;
colonna = 0;
}
else
{
colonna++;
}
stato = S0;
}
else
{
cout << "Errore: stato S6 riga " << riga << " colonna " << colonna << endl;
fclose(fp);
return S_ERROR;
}
break;
case S7:
if ( c >= '0' && c <= '9' )
{
szNum[j++] = c;
stato = S9;
}
else if ( c == '-' || c == '+' )
{
szNum[j++] = c;
stato = S8;
}
else
{
cout << "Errore: stato S7 riga " << riga << " colonna " << colonna << endl;
fclose(fp);
return S_ERROR;
}
break;
case S8:
case S9:
if ( c >= '0' && c <= '9' )
{
szNum[j++] = c;
stato = S9;
}
else if ( c == ' ' || c == '\t' || c == byteLF )
{
szNum[j] = '\0';
pArray->m[riga][colonna] = atof(szNum);
if ( c == byteLF )
{
riga++;
colonna = 0;
}
else
{
colonna++;
}
stato = S0;
}
else
{
cout << "Errore: stato S9 riga " << riga << " colonna " << colonna << endl;
fclose(fp);
return S_ERROR;
}
break;
}
if ( k >= numread )
{
numread = fread(buffer, 1, BUFFER_SIZE, fp);
k = 0;
x++;
}
}
fclose(fp);
if ( stato == S2 || stato == S4 || stato == S6 || stato == S9 )
{
szNum[j] = '\0';
pArray->m[riga][colonna] = atof(szNum);
}
return stato;
}
int main()
{
Stati stato;
Array myArray;
clock_t c_start, c_end;
char *szFileName = "C:\\Temp\\test3.txt";
c_start = clock();
stato = DFA(szFileName, &myArray);
c_end = clock();
printf("\nTempo impiegato -> %5.5f secondi\n", (double)(c_end - c_start) / CLOCKS_PER_SEC);
if ( stato == S0 || stato == S2 || stato == S4 || stato == S6 || stato == S9 )
{
// stampa il primo elemento dell'array(riga 0, colonna 0)
cout << endl << "array[0][0] -> " << myArray.m[0][0] << endl;
// stampa l'ultimo elemento(ultima riga, ultima colonna)
cout << "array[" << myArray.rows - 1 << "][" << myArray.cols - 1 << "] -> " << myArray.m[myArray.rows - 1][myArray.cols - 1] << endl;
for ( size_t row(0); row != myArray.rows; ++row )
delete [] myArray.m[row];
delete [] myArray.m;
}
else
{
cout << "L'automa ha restituito un errore. Stato " << stato << endl;
}
return 0;
}
Sfido chiunque a ottenere gli stessi tempi, in puro C++, con fstream e vector |
|
|
|
|
|
|
#18 | |
|
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Quote:
Il link è corretto?
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
|
|
|
|
|
|
#19 |
|
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
Ciao Banryu,
si, è corretto. Ho provato proprio adesso a cliccarci sopra e funziona Ciao P.S. Approfitto per chiedere il permesso a Cionci di postare le due mail che ha tolto nel post precedente. Ho cancellato ogni riferimento all'autore delle mail, compreso il numero di telefono della società. Ultima modifica di Vincenzo1968 : 16-09-2008 alle 10:35. |
|
|
|
|
|
#20 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Riguardo alla gestione degli errori è stata volutamente lasciata così, basta un counter ed una lettura delle colonne separata per sapere riga e colonna dell'errore
Che il numero di colonne sia variabile sinceramente non l'ho letto, credevo fossero tre Le prestazioni al solito non sono tutto in un programma, molte volte è più importante la leggibilità e la manutenibilità Per aumentare le prestazioni siamo sempre in tempo ad andare a lavorare sul punto in cui le prestazioni sono deficitarie con un profiler, questo non è un grosso problema. Per il numero di colonne variabili la questione è comunque abbastanza semplice: Codice:
class DataMatrix
{
vector<float *> matrix;
int currentColumn;
int columns;
int rows;
public:
DataMatrix(int columns)
{
this->columns = columns;
rows = 0;
newLine();
}
void insert(float f)
{
matrix.back()[currentColumn++] = f;
}
void newLine()
{
matrix.push_back(new matrix[columns]);
rows++;
}
int getLines() { return rows; };
int getRows() { return columns; };
float getElement(int row, int column)
{
return matrix[row][column];
}
~DataMatrix()
{
while(matrix.size() > 0)
{
delete[] matrix.back();
matrix.pop_back();
}
}
};
class MalformedLineException
{
int row;
int column;
string message;
public;
MalformedLineException(int row, int column)
{
this->row = row;
this->column = column;
ostringstream oss;
oss << "Malformed line at row " << row << " and column " << column;
message = oss.str();
}
string getMessage() { return message; };
int getRow() { return row; };
int getColumn() { return column; };
};
int countColumns(string line)
{
istringstream iss(line);
int lineCounter = 0;
while(1)
{
flot tmp;
iss >> tmp;
if(iss.fail() && !iss.eof())
throw MalformedLineException(1, lineCounter + 1);
if(iss.eof())
break;
lineCounter++;
}
return lineCounter;
}
void parseLine(string line, DataMatrix &data)
{
istringstream iss(line);
for(int i = 0; i < data.getColumns(); ++i)
{
float f;
iss >> f;
if(iss.fail())
throw MalformedLineException(data.getRows(), data.getColumns());
matrix.insert(f);
}
}
int main()
{
ifstream inputFile("nomefile");
try
{
string line;
getline(inputFile, line);
int columns = countColumns(line);
DataMatrix data(columns);
while(1)
{
if(inputFile.fail())
break;
data.newLine();
parseLine(line, data);
getline(inputFile, line);
}
}
catch(MalformedLineException ex)
{
cout << ex.getMessage();
}
return 0;
}
Per chiarirmi meglio sulle prestazioni...il problema è il vector ? Bene se castra le prestazioni si elimina e si aggiunge una riallocazione a blocchi. Il problema è l'istringstream ? Si sostituisce con una lettura carattere per carattere fino al primo carattere che uno spazio (nel senso di isspace). Ultima modifica di cionci : 16-09-2008 alle 10:53. |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 20:32.






















