Modify record in a data file - c++

I am creating a program to modify the records in a binary file. But i always end up creating two similar records.
I copy all the data to another file. if I find the record to be modified, I read the modified data and copy it to the new file. When all the records are copied, The remporary file is renamed
The class:
class student
{
char name[200];
int rno;
float marks;
char grad;
void grade()
{
if(marks < 33)
grad = 'F';
else if(marks < 50)
grad = 'D';
else if(marks < 60)
grad = 'C';
else if(marks < 80)
grad = 'B';
else
grad = 'A';
}
public:
void get()
{
fflush(stdin);
cout << "Name: ";
gets(name);
cout << "Roll number: ";
cin >> rno;
cout << "Marks:" ;
cin >> marks;
grade();
}
///////////////////////////////////////////////////////////
void showname()
{
cout << "Name: " << name << endl;
}
///////////////////////////////////////////////////////////
void show()
{
cout << "Name: " << name << endl;
cout << "Roll number: " << rno << endl;
cout << "Marks: " << marks << endl;
cout << "Grade: " << grad << endl;
}
///////////////////////////////////////////////////////////
int get_rno()
{
return rno;
}
////////////////////////////////////////////////////////////
float get_marks()
{
return marks;
}
////////////////////////////////////////////////////////////
char get_grade()
{
return grad;
}
////////////////////////////////////////////////////////////
char* getname()
{
return name;
}
};
The modify function:
void modify_rec()
{
int rno;
ifstream fin("stu.dat",ios::binary);
ofstream fout("modif.dat",ios::binary);
student s;
cout << "Enter the roll number whose details you want to edit:";
cin >> rno;
while(!fin.eof())
{
if(fin.eof())
break;
fin.read((char*)&s, sizeof(s));
if(s.get_rno() == rno)
{
s.get();
fout.write((char*)&s, sizeof(s));
rno = -1;
}
else
{
fout.write((char*)&s, sizeof(s));
}
}
fin.close();
fout.close();
remove("stu.dat");
rename("modif.dat","stu.dat");
}
Main function:
int main()
{
char op;
int ch;
do
{
system("CLS");
cout << "Select an option:" << endl;
cout << "\t1.)Add record." << endl;
cout << "\t2.)Display all." << endl;
cout << "\t3.)Search by roll number." << endl;
cout << "\t4.)Search by name" << endl;
cout << "\t5.)Modify record." << endl;
cout << "\t6.)Delete record." << endl;
cout << "\t7.)Display list of distinction holders." << endl;
cout << "\t8.)Create list of failures." << endl;
cout << "\t9.)Display report card." << endl;
cin >> ch;
switch(ch)
{
case 1: add_rec(); break;
case 2: disp_all(); break;
case 3: search_rno(); break;
case 4: search_name(); break;
case 5: modify_rec(); break;
case 6: delete_rec(); break;
case 7: disp_distinction(); break;
case 8: create_failure(); break;
case 9: disp_repcrd(); break;
}
cout << "Do you want to continue?" << endl;
cin >> op;
}while(tolower(op) == 'y');
}

Related

C++ Run error with wild characters; no compile and build errors

