I'm writing a library application. Part of the application is allowing users to login. I'm using a vector of structs to store the usernames/passwords. When I try to access a member variable of the struct, I get an out of range error. The vector is full (I checked with both the vector.size and vector.empty methods), and I believe I am assigning values to the member variables correctly (although clearly I'm not).
Here is main.cpp:
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include "userService.h"
using namespace std;
void countRecords(string& pathName, ifstream& inFile);
void loadCredentials(string pathName, ifstream& inFile, string& username, string& password, userService newUser);
void login(string username, string password, userService newUser, bool& loggedIn);
int numRecords;
int main()
{
string username, password;
string pathName = "/home/seth/Desktop/credentials";
ifstream inFile;
userService newUser;
char menuSelection;
bool loggedIn = false;
countRecords(pathName, inFile);
cout << "Welcome to Library Information System." << endl << endl;
do{
cout << "choose a) to login or b) to register as a new user." << endl << endl;
cin >> menuSelection;
switch (menuSelection)
{
case 'a':
{
cout << "Username: ";
cin >> username;
cout << endl;
cout << "Password: ";
cin >> password;
cout << endl;
loadCredentials(pathName, inFile, username, password, newUser);
login(username, password, newUser, loggedIn);
if (loggedIn == true)
{
cout << "You logged in! " << endl; //placeholder, will be more menu options here
}
else
{
cout << "Invalid credentials! Please check your username and password and try again!" << endl;
}
break;
}
}
} while (loggedIn == false);
return 0;
}
void countRecords(string& pathName, ifstream& inFile)
{
string temp; //string to count records using getline
inFile.open(pathName);
while (inFile)
{
getline(inFile, temp, '\n');
if (inFile.eof())
{
break;
}
++numRecords;
}
cout << "numRecords = " << numRecords << endl;
inFile.close();
inFile.clear(std::ios_base::goodbit);
}
void loadCredentials(string pathName, ifstream& inFile, string& username, string& password, userService newUser)
{
string tempUsername, tempPassword;
inFile.open(pathName);
if (!inFile)
{
cout << "Error opening file" << endl;
}
for (int i = 0; i < numRecords; i++)
{
getline(inFile, tempUsername, ',');
getline(inFile, tempPassword, '\n');
newUser.loadCredentials(tempUsername, tempPassword);
}
}
void login(string username, string password, userService newUser, bool& loggedIn)
{
newUser.resetVectorCounter();
for (size_t i = 0; i < numRecords; i++)
{
cout << "i = " << i << endl;
cout << newUser.getUsername() << endl;
cout << newUser.getPassword() << endl;
newUser.incrementVector();
}
}
userService.h:
#include <string>
#include <fstream>
#include <vector>
using namespace std;
struct credentials
{
string username = "";
string password = "";
};
class userService
{
private:
vector<credentials> credentialsList;
int vectorCounter = 0;
string username_, password_;
public:
void loadCredentials(string username_, string password_);
bool check();
int sizeOfVec();
string getUsername();
string getPassword();
void incrementVector();
void resetVectorCounter();
};
Implementation of userService:
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include "userService.h"
using namespace std;
credentials users;
void userService::loadCredentials(string username_, string password_)
{
users.username = username_;
users.password = password_;
credentialsList.push_back(users);
}
bool userService::check()
{
return credentialsList.empty();
}
int userService::sizeOfVec()
{
return credentialsList.size();
}
string userService::getUsername()
{
return credentialsList.at(vectorCounter).username;
}
string userService::getPassword()
{
return credentialsList.at(vectorCounter).password;
}
void userService::incrementVector()
{
vectorCounter++;
}
void userService::resetVectorCounter()
{
vectorCounter = 0;
}
The exact error that is being thrown is:
'std::out_of_range' what(): vector::_M_range_check: __n (which is 0) >= this->size (which is 0)
This happens immediately after calling getUserName. I believe this means the member variables are empty, but if so, I do not know how to assign them values properly. Any help would be appreciated.
I've tried using a debugger, and here is where the debugger shows this problem is:
protected:
/// Safety check used only from at().
void
_M_range_check(size_type __n) const
{
if (__n >= this->size())
__throw_out_of_range_fmt(__N("vector::_M_range_check: __n "
"(which is %zu) >= this->size() "
"(which is %zu)"),
__n, this->size());
}