2

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 << "\t\t\t *** 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;
}
Jogofus
  • 765
  • 3
  • 15
  • 27
  • Estas comparando `char *` con `char *` por lo que `busqueda != linea` siempre será `true`... Y el operador `||` dentro del `while` va a continuar mientras sea verdadero, independientemente de si `!archivo.eof()` es falso... En adición, ¿Por qué no utilizar `string` en vez de `char *`? – NaCl Apr 04 '17 at 20:40
  • Creo que ya lo tengo solucionado. Era a la hora de comparar, que con getline añadia lo que queria buscar al string (en el caso que he subido aqui, el char) de tal forma que siempre comparaba un string con un string vacio... – Jogofus Apr 04 '17 at 20:45
  • 3
    Si has encontrado la respuesta te agradecería que te autorespondas y marques dicha respuesta como correcta. – eferion Apr 05 '17 at 06:47
  • Dije que creia que la habia encontrado, pero no.. A la hora de leer el fichero, solo compara la primera linea.. – Jogofus Apr 07 '17 at 18:28
  • Me he dado cuenta de que con getline() no me coge los saltos de linea del documento. Si tengo un documento tipo: "Nombre | Apellido" en varias lineas, si leo con getline me lo toma todo como una misma linea... – Jogofus Apr 08 '17 at 00:22

1 Answers1

0

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 << "\n\n\nLOGIN CORRECTO";
            }
            else
            {
                std::cout << "\n\nLogin 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í).

PaperBirdMaster
  • 44,474
  • 6
  • 44
  • 82