I have an Addressbook C++ program that compiles and everything, but I cannot figure out how to write it to a file that saves the data each time it exits. Here is my code:
//AddressBook Program
#include <iostream>
#include <string.h>
#include <cstdlib>
#include <stdio.h>
using namespace std;
class AddressBook{
public :
AddressBook()
{
count = 0;
}
void AddEntry();
void DisplayAll();
void DisplayEntry(int i); // Displays one entry
void SearchEntry();
int MainMenu();
struct Entry_Struct
{
char firstName[ 15 ] ;
char lastName[ 15 ] ;
char birthday[ 15 ] ;
char phone[ 15 ] ;
char email[ 15 ] ;
};
Entry_Struct entries[100];
unsigned int count;
};
void AddressBook::AddEntry()
{
cout << "Entry number " << (count + 1) << " : " << endl;
cout << "Enter First Name: ";
cin >> entries[count].firstName;
cout << "Enter Last Name: ";
cin >> entries[count].lastName;
cout << "Enter Date of Birth: ";
cin >> entries[count].birthday;
cout << "Enter Phone Number: ";
cin >> entries[count].phone;
cout << "Enter Email: ";
cin >> entries[count].email;
++count; // tally total entry count
}
void AddressBook::DisplayEntry(int i)
{
cout << "Entry[" << i + 1 << "] : " << endl; // states # of entry
cout << "First name : " << entries[i].firstName << endl;
cout << "Last name : " << entries[i].lastName << endl;
cout << "Date of birth : " << entries[i].birthday << endl;
cout << "Phone number : " << entries[i].phone << endl;
cout << "Email: " << entries[i].email << endl;
}
void AddressBook::DisplayAll()
{
cout << "Number of entries : " << count << endl;
for(int i = 0;i < count;++i)
DisplayEntry(i);
}
void AddressBook::SearchEntry()
{
char lastname[32];
cout << "Enter last name : ";
cin >> lastname;
for(int i = 0;i < count;++i)
{
if(strcmp(lastname, entries[i].lastName) == 0)
{
cout << "Found ";
DisplayEntry(i);
cout << endl;
}
}
}
// Your class
AddressBook my_book;
int MainMenu()
{
int num;
bool bQuit = false;
// Put all your code into a while loop.
while(bQuit == false)
{
cout << "+-------------------------------------+" << endl;
cout << "| Address Book Menu |" << endl;
cout << "| |" << endl;
cout << "| 1- Add an entry |" << endl;
cout << "| 2- Search for an entry by last name |" << endl;
cout << "| 3- Display all entries |" << endl;
cout << "| 4- Exit |" << endl;
cout << "| |" << endl;
cout << "+-------------------------------------+" << endl;
cout << endl;
cout << "Please enter a number for one of the above options: ";
cin >> num;
cout << endl;
if (num == 1)
my_book.AddEntry();
else if (num == 2)
my_book.SearchEntry();
else if (num == 3)
my_book.DisplayAll();
else if (num == 4)
bQuit = true;
else
cout << "Invalid choice. Please try again" << endl;
cout << endl;
}
return 0;
}
int main (){
MainMenu();
return 0;
}
I've gone over my textbook all day and nothing I'm doing is working.
Here is a basic example of opening, and writing an output file,
// basic file operations
#include <iostream>
#include <fstream>
using namespace std;
int main () {
ofstream outfile;
outfile.open ("addressbook.txt");
outfile << "Daffy,Duck,123 Main Street,Anytown,OH,USA,123-456-7890\n";
myfile.close();
return 0;
}
You need to have an inserter for your class. It's done using operator <<:
// Inside your class:
friend std::istream& operator<<(std::ostream& os, const AddressBook ab)
{
return os << /* ... */
}
As you can see, a user-defined operator << can be implemented in terms of the pre-defined standard inserter. You can use it in the following way:
std::ifstream in("yourtxtfile.txt");
in << my_book;
Related
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;
});
I'm working on an assignment in my first semester of C++ and I just can't figure out working syntax for it. I need to pass a struct as a parameter to a class function using a pointer. This code I've copied is my best attempt, and it will compile but it crashes when it asks for the first name. When I try variations in the syntax, I get errors about incomplete struct, undefined variables (warrior was or invalid operators. What am I doing wrong?
#include <iostream>
using namespace std;
class StarWars
{
public:
int totalNumber;
struct data_clone
{
int ID, timeCounter;
string name;
};
data_clone *warrior;
void createClone()
{
cout << "How many clone warriors do you want to create in total?" << endl;
cin >> totalNumber;
}
void input(struct data_clone *pointer, int total)
{
for(int i = 1; i <= total; i++)
{
cout << "For warrior number " << i << ":" << endl;
cout << "What is the warrior's name?" << endl;
cin >> pointer[i].name;
cout << "What is the warrior's ID number?" << endl;
cin >> pointer[i].ID;
cout << "What is the warrior's time counter?" << endl;
cin >> pointer[i].timeCounter;
}
}
void lifeSpan(struct data_clone *pointer, int total)
{
for(int i = 1; i <= total; i++)
{
cout << "Warrior number " << pointer[i].name << ": " << endl;
while(pointer[i].timeCounter > 0)
{
cout << "Warrior name: " << pointer[i].name << endl;
cout << "Warrior ID number: " << pointer[i].ID << endl;
cout << "Warrior time counter: " << pointer[i].timeCounter << endl;
cout << "Clone is alive." << endl;
pointer[i].timeCounter--;
}
cout << "Warrior name: " << pointer[i].name << endl;
cout << "Warrior ID number: " << pointer[i].ID << endl;
cout << "Warrior time counter: " << pointer[i].timeCounter << endl;
cout << "Clone is dead." << endl;
}
}
};
int main(void)
{
StarWars clones;
clones.createClone();
clones.input(clones.warrior, clones.totalNumber);
clones.lifeSpan(clones.warrior, clones.totalNumber);
}
You don't initialise the memory warrior points to, so you're working with uninitiailised memory - always a bad thing. There's two things to keep in mind here:
When working with pointers, always initialise the memory behind them first. Prefer using RAII concepts like std::unique_ptr / std::shared_ptr
void DoStuff(Widget* w);
std::unique_ptr<Widget> pw = std::make_unique<Widget>();
DoStuff(w.get());
When working with normal variables, use the dereference / reference operators to take a pointer to the variable.
void DoStuff(Widget* w);
Widget widget;
DoStuff(&w);
struct data_clone
{
int ID, timeCounter;
string name;
};
class StarWars
{
private:
data_clone *warrior;
int totalNumber;
public:
StarWars()
{
}
~StarWars()
{
delete[] warrior; // clean up
}
void createClone();
void input();
void lifeSpan();
};
void StarWars::createClone()
{
cout << "How many clone warriors do you want to create in total?" << endl;
cin >> totalNumber;
// construct structure baased on input
warrior = new data_clone[totalNumber];
}
void StarWars::input()
{
for(int i = 0; i < totalNumber; i++)
{
cout << "For warrior number " << i+1 << ":" << endl;
cout << "What is the warrior's name?" << endl;
cin >> warrior[i].name;
cout << "What is the warrior's ID number?" << endl;
cin >> warrior[i].ID;
cout << "What is the warrior's time counter?" << endl;
cin >> warrior[i].timeCounter;
}
}
void StarWars::lifeSpan()
{
std::cout<<"**********Print data**********\n";
for(int i = 0; i < totalNumber; i++)
{
cout << "Warrior number " << warrior[i].name << ": " << endl;
while(warrior[i].timeCounter > 0)
{
cout << "Warrior name: " << warrior[i].name << endl;
cout << "Warrior ID number: " << warrior[i].ID << endl;
cout << "Warrior time counter: " << warrior[i].timeCounter << endl;
cout << "Clone is alive." << endl;
warrior[i].timeCounter--;
}
cout << "Warrior name: " << warrior[i].name << endl;
cout << "Warrior ID number: " << warrior[i].ID << endl;
cout << "Warrior time counter: " << warrior[i].timeCounter << endl;
cout << "Clone is dead." << endl;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
StarWars clones;
clones.createClone();
clones.input();
clones.lifeSpan();
return 0;
}
You never created your clones, you only read how many there should be.
Allocate space for them:
void createClone()
{
cout << "How many clone warriors do you want to create in total?" << endl;
cin >> totalNumber;
warrior = new data_clone[totalNumber];
}
Your array indexes are also off - an array of size N is indexed from 0 to N - 1.
But the more common way of handling this is to pass the amount to the constructor and let the object handle its own members:
class StarWars
{
public:
StarWars(int clones)
: totalNumber(clones),
warrior(new data_clone[clones])
{
}
void input()
{
for(int i = 0; i < totalNumber; i++)
{
cout << "For warrior number " << i << ":" << endl;
cout << "What is the warrior's name?" << endl;
cin >> warrior[i].name;
cout << "What is the warrior's ID number?" << endl;
cin >> warrior[i].ID;
cout << "What is the warrior's time counter?" << endl;
cin >> warrior[i].timeCounter;
}
}
void lifeSpan()
{
for(int i = 0; i < totalNumber; i++)
{
cout << "Warrior number " << i << ": " << endl;
while(warrior[i].timeCounter > 0)
{
cout << "Warrior name: " << warrior[i].name << endl;
cout << "Warrior ID number: " << warrior[i].ID << endl;
cout << "Warrior time counter: " << warrior[i].timeCounter << endl;
cout << "Clone is alive." << endl;
warrior[i].timeCounter--;
}
cout << "Warrior name: " << warrior[i].name << endl;
cout << "Warrior ID number: " << warrior[i].ID << endl;
cout << "Warrior time counter: " << warrior[i].timeCounter << endl;
cout << "Clone is dead." << endl;
}
}
private:
int totalNumber;
struct data_clone
{
int ID, timeCounter;
string name;
};
data_clone *warrior;
};
int main()
{
int number = 0;
cout << "How many clone warriors do you want to create in total?" << endl;
cin >> number;
StarWars clones(number);
clones.input();
clones.lifeSpan();
}
Note that you need to handle the destructor, the copy constructor, and the assignment operator properly as well (left as an exercise).
class StarWars
{
private:
struct data_clone
{
int ID, timeCounter;
string name;
};
public:
StarWars()
{
warrior = new data_clone[4];
}
~StarWars()
{
delete[] warrior;
}
int totalNumber;
data_clone *warrior;
void createClone()
{
cout << "How many clone warriors do you want to create in total?" << endl;
cin >> totalNumber;
}
void input(struct data_clone *pointer, int total)
{
for(int i = 0; i < total; i++)
{
cout << "For warrior number " << i << ":" << endl;
cout << "What is the warrior's name?" << endl;
cin >> pointer[i].name;
cout << "What is the warrior's ID number?" << endl;
cin >> pointer[i].ID;
cout << "What is the warrior's time counter?" << endl;
cin >> pointer[i].timeCounter;
}
}
void lifeSpan(struct data_clone *pointer, int total)
{
for(int i = 0; i < total; i++)
{
cout << "Warrior number " << pointer[i].name << ": " << endl;
while(pointer[i].timeCounter > 0)
{
cout << "Warrior name: " << pointer[i].name << endl;
cout << "Warrior ID number: " << pointer[i].ID << endl;
cout << "Warrior time counter: " << pointer[i].timeCounter << endl;
cout << "Clone is alive." << endl;
pointer[i].timeCounter--;
}
cout << "Warrior name: " << pointer[i].name << endl;
cout << "Warrior ID number: " << pointer[i].ID << endl;
cout << "Warrior time counter: " << pointer[i].timeCounter << endl;
cout << "Clone is dead." << endl;
}
}
};
Note: I just hardcoded it which is not the correct way, it force you to enter only 4 tyeps of dataclone
"warrior = new data_clone[4];"
you will at least get your result
So, I have several fields to fill in with numerals. And if I try to fill in the input with letters (ex. 'noway' or 'gg1337' - it makes and error and asks for a valid number (without letters for ex. '13' or '1500000').
BUT there is one problem, if I start to fill the input with numbers and then I add some letters (for ex. '12nowshithappens'), this jumps to the next field of input, thinking it is a valid number, but showing an error in the next input field.
Here is the function code:
int appled()
{
cin >> appleds;
while(cin.fail())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
cout << "An arror occured!\nPlease, enter a valid number: ";
cin >> appleds;
}
return appleds;
}
If I described something wrong - here is the full code of my test program :)
// exZerry presents
#include <iostream>
#include <conio.h>
int apples;
int fruit;
int oranges;
int x;
int appleds;
int orangeds;
using std::cout;
using std::cin;
using std::endl;
using std::numeric_limits;
using std::streamsize;
char newline = '\n';
bool ok;
bool ok2;
bool ok3;
int appled() //Function to receive 'apples' input
{
cin >> appleds;
while(cin.fail())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
cout << "An arror occured!\nPlease, enter a valid number: ";
cin >> appleds;
}
return appleds;
}
int oranged() //Function to receive 'oranges' input
{
cin >> orangeds;
while(cin.fail())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
cout << "An arror occured!\nPlease, enter a valid number: ";
cin >> orangeds;
}
return orangeds;
}
int main()
{
ok = ok2 = ok3 = false; //Some testing
while(!ok2) //Actual program loop
{
x = 0; // Dropping program restart.
//cout << "-----------------------" << endl;
//cout << "DEBUG MODE: " << x << endl;
//cout << "-----------------------" << endl;
cout << "=====================================================" << endl;
cout << "Enter apples: ";
apples = appled();
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n'); //Now we have apples
cout << "Enter oranges: ";
apples = oranged();
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n'); //And now we have oranges
cout << "\n=====================================================" << endl;
cout << "Calculating..." << endl;
cout << "=====================================================" << endl;
fruit = apples + oranges;
cout << "In total we have " << fruit << " fruit" << endl;
cout << "=====================================================" << endl;
cout << newline;
//Option to go out or continue the loop
//If you enter 1 - resets the program, any other char - exit
cout << "Go out? (1 - 'No', Others - 'Yeap'):" << " ";
cin >> x;
cout << newline;
// ok2 = true;
if (x == 1)
{
cout << "Continue the program..." << endl;
//cout << "-----------------------" << endl;
//cout << "DEBUG MODE: " << x << endl;
//cout << "-----------------------" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
ok = false;
ok3 = false;
continue;
}
if (x == 0)
{
cout << "Shutting down the app..." << x << endl;
//cout << "-----------------------" << endl;
//cout << "DEBUG MODE: " << x << endl;
//cout << "-----------------------" << endl;
break;
}
else
{
cout << "Shutting down the app..." << x << endl;
//cout << "-----------------------" << endl;
//cout << "DEBUG MODE: " << x << endl;
//cout << "-----------------------" << endl;
break;
}
}
cout << "Press any key to exit :D" << endl;
getch();
return 0;
}
You can make your own facet that parses character sequence like that add invalid. Like this:
class num_get : public std::num_get<char>
{
public:
iter_type do_get( iter_type it, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, long& v) const
{
auto& ctype = std::use_facet<std::ctype<char>>(str.getloc());
it = std::num_get<char>::do_get(it, end, str, err, v);
if (it != end && !(err & std::ios_base::failbit)
&& ctype.is(ctype.alpha, *it))
err |= std::ios_base::failbit;
return it;
}
};
Now you can install it into your stream:
std::locale orig(std::cin.getloc());
std::cin.imbue(std::locale(orig, new num_get));
while (!(std::cin >> appleds)) {
// input was not entirely numeric
}
// input was entirely numeric
So I tried and it worked, thanks, Batmaaaan :D
Adding full working code. What's it doing? Simple: When you wish to count something and you obviously do not want to count letters in your program, this might help you to do it, while styding C++ or whatever. Some basics, I guess, for everyone =)
Made and tested in Visual Studio 2012. Took some time to gather every peace of code in one place.
// exZerry presents
// Apples & Oranges V2.1
#include <iostream>
#include <conio.h>
int apples;
int juce;
int oranges;
int x;
int appleds;
int orangeds;
using std::cout;
using std::cin;
using std::endl;
using std::numeric_limits;
using std::streamsize;
using std::locale;
char newline = '\n';
bool ok;
bool ok2;
bool ok3;
class num_get : public std::num_get<char>
{
public:
iter_type do_get( iter_type it, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, long& v) const
{
auto& ctype = std::use_facet<std::ctype<char>>(str.getloc());
it = std::num_get<char>::do_get(it, end, str, err, v);
if (it != end && !(err & std::ios_base::failbit)
&& ctype.is(ctype.alpha, *it))
err |= std::ios_base::failbit;
return it;
}
};
/*
int appled()
{
cin >> appleds;
while(cin.fail())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
cout << "An arror occured!\nPlease, enter a valid number: ";
cin >> appleds;
}
return appleds;
}
int oranged()
{
cin >> orangeds;
while(cin.fail())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
cout << "An arror occured!\nPlease, enter a valid number: ";
cin >> orangeds;
}
return orangeds;
}
*/
int main()
{
cout << "=====================================================" << endl;
cout << "Welcome to exZerry's 'Apples & Oranges V2'" << endl;
cout << "=====================================================" << endl;
cout << newline;
cout << newline;
ok = ok2 = ok3 = false;
while(!ok2)
{
x = 0;
//cout << "-----------------------" << endl;
//cout << "DEBUG MODE: " << x << endl;
//cout << "-----------------------" << endl;
cout << "=====================================================" << endl;
cout << "Enter apples: ";
// apples = appled();
locale orig(cin.getloc());
cin.imbue(locale(orig, new num_get));
while (!(cin >> apples)) {
cout << "An arror occured!\nPlease, enter a valid number: ";
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
}
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
cout << "Enter oranges: ";
// oranges = oranged();
//std::locale orig(std::cin.getloc());
cin.imbue(locale(orig, new num_get));
while (!(cin >> oranges)) {
cout << "An arror occured!\nPlease, enter a valid number: ";
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
}
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
cout << "\n=====================================================" << endl;
cout << "Calculating..." << endl;
cout << "=====================================================" << endl;
juce = apples + oranges;
cout << "In total we have " << juce << " fruit" << endl;
cout << "=====================================================" << endl;
cout << newline;
cout << "Go out? (1 - 'No', Others - 'Yeap'):" << " ";
cin >> x;
cout << newline;
// ok2 = true;
if (x == 1)
{
cout << "Continue the program..." << endl;
//cout << "-----------------------" << endl;
//cout << "DEBUG MODE: " << x << endl;
//cout << "-----------------------" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
ok = false;
ok3 = false;
continue;
}
if (x == 0)
{
cout << "Shutting down the app..." << x << endl;
//cout << "-----------------------" << endl;
//cout << "DEBUG MODE: " << x << endl;
//cout << "-----------------------" << endl;
break;
}
else
{
cout << "Shutting down the app..." << x << endl;
//cout << "-----------------------" << endl;
//cout << "DEBUG MODE: " << x << endl;
//cout << "-----------------------" << endl;
break;
}
}
cout << "Press any key to exit :D" << endl;
getch();
return 0;
}
I wrote some codes for house manager.
I want to keep user's entries to sort by one of objects and display them.
I know how to sort data but first I need to keep data in class to display before and after the sorting .
What is the easiest way to keep data?
#include "stdafx.h"
#include <iostream>
using namespace std;
class House
{
private :
int NumRooms;
int Area;
int FloorNumber;
public :
void Getdata()
{
cout << "Enter number of rooms in house: ";
cin >> NumRooms;
cout << "Enter area of house: ";
cin >> Area;
cout << "Enter floor number of house: ";
cin >> FloorNumber;
}
void Putdata()
{
cout << "Number of rooms: " << NumRooms << endl;
cout << "Area of house: " << Area << endl;
cout << "Floor number: " << FloorNumber << endl;
}
};
int menu ();
int _tmain(int argc, _TCHAR* argv[])
{
int n;
House s;
switch(menu())
{
case 1 :
cout << "How many houses:";
cin >> n;
if(n > 20)
cout << "Number of houses is more than max.20!!!" << endl;
else
{
for(int i=1; i<=n; i++)
{
cout << "Details of " << i << " house" << endl;
s.Getdata();
}
}
menu();
case 2 :
menu();
case 3 :
s.Putdata();
menu();
default :
cout << "End of program!!!" << endl;
}
system("pause");
return 0;
}
int menu()
{
int c;
cout << "Wlcome to house manager! Choose one of actions" << endl;
cout << "1. Enter data (max.20 houses)" << endl;
cout << "2. Sort houses" << endl;
cout << "3. Display list" << endl;
cout << "4. Exit" << endl;
cout << "Choice: ";
cin >> c;
return c;
}
Easiest way just put them in std::vector<House>
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class House
{
private :
int NumRooms;
int Area;
int FloorNumber;
public :
bool operator<(const House& other)
{
return (this->Area < other.Area);
}
void Getdata()
{
cout << "Enter number of rooms in house: ";
//cin >> NumRooms;
cout << "Enter area of house: ";
//cin >> Area;
cout << "Enter floor number of house: ";
//cin >> FloorNumber;
NumRooms= rand() * 10;
Area = NumRooms * rand();
FloorNumber=rand();
}
void Putdata()
{
cout << "Number of rooms: " << NumRooms << endl;
cout << "Area of house: " << Area << endl;
cout << "Floor number: " << FloorNumber << endl;
}
};
int menu ();
typedef std::vector<House> houseCollection;
int _tmain(int argc, _TCHAR* argv[])
{
int n;
House s;
houseCollection houses;
switch(menu())
{
case 1 :
cout << "How many houses:";
//cin >> n;
n=5;
if(n > 20)
cout << "Number of houses is more than max.20!!!" << endl;
else
{
for(int i=1; i<=n; i++)
{
cout << "Details of " << i << " house" << endl;
s.Getdata();
houses.push_back(s);
}
}
menu();
case 2 :
std::sort(houses.begin(), houses.end());
menu();
case 3 :
for( houseCollection::iterator it = houses.begin(); it != houses.end(); it++)
{
s = (*it);
s.Putdata();
}
menu();
default :
cout << "End of program!!!" << endl;
}
system("pause");
return 0;
}
int menu()
{
int c;
cout << "Wlcome to house manager! Choose one of actions" << endl;
cout << "1. Enter data (max.20 houses)" << endl;
cout << "2. Sort houses" << endl;
cout << "3. Display list" << endl;
cout << "4. Exit" << endl;
cout << "Choice: ";
cin >> c;
return c;
}
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;
}
}