Torna indietro   Hardware Upgrade Forum > Software > Programmazione

DJI Neo 2 in prova: il drone da 160 grammi guadagna il gimbal e molto altro
DJI Neo 2 in prova: il drone da 160 grammi guadagna il gimbal e molto altro
DJI aggiorna la sua linea di droni ultraleggeri con Neo 2, un quadricottero da 160 grammi che mantiene la compattezza del predecessore ma introduce una stabilizzazione meccanica a due assi, sensori omnidirezionali e un sistema LiDAR
L'IA "seria" di Appian è diversa: inserita nei processi e rispetta dati e persone
L'IA "seria" di Appian è diversa: inserita nei processi e rispetta dati e persone
Ad Appian Europe 2025, l'azienda parla molto della sua visione di cos'è e come dovrebbe essere usata l'intelligenza artificiale: è uno strumento che va sempre adoperato dalle persone, che devono rimanere responsabili dei processi all'interno dell'azienda. Non è un giocattolo con cui sperimentare, ma un aiuto per superare le sfide di business più importanti
Polestar 3 Performance, test drive: comodità e potenza possono convivere
Polestar 3 Performance, test drive: comodità e potenza possono convivere
Abbiamo passato diversi giorni alla guida di Polestar 3, usata in tutti i contesti. Come auto di tutti i giorni è comodissima, ma se si libera tutta la potenza è stupefacente
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 10-09-2008, 10:43   #1
Mattiatn
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++ se non in qualche passaggio semplice, vi sarei estremamente grato se mi potrete aiutare. Grazie mille.
Mattiatn è offline   Rispondi citando il messaggio o parte di esso
Old 10-09-2008, 18:32   #2
Vincenzo1968
Bannato
 
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
Quote:
Originariamente inviato da Mattiatn Guarda i messaggi
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++ se non in qualche passaggio semplice, vi sarei estremamente grato se mi potrete aiutare. Grazie mille.
Ciao Mattia,

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?
Vincenzo1968 è offline   Rispondi citando il messaggio o parte di esso
Old 11-09-2008, 09:46   #3
Mattiatn
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
Mattiatn è offline   Rispondi citando il messaggio o parte di esso
Old 12-09-2008, 02:00   #4
Vincenzo1968
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
l'output è:

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.
Vincenzo1968 è offline   Rispondi citando il messaggio o parte di esso
Old 12-09-2008, 07:57   #5
Mattiatn
Member
 
Iscritto dal: Jul 2006
Messaggi: 64
Grazie mille, adesso lo provo.
Spero che non sei stato sveglio fino alle 2 per me!
Mattiatn è offline   Rispondi citando il messaggio o parte di esso
Old 12-09-2008, 22:02   #6
71104
Bannato
 
L'Avatar di 71104
 
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
Quote:
Originariamente inviato da Vincenzo1968 Guarda i messaggi
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
l'output è:

Codice:
array[0][0] -> 2.025e+012
array[1][2] -> 5.12548e-012
Codice:
[cut per pietà]
ammazza che porcata, hai reinventato circa una dozzina di ruote implementando in C++ una macchina a stati e perdipiù facendo uso della libreria di I/O del C

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;
}
71104 è offline   Rispondi citando il messaggio o parte di esso
Old 12-09-2008, 22:09   #7
Vincenzo1968
Bannato
 
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
Quote:
Originariamente inviato da 71104 Guarda i messaggi
ammazza che porcata, hai reinventato circa una dozzina di ruote implementando in C++ una macchina a stati e perdipiù facendo uso della libreria di I/O del C

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?
...
Porcata? Dipende.
La tua implementazione è una porcata dal punto di vista delle prestazioni.
Vogliamo provare a confrontare i tempi su file di grosse dimensioni?
Vincenzo1968 è offline   Rispondi citando il messaggio o parte di esso
Old 12-09-2008, 22:33   #8
Vincenzo1968
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
a cosi:

Codice:
2.025e+12 3.125e-15 2.125e-5
1.0125e-10 2.ciao 5.12548e-12
La mia implementazione restituisce il seguente messaggio di errore:

Errore stato S4 riga 1 colonna 1

La tua breve(nonché intelligente) applicazione, si blocca
Vincenzo1968 è offline   Rispondi citando il messaggio o parte di esso
Old 13-09-2008, 00:38   #9
Vincenzo1968
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 primo è un file che contiene 1.000 righe e 365 colonne di numeri double nel formato scientifico. 0.82 secondi contro 0.28 secondi.
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?
Vincenzo1968 è offline   Rispondi citando il messaggio o parte di esso
Old 13-09-2008, 01:19   #10
slartibartfast
Senior Member
 
L'Avatar di slartibartfast
 
Iscritto dal: May 2005
Messaggi: 564
Quote:
Originariamente inviato da Vincenzo1968 Guarda i messaggi
Ho preso i tempi di esecuzione:



