Need help deleting loaded array and clearing it from count - c++

I have been messing around with some code. I've really just mashed things together and exploring ways to get what I want out of it.
Right now something that has been bothering me is that when I try to delete a user it leaves the user blank instead of deleting it completely. I would rather it delete/remove the line completely and adjust the count without removing any other user data.
EDIT:
The problem is that after I delete a user. When I list every user it displays a blank User: pass: etc instead of not listing those to begin with. if I were to save the file it would have 5 empty spaces. I'd rather it remove those lines completely as if they were never there to begin with.
This is how I load the code:
int Loadpdata()
{
ifstream fp_in;
if(count > 0)
{
cout << "pdata already Loaded.\nTotal of " << count << " users loaded." << endl;
return 0;
}
fp_in.open("p.data"); //Open user file
if(fp_in == NULL)
{
cout << "Could not open user file, exiting." << endl;
}
while(!fp_in.eof()) { //While there is something to read
getline(fp_in,userd[count]);
getline(fp_in,passd[count]); //Read a line from the file
getline(fp_in,aged[count]); //Read a line from the file
getline(fp_in,locationd[count]); //Read a line from the file
getline(fp_in,emaild[count]); //Read a line from the file
getline(fp_in,mid[count]); //Read a line from the file
cout << "User: " << userd[count] << " Loaded Successfully." << endl;
userstotal++;
count++;
}
fp_in.close(); //Done with the user file
cout << "Total Users Loaded: " << count << endl;
if(!count > 0)
{
cout << "Userlist is empty, exiting" << endl;
return -2;
}
return 0;
}
Now this is how I delete the user:
int Deletedata()
{
char user[80];
int logged_in=0;
while(!logged_in) { //Force user to login. Give a quit option if you'd like
cout << "Enter user name: ";
cin >> user;
int found = 0;
for(int x=0;x<count && !found;x++) { //For each user/password pair..
if(userd[x].compare(user) == 0) { //Matched the username
found = 1;
logged_in = 1;
userd[x].clear();
passd[x].clear();
aged[x].clear();
locationd[x].clear();
emaild[x].clear();
mid[x].clear();
}
}
if(!found) {
cout << "Invalid username!" << endl;
}
}
//Once we're done with that loop, they logged in successfully.
cout << "Deleted " << user << " Successfully." << endl;
return 0;
}
The more I think about this the more I realize I may have to scrap it and come up with a new format.

If you want to just remove one entry and not touch any of the other entries, you'll need to use a node-based container, e.g., a std::list<T> or a std::map<K, V> (the latter would match your needs of locating an object by a key anyway).
That said, if you want to stick with an array and fill the gap, you have two principle options:
If you don't care about the order of the objects, you could just std::swap() the to-be-removed object with the last copy and then remove the newly last element.
If the order matters to you, you'll need to move all the objects after the gap forward. The easiest way to do that is probably to use std::remove_if().
BTW, trying to read a file and checking in.eof() does not work reliable. In particular, when there are no more objects eof() may or may not be true and you don't check after reading whether the read was successful. Also note that eof() may never become true, e.g., if the file contains a format error and gets into fail state. You should read you data using something like
while (std::getline(in, userd[count])
&& std::getline(in, passd[count])
// ...
&& std::getline(in, mid)) {
++count;
}

Instead of clearing the element at position x, use erase on the vector (must be std::vector, and not C-array)

Related

fstream is writing on file against an if else statement