I am using Code::Blocks to write this C++ program, but everytime I do a 3rd Insert on the Link List, and when I use the Display option to check my work, I get a strange error. I have encountered no build errors. Please help check and advise when you have the chance, thank you.
#include <iostream>
#include <fstream>
#include <cmath>
using namespace std;
typedef struct student
{
string name;
int quiz1, quiz2, quiz3;
struct student *nxt;
} STUDENT;
class studentsStruct
{
private:
STUDENT *S; //Header of the Student List
public:
void init();
void add(string n, int a, int b, int c);
void del(string n);
void update(string n);
void save();
void retrieve();
void display();
};
int menu();
int updatemenu();
float round2(float x); // function to round the average and limit to 2 decimal points
int main()
{
studentsStruct ars;
string nm;
int a, b, c;
ars.init(); // Initialize the S Header of the Student List
ars.retrieve(); // Check if the "studentsdb.txt" is available and load the data as needed
while (1)
{
switch (menu())
{
case 1:
system("cls");
cout << "Insert Mode" << endl;
cout << "Name: ";
cin >> nm;
cout << "Input Quiz 1: ";
cin >> a;
cout << "Input Quiz 2: ";
cin >> b;
cout << "Input Quiz 3: ";
cin >> c;
ars.add(nm, a, b, c);
break;
case 2:
system("cls");
cout << "Update Mode" << endl;
cout << "Input Students Name: ";
cin >> nm;
ars.update(nm);
break;
case 3:
system("cls");
cout << "Delete Mode" << endl;
cout << "Enter Name: ";
cin >> nm;
ars.del(nm);
break;
case 4:
ars.display();
break;
case 5:
ars.save();
exit(0);
default:
cout << "1 to 5 only. ";
system("pause");
}
}
return 0;
}
void studentsStruct::init()
{
S = NULL;
}
void studentsStruct::add(string n, int a, int b, int c)
{
STUDENT *p, *q, *temp;
p = q = S;
temp = new STUDENT;
temp->name = n;
temp->quiz1 = a;
temp->quiz2 = b;
temp->quiz3 = c;
while (p != NULL)
{
q = p;
p = p->nxt;
}
if (p == S)
{
S = temp;
}
else
{
q->nxt = temp;
temp->nxt = p;
}
}
void studentsStruct::del(string n)
{
STUDENT *p, *q;
p = q = S;
while (p != NULL && p->name != n)
{
q = p;
p = p->nxt;
}
if (p == NULL)
{
cout << n << (" is not found.") << endl;
system("pause");
}
else
{
if (p == S)
{
S = S->nxt;
}
else
{
q->nxt = p->nxt;
delete (p);
cout << n << (" is deleted from the student records") << endl;
}
}
}
void studentsStruct::update(string n)
{
STUDENT *p, *q;
p = q = S;
int ua, ub, uc;
while (p != NULL && p->name != n)
{
q = p;
p = p->nxt;
}
if (p == NULL)
{
cout << ("Not Found") << endl;
system("pause");
}
else
{
while (1)
{
cout << "Update Mode" << endl;
cout << "Student : " << p->name << endl;
cout << "Quiz 1 Grade: " << p->quiz1 << endl;
cout << "Quiz 2 Grade: " << p->quiz2 << endl;
cout << "Quiz 3 Grade: " << p->quiz3 << endl;
switch (updatemenu())
{
case 1:
cout << "Quiz 1 Grade: ";
cin >> ua;
p->quiz1 = ua;
save();
break;
case 2:
cout << "Quiz 2 Grade: ";
cin >> ub;
p->quiz2 = ub;
save();
break;
case 3:
cout << "Quiz 3 Grade: ";
cin >> uc;
p->quiz3 = uc;
save();
break;
case 4:
main();
save();
break;
default:
cout << "Select an option between 1 to 3" << endl;
cout << "or select 4 to exit the Update Menu: " << endl;
}
}
}
}
int updatemenu()
{
int um;
cout << "Update Menu" << endl;
cout << "1.) Update Quiz 1 Grade" << endl;
cout << "2.) Update Quiz 2 Grade" << endl;
cout << "3.) Update Quiz 3 Grade" << endl;
cout << "4.) Return to the Main Menu" << endl;
cout << "Select an option between 1 to 3" << endl;
cout << "or select 4 to exit the Update Menu: ";
cin >> um;
return (um);
}
void studentsStruct::display()
{
STUDENT *p;
int i = 1;
p = S;
float ave;
string remarks;
system("cls");
cout << "No.\tName\tQuiz 1\tQuiz 2\tQuiz 3\tAverage\tRemarks\n";
while (p != NULL)
{
ave = (p->quiz1 + p->quiz2 + p->quiz3) / 3.0;
remarks = ave >= 75 ? "Passed" : "Failed";
cout << i++ << ".)\t" << p->name << "\t" << p->quiz1 << "\t" << p->quiz2 << "\t" << p->quiz3 << "\t" << round2(ave) << "\t" << remarks << endl;
p = p->nxt;
}
system("pause");
}
int menu()
{
int op;
cout << "Menu" << endl;
cout << "1.) Insert" << endl;
cout << "2.) Update" << endl;
cout << "3.) Delete" << endl;
cout << "4.) Display" << endl;
cout << "5.) Exit" << endl;
cout << "Select(1-5): ";
cin >> op;
return (op);
}
// Save the student data to "studentdb.txt" if available and create a file if needed
void studentsStruct::save()
{
STUDENT *p;
p = S;
ofstream stuData;
stuData.open("studentdb.txt");
while (p != NULL)
{
stuData << p->name << " " << p->quiz1 << " " << p->quiz2 << " " << p->quiz3 << endl;
p = p->nxt;
}
stuData.close();
}
// Check if the "studentdb.txt" is available and load the data as needed
void studentsStruct::retrieve()
{
ifstream fp;
string n;
int ax, by, cz;
fp.open("studentdb.txt");
if (fp.peek() != std::ifstream::traits_type::eof())
{
while (fp >> n >> ax >> by >> cz)
{
add(n, ax, by, cz);
}
}
else
{
cout << "The file is available but contains no records" << endl;
}
fp.close();
}
// function to round the average and limit to 2 decimal points
float round2(float x)
{
return trunc(x * 100.0) / 100.0;
}
And this is the error I am encountering (see screenshot below):

Referencing Class Object Inside of Class Not Working

I am trying to write a Program to solve the Die Hard Bucket Puzzle, Most of the Code works fine except for the Pour Function which references the class objects.
I have double checked the arrhythmic in the pour function and have checked that the function is reading the correct capacities
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
class Bucket{
private:
string name;
int capacity, contents;
public:
Bucket(string name_, int capacity_){
name = name_;
capacity = capacity_;
}
void Print(){
cout << "Bucket Name: " << name << endl;
cout << "Capacity: " << capacity << " Gallons" << endl;
cout << "Contents: " << contents << " Gallons" << endl;
}
void Fill(){
contents = capacity;
}
void Empty(){
contents = 0;
}
void Pour(Bucket A){
if (contents + A.contents > A.capacity){
contents -= A.capacity;
A.contents = A.capacity; //Error Here
}
else{
A.contents += contents; //Error Here
contents = 0;
}
}
};
int main(){
Bucket A1("A", 3), A2("B", 5);
int x;
cout << "0 - Exit" << endl << "1 - Fill Bucket A" << endl;
cout << "2 - Empty Bucket A" << endl << "3 - Pour A into B" << endl;
cout << "4 - Fill Bucket B" << endl << "5 - Empty Bucket B" << endl;
cout << "6 - Pour B into A" << endl << "7 - Print" << endl;
cout << "8 - Solve Die Hard Puzzle" << endl;
cin >> x;
while (x != 0){
switch (x){
case 0:{
return 0;
}
case 1:{
A1.Fill();
A1.Print();
cin >> x;
break;
}
case 2:{
A1.Empty();
A1.Print();
cin >> x;
break;
}
case 3:{
A1.Pour(A2);
A1.Print();
A2.Print();
cin >> x;
break;
}
case 4:{
A2.Fill();
A2.Print();
cin >> x;
break;
}
case 5:{
A2.Empty();
A2.Print();
cin >> x;
break;
}
case 6:{
A2.Pour(A2);
A1.Print();
A2.Print();
cin >> x;
break;
}
case 7:{
A1.Print();
A2.Print();
}
case 8:{
A2.Fill();
A2.Pour(A1);
A2.Fill();
A2.Pour(A1);
A2.Print();
}
default:{
cout << "Invailid Input." << endl;
cin >> x;
break;
}
}
}
return 0;
}
The programming outputs the incorrect contents for the bucket being poured into, outputting 0 instead of the actual number

