Login e fstream

di il
8 risposte

Login e fstream

Ciao ragazzi, sto avendo problemi con una funzione per il login..
In pratica questa vede se esiste un file contenente i dati di login, se non esiste lo crea e va a scrivere i dati presi in input;
altrimenti, se è esiste il file, vengono richiesti i dati di accesso.
Adesso vi spiego il problema, se inserisco i dati correttamente, la funzione ritorna true, dovrebbe tornare nel main e terminare... invece mi genera un'eccezione e non capisco il perchè
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

struct userData // Struct da leggere/scrivere su file login
{
	string username; // Nome Utente
	string password; // Password
}userLogin;

bool login()
{
	system("cls");
	fstream loginFile; // Creo un file

	loginFile.open("Access.dat", ios::binary | ios::in); // Provo ad aprirlo in lettura
	if (!loginFile.is_open()) // Se non esiste
	{
		cout << "Registrazione\n\n";
		loginFile.open("Access.dat", ios::binary | ios::out); // Lo apro in scrittura
		cout << "Inserisci Username: ";
		getline(cin, userLogin.username); // Input Nome Utente nella Struct
		cout << "Inserisci Password: ";
		getline(cin, userLogin.password); // Input Password nella Struct
		loginFile.write((char*)&userLogin, sizeof(userData)); // Scrivo la struct nel file
		loginFile.close(); // Chiudo il file
		return false; // Ritorno false, in modo da far eseguire di nuovo la funzione
	}
	else // Se il file esiste
	{
		string user; // Nome Utente
		string pass; // Password
		cout << "Accedi\n\n";
		cout << "Inserisci Username: ";
		getline(cin, user); // Input Nome Utente
		cout << "Inserisci Password: ";
		getline(cin, pass); // Input Password
		loginFile.read((char*)&userLogin, sizeof(userData)); // Leggo un record dal file
		loginFile.close(); // Lo chiudo
		if (userLogin.username == user && userLogin.password == pass) // Se i dati presi in input sono uguali a quelli letti dal file
			return true; // Ritorna true
	}
}

int main()
{
	bool check;
	do
		check = login();
	while (!check);

	return 0;
}