I have a file named "password.txt" which has 2 rows of usernames and passwords
2 string vectors named, user & password
This function uses a new username and password and checks if the username already exists in the user vector using a for loop
If it does exist, it breaks out of the loop
If it does not exist, it will add the username and password to the vectors and write them both on the file
void PasswordFile::addpw(string newuser, string newpassword) {
fstream file;
file.open("password.txt", ios::app);
//if the vectors is empty it automatically adds a new user
//is working
if (user.size() < 1){
user.push_back(newuser);
password.push_back(newpassword);
file << newuser << " " << newpassword << "\r";
}
//the loop (is not working)
for (int i=0; i < user.size(); i++){
string name = user[i];
if (name == newuser) {
break;
} //it shouldn't continue past this point if the name is in the vector but it does
else {
cout << newuser;
cout << " is being written onto the file\n";
user.push_back(newuser);
password.push_back(newpassword);
file << newuser << " " << newpassword << "\r";
}
}
file.close();
}
the problem is that it is writing the second name twice and the third name three times
I know also that it is pushing the newuser and newpassword multiple times onto the vector, but I can't figure out where or why its looping more than it should or why its ignoring the break and writing onto the file anyway
"password.txt" 1 run
dbotting 123qwe
egomez qwerty
tongyu liberty
tongyu liberty
"password.txt" second run
dbotting 123qwe
egomez qwerty
tongyu liberty
tongyu liberty
egomez qwerty
tongyu liberty
tongyu liberty
it keeps adding the last 2 every time its run
WHILE you are looping through the user vector, any time you encounter an entry that does not match the newuser being searched for, you are writing the newuser/newpassword to the file and pushing them into the vectors 1 (which then affects subsequent iterations of your loop), and then you move on to the next entry.
So, for example, if you start with a file like:
dbotting 123qwe
egomez qwerty
tongyu does not match dbotting, so you add tongyu. And then tongyu does not match egomez, so you add tongyu again. So you end up with:
dbotting 123qwe
egomez qwerty
tongyu liberty
tongyu liberty
And then on the next run, tongyu doesn't match dbotting or egomez, so you add tongyu twice again. But then it does match tongyu, so you don't add it again, and break the loop. So you end up with:
dbotting 123qwe
egomez qwerty
tongyu liberty
tongyu liberty
tongyu liberty
tongyu liberty
And so on.
Online Demo
To fix this, the code inside of your else block needs to be moved out of the for loop entirely. You need to search the entire vector to determine if the user already exists or not, and then write that user to the file only if they don't exist at all, eg:
void PasswordFile::addpw(const string &newuser, const string &newpassword) {
for (size_t i = 0; i < user.size(); ++i){
if (user[i] == newuser) {
cout << newuser << " already exists" << endl;
return;
}
}
/* alternatively:
if (find(user.begin(), user.end(), newuser) != user.end()) {
cout << newuser << " already exists" << endl;
return;
}
*/
ofstream file("password.txt", ios::app);
if (!file.is_open()) {
cout << "cannot open password file" << endl;
return;
}
cout << newuser << " is being written onto the file\n";
if (!(file << newuser << " " << newpassword << "\r")) {
cout << "cannot write to password file" << endl;
return;
}
user.push_back(newuser);
password.push_back(newpassword);
}
1: On a side note, you should not maintain two separate vectors that are closely related. Just use a single vector instead, eg:
struct UserInfo
{
string username;
string password;
};
std::vector<UserInfo> users;
void PasswordFile::addpw(const string &user, const string &password) {
for (size_t i = 0; i < users.size(); ++i){
if (users[i].username == user) {
cout << user << " already exists" << endl;
return;
}
}
/* alternatively:
if (find_if(users.begin(), users.end(), [&](const UserInfo &u){ return u.username == user; }) != users.end()) {
cout << user << " already exists" << endl;
return;
}
*/
ofstream file("password.txt", ios::app);
if (!file.is_open()) {
cout << "cannot open password file" << endl;
return;
}
cout << user << " is being written onto the file\n";
if (!(file << user << " " << password << "\r")) {
cout << "cannot write to password file" << endl;
return;
}
UserInfo newuser;
newuser.username = user;
newuser.password = password;
users.push_back(newuser);
}
Remy has done a good job of pointing out the problems you're seeing.
Rather than fixing your loop, I would fix the data structures you're using.
Instead of a pair of vectors, one for user names and one for passwords, I'd start by creating an std::map to hold the usernames and passwords:
std::map<std::string, std::string> credentials;
A map already provides most of what you want, as far as guaranteeing that an entry is unique (each username occurs only once), and lets you check whether an insertion succeeded, so an equivalent of your addpw comes down to something like this:
std::map<std::string, std::string> credentials;
void addpw(std::string newuser, std::string newpass) {
if (credentials.insert({newuser, newpass}).second) {
std::cout << "Adding new user: " << newuser << "\n";
file << newuser << " " << newpass << "\n";
} else {
std::cerr << "User already exists--not adding\n";
}
}
Of course, if you care about security at all, you really don't want to store user names and passwords in a plain text file. In fact, you usually don't want to store actual passwords at all--as a bare minimum, you want to salt the password, the hash it with a cryptographic hash algorithm (e.g., SHA-256) then store the salt and the hash, not the password itself. Then to check a user's credentials when they try to log in, you salt what they provide, hash it, and compare the resulting hash to the one you have on file and see if they match.
Now don't get me wrong: that's not the ideal to provide truly maximum security--but at least it's enough to make hackers work a little bit to steal your users' credentials.

