Searching a txt file

How would I scan the file first for the keyword 'password' and then return all chars after 'password:'


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
using namespace std;
bool UserVerified;
void addUser()
    {
        string newUser;
        string newPass;

            cout << "Please enter a Username: ";
            cin >> newUser;
            cout << "\nPlease enter a Password: ";
            cin >> newPass;
            string fname = "Usernames/" + newUser + ".txt";
            ofstream myfile;
            myfile.open(fname.c_str());
            myfile << "Username: " << newUser;
            myfile << "\nPassword: " << newPass;
            myfile << "\nAdministration: ";
            myfile.close();

    }
    string findPass()
    {

        string UserEntered;
        string PassEntered;
        string line;
        string passwordRetrieved;
        cout << "Please sign in." << "\nUsername: ";
        cin >> UserEntered;
        cout << "\nPassword: ";
        cin >> PassEntered;
        ifstream myfile;
        string fname = "Usernames/" + UserEntered + ".txt";
        myfile.open(fname.c_str());
        while(myfile.good())
        {
            start:
                getline(myfile, line);
                if(line == "Password")
                {
                    passwordRetrieved = line;
                    myfile.close();
                    return passwordRetrieved;
                }
                else
                {
                    goto start;
                }
        }
        if(passwordRetrieved == "Password: " + PassEntered)
        {
            UserVerified = true;

        }
        else
        {
            cout << "Invalid Password";
        }
        return passwordRetrieved;
    }
int main()
{
    findPass();
    if(UserVerified)
    {
        addUser();
    }
    else
    {
        cout << "Insufficient permissions";
        return (0);
    }
}
closed account (SECMoG1T)
Hi , yeah its possible to achieve that by parsing strings read from the txt file, however that will be really tedious, instead we can tweak your code a little bit to avoid all those problems


From what I can figure out if we 'av got 1000 users then we'll end up with 1000 text files , a single txt file can still fulfil our task and make our directory cleaner mmh, we can also use simple structs to hold user records , to make our lookup easier escpecially if our text file hosts a large number of users we can use a map library, the first thing that will happen when we run our program is to load our txt file into the map.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
struct User
 {
    std::string userName;
    std::string passWord; 
 };

///lets use a class to handle our operations.

