Unable to Process Data from Text File in C++

Why is it that this program will not register the correct ID and Pin number entered?

Anything typed will proceed to wrong data being input but the correct data doesn't get recognized.

Inside the text file is 5 IDs, and 5 Pin numbers in a format of 5 rows 2 columns.

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
using namespace std;
void main()
{
	const int MAX=10, screenWidth=80;
	string A = "Welcome to ABC Bank!";
	int i=0;
	int ID[MAX], Password[MAX], pin, acc, counter=1 ,limit=2;
	cout<<setw((screenWidth-A.size())/2)<<" "<<A<<endl;
	cout<<"\nAccount ID: ";
	cin>>acc;
	cout<<"Pin: ";
	cin>>pin;

	ifstream accountFile;
	accountFile.open("AccountDetails.txt");

	if (!accountFile)
		cout<<"Unable to open requested file!";
	else
	{
		while (accountFile>>ID[i]>>Password[i])
		{
			i++;
		}
		accountFile.close();
		
		bool success = false;
		for (int j=0; !success && j<i; j++)
		{
			if (ID[j] == acc && Password[j] == pin)
				success = true;	
		}
		if (success)
			cout<<"\nLogin Successful!\n";
		else
		{
			while (!success)
			{
				cout<<"\nAccount ID/Pin is incorrect. Please try again!"<<" (Attempts Left: "<<limit<<" )";
				cout<<"\nAccount ID: ";
				cin>>acc;
				cout<<"Pin: ";
				cin>>pin;
				counter++;
				limit--;
				if (counter==3)
				{
					cout<<"Unauthorized Access Detected! Account Has Been LOCKED!\n";
					break;
				}
			}
		}
	}			
	system("pause");
}
	
The loop at lines 28 to 32 which searches for matching account and pin is executed only on the first attempt.

When the user tries again at line 41 - 43, there is no checking.

You need to rearrange the loop structure so that after re-entering the account and pin, the search loop is executed. (No need to duplicate the code, just a change in the scope and position of the while loop).

I don't think both limit and counter are needed, after you fix the other issues, you might simplify the code to use just one or other of these.

Also, void main() is not valid - some compilers may accept it but you shouldn't rely on non-standard behaviour. It should always be int main().
No need to duplicate? Even so, I do not know how to rearrange the while loop because the nested loop is getting a bit complicated for me. Not really good with for loops

The limit and counter is just to show the number of attempts for me. It is rather simplified for me but that isn't really the matter here.

Changed to int main() as well.
the nested loop is getting a bit complicated for me.

Then it is a good time to move the code to a function.

Your loop at 28-32 continues after finding a match. This is unnecessary. You should break out of the for loop as soon as you find a match.


By all means use function(s) to break up the code into smaller, more manageable pieces. That is a good idea.

For the record, what I had in mind was to begin the while loop a bit like this:
27
28
29
30
31
32
33
34
35
        bool success = false;
        
        while (!success)
        {        
            for (int j=0; !success && j<i; j++)
            {
                if (ID[j] == acc && Password[j] == pin)
                // etc.
                // etc. 


... the idea being that after the user has re-entered their 2nd or 3rd try at account and pin, execution of the code will go back to the start of this loop and search for a matching value.

Your loop at 28-32 continues after finding a match.

The condition in the for loop should take care of that: !success && j<i unless I misunderstood the point, which is always possible.
If there are more than MAX records in the file, the above and the first while loop could try to access the arrays out of bounds.

Last edited on
@chervil - you're right. I missed the extra condition on the terminal condition of the for loop.
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
using namespace std;
int main()
{
	const int MAX=10, screenWidth=80;
	string A = "Welcome to ABC Bank!";
	int i=0;
	int ID[MAX], Password[MAX], pin, acc, counter=1 ,limit=2;
	cout<<setw((screenWidth-A.size())/2)<<" "<<A<<endl;
	cout<<"\nAccount ID: ";
	cin>>acc;
	cout<<"Pin: ";
	cin>>pin;

	ifstream accountFile;
	accountFile.open("AccountDetails.txt");

	if (!accountFile)
		cout<<"Unable to open requested file!";
	else
	{
		while (accountFile>>ID[i]>>Password[i])
		{
			i++;
		}
		accountFile.close();
		
		bool success = false;
		while (!success)
		{
		for (int j=0; !success && j<i; j++)
		{
			if (ID[j] == acc && Password[j] == pin)
				success = true;	
		}
		if (success)
			cout<<"\nLogin Successful!\n";
		else
		{			
			cout<<"\nAccount ID/Pin is incorrect. Please try again!"<<" (Attempts Left: "<<limit<<" )";
			cout<<"\nAccount ID: ";
			cin>>acc;
			cout<<"Pin: ";
			cin>>pin;
			counter++;
			limit--;			
		}
		if (counter==4)
			{
				cout<<"Unauthorized Access Detected! Account Has Been LOCKED!\n";
				break;
			}
		}
	}			
	system("pause");
}


THE CODE WORKS NOW, THANKS A LOT GUYS!!
Yes, it seems to work.

Though viewed from the users point of view, the behaviour seems a bit odd.

My test output:
                              Welcome to ABC Bank!

Account ID: 5 5
Pin:
Account ID/Pin is incorrect. Please try again! (Attempts Left: 2 )
Account ID: 5 5
Pin:
Account ID/Pin is incorrect. Please try again! (Attempts Left: 1 )
Account ID: 5 5
Pin:
Account ID/Pin is incorrect. Please try again! (Attempts Left: 0 )
Account ID: 5 7
Pin: Unauthorized Access Detected! Account Has Been LOCKED!
Press any key to continue . . .


Now it allowed me to enter the account number and pin four times. Even though on the last try, I entered valid details (acc = 5 and pin = 7) it was still rejected.

I think the problem here is that after the third incorrect attempt, it should output the "Unauthorized Access" message, instead of inviting the user to try again. The program logic needs a little bit of adjustment to make that happen.
Yeah, i just noticed that. Tweaked the limit and counter initialized values and it seems to work fine.
Topic archived. No new replies allowed.