Risolto Prendere in input dati da file csv

enk17

Utente Bronze
23 Ottobre 2021
69
17
8
37
Salve sto scrivendo un codice che calcola un codice fiscale, il mio problema è che quando devo prendere il Codice del comune (quattro caratteri) da un file csv che è scritto in questo modo
ABBADIA CERRETO;A004
non so come scrivere che una volta trovato la riga della città prenda in input il codice che si trova dopo il ; ho provato in tutti i modi che conosco e anche cercato online ma non capisco o non funziona.

Questo è il codice
C++:
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <algorithm>

using namespace std;
string file_content();

int main()
{
    char a_mesi[12] = {'A', 'B', 'C', 'D', 'E', 'H', 'L', 'M', 'P', 'R', 'S', 'T'};
    char vocale_cognome,vocale_nome;
    int len_cognome, len_nome,mese;
    string nome,cognome,anno,result,data, giorno,codice_comune,provincia,citta;
    string database = file_content();
    bool femmina = false;
    int len_database = database.size();


    cout << "inserisci il tuo nome ";
    cin >> nome;
    cout << "inserisci il tuo cognome ";
    cin >> cognome;
    cout << "inserisci il giorno in cui sei nato ";
    cin >> giorno;
    cout << "inserisci il mese in cui sei nato ";
    cin >> mese;
    mese = mese-1;
    cout << "inserisci l'anno in cui sei nato ";
    cin >> anno;
    cout << "In che provincia sei nato? ";
    cin >> provincia;
    cout << "in che città sei nato? ";
    cin >> citta;
    int verifica;
    cout << "Se sei maschio digita 0 altrimenti digita 1 ";
    cin >> verifica;
    if (verifica == 1)
    {
        femmina = true;
    }

    len_nome = nome.size();
    len_cognome = cognome.size();
    for (int j = 0; j < len_cognome; j++)
    {
        if(cognome[j] == 'a' || cognome[j] == 'e' || cognome[j] == 'i' || cognome[j] == 'o' || cognome[j] == 'u' || cognome[j] == 'A' || cognome[j] == 'E' || cognome[j] == 'I' || cognome[j] == 'O' || cognome[j] == 'U')
        {
            vocale_cognome = cognome[j];
            cognome.erase(j, 1);
            len_cognome--;
            j--;
        }
    }
    for (int j = 0; j < len_nome; j++)
    {
        if (nome[j] == 'a' || nome[j] == 'e' || nome[j] == 'i' || nome[j] == 'o' || nome[j] == 'u' || nome[j] == 'A' || nome[j] == 'E' || nome[j] == 'I' || nome[j] == 'O' || nome[j] == 'U')
        {
            vocale_nome = nome[j];
            nome.erase(j, 1);
            len_nome--;
            j--;
        }
    }
    anno.erase(0, 2);
    int app = stoi(giorno);
    if (femmina == true)
    {
        app = app + 40;
        data = app;
    }
    else {
        data = giorno;
    }


    }
    result = cognome + vocale_cognome+nome+anno+a_mesi[mese]+data;
    cout << result;
    return 0;
}


string file_content()
{
    // filestream variables
    fstream file;
    string filename;

    // we declare filename which corresponds to the file we want to open
    filename = "lista-codici.txt";

    //open the file
    file.open(filename.c_str());

    // create a stringstream
    stringstream buffer;

    //passes the file buffer to the stringstream
    buffer << file.rdbuf();

    //reading the file
    return buffer.str();

}
 
Quindi dovrei scrivere
C++:
getline(citta,database,";")

 
Ultima modifica:

ci sto provando ma restituisce sempre errore con getline, ho fatto anche dei test per vedere se leggeva correttamente il file ed lo legge.
C++:
    if (database.find(citta) != string::npos) 
    {
        cout << "la città è nel database!" << '\n';
    }else{
        cout << "non è presente nel database! ";
        return 0;
    }
 
Ciao @enk17 , non ho mai utilizzato file csv, ma per ogni riga del file potresti utilizzare questa tecnica, l'ho fatta ad hoc...è molto rozza, ma funziona:
C++:
// Procedura da iterare su ogni riga del file per selezionare caratteri dopo il punto e virgola.
vector <char> vettore;
    string frase = "Questa è una frase;ABCD";
     int len = frase.size();
     for (int i = 0; i < len; i++){
        if (frase[i] == ';'){
            for (int j = i+1; j < len; j++){
                //Aggiungo i valori dopo il punto e virgola dove mi servono, io ho scelto un vettore.
                vettore.push_back(frase[j]);
            }
        }
    }
 
  • Mi piace