class LogOn
 {
    private:
        std::map <std::string, std::string> login_records; //<username, password>
        void addUser (const User& user);
        void login ();
        void signup ();
        void loadRecords ();
    public:
        LogOn ();
        void manage ();
   };
    

 LogOn::loadRecords ()
  {
      ifstream in("admin.txt");///all records are stored here, each line consists of a 
      if (!in)                                /// username followed by a password. 
          { std::cout <<" Fatal error! "; return (1);}

      User temp;
      while (in>> temp.userName>> temp.passWord)
        {
                 login_records [temp.userName]=temp.passWord; 
        }
   }
  
 LogOn::LogOn ()
   {
         loadRecords ();
   }
        
 void addUser (const User& temp)
   {
         ofstream out ("admin.txt", std::ios::app);
         out <<temp.userName <<temp.passWord <<std::endl;
          login_records[temp.userName ]=temp.passWord; 
    }


 void LogOn::signup ()
   {
        User temp;
        std::string pass_confirm("null");
              
        while (login_records.find (temp.userName)!=login_records.end ())
           {
                 std::cout <<" Enter your username  ";  std::cin>> temp.userName; 
                 
                if (login_records.find (temp.userName)!=login_records.end ())
                 std::cout <<" \t username already exists\n";
           }
 
        while (pass_confirm!=temp.passWord)
           {
                 std::cout <<" Enter your password   ";  std::cin>> temp.passWord; 
                 std::cout <<" Please confirm your password "; std::cin>> pass_confirm;
                
                  if (pass_confirm!=temp.passWord)
                      std::cout<<"\t\t\t Password entries din't match \n";
           }
               
         addUser (temp);
   }

 void logOn::login ()
   {
          User temp;
           int attempts=0;  

           while (attemps <3)
             {
                std::cout <<" Enter your username : "; std::cin>> temp.userName;
                std::cout <<" Enter your password : "; std::cin>> temp.passWord; 
   
                if (login_records.find (temp.userName)!= login_details. end ())
                 {
                       if (login_records [temp.userName]==temp.passWord)
                         {
                           std::cout <<" Access granted. . . . \n\t\t\t\t Logged on as : " <<temp.userName <<std::endl;
                         }
                  
                        else { std::cout <<" Error!  wrong password  \n";
                  }
          
                 else
                   std::cout <<" The username \/ password provided were not found \n";
                   ++attempts;
            }
        
            int choice=0;
            std::cout <<" invalid login details \n select 1 to signup , 2 to contact Admin else Exit : ";
            std::cin>> choice;

             if (choice==1) 
              { signup (); login ();}///recurring , additional control might be necessary

            else if (choice==2)
               {//add admin support }
       }

 void LogOn::manage ()
   {
       login ();
   }


 int main ()
  {
       LogOn session; 
       session.manage ();\\\ you can add a loop
  }
       


That might give you a better idea.

Last edited on
Andy, I'm only trying to figure out how to do this specific task. Here is the bigger project it's part of...

Main
1
2
3
4
5
6
7
8
9
10
11
12
#include "LoginSystem.h"

int main()
{
	// create one system:
	LoginSystem mySystem;

	// then call whatever methods you want, for example:
	mySystem.adminMenu();

}


LoginSystem.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#ifndef LOGINSYSTEM_H
#define LOGINSYSTEM_H


#include <vector>
#include <string>
using namespace std;

class LoginSystem
{
public:
	bool signIn();
	int reSign();
	void addUser();
	void adminMenu();
	void removeUser();
private:
        // no one in the outside world (i.e. main) needs to see these variables
	vector <string> passwordlist;
	vector <string> usernamelist;
	string adminUser;
	string adminPass;
	string UserEntered;
	string PassEntered;
	bool ValidUser;
};

#endif /* LOGINSYSTEM_H */

LoginSystem.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include"LoginSystem.h"
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
/*
bool LoginSystem::signIn()
{
	//need to remake this after changing usernames to .txt files
}
*/





void LoginSystem::addUser()
{

		string newUser;
		string newPass;
        startEntering:
			cout << "Add a username then password.\n";
			cout << "Enter user name: ";
			cin >> newUser;
			cout << "Enter password: ";
			cin >> newPass;
			string fname = newUser;
			fname += ".txt";
			ofstream myfile;
			myfile.open(fname.c_str());
			myfile << "Username: " << newUser;
			myfile << "\nPassword: " << newPass;
			myfile.close();
            string continueAdding;
            cout << "Would you like to create another user? ";
            cin >> continueAdding;
            if(continueAdding == "yes")
            {
                goto startEntering;
            }
            else
            {
                adminMenu();
            }

}
void LoginSystem::removeUser()
{
    string removingUser;
    cout << "Enter the username you would like to remove: ";
    cin >> removingUser;
    string fRem = removingUser;
    fRem += ".txt";
    remove(fRem.c_str());
    adminMenu();
}

void LoginSystem::adminMenu()
{
	int option;
	cout << "Welcome to the Administrator menu." << "\n" << "Please choose an option." << "\n";
	cout << "1. Add User" << "\n";
	cout << "2. Remove User" << "\n";
	cout << "3. Edit User Files\n";
	cin >> option;
	switch (option)
	{
	case 1:
		addUser();
		break;
    case 2:
        removeUser();
        break;
	}

}


First I tried to use vectors to accomplish this and realized that .txt would be much easier. So I'm basically in the process of rewriting it to support the .txt files

However, I do like how you created a User class that defines the properties of a User. I plan on adding a lot more to the user class and giving users permissions in order to do things in the program.
Last edited on
closed account (SECMoG1T)
Hi , gr8 progress wow. yeah i agree the best way to work with text files would involve loading them to a container in RAM escpecially when they are quite large to avoid the overhead that would be incurred by calling streams multiple times when we need to use the txt file data.

The reason I used a map is because they offer a fast look up as compared to most library containers, we can use the username as the index whle the password is the value at the index, for vectors they are awesome but when it comes to lookup you might end up using O(n) as compared to O(1) lookup time that a map could offer, however vectors can still be fine for small numbers of records.

Another pointer I could suggest to improve your program efficiency, avoid using multiple textfiles - in your case I can see that each user added to your system will secure him\herself a textfiles in your DIR, well am sure that a single textfile will perform better, by this I mean the addUser function will always new users to a single file as opposed to (n) textfiles laying around.

For password string parse to lookup for the characters after it well here is a workable solution

1
2
3
4
5
6
7
std::string line, passwrd;
getline (myfile, line);///acquire the string from file.

///search for the phrase "password"
auto index=line.find ("Password:"); ///index holds the first index at which password occurs
index+=9;///9 is the length of "password:", now index is located after the password sub- string. 
passwrd=line.substr(index,(line.size ()-index));///passwrd contains your password.  


However if we use a single textfile to hold our users records we can alter slightly how data is stored in it such that we can completely do away with the overhead induced by parsing strings.

Also I din't quite clearly get what this intended to mean
I'm basically in the process of rewriting it to support the .txt files


Last edited on
Topic archived. No new replies allowed.