8 Risposte

  • Re: Login e fstream

    Non puoi scrivere su un file binario degli oggetti string e poi rileggerli. L'oggetto sarà in uno stato non adeguato in quanto, le strutture interne punteranno ad aree non allocate attualmente. Non puoi operare in questo modo con gli oggetti del C++. Salva il contenuto (ovvero l'array di caratteri corrispondente) e non l'oggetto).
  • Re: Login e fstream

    Ciao, premetto che ho capito che l'oggetto string non è adatto alla scrittura/lettura nei file binari... quindi ho sostituito le string con dei char[]
    Il problema adesso è che, in fase di "login", nonostante i dati siano correti l'espressione di controllo mi viene valutata come falsa..
    if (userLogin.username == user && userLogin.password == pass)
    Il codice:
    #include <iostream>
    #include <fstream>
    #include <string>
    using namespace std;
    
    struct userData // Struct da leggere/scrivere su file login
    {
    	char username[25]; // Nome Utente
    	char password[25]; // Password
    }userLogin;
    
    bool login()
    {
    	system("cls");
    	fstream loginFile; // Creo un file
    
    	loginFile.open("Access.dat", ios::binary | ios::in); // Provo ad aprirlo in lettura
    	if (!loginFile.is_open()) // Se non esiste
    	{
    		cout << "Registrazione\n\n";
    		loginFile.open("Access.dat", ios::binary | ios::out); // Lo apro in scrittura
    		cout << "Inserisci Username: ";
    		cin.getline(userLogin.username, '\n'); // Input Nome Utente nella Struct
    		cout << "Inserisci Password: ";
    		cin.getline(userLogin.password, '\n'); // Input Password nella Struct
    		loginFile.write((char*)&userLogin, sizeof(userData)); // Scrivo la struct nel file
    		loginFile.close(); // Chiudo il file
    		return false; // Ritorno false, in modo da far eseguire di nuovo la funzione
    	}
    	else // Se il file esiste
    	{
    		char user[25]; // Nome Utente
    		char pass[25]; // Password
    		cout << "Accedi\n\n";
    		cout << "Inserisci Username: ";
    		cin.getline(user, '\n'); // Input Nome Utente
    		cout << "Inserisci Password: ";
    		cin.getline(pass, '\n'); // Input Password
    		loginFile.read((char*)&userLogin, sizeof(userData)); // Leggo un record dal file
    		loginFile.close(); // Lo chiudo
    		if (userLogin.username == user && userLogin.password == pass) // Se i dati presi in input sono uguali a quelli letti dal file
    			return true; // Ritorna true
    	}
    	return false;
    }
    
    int main()
    {
    	bool check;
    	do
    		check = login();
    	while (!check);
    	return 0;
    }
  • Re: Login e fstream

    Non puoi confrontare due char[] con ==

    Devi usare strcmp
  • Re: Login e fstream

    Giustissimo, avevo risolto ieri notte... avevo dimenticato questo particolare.
    Grazie mille!
  • Re: Login e fstream

    @ NewBie12_
    Anche se il quesito da risolvere era semplice, ci potrebbe essere qualcuno con meno eperienza, che magari non sa correggere il tuo codice con le info date. Sarebbe carino postare la soluzione funzionante anche per loro.
    Con le mie modeste conoscenze del C++, ho aggiunto al tuo codice la funzionalità segnaposto nella password, all'accesso invece della passw viene mostrato *****
    Per farlo ho usato getch(), contenuto nella controversa libreria <conio.h>.
    Ne approfitto per chiedere cosa ne pensate di questa libreria, e se non usata, come sopperire alle sue funzionalità.
    
    #include <iostream>
    #include <fstream>
    #include <string.h>
    #include <conio.h>
    
    #define inBuff 25 // lunghezza massima per gli input (se cambiato il file con le credenziali va ricreato)
    
    using namespace std;
    
    struct userData{ // Struct da leggere/scrivere su file login
    	char username[inBuff]; // Nome Utente
    	char password[inBuff]; // Password
    }userLogin;
    
    bool inputPassw(char *Pass){
        unsigned short _ascii = 0;
        unsigned int i = 0;
    next:
        do{
            _ascii = getch (); // lettura tastiera
            if (_ascii == 27) {cout<<endl; exit(0);} // Esc
            if (_ascii == 8) {cout<<endl; return false;}  // BackSpace
        }while ((_ascii<33 || _ascii>255) && _ascii != 13);
    
        if (_ascii != 13){ // non è invio
            if (i>inBuff-1) return false; // eccesso lunghezza
            cout<<"*"; // visualizzazione segnaposto
            Pass[i] = _ascii; // aggiunta carattere
            i++;
            goto next;
        }
        return true; // password composta
    }
    
    bool login(){
    	system("cls");
    	fstream loginFile; // Creo un file
    	loginFile.open("Access.dat", ios::binary | ios::in); // Provo ad aprirlo in lettura
    	if (!loginFile.is_open()){ // Se non esiste
    		cout << "Registrazione\n\n";
    		loginFile.open("Access.dat", ios::binary | ios::out); // Lo apro in scrittura
    		cout << "Inserisci Username: ";
    		cin.getline(userLogin.username, '\n'); // Input Nome Utente nella Struct
    		cout << "Inserisci Password: ";
    		cin.getline(userLogin.password, '\n'); // Input Password nella Struct
    		loginFile.write((char*)&userLogin, sizeof(userData)); // Scrivo la struct nel file
    		loginFile.close(); // Chiudo il file
    		return false; // Ritorno false, in modo da far eseguire di nuovo la funzione
    	}
    	else{ // Se il file esiste
            	char user[inBuff]; // Nome Utente
            	cout << "Accedi\n\n";
            	cout << "Inserisci Username: ";
            	cin.getline(user, '\n'); // Input Nome Utente
            	cout << "Inserisci Password: ";
            	char Pass[inBuff] = {0}; // Pass verrà modificato da inputPassw
            	bool res = inputPassw(Pass); // routine che mette gli asterischi
            	if (res == false) return false;
            	loginFile.read((char*)&userLogin, sizeof(userData)); // Leggo un record dal file
           		loginFile.close(); // Lo chiudo
            	if (strcmp(userLogin.username, user)==0 && strcmp(userLogin.password, Pass)==0) // Se i dati presi in input sono uguali a quelli letti dal file
                		return true; // Ritorna true
    	}
    	return false;
    }
    
  • Re: Login e fstream

    @Rubik .... evita i goto ...
  • Re: Login e fstream

    Perché controversa? getch() c'è anche in ncurses.h di Linux: con una #define sul sistema operativo decidi quale libreria includere e puoi usare lo stesso codice.
    Comunque penso che un programma da terminale sia più comodo scriverlo in C# se c'è la scelta.

    P.s.: ho visto che usi le label e il goto. Io personalmente sono a favore, anche se le uso solo per uscire in un unico punto dai loop annidati o dal loop infinito. Un altro utilizzo tipico è quando devi fare il cleanup con punti di ingresso a cascata. Occhio, però, che usare il goto in generale è malvisto
  • Re: Login e fstream

    oregon ha scritto:


    @Rubik .... evita i goto ...
    In Vb.Net e C#.Net i goto li ho eliminati da tempo, ma in C con i programmini risicati che scrivo, la tentazione è forte...

    Weierstrass ha scritto:


    Perché controversa? getch() c'è anche in ncurses.h di Linux: con una #define sul sistema operativo decidi quale libreria includere e puoi usare lo stesso codice.
    Ho chiesto proprio perché ho trovato opinioni discordanti, almeno in C, qualche purista visto che non fa parte delle librerie standard del C, conio.h la snobba, anche in Linux mi sembra che ncurses.h, sia deprecata. Non ho le competenze per dire: usa si, usa no, mi piacerebbe sapere cosa si usa in sostituzione.

    Weierstrass ha scritto:


    Comunque penso che un programma da terminale sia più comodo scriverlo in C# se c'è la scelta.
    Se devo scrivere un programma posso usare solo Vb.Net o C#, quel poco che so fare in C/C++, in C# lo faccio in 10 volte meno del tempo.
Devi accedere o registrarti per scrivere nel forum
8 risposte