Unable to solve the probelm

In the adding user section in the code below, I am unable to type any characters for the "Add another person?(y/n): " question. it just jumps back to entering age. How do I fix this?
I've tried to change ans into a string, implement a while loop to force the question to show up, and many other things. It just seems that nothing works and I've been trying it for the good part of two hours
#include <iostream>
#include <string>
#include <Windows.h>
using namespace std;
int main()
{
char ans;
int people;
int option;
int count = 0;
struct data
{
string name;
int age;
char gender;
string comments;
}person[100];
// homescreen
homescreen:
cout << "Welcome to the Data Base!" << endl;
cout << endl;
// displaying all people
for (int list = 0; list < count; list++)
{
cout << list << ".) " << person[list].name << endl;
}
cout << endl;
cout << "[1] View Person" << endl;
cout << "[2] Add Person" << endl;
cout << "[3] Edit Person" << endl;
cout << "[4] Delete Person" << endl;
cout << "[5] Exit" << endl;
cout << "Choose Option: "; cin >> option;
// using options
while (option != 5)
{
if (option == 1)
{
view:
for (int list2 = 0; list2 < count; list2++)
{
cout << list2 << ".) " << person[list2].name << endl;
}
cout << endl;
cout << "Enter number of person you want: "; cin >> people;
system("cls");
cout << "Name: " << person[count].name << endl;
cout << "Age: " << person[count].age << endl;
cout << "Gender: " << person[count].gender << endl;
cout << "Comments: " << person[count].comments << endl << endl;
cout << "View another person?(y/n): "; cin >> ans;
if (ans == 'y')
{
system("cls"); goto view;
}
else if (ans == 'n')
{
system("cls"); goto homescreen;
}
}
if (option == 2)
{
add:
system("cls");
cout << "Name: "; cin >> person[count].name;
system("cls");
cout << "Age: "; cin >> person[count].age;
system("cls");
cout << "Gender(M/F/H): "; cin >> person[count].gender;
system("cls");
cout << "Comments: "; cin >> person[count].comments;
count++;
system("cls");
cout << "Add another person?(y/n): "; cin >> ans;
if (ans == 'y')
{
system("cls");
goto add;
}
else if (ans == 'n')
{
system("cls");
goto homescreen;
}
}
}
}
If you anybody can help me I'd be grateful
The goto statements in your code makes the program really good
spaghetti
structure and that is not
good.
Therefore, think instead of goto other options, such as infinite
while loop which will break once the user enters the n or moving
the code to the function.
Secondly what if you have not entered any persons and choosing the
option 1. You still output the attributes of the person as
count is initialized zero at least. Remember the attributes are
not initialized at this point. Accessing the uninitialized
variables will invoke undefined
behavior. Therefore,
provide a check (something like if(count > 0) )before you execute the code in option 1.
In addition to that, remember that
std::endl flushes the output buffer, and '\n' doesn't. Therefore, most of
the cases you might wanna use just
\n.
Last but not the least, use std::vector instead of the using C style arrays with some predefined size. What if the user has more than 100 inputs? The solution in C++ is std::vector, which can expand dynamically as its storage is handled automatically.
Following is a possible solution to your program, in which the comments will guide you through to the things that I mentioned above.
#include <iostream>
#include <string>
#include <vector>
#include <windows.h>
struct Data
{
std::string name;
int age;
char gender;
std::string comments;
Data(const std::string& n, int a, char g, const std::string& c) // provide a Constructor
:name(n), age(a), gender(g), comments(c)
{}
};
void debugMsg(const std::string& msg)
{
system("cls");
std::cout << "\n\n\t\t" << msg << "\n\n";
Sleep(3000);
}
int main()
{
std::vector<Data> person; // use std::vector to store the datas
while (true) // loop: 1
{
system("cls");
std::cout << "Welcome to the Data Base! \n\n";
std::cout << "[1] View Person\n";
std::cout << "[2] Add Person\n";
std::cout << "[3] Edit Person\n";
std::cout << "[4] Delete Person\n";
std::cout << "[5] Exit\n";
std::cout << "Choose Option: ";
int option; std::cin >> option;
switch (option) // use switch to validate the options
{
case 1:
{
while (true) // loop - 2 -> case 1
{
// if no data available to show -> just break the loop 2 and return to the outer loop(i.e, loop 1)
if (person.empty()) { debugMsg("No person available to show ....going to main manu...."); break; }
// otherwise: displaying all people
for (std::size_t index = 0; index < person.size(); ++index)
std::cout << index << ".) " << person[index].name << "\n";
std::cout << "\nEnter number of person you want: ";
std::size_t index; std::cin >> index;
// if the index is not valid -> just break the loop 2 and return to the outer loop(i.e, loop 1)
if (index < 0 || index >= person.size()) { debugMsg("Sorry, wrong index!... returning to the main menu......"); break; }
system("cls");
std::cout << "Name: " << person[index].name << std::endl;
std::cout << "Age: " << person[index].age << std::endl;
std::cout << "Gender: " << person[index].gender << std::endl;
std::cout << "Comments: " << person[index].comments << std::endl << std::endl;
std::cout << "View another person?(y/n): ";
char ans; std::cin >> ans;
if (ans == 'y') { system("cls"); continue; } // just continue looping
else if (ans == 'n') { break; } // this will break the loop 2 and return to the outer loop(i.e, loop 1)
else { debugMsg("Sorry, wrong option!... returning to the main menu......"); break; }
}
} break;
case 2:
{
while (true) // loop - 3 -> case 2
{
system("cls");
std::string name, comments; int age; char gender;
std::cout << "Name: "; std::cin >> name;
std::cout << "Age: "; std::cin >> age;
std::cout << "Gender(M/F/H): "; std::cin >> gender;
std::cout << "Comments: "; std::cin >> comments;
// simply construct the Data in person vector in place
person.emplace_back(name, age, gender, comments);
std::cout << "\n\nAdd another person?(y/n): ";
char ans; std::cin >> ans;
if (ans == 'y') { system("cls"); continue; }
else if (ans == 'n') { system("cls"); break; } // same as case 1
else { debugMsg("Sorry, wrong option!... returning to the main menu......"); break; }
}
} break;
case 3: { /*code*/ debugMsg("Sorry, Not implemented!... returning to the main menu......"); } break;
case 4: { /*code*/ debugMsg("Sorry, Not implemented!... returning to the main menu......"); } break;
case 5: return 0; // if its 5, just retun the main
default: break;
}
}
return 0;
}
As mentioned above, using "goto" is a bad style, so i would suggest structure your program a little. Below is my version.
Naturally, I did not add any checks and controls, the author will be able to do this on his own. But main logics should work. And, of course, it is better to use vector instead of static array.
#include <iostream>
#include <string>
#include <Windows.h>
using namespace std;
enum options { OPT_VIEW = 1, OPT_ADD = 2, OPT_EDIT = 3, OPT_DELETE = 4, OPT_EXIT = 5 };
struct data
{
string name;
int age;
char gender;
string comments;
};
class App
{
private:
data person[100];
int count = 0;
public:
App();
void Run();
int HomeScreen();
void View();
void Add();
};
App::App() : count(0)
{}
void App::Run()
{
int option = HomeScreen();
while(option != OPT_EXIT)
{
switch(option)
{
case OPT_VIEW:
View();
break;
case OPT_ADD:
Add();
break;
}
option = HomeScreen();
}
}
int App::HomeScreen()
{
int option = 0;
cout << "Welcome to the Data Base!" << endl;
cout << endl;
// displaying all people
for(int list = 0; list < count; list++)
{
cout << list << ".) " << person[list].name << endl;
}
cout << endl;
cout << "[1] View Person" << endl;
cout << "[2] Add Person" << endl;
cout << "[3] Edit Person" << endl;
cout << "[4] Delete Person" << endl;
cout << "[5] Exit" << endl;
cout << "Choose Option: "; cin >> option;
return option;
}
void App::View()
{
char ans = 0;
do
{
int people = 0;
for(int list2 = 0; list2 < count; list2++)
{
cout << list2 << ".) " << person[list2].name << endl;
}
cout << endl;
cout << "Enter number of person you want: "; cin >> people;
system("cls");
cout << "Name: " << person[people].name << endl;
cout << "Age: " << person[people].age << endl;
cout << "Gender: " << person[people].gender << endl;
cout << "Comments: " << person[people].comments << endl << endl;
cout << "View another person?(y/n): "; cin >> ans;
}
while(ans == 'y');
system("cls");
}
void App::Add()
{
char ans = 0;
do
{
system("cls");
cout << "Name: "; cin >> person[count].name;
system("cls");
cout << "Age: "; cin >> person[count].age;
system("cls");
cout << "Gender(M/F/H): "; cin >> person[count].gender;
system("cls");
cout << "Comments: "; cin >> person[count].comments;
count++;
system("cls");
cout << "Add another person?(y/n): "; cin >> ans;
}
while(ans == 'y');
system("cls");
}
int main()
{
App program;
program.Run();
}

