Lectura linea a linea de archivo .txt

publicado por: Anonymous

Estoy intentando leer un archivo .txt mediante C++, en el que el usuario introduce (en este caso un “usuario” y una “pass”) dos datos, y que cuando los compare, si estan los dos, imprima por pantalla un tipo “Login correcto”. El codigo es el siguiente:

#include <iostream>
#include <fstream>
#include <cstring>

using namespace std;

int main(){
    ifstream archivo("user.txt");

    //Obtencion de datos
    cout << "Usuario: ";
    char user[25];
    cin.getline(user,25,'n');

    cout << "Pass: ";
    char pass[25];
    cin.getline(pass,25,'n');

    //Creacion de la linea a buscar
    char busqueda[100];
    strcpy(busqueda, user);
    strcat(busqueda, " ");
    strcat(busqueda, pass);

    char linea[100];
    while(!archivo.eof() || busqueda != linea){
        for(int i = 0; i!=archivo.eof(); i++){
            archivo.getline(linea, 100);
        }
    }

    cout << endl << endl << "LOGIN CORRECTO." << endl << linea; 

    return 0;
}

El problema es que una vez que introduce los dos datos, se queda en un bucle infinito en el que no hace nada. Puedes estar dandole intro todo el rato que no sale de ahi…

Haciendo más pruebas, he llegado al siguiente codigo. Lo unico es que solo compara con la primera linea del archivo.

#include <iostream>
#include <fstream>
#include <cstdlib>

using namespace std;

struct registro{
    string name;
    string second;
    string street;
    string user;
    string pass;
} usuario;

void registroUsuario(){
    ofstream archivo("registro.txt");
    archivo << "----------------------" << endl;
    archivo << "Nombre: " << usuario.name << endl;
    archivo << "Apellido: " << usuario.second << endl;
    archivo << "Direccion: " << usuario.street << endl;
    archivo << "Usuario: " << usuario.user << endl;
    archivo << "Password: " << usuario.pass << endl;
    archivo.close();
}

void registroLogin(){
    ofstream archivo("usuarios.txt");
    archivo << usuario.user;
    archivo << " ";
    archivo << usuario.pass;
    archivo << "n";
    archivo.close();
}

bool login(string usuario, string password){
    ifstream archivo("usuarios.txt");
    string busqueda = usuario + " " + password;
    string linea;
    while(!archivo.eof()){
        getline(archivo, linea);
        if(linea == busqueda){
            return true;
        }
        else{
            return false;
        }
    }
}

int main(){
    menu:
        cout << "ttt *** Base de datos ***" << endl << endl;
        cout << "1. Registro de usuario" << endl;
        cout << "2. Login" << endl;
        cout << "0. Salir" << endl << endl;

        cout << "Escoge una opcion: ";
        int option;
        cin >> option;
        cin.ignore();
        cout << endl << endl;
        system("pause");

        switch(option){
            case 1:{
                system("cls");
                cout << "Nombre: ";
                getline(cin, usuario.name);
                cout << endl << "Apellido: ";
                getline(cin, usuario.second);
                cout << endl << "Direccion: ";
                getline(cin, usuario.street);
                cout << endl << endl << "Nombre de usuario: ";
                getline(cin, usuario.user);
                cout << endl << "Password: ";
                getline(cin, usuario.pass);

                registroUsuario();
                registroLogin();
                cout << endl << endl;
                system("pause");
                goto menu;
                break;
            }
            case 2:{
                system("cls");
                cout << "Usuario: ";
                getline(cin, usuario.user);
                cout << endl << "Password: ";
                getline(cin, usuario.pass);

                if(login(usuario.user, usuario.pass) == true){
                    goto login;
                }
                else{
                    cout << endl << endl << "Login incorrecto.";
                    goto menu;
                }
                break;
            }
        }
    login:
        cout << endl << endl << endl << "LOGIN CORRECTO";


    return 0;
}

solución

No es necesario reinventar la rueda para esto, puedes almacenar tus objetos de tipo registro en un std::map indexado por nombre:

struct registro{
    std::string name;
    std::string second;
    std::string street;
    std::string user;
    std::string pass;
};

std::map<std::string, registro> registros;

Te aconsejo crear una función que guarde registros en archivo:

void guardar_registro(const registro &un_registro)
{
    // Abrir el archivo para agregar datos al final del mismo
    if (std::ofstream user{"user.txt", std::ios_base::app})
    {
        user << un_registro.name   << 'n'
             << un_registro.second << 'n'
             << un_registro.street << 'n'
             << un_registro.user   << 'n'
             << un_registro.pass   << 'n';
    }
}

Y otra que lea el archivo y rellene el mapa de registros:

std::map<std::string, registro> leer_registros()
{
    std::map<std::string, registro> resultado;

    if (std::ifstream user{"user.txt"})
    {
        registro nuevo_registro{};

        while (
               std::getline(user, nuevo_registro.name)   &&
               std::getline(user, nuevo_registro.second) &&
               std::getline(user, nuevo_registro.street) &&
               std::getline(user, nuevo_registro.user)   &&
               std::getline(user, nuevo_registro.pass)) {
            resultado.insert(nuevo_registro.user, nuevo_registro);
        }
    }

    return resultado;
}

De esta manera, es fácil verificar si un usuario existe y su contraseña coincide, delegando en la función std::map::find de map:

int main(){
    std::map<std::string, registro> registros = leer_registros();
    bool login = false;

    while (!login) {
        std::cout << "Usuario: ";
        std::string u;
        std::getline(std::cin, u);

        std::cout << "nPassword: ";
        std::string p;
        std::getline(std::cin, p);

        auto usuario_existe = registros.find(u);
        if ( (login = (usuario_existe != registros.end())) )
        {
            if ( (login = (usuario_existe->second.pass == p)) )
            {
                std::cout << "nnnLOGIN CORRECTO";
            }
            else
            {
                std::cout << "nnLogin incorrecto.";
            }
        }
    }

    return 0;
}

La función std::getline lee líneas completas y devuelve el flujo (“stream“) que realizó la lectura, este flujo tiene un operador de conversión a booleano que, si el flujo está en estado correcto, devolverá verdadero (más detalles aquí).

Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *