Manipolazione dati in C++
CSV
Un testo in formato CSV (comma separated values) consiste in testo semplice che però è formattato in modo tale da rappresentare informazioni in maniera tabellare.
Ogni riga rappresenta un insieme di informazioni tra loro collegate che insieme costituiscono un record. All’interno della riga, i singoli dati del record sono separati da virgole1 . Questi singoli dati sono chiamati campi.
Qui un esempio:
John,Doe,120 jefferson st.,Riverside, NJ, 08075
Jack,McGinnis,220 hobo Av.,Phila, PA,09119
John,Da Man,Repici,120 Jefferson St.,Riverside, NJ,08075
Stephen,Tyler,7452 Terrace At the Plaza road,SomeTown,SD, 91234
Joan the bone,Anne,9th at Terrace plc,Desert City,CO,00123
Riassumendo ogni riga rappresenta un record (in questo caso il record anagrafico di una persona) ed ogni elemento della riga racchiuso tra virgole è chiamato campo (in questo caso nome, cognome, indirizzo, ecc,).
Per poter gestire queste informazioni in C++ possiamo usare la funzione Strtok che ci permette di separare sia le righe (carattere “\n”) che le colonne (“,”).
Strtok quando estrae una sottostringa da una stringa di input (ad esempio una frase, un testo, un csv, ecc.) non ha modo di conoscerne la lunghezza se non durante l’esecuzione perché la sua attività consiste proprio nel cercare di estrarre tutti i caratteri fino al separatore indicato. Per questa ragione, non può restituire un array a lunghezza fissa (char[][]) ma un puntatore a char (char*).
Tuttavia per poter memorizzare un csv una struttura adatta è quella invece di una matrice (dove ogni riga è quindi un char[][]). Per risolvere il problema è sufficiente quindi copiare ogni token estratto nell’array. Qui un esempio di codice che estrae tutte le righe.
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
char csv[]="John,Doe,120 jefferson st.,Riverside, NJ, 08075\nJack,McGinnis,220 hobo Av.,Phila, PA,09119\nJohn,Da Man,Repici,120 Jefferson St.,Riverside, NJ,08075\nStephen,Tyler,7452 Terrace At the Plaza road,SomeTown,SD, 91234\nJoan the bone,Anne,9th at Terrace plc,Desert City,CO,00123";
char *token;
char rows[5][200]; // definiamo una riga sufficientemente grande di 200 caratteri
int i=0;
token = strtok(csv, "\n"); // prima estrazione
while (token != NULL) { // se non nullo si ripete
strcpy(rows[i], token); // copiamo il char* in un char[]
i++; // incrementiamo la riga
token = strtok(NULL, "\n"); // nuova estrazione
}
for (int i=0; i<5; i++) {
cout << i << ": " << rows[i] << endl;
}
return 0;
}
Dato il codice dell’esempio separarlo in colonne e memorizzare il risultato in una matrice di stringhe (quindi char[][][]) dove quindi prima (come nell’esempio) sono estratte le righe e poi sono estratte le colonne.
Magazzino
Dato un CSV come il seguente:
nome, categoria, prezzo, quantità
pane, alimenti, 2, 108
latte, alimenti, 1, 89
detersivo, casalinghi, 2, 53
a) Leggere la stringa CSV e produrre una matrice contenente i valori.
b) Scrivere un CSV che contiene le seguenti colonne: nome, categoria, valore dove valore
indica il valore totale (prezzo * quantità)
Ad esempio:
nome, categoria, valore
pane, alimenti, 216
latte, alimenti, 89
detersivo, casalinghi, 106
- o meglio la virgola è il separatore più diffuso, ma talvolta vengono usati altri caratteri come ;:- ecc ↩︎