C++ MDC Final - Sort Names in Records Alphabetically While in Array Struct of Type Char

I was able to write a program to pass my c++ class in college except for one feature. I was unable to create a function that sorted the names inside an array of structs with name of type char alphabetically. Please advise on how to tackle this problem.
I would need a function that sorts the accountRecords array alphabetically.
#include <iostream>
#include <ctime>
#include <fstream>
#include <string>
#include <vector>
#include <string>
#include <iomanip>
using namespace std;
//Structure Initilizations
const int NAME_SIZE = 25, ADDR_SIZE = 100, CITY_SIZE = 51, STATE_SIZE = 4, DATE_SIZE = 16, CUSTOMER_ID = 10, TRANSACTION_TYPE = 16;
struct MasterRecord
{
int customerID;
char name[NAME_SIZE]; // SORT THIS FIELD ALPHABETICALLY
char address[ADDR_SIZE];
char city[ADDR_SIZE];
char state[STATE_SIZE];
char zip[STATE_SIZE];
float accountBalance;
char lastTransactionDate[15];
};
struct TransactionRecord
{
int customerID;
char transactionType;
float amount;
char transactionDate[15];
};
//File Array Initializations
vector<MasterRecord> masterRecordList(101);
vector<TransactionRecord> transRecordList(101);
//Array List Record Position
int masterRecordArrayPosition = 0;
int transactionRecordArrayPosition = 0;
//User Menu Answer Variable Initialization
int userAnswer = 0;
string recordNotFoundAnswer = "";
//Print Function Prototypes
void showMenu();
void showMasterRecord(int);
void showTransactionRecord(int);
//Main Menu Function Prototypes
void newCustomerRecord(int);
void editCustomerRecord(int);
void deleteCustomerRecord(int);
int randomComputerID();
int searchMasterRecord(int);
void saveAccountRecords();
void saveTransRecords();
void newTransactionRecord(int);
//Placeholders Variables
int customerIDsearch = 0;
int customerIDSearchArrayPosition = 0;
int userNameCharactererror = 0;
//Function Loop Counters
int accountWriteCounter = 0;
int transWriteCounter = 0;
int showRecordCounter = 0;
int showTransCounter = 0;
//System time Declaration and Conversion for [lastTransactionDate]
time_t now = time(0);
tm *ltm = localtime(&now);
string currentYearInString = to_string(1900 + ltm->tm_year);
string currentMonthInString = to_string(1 + ltm->tm_mon);
string currentDayInString = to_string(ltm->tm_mday);
string currentDateInString = currentMonthInString + "/" + currentDayInString + "/" + currentYearInString;
char dateInChar[15];
//Main Program
int main()
{
//Final conversion of time in string to char for storage
strncpy_s(dateInChar, currentDateInString.c_str(), 15);
//Open MasterRecord file and read records to arrays
fstream masterRecord("masterRecord.dat", ios::in | ios::binary);
int listCounter = 0;
if (!masterRecord) {
cout << "Unable to open the user records file, creating file database....Done!" << endl;
masterRecord.open("masterRecord.dat", ios::out | ios::binary);
}
else {
while (!masterRecord.eof()) {
masterRecord.read(reinterpret_cast<char *>(&masterRecordList[listCounter]), sizeof(masterRecordList[0]));
if (masterRecordList[listCounter].customerID != 0) {
listCounter++;
}
masterRecordArrayPosition = listCounter;
}
masterRecord.close();
}
//Open Transaction Record and read to arrays
fstream transactionRecord("transactionRecord.dat", ios::in | ios::binary);
int listCounter2 = 0;
if (!transactionRecord) {
cout << "Unable to open the transaction file, creating file database....Done!" << endl << endl;
transactionRecord.open("transactionRecord.dat", ios::out | ios::binary);
}
else {
while (!transactionRecord.eof()) {
transactionRecord.read(reinterpret_cast<char *>(&transRecordList[listCounter2]), sizeof(transRecordList[0]));
if (transRecordList[listCounter2].customerID != 0) {
listCounter2++;
}
transactionRecordArrayPosition = listCounter2;
}
transactionRecord.close();
}
//Time Declaration Used to Generate Random IDs
srand((unsigned)time(0));
//Main user Program Loop
while (userAnswer != 6) {
showMenu();
cin >> userAnswer; cout << endl;
//Menu Input Data Validation
if (cin.fail()) {
cout << "Please only enter numbers 1-6 for the corresponding menu selection." << endl;
cin.clear();
cin.ignore();
}
else {
if (userAnswer < 1 || userAnswer > 7) {
cout << "Please only enter numbers 1-6 for the corresponding menu selection." << endl;
userAnswer = 0;
}
}
//Menu Selection Switch Case
switch (userAnswer) {
case 1:
newCustomerRecord(masterRecordArrayPosition);
cout << "Record has been saved." << endl << endl;
break;
case 2:
newTransactionRecord(transactionRecordArrayPosition);
break;
case 3:
cout << "Please enter the Customer ID you would like to Delete" << endl << endl; //[Delete Customer Record] Function goes here
cin >> customerIDsearch;
customerIDSearchArrayPosition = searchMasterRecord(customerIDsearch);
if (customerIDSearchArrayPosition != 9999) {
deleteCustomerRecord(customerIDSearchArrayPosition);
}
break;
case 4:
cout << "Please enter the Customer ID you would like to edit." << endl << endl; //[Search/Edit Customer Record] Function goes here
cin >> customerIDsearch;
customerIDSearchArrayPosition = searchMasterRecord(customerIDsearch);
if (customerIDSearchArrayPosition != 9999) {
editCustomerRecord(customerIDSearchArrayPosition);
}
else {
cout << "Record was not found, would you like to add a new record? Y = Yes, N = No" << endl << endl;
cin >> recordNotFoundAnswer;
if (recordNotFoundAnswer == "Y" | recordNotFoundAnswer == "y") {
newCustomerRecord(masterRecordArrayPosition);
cout << "Record has been saved." << endl << endl;
}
else if (recordNotFoundAnswer == "N" | recordNotFoundAnswer == "n") {
userAnswer = 0;
}
}
break;
case 5:
cout << setw(212) << "Please find all customer records in the database" << endl << endl; //[Show all Records] Function goes here
cout << setw(40) << "Name:" << setw(10) << "ID:" << setw(23) << "Street Address:" <<setw(10) << "ZIP:" << setw(16) << "L.Trans Date:" << setw(11) << "Balance: " << endl;
while (showRecordCounter < 100) {
if (masterRecordList[showRecordCounter].customerID != 0) {
showMasterRecord(showRecordCounter);
}
showRecordCounter = showRecordCounter + 1;
} showRecordCounter = 0;
userAnswer = 0;
cout << endl;
break;
case 6:
cout << "Saving changes to database...Done!" << endl;
saveAccountRecords();
saveTransRecords();
cout << "Done!" << endl;
break;
case 7:
cout << "Showing all transaction Records:" << endl << endl;
while (showTransCounter < 100) {
if (transRecordList[showTransCounter].customerID != 0) {
showTransactionRecord(showTransCounter);
}
showTransCounter = showTransCounter + 1;
} showTransCounter = 0;
userAnswer = 0;
break;
}
}
return 0;
}
//Databas Management Functions
void saveAccountRecords() {
fstream masterRecord("masterRecord.dat", ios::out | ios::binary);
while (accountWriteCounter < 100) {
masterRecord.write(reinterpret_cast<char *>(&masterRecordList[accountWriteCounter]), sizeof(masterRecordList[0]));
accountWriteCounter++;
}
masterRecord.close();
}
void saveTransRecords() {
fstream transRecord("transactionRecord.dat", ios::out | ios::binary);
while (transWriteCounter < 100) {
transRecord.write(reinterpret_cast<char *>(&transRecordList[transWriteCounter]), sizeof(transRecordList[0]));
transWriteCounter++;
}
transRecord.close();
}
//Random Function
int randomComputerID() {
int randomNumber;
randomNumber = (rand() % 1000) + 10000;
return randomNumber;
}
//Program Print Functions
void showMenu() {
cout << "Welcome to your C++ company terminal! Please enter one of the options below to continue." << endl << endl;
cout << "1. New Customer Record" << endl;
cout << "2. New Transaction Record" << endl;
cout << "3. Delete Customer Record" << endl;
cout << "4. Edit Customer Record" << endl;
cout << "5. Show all Account Records in Database" << endl;
cout << "6. Exit and Save Changes to Database" << endl << endl;
cout << "Please enter the number for the correspondent action you would like to perform:" << endl;
}
void showMasterRecord(int arrayNum) {
cout << setw(40)
<< masterRecordList[arrayNum].name << setw(10) << masterRecordList[arrayNum].customerID << setw(23)
<< masterRecordList[arrayNum].address << setw(10)
<< masterRecordList[arrayNum].zip << setw(16)
<< masterRecordList[arrayNum].lastTransactionDate << setw(6) <<"$"
<< masterRecordList[arrayNum].accountBalance; cout << endl;
}
void showTransactionRecord(int arrayNum) {
cout << "Customer ID: " << transRecordList[arrayNum].customerID << endl;
cout << "Amount: $" << transRecordList[arrayNum].amount << endl;
cout << "Transaction Type: " << transRecordList[arrayNum].transactionType << endl;
cout << "Transaction Date: " << transRecordList[arrayNum].transactionDate << endl << endl;
}
//Main Menu Functions [Please insert your functions here and prototype them above].
void newCustomerRecord(int arrayNum) {
cout << "Customer ID: ";
masterRecordList[arrayNum].customerID = randomComputerID();
cout << masterRecordList[arrayNum].customerID; cout << endl;
cin.ignore();
do
{
cout << "Name: ";
cin.getline(masterRecordList[arrayNum].name, 25);
if (cin.fail()) {
cout << endl << "Please enter only characters up 25 chracters for your name." << endl;
userNameCharactererror = 1;
cin.clear();
cin.ignore(80, '\n');
}
else {
userNameCharactererror = 0;
}
} while (userNameCharactererror == 1);
cout << "Address: ";
cin.getline(masterRecordList[arrayNum].address, 100);
cout << "City: ";
cin >> masterRecordList[arrayNum].city;
cout << "State: ";
cin >> masterRecordList[arrayNum].state;
cout << "Zip Code: ";
cin >> masterRecordList[arrayNum].zip;
cout << "Opening Balance: $";
cin >> masterRecordList[arrayNum].accountBalance; cout << endl; cout << endl;
masterRecordArrayPosition = masterRecordArrayPosition + 1;
}
void editCustomerRecord(int arrayNum) {
cout << "Customer ID: ";
cout << masterRecordList[arrayNum].customerID; cout << endl;
cin.ignore();
cout << "Name: ";
cin.getline(masterRecordList[arrayNum].name, 51);
cout << "Address: ";
cin.getline(masterRecordList[arrayNum].address, 100);
cout << "City: ";
cin >> masterRecordList[arrayNum].city;
cout << "State: ";
cin >> masterRecordList[arrayNum].state;
cout << "Zip Code: ";
cin >> masterRecordList[arrayNum].zip;
cout << "Edit Balance: $";
cin >> masterRecordList[arrayNum].accountBalance; cout << endl; cout << endl;
}
void deleteCustomerRecord(int arrayNum) {
if (masterRecordList[arrayNum].accountBalance == 0)
{
masterRecordList[arrayNum].customerID = 0;
cout << "Record has been deleted" << endl << endl;
}
else {
cout << "Unable to delete record, customer accounts holds a positive balance" << endl << endl;
}
}
int searchMasterRecord(int customerID) //Search by customer name and returns array position
{
int arrayPosition = 0;
int arrayCounter = 0;
int customerIdPlaceholder = 0;
while (arrayCounter < 100) {
customerIdPlaceholder = masterRecordList[arrayCounter].customerID;
if (customerIdPlaceholder == customerID) {
cout << "Record has been found!" << endl << endl;
arrayPosition = arrayCounter;
arrayCounter = 100;
}
else {
arrayPosition = 9999;
}
arrayCounter = arrayCounter + 1;
}
return arrayPosition;
};
void newTransactionRecord(int arrayNum) {
// Request customer ID and transaction type from the user
cout << "Customer ID: ";
cin >> transRecordList[arrayNum].customerID;
cin.ignore();
cout << "Date: ";
strncpy_s(transRecordList[arrayNum].transactionDate, dateInChar, 15);
cout << transRecordList[arrayNum].transactionDate << endl;
cout << "Transaction Type [D = Deposit] [W = Withdrawal]: ";
cin >> transRecordList[arrayNum].transactionType;
cout << "Amount: $";
cin >> transRecordList[arrayNum].amount;
//Search for customer account, update balance, and assign last transaction date
customerIDSearchArrayPosition = searchMasterRecord(transRecordList[arrayNum].customerID);
if (customerIDSearchArrayPosition != 9999) {
if (transRecordList[arrayNum].transactionType == 'D') {
masterRecordList[customerIDSearchArrayPosition].accountBalance = masterRecordList[customerIDSearchArrayPosition].accountBalance + transRecordList[arrayNum].amount;
strncpy_s(masterRecordList[customerIDSearchArrayPosition].lastTransactionDate, dateInChar, 9);
cout << "Deposit Successful! " << endl << endl;
}
else if (transRecordList[arrayNum].transactionType == 'W') {
masterRecordList[customerIDSearchArrayPosition].accountBalance = masterRecordList[customerIDSearchArrayPosition].accountBalance - transRecordList[arrayNum].amount;
strncpy_s(masterRecordList[customerIDSearchArrayPosition].lastTransactionDate, dateInChar, 9);
cout << "Withdrawl Successful" << endl << endl;
}
}
else {
cout << "Customer account record was not found, transaction was not saved." << endl << endl;
}
transactionRecordArrayPosition = transactionRecordArrayPosition + 1;
}
Something along these lines:
std::sort(masterRecordList.begin(),
masterRecordList.begin() + masterRecordArrayPosition,
[](const MasterRecord& l, const MasterRecord& r) {
return strcmp(l.name, r.name) < 0;
});