Deleting content from a file [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I am making a program that allows a user to make bank accounts and save them too a file, you can also delete them. I am having issues with my code for deleting an account on the file, my function for deleting the account looks like this.
int deleteCustomer(account acc[], int numCust)
{
string target;
bool accFound = false;
int count = 0;
cout << "Enter account number: ";
cin >> target;
for (int i = 0; i < numCust; i++)
{
if (acc[i].acctNum == target)
{
accFound = true;
break;
}
count++;
}
if (accFound == false)
{
cout << "That account does not exist." << endl;
system("pause");
system("cls");
}
else if (accFound == true)
{
ofstream outFile;
outFile.open("customer.dat");
for (int i = count; i < numCust - 1; i++)
{
outFile << acc[i+1].acctNum;
outFile << '#';
outFile << acc[i+1].name;
outFile << '#';
outFile << acc[i+1].cBal;
outFile << '#';
outFile << acc[i+1].sBal;
outFile << '#';
}
numCust--;
outFile.close();
}
return numCust;
}
The function is supposed to overwrite the account selected by the user by saving the file ahead of it to the previous spot and return the new number of customers. It appears to run through fine but it does not do anything and I am uncertain as to why. Any input would be helpful, thank you.
Several problems here:
Your account lookup should be working, but you're overcomplicating this a bit (you'd only need one value rather than three, but let's skip that for now). If you're interested let me know.
You're never actually removing any account (just reducing the number of total accounts; which will then cause the last entry to be removed).
When saving you accounts to the file, you start at that selected index, which doesn't make any sense at all.
Let's assume you've got 10 accounts, indices 0 through 9.
The user picks the account at index 5.
You save accounts index 6 through 9(!) only.
The user picks the account at index 0.
You save accounts index 1 through 9 only.
Some style things:
You essentially store the selected account's index in count. That's fine, but very misleading. Don't ever use misleading variable names. As you might be able to tell from my comment above, I misread that part as well.
Rather than writing if (booleanValue == true) you could just write if (booleanValue), which results in the same code, but is shorter and might be faster to read. In a similar way, you could replace if (booleanValue == false) with !booleanValue.
Don't omit namespaces like std, if you can (e.g. use std::string rather than string and avoid using namespace std;) to avoid writing ambigious code. If some other namespace you use has string (or any other member) as well, you'll either have to explicitly name the namespace anyway or you're at least confusing others reading your code. Also there's always the potential bug introduced by unintentionally using a different type.
Fixing the actual problem:
I assume this is some homework assignment or some tutorial/class code or anything similar? If so, don't just copy the following code and instead try to think about how it's working. Once you understood, implement it yourself and only use my snippets if you're really stuck.
In general, it's good software design to keep code and functions minimal. Don't create "super functions" that do several things. Also try to make code reusable, so in case you change something, you're able to adjust it in one place only.
Take your code above for example. Whenever you add, delete, or update an account, you'll have to write the new file. Did you plan on replicating the same code multiple times? If you'd have to adjust your file format, you'd have to change it everywhere.
You'll also need some way to actually remove customer datasets. As you might be aware, deleteing entries in an array would require you to move all entries behind it (to keep it continguous). This can be a very expensive operation.
To avoid this, I'm adding a new member bool valid to account. By default, this is set to false. Once there's some data put there (either through reading from a file or by the user), it's value is set to true.
So instead split this into two separate functions (moving the common code - saving - to its own function):
// By returning an integer value, you're able to communicate issues or problems
// without having to rely on exceptions (in case you're using C++).
// Note that I don't do any error checking here for simplicity.
// Parameters:
// filename - the target file to write
// acc - the array holding all customer accounts
// size - the maximum amount of values in acc
// Return value: 0, if everything went fine
// (I skipped actual error handling to keep it simple!)
int saveCustomers(const char *filename, account acc[], int size) {
std::ofstream outFile(filename);
// Iterate over all entries
for (int i = 0; i < num; ++i) {
// Do we actually have to store the account?
if (acc[i].valid) {
outfile << acc[i].acctNum << '#' << acc[i].name; // write all the values the way you did
}
}
outFile.close();
return 0; // Everything ok
}
Now that this is done, you're able to create your functions to modify your customer data:
int deleteCustomerByNumber(account acc[], int num, std::string target) {
// Iterate over all accounts and look for the selected one
for (int i = 0; i < num; ++i) {
// Only check valid accounts and see whether it's the target
if (acc[i].valid && acc[i].acctNum == target) {
acc[i].valid = false; // Mark it as invalid
return 0; // Everything ok
}
}
return 1; // Didn't find it!
}
In a similar way you can look for empty/unused entries to actually write data to them.
Bonus - alternative (STL) approach:
Since you're using C++, I'd suggest you use a different data structure, not just a simple array:
If you use a STL container (more specific: a map), you're able to handle everything a lot easier.
#include <map>
// Create a typedef to simplify expressions
typedef std::map<std::string, account> accmap;
// All accounts would be stored in this object:
accmap accounts;
// To do a quick lookup of any account:
accmap::const_iterator a = accounts.find(accountNumber);
if (a == accounts.end())
;// Account not found!
else {
a->first; // This is your account number
a->second; // This is your `account` object
}
// To delete a specific account:
accounts.erase(accountNumber)
// To create a new account simply access it:
accounts[accountNumber].name = newName;
You need to save all of the records before the index and after the index, otherwise you are effectively deleting more than just the one account. Presumably you should also remove the record from the input array as well. You are also not doing any error handling on the input or output. And you need to fix your output loop, it is not using indexes correctly.
Try this:
int deleteCustomer(account acc[], int numCust)
{
string target;
int accFound = -1;
cout << "Enter account number: ";
if (cin >> target)
{
for (int i = 0; i < numCust; ++i)
{
if (acc[i].acctNum == target)
{
accFound = i;
break;
}
}
}
if (accFound == -1)
{
cout << "That account does not exist." << endl;
system("pause");
system("cls");
}
else
{
for (int i = accFound+1; i < numCust; ++i)
acc[i-1] = acc[i];
--numCust;
ofstream outFile;
outFile.open("customer.dat");
for (int i = 0; (i < numCust) && (outFile); ++i)
{
outFile << acc[i].acctNum;
outFile << '#';
outFile << acc[i].name;
outFile << '#';
outFile << acc[i].cBal;
outFile << '#';
outFile << acc[i].sBal;
outFile << '#';
}
if (!outFile)
cout << "Error saving customer file" << endl;
}
return numCust;
}
If you don't want to update the array, then you can do this instead:
int deleteCustomer(account acc[], int numCust)
{
string target;
int accFound = -1;
cout << "Enter account number: ";
if (cin >> target)
{
for (int i = 0; i < numCust; ++i)
{
if (acc[i].acctNum == target)
{
accFound = i;
break;
}
}
}
if (accFound == -1)
{
cout << "That account does not exist." << endl;
system("pause");
system("cls");
}
else
{
ofstream outFile;
outFile.open("customer.dat");
for (int i = 0; (i < numCust) && (outFile); ++i)
{
if (i != accFound)
{
outFile << acc[i].acctNum;
outFile << '#';
outFile << acc[i].name;
outFile << '#';
outFile << acc[i].cBal;
outFile << '#';
outFile << acc[i].sBal;
outFile << '#';
}
}
if (!outFile)
Cout << "Error saving customer file" << endl;
--numCust;
}
return numCust;
}
Lastly, when updating a file, it is a good idea to write the new data to a temp file first, then replace the original file with the temp file only if everything is successful. That way you reduce the risk of corrupting the original file.
To "deleting an account on the file", this part of code:
for (int i = count; i < numCust - 1; i++)
{
outFile << acc[i+1].acctNum;
outFile << '#';
outFile << acc[i+1].name;
outFile << '#';
outFile << acc[i+1].cBal;
outFile << '#';
outFile << acc[i+1].sBal;
outFile << '#';
}
should be
for (int i = 0; i < numCust; i++)
{
if(i == count) continue;// remove the account user selected
outFile << acc[i].acctNum;
outFile << '#';
outFile << acc[i].name;
outFile << '#';
outFile << acc[i].cBal;
outFile << '#';
outFile << acc[i].sBal;
outFile << '#';
}

strcmp() function does not compare properly against user input and struct file data

I'm trying to solve this issue where when i try and search for a certain module name in my .dat file, it doesn't show the info of some module like module name, module code.
Example: if I search CSCI124, it shows all of the needed info i need in the output.
However if i try searching for CSCI114 or MATH121, it doesn't show any info except for "Subject Code not found.."
I have tried playing around with not putting in the while loop however it doesn't work as well.
It would be awesome if you guys could help me out, just started learning about c++
Subject subjectDB;
char subCode[MAX];
int printOnce = 0;
int position = 0;
cout << "Enter Subject Code: ";
cin >> subCode;
// Open binary file
ifstream fin("Subject.dat", ios::out | ios::binary);
if (!fin)
{
cout << "\nError opening database..\n"
<< "\tQuitting System..";
exit(-1);
}
cin.clear();
cin.ignore(100, '\n');
while(fin.read(reinterpret_cast<char*>(&subjectDB), sizeof(Subject)))
{
if (!(strcmp(subCode, subjectDB.subjectCode) == 0))
{
// Print this section once
if (printOnce == 0)
{
cout << "Subject Code not found..\n";
printOnce++;
}
}
else
{
// Print this section once
if (printOnce == 0)
{
cout << "\nSubject Code: "
<< subjectDB.subjectCode
<< "\nSubject Name: "
<< subjectDB.subjectName
<< "\n"
<< endl;
cout << "Task\t"
<< "Title\t\t"
<< "Weight\t"
<< "Upon\t"
<< "Mark\t"
<< "Obtained\n";
// PrintOnce++ : 1 != 0
// So it only prints once
printOnce++;
}
cout << position + 1
<< "\t"
<< subjectDB.assessment[position].title
<< "\t"
<< subjectDB.assessment[position].weight
<< "\t"
<< subjectDB.assessment[position].upon
<< "\t"
<< subjectDB.assessment[position].taskMark
<< "\t"
<< "testing\n";
position++;
}
}
Writing a struct to a file or reading a struct from a file is totally non-portable. Compile the same code on two different compilers, or on the same compiler with different settings, and what you wrote and what you read might be very different. That's not necessarily your problem, but it will be your problem one day.
Your display code logic is flawed.
Explanation:
If the subject code is in the first record you read, you'll get the correct answer. However as soon as your fist record does not match, the "Not found" message is displayed, printOnce is incremented. If the matching subject coe is found later in the file printOnce is no longer 0 and it' will not be displayed.
Solution:
Organise your loop in the opposite way:
while (...) {
if (strcmp(..)==0) {
// your code to display the found item here
printOnce++;
break; // ?? optional: you could stop the loop at first found occurence unless you suppose there could be duplicates
}
}
and once the loop is finished, check OUTSIDE OF THE LOOP if you've found something:
if (printOnce==0) { // nothing was found in the loop
// display that nothing was found !
}
Remark:
Reading directly from file as you do has limitations. It can only work with plain old data (POD), not with more advanced types using string members or containters. For learning it's a good start but I'd suggest to foresee a Subject member function that loads the data from a stream. This proves to be more flexible when your data structure evolves: the member function could ealsily read each member data and sub-objects using the most apporpriate way.
Thanks for your help! I managed to get the function to compare properly against user input and struct file by creating a function that checks the .dat file if the subject is existing or not.
int row = checkNumberOfData(fileName);
if (row > 0)
exist = doesSubjectExist(file, fileName, code); // checks input
if (!exist)
{
file.open(fileName, ios::out | ios::app | ios::binary);
if (!file)
{
cout << "Error opening database..\n"
<< "\tQuitting System ..\n";
exit(-1);
}
strcpy(subjectDB.code, code);
cout << "Subject Name: ";
cin.getline(subjectDB.name, MAX);
cout << "No of assessment tasks: ";
cin >> subjectDB.num;
cout << endl;
.... etc
}

File IO - delete a line of text that contains a specific string C++

I've written a function that reads in a text file, allows the user to pick an account to delete and deletes the specified account. What I need to do now is delete the line of text from the text file that lists the accounts on it. What good does it do to delete an account, but still have it show up in the list of accounts, right? Below is my code. What happens is that the entire contents of the account list text file get deleted, not just the line with the specific account number. The actual deletion of the account's text file works fine, it's just the deletion of that one line of text that is giving me trouble. Thanks for any assistance!
void UserInfo::deleteAccount() {
vector<string> accounts;
string line;
char answer;
ifstream acctList("accountList.txt");
if (acctList.fail()) {
cout << "There is a problem opening the file.\n";
exit(1);
}
//populate vector with the list of accounts and display them.
while (getline(acctList, line)) {
accounts.push_back(line);
}
for (unsigned int i = 0; i < (accounts.size()); i++) {
cout << accounts[i] << endl;
}
cout << "\nEnter the account number of the account you would like to delete: ";
cin >> acctNo;
cout << "Are you sure you want to delete account number " << acctNo << "? ";
cin >> answer;
const char * result = (acctNo + ".txt").c_str(); //convert the selection choice to a c-string
if (answer == 'y' || answer == 'Y') {
if (remove(result) != 0)
cout << "Unable to delete account." << endl;
else
cout << "\nThe account has been deleted successfully." << endl;
//delete the account name and number from the list of accounts
//temporary file to store the new list of accounts
ofstream out("newAcctList.txt", ios::app);
while (getline(acctList, line)) {
if (line != acctNo)
out << line << "\n";
acctList.close();
out.close();
// delete the original file
}
if(out){
remove("accountList.txt");
// rename old to new
rename("newAcctList.txt", "accountList.txt");
} else {
cout << "Error on output" << endl;
}
}//end if
You've already read acctList in the first while loop, so when you try to read it again to write out, it's already at the end. You can just iterate over the vector accounts - throwing away the entry matching acctNo (which should be a local variable BTW) - instead of re-reading the file.

else if looping quandry

I am in the second phase of a project where I need to extend my program into a menu driven application to query the database I have on a .txt file. So, my trouble is that I cannot get my loop to be perpetual. It always terminates when it initializes from one option to the next. Here is the snippet of my code that is my int main:
int main ()
{
char Q,q;
char S,s;
char task;
string pathname;
string z;
int count=0;
cout << "Welcome to Jason Rodriguez's Library Database." << endl;
cout << "Please enter the name of the backup file: ";
cin >> pathname;
ifstream inFile(pathname.c_str());
while(!inFile.eof())
{
getline(inFile,z);
count++;
}
while (task != 'Q' || task != 'q') {
cout << count << " records loaded successfully." << endl;
cout << "Enter Q to (Q)uit, Search (A)uthor, Search (T)itle, (S)how All: ";
cin >> task;
if ((task == 'Q')||(task =='q'))
{
cout << "Program will now terminate";
break;
}
else if ((task == 'S')||(task =='s'))
{
showAll (loadData (pathname));
cout << endl;
cout << "Enter Q to (Q)uit, Search (A)uthor, Search (T)itle, (S)how All: ";
cin >> task;
}
}
}
I need to add two more options into the loop on top of these two but I figured I should get the first two working correctly first. The other two should be plug & chug after that. Basically what I was trying to do is say if the user enters Q or q, terminate the program. Else, if user hits S or s, activate showall function and after ward, go back to the original query. It isn't working though. Assistance is welcome and appreciated.
Menus almost always require loops - especially ones that require the user to enter the correct choice input. The most applicable one in a case like this is the while loop - but essentially, any other loop variant can be used.
UPDATE:
int main ()
{
char task;//this is the only char needed. Your other chars were redundant
string pathname;
string temp;//I changed z to temp to better reflect its purpose
int count=0;
cout << "Welcome to Jason Rodriguez's Library Database." << endl;
cout << "Please enter the name of the backup file: ";
cin >> pathname;
ifstream inFile(pathname.c_str());//this is potentially a problem in that you aren't verifying that the pathname is a valid one
//you did not check to see that your file was open, otherwise there is no way to tell that you successfully opened the file
if (inFile.is_open()) {
//while(!inFile.eof()) is a character by character read and comparison
//made your life easier by shortening it down to this - which ensures
//that a line is read. (Much faster and more readable)
while(getline(inFile,temp))
{
count++;
}
inFile.close();//always close a file after you've used it
//At this point the entire file has been read. So, this is where this message SHOULD be
cout << count << " records loaded successfully." << endl;
}
else {
//if there was an error opening the file (i.e. wrong path, or it simply does not exist), this will be displayed
cout << "There was a problem opening your file" << endl;
exit(0);//and the program will terminate
}
while (task != 'Q' || task != 'q') {
cout << "Enter Q to (Q)uit, Search (A)uthor, Search (T)itle, (S)how All: ";
cin >> task;
if ((task == 'Q')||(task =='q'))
{
cout << "Program will now terminate";
break;
}
else if ((task == 'S')||(task =='s'))
{
string author;
//showAll (loadData (pathname));
cout << endl;
cout << "Search an Author" << endl;
cin >> author;//get the author name to search from the user
//write code to search an author here
}
}
}
There are a number of issues with the code that you posted which I will forgo for the sake of brevity. Hence, note the following:
Your code was printing the same message per option (except for quit). Of course it would appear that it didn't work. Each option is a different task. Print what each task does (similar to what I did).
You wish to search the file for an author, but you have not stored it. Look into a way of storing it that appeases your instructor.
It would be ideal for you to use switch in this case, considering the increasing complexity of your code.
Try breaking down each task into functions, and call them to make your main function readable. In fact, it is a good programming practice for your main function to be as small as possible.
And, as juanchopanza quite rightly pointed out: you have some fundamental issues with C++. Try doing some more exercises and do more examples from a good C++ book.