cerca
Gruppi di Scansione
modifica cronologia stampa login logout

Wiki

UniCrema


Materie per semestre

Materie per anno

Materie per laurea


Help

Return to Gruppi di Scansione  (Edit)

Uni.GruppiDiScansione History

Hide minor edits - Show changes to markup

Changed lines 1-62 from:

(:title Esportare tabelle in C++ :)

 :: Esportare tabelle in C++ ::

File CSV

Il CSV è un file di testo concepito per poter rappresentare in modo semplice dei dati in forma tabulare. La sigla è illuminante: CSV sta infatti per Comma Separated Values, ovvero valori separati da una virgola, il che è sostanzialmente l'unica particolarità del formato.

In un file CSV i campi dei dati (che in un foglio di calcolo saranno rappresentati all'interno di celle) sono separati da una virgola, o da altri simboli da concordare all'apertura del file. Mettendo i dati tra virgolette si può utilizzare il delimitare di campo anche al loro interno.

Ma facciamo un esempio velocissimo. Dobbiamo tradurre come testo la seguente tabella:

(:table width=90% border=0 cellpadding=5 cellspacing=0 align=center:) (:cellnr bgcolor=#d9e4f2 align=center:) Giorno (:cell:) Mese (:cell:) Anno (:cellnr:) 14 (:cell:) Ottobre (:cell:) 2006 (:cellnr:) 25 (:cell:) Novembre (:cell:) 2007 (:tableend:)

In .csv diventerà:

Giorno,Mese,Anno
14,Ottobre,2006
25,Novembre,2007

Ricapitolando, per rappresentare una tabella in CSV con le , (o altro simbolo concordato) si indicano le colonne, con gli "a capo" le righe.

Come creare un file CSV in C++

Beh, abbiamo appena detto che un CSV è sostanzialmente un file di testo, quindi in C++ andrà creato come tale. Siamo tutti capaci di farlo, no? Nel caso, facciamo un esempio semplice semplice:

#include <stdio.h>
#include <stdlib.h>

//crea una tabella di due colonne con le potenze di 2 e di 3
int main()
{
   int i;
   FILE *Fp_out;

   Fp_out = fopen("potenze.csv", "w");

   fprintf(Fp_out, "Potenze 2, Potenze 3\n"); //intestazione

   for(i=0;i<=10;i++)
      fprintf(Fp_out, "%d, %d\n", 2*i, 3*i);

   fflush(Fp_out);
   fclose(Fp_out);
   return 0;
}

Come aprirlo

L'esecuzione del programma sopra comporta la creazione di un file .csv. Con che programma lo apro? Dal momento che abbiamo fatto una tabella, la scelta più immediata è adoperare un foglio elettronico, ad esempio Calc della suite open-source OpenOffice. Ci apparirà questa schermata

che ci dà tra le altre cose la possibilità di selezionare il carattere di separazione dei campi di dati. Nel nostro caso lasciamo la virgola, premiamo Ok ed il gioco è fatto.

to:

(:title Gruppi di Scansione:)

 :: Gruppi di Scansione ::

Possa fscanf con tutti i suoi derivati morire nella Geenna! Sciagura su di essi per 7 generazioni!

In questa pagina affronto lo spinoso argomento della fscanf. Perché spinoso? E che ne so, l'aggettivo suonava bene.

Tutto nacque da un problema di Lorenzo: (immaginate la sua voce)
"Yuck! Ho un file di log come il seguente, e devo scansionarlo:":

 log.txt
 www.donnebiotte.it 234
 ftp.ilsitodeipornazzi.com 1982
 www.alfredocimangia.com 9
 www.cheballefscanf.com 9999

Voglio

  1. riconoscere il protocollo, cioè la parte prima del primo punto (www, ftp o quello che ci sarà)
  2. riconoscere il nome
  3. riconoscere l'estensione
  4. riconoscere il numero di visite

Ecco a voi la soluzione, con commenti finali

 gruppo.c
 #include <stdio.h>

 int main() {
	FILE * file;
	char tipo[10];
	char nome[20];
	char estensione[20];
	int valore;

	file = fopen("log.txt", "r");

	while (fscanf(file, "%[^.].%[^.].%[^ ] %d\n",tipo,nome,
                                                     estensione,&valore) !=EOF)   {	

		printf("'s' 'd'\n", tipo,nome,estensione,valore);
                /* etc. etc.*/
	}	

	fclose(file);

	return 0;
 }

Il gruppo di scansione

La riga

 fscanf(file, "%[^.].%[^.].%[^ ] %d\n",tipo,nome,estensione,&valore)

fa tutto il lavoro sporco.

Le parentesi quadre [ ] circondano un cosiddetto gruppo di scansione. Come dice il professore, è un setaccio. Tutto ciò che viene messo tra le quadre, viene letto. Non appena si trova qualche cosa che NON appartiene a ciò che è contenuto tra le quadre, la scansione si ferma.
Quindi, una riga come

 fscanf(file, "%[tetty]", stringa);

leggerà solo le stringhe che contengono una delle lettere contenute nella stringa tetty, come per esempio:

 tetty
 ttteeettttyyttytytttteee
 eeee
 yyyyyy

ma non

 tettamanzi

Non appena arriva alla prima a, la scansione si ferma.

Il gruppo di scansione invertito

Il gruppo di scansione funziona anche con l'accento circonflesso o quel diavolo che è, insomma, il ^, e vuol dire: "tutto ciò che NON è contenuto nelle quadre, va bene. Non appena trovi qualche cosa contenuto nelle parentesi quadre, fermati".

Quindi, la riga

 fscanf(file, "%[^abc]", stringa);

leggerà tutte le stringhe che NON contengono abc, cioè

 defghi
 lmnop
 dddfdssdljfljwer

ma non

 dario

Appena arriva alla a, si ferma, perché è contenuta nel gruppo di scansione.

Nel nostro caso, quindi, la parte

 %[^.].%[^.].%[^ ] %d\n

vuol dire esattamente:

  • Leggi tutto fino a che non trovi un punto, e mettilo nella prima variabile
  • Leggi il punto
  • Leggi quello che resta, fino al prossimo punto, e mettilo nella seconda variabile
  • Leggi il secondo punto
  • Leggi etc. terza variabile
  • Spazio
  • Leggi un intero e salvalo nella variabile
  • Leggi un ritorno a capo (un finelinea)

Credo sia chiaro.

Complichiamoci un poco la vita

Se avessi usato una fscanf così:

 fscanf(file, "%[^.]%*c%[^.]%*c%[^ ] %d\n", tipo,nome,estensione,&valore)

avrebbe funzionato ugualmente.

Il motivo è che ho introdotto una cosa diversa: il %*c. Ciò vuol dire "leggi un carattere e fregatene, e passa al resto", e il resto lo conosciamo già.

Quindi, %*d vuol dire "leggi un intero e fregatene", %*s fregatene della stringa e così via.

I valori di ritorno di fscanf

Nel file ho scritto:

 while(fscanf(...) != EOF) {

La fscanf ritorna

  • il numero di variabili correttamente lette
  • oppure EOF se ha finito il file

Nel nostro caso, quindi, avrei anche potuto scrivere

 while(fscanf(...) == 4) {

cioè, esegui il ciclo fintantoché fscanf legge correttamente 4 variabili per volta. E infatti avevo 4 variabili (andate sopra a vedere, se non ci credete).

Se avessimo trovato una riga, nel file log.txt, del tipo

 ...
 www.negroni.it
 ...

senza un numero dopo, fscanf avrebbe ritornato un 3, e il while avrebbe rilevato 3 != 4 e avrebbe terminato il ciclo.

Changed line 144 from:
to:
Changed lines 1-142 from:

(:title Gruppi di Scansione:)

 :: Gruppi di Scansione ::

Possa fscanf con tutti i suoi derivati morire nella Geenna! Sciagura su di essi per 7 generazioni!

In questa pagina affronto lo spinoso argomento della fscanf. Perché spinoso? E che ne so, l'aggettivo suonava bene.

Tutto nacque da un problema di Lorenzo: (immaginate la sua voce)
"Yuck! Ho un file di log come il seguente, e devo scansionarlo:":

 log.txt
 www.donnebiotte.it 234
 ftp.ilsitodeipornazzi.com 1982
 www.alfredocimangia.com 9
 www.cheballefscanf.com 9999

Voglio

  1. riconoscere il protocollo, cioè la parte prima del primo punto (www, ftp o quello che ci sarà)
  2. riconoscere il nome
  3. riconoscere l'estensione
  4. riconoscere il numero di visite

Ecco a voi la soluzione, con commenti finali

 gruppo.c
 #include <stdio.h>

 int main() {
	FILE * file;
	char tipo[10];
	char nome[20];
	char estensione[20];
	int valore;

	file = fopen("log.txt", "r");

	while (fscanf(file, "%[^.].%[^.].%[^ ] %d\n",tipo,nome,
                                                     estensione,&valore) !=EOF)   {	

		printf("'s' 'd'\n", tipo,nome,estensione,valore);
                /* etc. etc.*/
	}	

	fclose(file);

	return 0;
 }

Il gruppo di scansione

La riga

 fscanf(file, "%[^.].%[^.].%[^ ] %d\n",tipo,nome,estensione,&valore)

fa tutto il lavoro sporco.

Le parentesi quadre [ ] circondano un cosiddetto gruppo di scansione. Come dice il professore, è un setaccio. Tutto ciò che viene messo tra le quadre, viene letto. Non appena si trova qualche cosa che NON appartiene a ciò che è contenuto tra le quadre, la scansione si ferma.
Quindi, una riga come

 fscanf(file, "%[tetty]", stringa);

leggerà solo le stringhe che contengono una delle lettere contenute nella stringa tetty, come per esempio:

 tetty
 ttteeettttyyttytytttteee
 eeee
 yyyyyy

ma non

 tettamanzi

Non appena arriva alla prima a, la scansione si ferma.

Il gruppo di scansione invertito

Il gruppo di scansione funziona anche con l'accento circonflesso o quel diavolo che è, insomma, il ^, e vuol dire: "tutto ciò che NON è contenuto nelle quadre, va bene. Non appena trovi qualche cosa contenuto nelle parentesi quadre, fermati".

Quindi, la riga

 fscanf(file, "%[^abc]", stringa);

leggerà tutte le stringhe che NON contengono abc, cioè

 defghi
 lmnop
 dddfdssdljfljwer

ma non

 dario

Appena arriva alla a, si ferma, perché è contenuta nel gruppo di scansione.

Nel nostro caso, quindi, la parte

 %[^.].%[^.].%[^ ] %d\n

vuol dire esattamente:

  • Leggi tutto fino a che non trovi un punto, e mettilo nella prima variabile
  • Leggi il punto
  • Leggi quello che resta, fino al prossimo punto, e mettilo nella seconda variabile
  • Leggi il secondo punto
  • Leggi etc. terza variabile
  • Spazio
  • Leggi un intero e salvalo nella variabile
  • Leggi un ritorno a capo (un finelinea)

Credo sia chiaro.

Complichiamoci un poco la vita

Se avessi usato una fscanf così:

 fscanf(file, "%[^.]%*c%[^.]%*c%[^ ] %d\n", tipo,nome,estensione,&valore)

avrebbe funzionato ugualmente.

Il motivo è che ho introdotto una cosa diversa: il %*c. Ciò vuol dire "leggi un carattere e fregatene, e passa al resto", e il resto lo conosciamo già.

Quindi, %*d vuol dire "leggi un intero e fregatene", %*s fregatene della stringa e così via.

I valori di ritorno di fscanf

Nel file ho scritto:

 while(fscanf(...) != EOF) {

La fscanf ritorna

  • il numero di variabili correttamente lette
  • oppure EOF se ha finito il file

Nel nostro caso, quindi, avrei anche potuto scrivere

 while(fscanf(...) == 4) {

cioè, esegui il ciclo fintantoché fscanf legge correttamente 4 variabili per volta. E infatti avevo 4 variabili (andate sopra a vedere, se non ci credete).

Se avessimo trovato una riga, nel file log.txt, del tipo

 ...
 www.negroni.it
 ...

senza un numero dopo, fscanf avrebbe ritornato un 3, e il while avrebbe rilevato 3 != 4 e avrebbe terminato il ciclo.

to:

(:title Esportare tabelle in C++ :)

 :: Esportare tabelle in C++ ::

File CSV

Il CSV è un file di testo concepito per poter rappresentare in modo semplice dei dati in forma tabulare. La sigla è illuminante: CSV sta infatti per Comma Separated Values, ovvero valori separati da una virgola, il che è sostanzialmente l'unica particolarità del formato.

In un file CSV i campi dei dati (che in un foglio di calcolo saranno rappresentati all'interno di celle) sono separati da una virgola, o da altri simboli da concordare all'apertura del file. Mettendo i dati tra virgolette si può utilizzare il delimitare di campo anche al loro interno.

Ma facciamo un esempio velocissimo. Dobbiamo tradurre come testo la seguente tabella:

(:table width=90% border=0 cellpadding=5 cellspacing=0 align=center:) (:cellnr bgcolor=#d9e4f2 align=center:) Giorno (:cell:) Mese (:cell:) Anno (:cellnr:) 14 (:cell:) Ottobre (:cell:) 2006 (:cellnr:) 25 (:cell:) Novembre (:cell:) 2007 (:tableend:)

In .csv diventerà:

Giorno,Mese,Anno
14,Ottobre,2006
25,Novembre,2007

Ricapitolando, per rappresentare una tabella in CSV con le , (o altro simbolo concordato) si indicano le colonne, con gli "a capo" le righe.

Come creare un file CSV in C++

Beh, abbiamo appena detto che un CSV è sostanzialmente un file di testo, quindi in C++ andrà creato come tale. Siamo tutti capaci di farlo, no? Nel caso, facciamo un esempio semplice semplice:

#include <stdio.h>
#include <stdlib.h>

//crea una tabella di due colonne con le potenze di 2 e di 3
int main()
{
   int i;
   FILE *Fp_out;

   Fp_out = fopen("potenze.csv", "w");

   fprintf(Fp_out, "Potenze 2, Potenze 3\n"); //intestazione

   for(i=0;i<=10;i++)
      fprintf(Fp_out, "%d, %d\n", 2*i, 3*i);

   fflush(Fp_out);
   fclose(Fp_out);
   return 0;
}

Come aprirlo

L'esecuzione del programma sopra comporta la creazione di un file .csv. Con che programma lo apro? Dal momento che abbiamo fatto una tabella, la scelta più immediata è adoperare un foglio elettronico, ad esempio Calc della suite open-source OpenOffice. Ci apparirà questa schermata

che ci dà tra le altre cose la possibilità di selezionare il carattere di separazione dei campi di dati. Nel nostro caso lasciamo la virgola, premiamo Ok ed il gioco è fatto.

Changed line 64 from:
to:
Changed lines 37-38 from:
	while (fscanf(file, "%[^.].%[^.].%[^ ] %d\n",tipo,nome,estensione,&valore) !=EOF)   {	
to:
	while (fscanf(file, "%[^.].%[^.].%[^ ] %d\n",tipo,nome,
                                                     estensione,&valore) !=EOF)   {	
Added line 3:
Added line 2:
 :: Gruppi di Scansione ::
Changed line 141 from:
to:
June 06, 2007, at 09:53 PM by Ido - aggiunto il ^ nel gruppo di scansione di esempio "abc"
Changed lines 76-77 from:
 fscanf(file, "%[abc]", stringa);
to:
 fscanf(file, "%[^abc]", stringa);
Changed line 117 from:

I valori di ritorno di fscanf

to:

I valori di ritorno di fscanf

Changed line 71 from:

Il gruppo di scansione invertito

to:

Il gruppo di scansione invertito

Changed lines 71-72 from:

Il gruppo di scansione funziona con l'accento circonflesso o quel diavolo che è, insomma, il ^, e vuol dire: "tutto ciò che NON è contenuto nelle quadre, va bene. Non appena trovi qualche cosa contenuto nelle parentesi quadre, fermati".

to:

Il gruppo di scansione invertito

Il gruppo di scansione funziona anche con l'accento circonflesso o quel diavolo che è, insomma, il ^, e vuol dire: "tutto ciò che NON è contenuto nelle quadre, va bene. Non appena trovi qualche cosa contenuto nelle parentesi quadre, fermati".

Added lines 1-140:

(:title Gruppi di Scansione:)

Possa fscanf con tutti i suoi derivati morire nella Geenna! Sciagura su di essi per 7 generazioni!

In questa pagina affronto lo spinoso argomento della fscanf. Perché spinoso? E che ne so, l'aggettivo suonava bene.

Tutto nacque da un problema di Lorenzo: (immaginate la sua voce)
"Yuck! Ho un file di log come il seguente, e devo scansionarlo:":

 log.txt
 www.donnebiotte.it 234
 ftp.ilsitodeipornazzi.com 1982
 www.alfredocimangia.com 9
 www.cheballefscanf.com 9999

Voglio

  1. riconoscere il protocollo, cioè la parte prima del primo punto (www, ftp o quello che ci sarà)
  2. riconoscere il nome
  3. riconoscere l'estensione
  4. riconoscere il numero di visite

Ecco a voi la soluzione, con commenti finali

 gruppo.c
 #include <stdio.h>

 int main() {
	FILE * file;
	char tipo[10];
	char nome[20];
	char estensione[20];
	int valore;

	file = fopen("log.txt", "r");

	while (fscanf(file, "%[^.].%[^.].%[^ ] %d\n",tipo,nome,estensione,&valore) !=EOF)   {	

		printf("'s' 'd'\n", tipo,nome,estensione,valore);
                /* etc. etc.*/
	}	

	fclose(file);

	return 0;
 }

Il gruppo di scansione

La riga

 fscanf(file, "%[^.].%[^.].%[^ ] %d\n",tipo,nome,estensione,&valore)

fa tutto il lavoro sporco.

Le parentesi quadre [ ] circondano un cosiddetto gruppo di scansione. Come dice il professore, è un setaccio. Tutto ciò che viene messo tra le quadre, viene letto. Non appena si trova qualche cosa che NON appartiene a ciò che è contenuto tra le quadre, la scansione si ferma.
Quindi, una riga come

 fscanf(file, "%[tetty]", stringa);

leggerà solo le stringhe che contengono una delle lettere contenute nella stringa tetty, come per esempio:

 tetty
 ttteeettttyyttytytttteee
 eeee
 yyyyyy

ma non

 tettamanzi

Non appena arriva alla prima a, la scansione si ferma.

Il gruppo di scansione funziona con l'accento circonflesso o quel diavolo che è, insomma, il ^, e vuol dire: "tutto ciò che NON è contenuto nelle quadre, va bene. Non appena trovi qualche cosa contenuto nelle parentesi quadre, fermati".

Quindi, la riga

 fscanf(file, "%[abc]", stringa);

leggerà tutte le stringhe che NON contengono abc, cioè

 defghi
 lmnop
 dddfdssdljfljwer

ma non

 dario

Appena arriva alla a, si ferma, perché è contenuta nel gruppo di scansione.

Nel nostro caso, quindi, la parte

 %[^.].%[^.].%[^ ] %d\n

vuol dire esattamente:

  • Leggi tutto fino a che non trovi un punto, e mettilo nella prima variabile
  • Leggi il punto
  • Leggi quello che resta, fino al prossimo punto, e mettilo nella seconda variabile
  • Leggi il secondo punto
  • Leggi etc. terza variabile
  • Spazio
  • Leggi un intero e salvalo nella variabile
  • Leggi un ritorno a capo (un finelinea)

Credo sia chiaro.

Complichiamoci un poco la vita

Se avessi usato una fscanf così:

 fscanf(file, "%[^.]%*c%[^.]%*c%[^ ] %d\n", tipo,nome,estensione,&valore)

avrebbe funzionato ugualmente.

Il motivo è che ho introdotto una cosa diversa: il %*c. Ciò vuol dire "leggi un carattere e fregatene, e passa al resto", e il resto lo conosciamo già.

Quindi, %*d vuol dire "leggi un intero e fregatene", %*s fregatene della stringa e così via.

I valori di ritorno di fscanf

Nel file ho scritto:

 while(fscanf(...) != EOF) {

La fscanf ritorna

  • il numero di variabili correttamente lette
  • oppure EOF se ha finito il file

Nel nostro caso, quindi, avrei anche potuto scrivere

 while(fscanf(...) == 4) {

cioè, esegui il ciclo fintantoché fscanf legge correttamente 4 variabili per volta. E infatti avevo 4 variabili (andate sopra a vedere, se non ci credete).

Se avessimo trovato una riga, nel file log.txt, del tipo

 ...
 www.negroni.it
 ...

senza un numero dopo, fscanf avrebbe ritornato un 3, e il while avrebbe rilevato 3 != 4 e avrebbe terminato il ciclo.


Programmazione | C