Why won't my ofstream work when I put it outside my while statement?

Every time I do anything, and my while(1) gets called in my main function, my file gets cleared. It's driving me crazy. I've tried EVERYTHING. I try to put my ofstream out("data.dat"); outside the while(1) statement so it isn't called everytime but then nothing is written to the file like the ofstream isn't even working!
I've tried to make the ofstream static, so it isn't called over and over again like:
static ofstream open("data.dat");
That doesn't work.
And like I said, when I put the ofstream OUTSIDE the while statement, nothing is written to the file. Like:
ofstream out("data.dat");
while (1)
{
string line = "";
cout << "There are currently " << structList.size() << " items in memory.";
cout << endl << endl;
cout << "Commands: " << endl;
cout << "1: Add a new record " << endl;
cout << "2: Display a record " << endl;
cout << "3: Edit a current record " << endl;
cout << "4: Delete a record " << endl;
cout << "5: Save current information " << endl;
cout << "6: Exit the program " << endl;
cout << endl;
cout << "Enter a command 1-6: ";
getline(cin , line);
int rValue = atoi(line.c_str());
system("cls");
switch (rValue)
{
case 1:
structList = addItem(structList);
break;
case 2:
displayRecord(structList);
break;
case 3:
structList = editRecord(structList);
break;
case 4:
deleteRecord(structList);
break;
case 5:
if (!structList.size()) { cout << "There are no items to save! Enter one first!" << endl << endl; system("pause"); system("cls"); break; }
writeVector(out , structList);
break;
case 6:
return 0;
default:
cout << "Command invalid. You can only enter a command number 1 - 6. Try again. " << endl;
}
out.close();
}
And can someone tell me why my check to prevent reading of a empty file won't work?
My Check:
bool checkFileEmpty()
{
ifstream in("data.dat");
if (in.peek() == in.eofbit)
{
return true;
}
return false;
}
I am so sick and tired of my program crashing on startup over and over again because my vector is getting set to a size of 200 million. I've tried a BUNCH of stuff for this... none of it works... Please GOD someone help me with both of these! I've been up for 18 hours working on this ( all night yes ) and i'm ALMOST done. I'm begging you....
My Code:
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace System;
using namespace std;
#pragma hdrstop
bool isValidChoice(int size, int choice);
bool checkFileEmpty();
template<typename T>
void writeVector(ofstream &out, const vector<T> &vec);
template<typename T>
vector<T> readVector(ifstream &in);
template<typename T>
vector<T> addItem(vector<T> &vec);
template<typename T>
void printItemDescriptions(vector<T> &vec);
template<typename T>
int displayRecord(vector<T> &vec);
template<typename T>
vector<T> editRecord(vector<T> &vec);
template<typename T>
vector<T> deleteRecord(vector<T> &vec);
struct InventoryItem {
string Description;
int Quantity;
int wholesaleCost;
int retailCost;
string dateAdded;
} ;
int main(void)
{
cout << "Welcome to the Inventory Manager extreme! [Version 1.0]" << endl;
ifstream in("data.dat");
if (in.is_open()) { cout << "File \'data.dat\' has been opened successfully." << endl; } else { cout << "Error opening data.dat" << endl;}
cout << "Loading data..." << endl;
vector<InventoryItem> structList = readVector<InventoryItem>( in );
cout <<"Load complete." << endl << endl;
in.close();
while (1)
{
string line = "";
cout << "There are currently " << structList.size() << " items in memory.";
cout << endl << endl;
cout << "Commands: " << endl;
cout << "1: Add a new record " << endl;
cout << "2: Display a record " << endl;
cout << "3: Edit a current record " << endl;
cout << "4: Delete a record " << endl;
cout << "5: Save current information " << endl;
cout << "6: Exit the program " << endl;
cout << endl;
cout << "Enter a command 1-6: ";
getline(cin , line);
int rValue = atoi(line.c_str());
system("cls");
ofstream out("data.dat");
switch (rValue)
{
case 1:
structList = addItem(structList);
break;
case 2:
displayRecord(structList);
break;
case 3:
structList = editRecord(structList);
break;
case 4:
deleteRecord(structList);
break;
case 5:
if (!structList.size()) { cout << "There are no items to save! Enter one first!" << endl << endl; system("pause"); system("cls"); break; }
writeVector(out , structList);
break;
case 6:
return 0;
default:
cout << "Command invalid. You can only enter a command number 1 - 6. Try again. " << endl;
}
out.close();
}
system("pause");
return 0;
}
template<typename T>
void writeVector(ofstream &out, const vector<T> &vec)
{
out << vec.size();
for(vector<T>::const_iterator i = vec.begin(); i != vec.end(); i++)
{
out << *i;
}
cout << "Save completed!" << endl << endl;
}
ostream &operator<<(ostream &out, const InventoryItem &i)
{
out << i.Description << ' ';
out << i.Quantity << ' ';
out << i.wholesaleCost << ' ' << i.retailCost << ' ';
out << i.dateAdded << ' ';
return out;
}
istream &operator>>(istream &in, InventoryItem &i)
{
in >> i.Description;
in >> i.Quantity;
in >> i.wholesaleCost >> i.retailCost;
in >> i.dateAdded;
return in;
}
template<typename T>
vector<T> readVector(ifstream &in)
{
size_t size;
if (checkFileEmpty())
{
size = 0;
} else {
in >> size;
}
vector<T> vec;
vec.reserve(size);
for(unsigned int i = 0; i < size; i++)
{
T tmp;
in >> tmp;
vec.push_back(tmp);
}
return vec;
}
template<typename T>
vector<T> addItem(vector<T> &vec)
{
system("cls");
string word;
unsigned int number;
InventoryItem newItem;
cout << "-Add a new item-" << endl << endl;
cout << "Enter the description for the item: ";
getline (cin , word);
newItem.Description = word;
cout << endl;
cout << "Enter the quantity on hand for the item: ";
getline (cin , word);
number = atoi(word.c_str());
newItem.Quantity = number;
cout << endl;
cout << "Enter the Retail Cost for the item: ";
getline (cin , word);
number = atoi(word.c_str());
newItem.retailCost = number;
cout << endl;
cout << "Enter the Wholesale Cost for the item: ";
getline (cin , word);
number = atoi(word.c_str());
newItem.wholesaleCost = number;
cout << endl;
cout << "Enter current date: ";
getline (cin , word);
newItem.dateAdded = word;
vec.push_back(newItem);
return vec;
}
template<typename T>
void printItemDescriptions(vector<T> &vec)
{
int size = vec.size();
if (size)
{
cout << "---------------------------------" << endl;
cout << "| ~ Item Descriptions ~ |" << endl;
cout << "---------------------------------" << endl;
cout << "*********************************" << endl;
for (int i = 0 ; i < size ; i++)
{
cout << "(" << i+1 << ")" << ": " << vec[i].Description << endl;
}
cout << "*********************************" << endl << endl;
}
}
template<typename T>
int displayRecord(vector<T> &vec)
{
string word = "";
string quit = "quit";
int choice = 1;
int size = vec.size();
if (size)
{
printItemDescriptions(vec);
cout << endl;
while (1)
{
cout << "Type \"exit\" to return to the Main Menu." << endl << endl;
cout << "Enter \"list\" to re-display the items." << endl << endl;
cout << endl;
cout << "Pick the number of the item you would like to display: ";
getline (cin , word);
if (convertToLower(word) == "exit") { system("cls"); return 0; }
if (convertToLower(word) == "list") { system("cls"); displayRecord(vec); }
choice = atoi(word.c_str());
choice -= 1;
if (isValidChoice(size, choice))
{
system("cls");
cout << endl << "[Item (" << choice << ") details] " << endl << endl;
cout << "******************" << endl;
cout << "* Description * " << vec[choice].Description << endl;
cout << "******************" << endl << endl;
cout << "******************" << endl;
cout << "*Quantity On Hand* " << vec[choice].Quantity << endl;
cout << "******************" << endl << endl;
cout << "******************" << endl;
cout << "* Wholesale Cost * " << vec[choice].wholesaleCost << endl;
cout << "****************** " << endl << endl;
cout << "******************" << endl;
cout << "* Retail Cost * " << vec[choice].retailCost << endl;
cout << "****************** " << endl << endl;
cout << "******************" << endl;
cout << "* Data Added * " << vec[choice].dateAdded << endl;
cout << "****************** " << endl << endl;
} else { system("cls"); cout << "That item doesn't exist!" << endl; cout << "Pick another item or enter \"list\" to see available items." << endl << endl; }
}
} else { cout << "There are currently no items to display." << endl << endl; system("pause"); system("cls"); return 0; }
return 1;
}
bool isValidChoice(int size, int choice)
{
for (int i = 0 ; i <= size ; i++)
{
if (choice == i) { return true; }
}
return false;
}
string convertToLower(string word)
{
for (unsigned int i = 0 ; i < word.size() ; i++)
{
word[i] = tolower(word[i]);
}
return word;
}
bool checkFileEmpty()
{
ifstream in("data.dat");
if (in.peek() == in.eofbit)
{
return true;
}
return false;
}
template<typename T>
vector<T> editRecord(vector<T> &vec)
{
string word;
int choice;
printItemDescriptions(vec);
cout << "Choose item to edit: ";
getline ( cin, word );
choice = atoi(word.c_str());
system("cls");
unsigned int number;
InventoryItem newItem;
cout << "-Edit an item-" << endl << endl;
cout << "Enter the description for the item: ";
getline (cin , word);
vec[choice-1].Description = word;
cout << endl;
cout << "Enter the quantity on hand for the item: ";
getline (cin , word);
number = atoi(word.c_str());
vec[choice-1].Quantity = number;
cout << endl;
cout << "Enter the Retail Cost for the item: ";
getline (cin , word);
number = atoi(word.c_str());
vec[choice-1].retailCost = number;
cout << endl;
cout << "Enter the Wholesale Cost for the item: ";
getline (cin , word);
number = atoi(word.c_str());
vec[choice-1].wholesaleCost = number;
cout << endl;
cout << "Enter current date: ";
getline (cin , word);
vec[choice-1].dateAdded = word;
system("cls");
cout << "Item edited successfully! " << endl;
return vec;
}
template<typename T>
vector<T> deleteRecord(vector<T> &vec)
{
if (!vec.size()) { cout << "There are no items to delete!" << endl << endl; return vec; }
printItemDescriptions(vec);
string word;
int choice;
cout << "Choose item to delete: ";
getline( cin, word);
choice = atoi(word.c_str());
vec.erase (vec.begin()+choice-1);
return vec;
}
You'd better move the ofstream openning and closing inside case 5.
Here you create a new file at each while iteration.
case 5:
{
ofstream out("data.dat");
writeVector(out , structList);
out.close();
}
break;
ofstream out("data.dat");
Opens the file for writing. By default, it will start at the very beginning wiping out anything that was there previously. First, use a different output file than the file you are reading from.
Try adding the close to the case 6 statements:
case 6:
out.close();
return 0;
I'm pretty sure the close isn't getting called as the return will exit main before getting to that statement. With the file unclosed you are left with a buffer unflushed and I suspect that will leave the data unwritten.
You should move the open to before the while loop and also remove the out.close() from the while loop as it's going to close the file after the first menu selection.
To check if a file is empty or cannot be opened
bool IsEmpty( const std::string & filename ) {
std::ifstream ifs( filename.c_str() );
if ( ifs.is_open() ) {
std::string line;
return ! std::getline( ifs, line );
}
else {
return true;
}
}