cut
Ti si legge “” dal path...

Ultima modifica di slartibartfast : 13-09-2008 alle 01:50.
slartibartfast è offline   Rispondi citando il messaggio o parte di esso
Old 13-09-2008, 01:28   #11
Vincenzo1968
Bannato
 
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
Quote:
Originariamente inviato da slartibartfast Guarda i messaggi
Ti si legge “coglione” dal path...
oops non me n'ero accorto.
Grazie per la segnalazione, provvedo subito
Vincenzo1968 è offline   Rispondi citando il messaggio o parte di esso
Old 13-09-2008, 03:27   #12
Vincenzo1968
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.
Vincenzo1968 è offline   Rispondi citando il messaggio o parte di esso
Old 13-09-2008, 09:36   #13
cionci
Senior Member
 
L'Avatar di cionci
 
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.
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 13-09-2008, 09:38   #14
cionci
Senior Member
 
L'Avatar di cionci
 
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.
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 13-09-2008, 09:38   #15
Mattiatn
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!!
Mattiatn è offline   Rispondi citando il messaggio o parte di esso
Old 13-09-2008, 09:59   #16
cionci
Senior Member
 
L'Avatar di cionci
 
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;
}
Poi per le prestazioni: si possono sempre aumentare se ce n'è bisogno.

Per i tab e i doppi spazi non ti devi preoccupare, almeno nel mio caso li salta tutti.
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 16-09-2008, 09:26   #17
Vincenzo1968
Bannato
 
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
Quote:
Originariamente inviato da cionci Guarda i messaggi
In C++ lo farei così:
...
Poi per le prestazioni: si possono sempre aumentare se ce n'è bisogno.

Per i tab e i doppi spazi non ti devi preoccupare, almeno nel mio caso li salta tutti.
Ohé Cionci,

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;
}
È abbastanza C++-Like e Object-Oriented?

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;
}
Questo è il risultato:



Sfido chiunque a ottenere gli stessi tempi, in puro C++, con fstream e vector
Vincenzo1968 è offline   Rispondi citando il messaggio o parte di esso
Old 16-09-2008, 09:46   #18
banryu79
Senior Member
 
L'Avatar di banryu79
 
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
Quote:
Originariamente inviato da Vincenzo1968 Guarda i messaggi
E per fortuna c'è anche chi la pensa diversamente sulle 'porcate' che scrivo:


http://www.democritos.it:8888/O-sesame/chngview?cn=6026

Vorrei leggere le info puntate da quel link ma non riesco a raggiungerlo, il browser mi va in timeout mentre tenta di caricare la pagina.
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)
banryu79 è offline   Rispondi citando il messaggio o parte di esso
Old 16-09-2008, 09:51   #19
Vincenzo1968
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.
Vincenzo1968 è offline   Rispondi citando il messaggio o parte di esso
Old 16-09-2008, 10:46   #20
cionci
Senior Member
 
L'Avatar di cionci
 
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 Comunque mi sembra di aver letto che c'è il vincolo che le colonne sono massimo 365 e sono sempre in numero costante.

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;
}
Ovviamente ci potrebbe essere qualche errore a giro perché l'ho scritto direttamente nella finestra del browser e non l'ho provato a compilare.

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.
cionci è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


DJI Neo 2 in prova: il drone da 160 grammi guadagna il gimbal e molto altro DJI Neo 2 in prova: il drone da 160 grammi guada...
L'IA "seria" di Appian è diversa: inserita nei processi e rispetta dati e persone L'IA "seria" di Appian è divers...
Polestar 3 Performance, test drive: comodità e potenza possono convivere Polestar 3 Performance, test drive: comodit&agra...
Qualcomm Snapdragon X2 Elite: l'architettura del SoC per i notebook del 2026 Qualcomm Snapdragon X2 Elite: l'architettura del...
Recensione DJI Mini 5 Pro: il drone C0 ultra-leggero con sensore da 1 pollice Recensione DJI Mini 5 Pro: il drone C0 ultra-leg...
Piratare Battlefield 6? Davvero una pess...
Arriva Veeam Data Platform v13. Pi&ugrav...
Framework interrompe la vendita di RAM: ...
Tachyum inventa le memorie TDIMM: una nu...
Roborock Q7 TF+, il robot economico cost...
Osca rinasce: le auto dei fratelli Maser...
Hlpy, la tecnologia al servizio dell’ass...
Ericsson rilancia sul 5G Standalone: l’I...
Black Friday Amazon: arrivano i super-sc...
Seagate raggiunge 6,9 TB per piatto con ...
Samsung lancia la One Shot Challenge: co...
Dell: il passaggio da Windows 10 a Windo...
Black Friday Speaker: JBL, Bose, Sony, M...
Hai un router ASUS? La nuova falla in Ai...
SK hynix trasforma i chip HBM in snack: ...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 20:32.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Served by www3v