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 output

Changed lines 1-62 from:
(:title Esportare tabelle in C++ :)
%titolo%''':: 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->Utenti
.SCP-SigleChePassione]] è 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

Attach
:importazione-csv.jpg

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:)
%titolo%''':: 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:"'':

%bgcolor=yellow%log.txt
www.donnebiotte.it 234
ftp.ilsitodeipornazzi.com 1982
www.alfredocimangia.com 9
www.cheballefscanf.com 9999

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

Ecco a voi la soluzione, con commenti finali

%bgcolor=yellow%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' '%s' '%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 %bgcolor=yellow%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:
[[!Programmazione]]
to:
[[Torna al Laboratorio di C->Uni.LaboratorioC]] | [[!Programmazione]]
Changed lines 1-142 from:
(:title Gruppi di Scansione:)
%titolo%''':: 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:"'':

%bgcolor=yellow%log.txt
www.donnebiotte.it 234
ftp.ilsitodeipornazzi.com 1982
www.alfredocimangia.com 9
www.cheballefscanf.com 9999

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

Ecco a voi la soluzione, con commenti finali

%bgcolor=yellow%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' '%s' '%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 %bgcolor=yellow%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++ :)
%titolo%''':: 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->Utenti
.SCP-SigleChePassione]] è 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

Attach
:importazione-csv.jpg

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:
[[Torna al Laboratorio di C->Uni.LaboratorioC]] | [[!Programmazione]]
to:
[[!Programmazione]]
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) {
Changed line 143 from:
[[!Programmazione]] | [[!UniCrema]]
to:
[[Torna al Laboratorio di C->Uni.LaboratorioC]] | [[!Programmazione]]
Added line 3:
Added line 2:
%titolo%''':: Gruppi di Scansione ::'''
Changed line 141 from:
[[!Programmazione]] | [[!C]]
to:
[[!Programmazione]] | [[!UniCrema]]
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:"'':

%bgcolor=yellow%log.txt
www.donnebiotte.it 234
ftp.ilsitodeipornazzi.com 1982
www.alfredocimangia.com 9
www.cheballefscanf.com 9999

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

Ecco a voi la soluzione, con commenti finali

%bgcolor=yellow%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' '%s' '%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 %bgcolor=yellow%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]]