Reazioni: enk17
Ultima modifica:
C++:
std::string GetCityCode(const std::string& city)
{
    std::string code, line;
    std::ifstream hFile;
    hFile.open("C:\\...\\lista_codici.csv");
    while (!hFile.eof())
    {
        std::getline(hFile, line);
        if (strnicmp(city.c_str(), line.c_str(), city.size()) == 0)
        {
            const char* sep = strrchr(line.c_str(), ';');
            if (sep != nullptr)
            {
                code = std::string(sep + 1);
                break;
            }
        }
    }
    hFile.close();
    return code;
}

// Esempi:
std::string codice = GetCityCode(citta);
std::string codice = GetCityCode("Roma");
if (codice.empty())
    std::cout << "Città non trovata";

Se usi Visual Studio o comunque MSVC rinomina strnicmp con _strnicmp.

EDIT: avevo dimenticato di chiudere l'handle del file dopo aver letto.
 
  • Mi piace
Reazioni: enk17
perfavore mi potresti spiegare cosa fa questo if?

Certamente, strnicmp è una funzione standard di C (e C++), nella libc le funzioni legate alle stringhe hanno nel nome dei caratteri che le differenziano: la funzione base di comparazione tra due stringhe è strcmp che le confronta interamente e se sono uguali ritorna 0, nella variante che ho usato ci sono la n e la i, dove la prima indica che deve comparare solo i primi N caratteri (il terzo parametro) e la i sta per case insensitive cioè che ignora differenze tra maiuscole e minuscole. In questo modo comparo i primi N caratteri dalla riga che leggo dal file (nella variabile line) con la stringa passata da parametro di cui si cerca il codice (variabile city). Appena l'inizio di una riga combacia con la ricerca si cerca il carattero punto e virgola con strchr che ritorna un puntatore al carattere ; e a quel punto si ritorna il codice corrispondente alla città che inizia dal carattere dopo quel puntatore (sep + 1).
 
  • Mi piace
Reazioni: enk17
C++:
std::string GetCityCode(const std::string& city)
{
    std::string code, line;
    std::ifstream hFile;
    hFile.open("C:\\...\\lista_codici.csv");
    while (!hFile.eof())
    {
        std::getline(hFile, line);
        if (strnicmp(city.c_str(), line.c_str(), city.size()) == 0)
        {
            const char* sep = strrchr(line.c_str(), ';');
            if (sep != nullptr)
            {
                code = std::string(sep + 1);
                break;
            }
        }
    }
    hFile.close();
    return code;
}

// Esempi:
std::string codice = GetCityCode(citta);
std::string codice = GetCityCode("Roma");
if (codice.empty())
    std::cout << "Città non trovata";

Se usi Visual Studio o comunque MSVC rinomina strnicmp con _strnicmp.

EDIT: avevo dimenticato di chiudere l'handle del file dopo aver letto.
@JunkCoder , voglio diventare un tuo adepto! 😂 Stima assoluta.
 
  • Geniale
Reazioni: enk17
Certamente, strnicmp è una funzione standard di C (e C++), nella libc le funzioni legate alle stringhe hanno nel nome dei caratteri che le differenziano: la funzione base di comparazione tra due stringhe è strcmp che le confronta interamente e se sono uguali ritorna 0, nella variante che ho usato ci sono la n e la i, dove la prima indica che deve comparare solo i primi N caratteri (il terzo parametro) e la i sta per case insensitive cioè che ignora differenze tra maiuscole e minuscole. In questo modo comparo i primi N caratteri dalla riga che leggo dal file (nella variabile line) con la stringa passata da parametro di cui si cerca il codice (variabile city). Appena l'inizio di una riga combacia con la ricerca si cerca il carattero punto e virgola con strchr che ritorna un puntatore al carattere ; e a quel punto si ritorna il codice corrispondente alla città che inizia dal carattere dopo quel puntatore (sep + 1).
Grazie mille!