Reading files in c ++

5

I have a Store class with a method to read users of a file:

 void Store::leerUsuarios(const string &nombreFichero){
 ifstream fichero;
 fichero.open(nombreFichero);
 if (fichero.is_open()) {
    string nom, mail, contrasenya;

    while (!fichero.eof()) {
        fichero >> nombre;
        fichero >> mail;
        fichero >> contrasenya;

        usuarios[m_numUsuarios].setUsuarios(nombre, mail, contrasenya);
        m_numUsuarios++;
         }
    fichero.close();
     }
 }

So, I have a .txt file with this:

USUARIO_NOM_1 USER_MAIL_1 USER_CONTRASENYA_1 USUARIO_NOM_2 USER_MAIL_2 USER_CONTRASENYA_2 USER_NOM_3 USER_MAIL_3 USER_CONTRASENYA_3 USER_NOM_4 USER_MAIL_4 USER_CONTRASENYA_4

The problem is that when I read it, when you finish reading user 4, you re-enter the while (! file.eof ()), should not you exit since you have finished reading it?

    
asked by Chariot 26.05.2018 в 02:17
source

2 answers

4

There is a nuance that stands out in std::ifstream::eof , this function will only return true after you have read the end of file mark but it does not indicate that the next reading is going to be the end of file.

That is why, after reading the user 4, he re-enters the loop, because at that moment he tries to read content from the file and can not, only then considers that he has reached the end of the file and in the next round the call to std::ifstream::eof returns true .

A possible solution is the one proposed by Triztian , another solution could be to take advantage of std::ifstream is convertible to boolean and that will be converted to false after a failed reading to write something like this:

while ((fichero >> nombre) && (fichero >> mail) && (fichero >> contrasenya)) {
    usuarios[m_numUsuarios].setUsuarios(nombre, mail, contrasenya);
    m_numUsuarios++;
}

If the reading fichero >> nombre fails due to lack of data, leaving the ifstream in an incorrect state, the conversion to boolean will return false and besides that the rest of the readings will not be made, will not enter the loop.

    
answered by 28.05.2018 / 07:41
source
3

try this, use sstream (streams of strings) to process each line:

#include <set>
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>

struct usuario {
    std::string nombre;
    std::string mail;
    std::string password;
};

// sobrecargar el operador "<" para que el struct se 
// pueda utilizar en el conjunto 'std::set<usuario>'
inline bool operator<(const usuario& x, const usuario& y) {
    return x.mail < y.mail && x.nombre < y.nombre;
}

// declarar el prototipo de la funcion
std::set<usuario> leerFichero(const std::string&);

int main(int argc, char **argv) {

    if (argc < 2) {
        std::cout << "ERROR: file path missing" << std::endl;
        return 1;
    }

    std::set<usuario> usuarios = leerFichero(std::string(argv[1]));

    std::cout << "Numero Usuarios: " << usuarios.size() << std::endl;

    for (auto user : usuarios) {
        std::cout << "Nombre: " << user.nombre << std::endl;
        std::cout << "Mail: " << user.mail << std::endl;
        std::cout << std::endl;
    }

    return 0;
}

/**
 * leerFichero recibe la ruta completa de un fichero a leer, cada
 * linea del ficher contiene 3 campos delimitados por espacios, siendo
 * estos 'nombre', 'mail' y 'contraseña'.
 * Si el fichero no puede ser abierto, regresa un conjunto vacío.
 */
std::set<usuario> leerFichero(const std::string& nombreFichero) {

    std::ifstream fichero;

    fichero.open(nombreFichero);

    std::set<usuario> usuarios;

    if (!fichero.is_open()) {
        return usuarios;
    }

    std::string line;
    while (std::getline(fichero, line)) {

        // saltarse la linea si esta vacía
        if ( line == "" ) {
            continue;
        }

        std::istringstream linestream(line);

        usuario *user = new usuario();

        linestream >> user->nombre;
        linestream >> user->mail;
        linestream >> user->password;

        usuarios.insert(*user);
    }

    fichero.close();

    return usuarios;
}
    
answered by 26.05.2018 в 09:40