I have the following problem: my program that uses fstream doesn't seem to be able to write more than 1 data struct into my .dat file.
Below is my code, I've only been able to add 1 set of data. When I tried to add another, it worked but did not write out. Any idea why?
For example, I run this function, type in the details, and successfully entered 1 set of booking information, and info is stored in my .dat file.
When I re-run this function, type in the details, the 2nd set of booking information is NOT recorded in my .dat file. Therefore my .dat file ends up having only the first entry, and not storing the subsequent entries
void booking::bkForm(fstream& afile, bForm& b)
{
customer c;
GM g;
GM::holidayPackages h;
char fname [30];
char lname [30];
char address [50];
char date [30];
char req [100];
int pid, position, choice;
bool iStat = false;
bool dStat = false;
int noOfRecords = getNoBFRecords(afile);
int q = g.getNoOfHRecords(afile);
cout << "Please Fill Up Required Booking Form." << endl;
cout << "Please enter your first name: ";
cin.clear();
cin.ignore(100, '\n');
cin.getline(fname, 30);
cout << "Please enter your last name: ";
cin.getline(lname,30);
cout << "Please enter your address: ";
cin.getline(address,50);
cout << "\nThese are the available Packages to choose from." << endl;
g.printHolidayPackages(afile, h);
afile.open("holidayPackages.dat", ios::in | ios::binary);
while(iStat == false)
{
cout << "\nPlease enter the Package ID of the tour that you want to join." << endl;
cout << "Package ID: ";
cin >> pid;
for(int i = 0; i < q; i++)
{
afile.read (reinterpret_cast <char *>(&h), sizeof(h));
if(pid == h.holID)
{
iStat = true;
position = i;
}
}
if(iStat == false)
{
cout << "ID not found, please enter valid Package ID" << endl;
}
}
while(choice!=1 && choice!=2)
{
afile.seekg ((position) * sizeof (GM::holidayPackages), ios::beg);
afile.read (reinterpret_cast <char *>(&h), sizeof (h));
cout << "\nPleasse choose the Date of tour that you want to join." << endl;
cout << "1) " << h.holDate1 << endl;
cout << "2) " << h.holDate2 << endl;
cout << "Your choice: ";
cin >> choice;
if(choice == 1)
{
strcpy(date, h.holDate1);
}
else
{
strcpy(date, h.holDate2);
}
}
cout << "\nPlease State Any Special Requirement That You Have Below." << endl;
cin.clear();
cin.ignore(100, '\n');
cin.getline(req, 100);
afile.close();
afile.open("bookingInfo.dat", ios::out | ios::app | ios::binary);
strcpy(b.bfName, fname);
strcpy(b.blName, lname);
strcpy(b.bAddress, address);
strcpy(b.bDate, date);
strcpy(b.bStatus, "Unchecked");
strcpy(b.bReq, req);
b.packageID = pid;
srand(time(NULL));
int a = rand () % 100000+899990; // random 6 digit number as booking ref.
for(int k = 0; k < noOfRecords; k++)
{
afile.read (reinterpret_cast <char *>(&b), sizeof(b));
while(a == b.bookingRef)
{
a = rand () % 100000+899990;
}
}
b.bookingRef = a;
cout << "Booking Submitted." << endl;
cout << "Please take down the booking reference no : " << b.bookingRef << endl;
cout << "You will need the reference number to check the status of your booking" << endl;
afile.write(reinterpret_cast <const char *>(&b), sizeof(b));
afile.close();
}
Tthis is some sample output. There is only 1 result instead of a few.
==========================================================
Details Of Booking Number: 0
===========================================================
Booking Reference no: 966373
Customer Name: Cheryl Tan
Customer Address: St24 Tampines
Package ID of Package Booked: 9102
Package Date Choosen: 02032014
Special Requirements: none
Booking Status: Unchecked
its okay, i realise my error.
the error being i called for read, but i've only opened the file for write/append.
corrected code fragment will be like this..
afile.open("bookingInfo.dat", ios::in | ios::binary); //changed here to read
srand(time(NULL));
int a = rand () % 100000+899990; // random 6 digit number as booking ref.
for(int k = 0; k < noOfRecords; k++)
{
afile.read (reinterpret_cast <char *>(&b), sizeof(b));
while(a == b.bookingRef)
{
a = rand () % 100000+899990;
}
}
afile.close(); // close read
afile.open("bookingInfo.dat", ios::out | ios::app | ios::binary); // open append
strcpy(b.bfName, fname);
strcpy(b.blName, lname);
strcpy(b.bAddress, address);
strcpy(b.bDate, date);
strcpy(b.bStatus, "Unchecked");
strcpy(b.bReq, req);
b.packageID = pid;
b.bookingRef = a;
cout << "Booking Submitted." << endl;
cout << "Please take down the booking reference no : " << b.bookingRef << endl;
cout << "You will need the reference number to check the status of your booking" << endl;
afile.write(reinterpret_cast <const char *>(&b), sizeof(b));
afile.close(); // close append
Related
I have an assignment in my c++ class which is: Write a program that declares a struct to store the data of a football player (player’s name, player’s position, number of touchdowns, number of catches, number of passing yards, number of receiving yards, and the number of rushing yards). Declare an array of 10 components to store the data of 10 football players. Your program must contain a function to input data from a file (You will need to create the input file) and functions to output data to the console. Add functions to search the array to find the index of a specific player, and update the data of a player. Before the program terminates, give the user the option to save data in a file (write a function for this). Your program should be menu driven, giving the user various choices. Your main function should mostly have variable declarations and function calls in it. Most operations should be handled by other functions.
I am stuck on getting my program to read the info on my input file. please help
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
using namespace std;
struct player {
string name;
string position;
int touchdowns;
int catches;
int pass;
int receive;
int rush;
};
int addData( ifstream& ifile, int count , player football[])
{
if (count == 0)
{
ifile >> football[count].name;
ifile >> football[count].position;
ifile >> football[count].touchdowns;
ifile >> football[count].catches;
ifile >> football[count].pass;
ifile >> football[count].receive;
ifile >> football[count].rush;
count++;
}
else if (count != 0)
{
int i = 0;
string name;
string position;
int touchdowns;
int catches;
int pass;
int receive;
int rush;
while (i != -1)
{
ifile >> name >> position >> touchdowns >> catches >> pass >> receive >> rush;
if((*(&football + 1) - football) > 0)
{
if (name == football[i].name)
{
i++;
}
if (name != football[i].name)
{
football[count].name = name;
football[count].position = position;
football[count].touchdowns = touchdowns;
football[count].catches = catches;
football[count].pass = pass;
football[count].receive = receive;
football[count].rush = rush;
i = -1;
count++;
}
}
}
}
return count;
}
void display(int count, player football[])
{
cout << "There are " << count << " players," << endl;
if (count <= 0)
{
cout << "No players to display. ";
}
else
{
for (int i = 0; i < count;i++)
{
cout << i + 1 <<". " << football[i].name << endl;
cout << "Position: " << football[i].position << endl;
cout << "Touchdowns: " << football[i].touchdowns << endl;
cout << "Catches: " << football[i].catches << endl;
cout << "Passes: " << football[i].pass << endl;
cout << "Receiving Yards: " << football[i].receive << endl;
cout << "Rushing Yards: " << football[i].rush << endl;
}
}
}
void findandUpdate(string search, int count, player football[])
{
string name;
string position;
int touchdowns;
int catches;
int pass;
int receive;
int rush;
bool found = false;
for (int i = 0; i < count; i++)
{
if (search == football[i].name)
{
found = true;
cout << "Searched player is at index " << i + 1 << endl;
cout << "You may now update the player's name, player's position, number of touchdowns, number of catches,"
<< "number of passing yards, number of receiving yards, and the number of rushing yards \n";
cout << "Name: "; cin >> name;
cout << "Position: "; cin >> position;
cout << "Touchdowns: "; cin >> touchdowns;
cout << "Catches: "; cin >> catches;
cout << "Passes: "; cin >> pass;
cout << "Received: "; cin >> receive;
cout << "Rushed: "; cin >> rush;
football[i].name = name;
football[i].position = position;
football[i].touchdowns = touchdowns;
football[i].catches = catches;
football[i].pass = pass;
football[i].receive = receive;
football[i].rush = rush;
}
}
if (found == false)
{
cout << "No results.";
}
}
int main()
{
cout << "Press 1 to add a player.\nPress 2 to display players.\nPress 3 to find a player.\nPress 4 to update player information.\nPress 5 to save data.\n";
int x = 0;
cin >> x;
ifstream ifile;
player football[10];
ifile.open("footballplayers.txt");
int i = 0;
int count = 0;
while (i != -1)
{
switch (x)
{
case 1:
{
count = addData(ifile, count, football);
}
break;
case 2: display(count, football);
break;
case 3:
{
string name;
cout << "Enter football player name: ";
cin >> name;
findandUpdate(name,count, football);
}
break;
default: i = -1;
}
}
ifile.close();
string answer;
cout << "Save data? Type yes or no.";
cin >> answer;
if (answer == "yes")
{
ofstream ofile;
ofile.open("SavePlayerData.txt");
for (int i = 0; i < count; i++) {
ofile << football[i].name + " ";
ofile << football[i].name + " ";
ofile << football[i].position + " ";
ofile << football[i].touchdowns + " ";
ofile << football[i].catches + " ";
ofile << football[i].pass + " ";
ofile << football[i].receive + " ";
ofile << football[i].rush + " ";
ofile << "\n";
}
ofile.close();
}
}
Input file:
George RB 12 5 0 47 578
Brett QB 5 0 2017 0 44
Peyton WR 3 15 0 246 12
Logan WR 2 7 0 89 6
Nolan WR 1 2 3 0 0
John TE 5 17 0 402 0
Brandon QB 4 0 310 0 0
Dalton RB 1 2 43 5
Justin WR 1 10 0 441 0
Mason WR 0 2 0 12 0
your basic logic does not do as asked in the specs. First thing it should do is read the file, before asking for any input from a menu. You have tried to create a strange hybrid of reading the file and interactively adding a player (which is not part of the requirements)
So simplify and get it so that you read the whole file in a function called 'loadFile' and then print the whole thing out (like your option 2).
Get those things going first then add the menu to ask for modify, find and print
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
using namespace std;
void getInformationKeyBoard(int, string[], int[]);
bool openFile(ifstream &infile, string fileName);
void display(int size, string array[]);
void read2Array(ifstream &infile, int size, string array[]);
void printReport(string name[], int score[], int NumberOfStudent);
int main()
{
const int size = 1024;
string Name[size], scoreFile[size];
int score[size];
int NumberOfStudent;
const int SIZE = 7;
ifstream inFile;
char choice;
cout << "You want to enter your scores by your keyboard (A) or from your input (B): ";
cin >> choice;
if (choice == 'a' || choice == 'A') // It will take information from keyboard
{
cout << "How many students do you want to enter: ";
cin >> NumberOfStudent;
getInformationKeyBoard(NumberOfStudent, Name, score);
printReport(Name, score, NumberOfStudent);
}
else if (choice == 'b' || choice == 'B') // It will take information from file
{
string name;
char again = 'Y';
bool close = false;
cout << "Enter name of file: ";
cin >> name;
openFile(inFile, name);
read2Array(inFile, SIZE, scoreFile);
display(SIZE, scoreFile);
}
else // If you choice is not A,a or B,b
cout << "Your did not follow the right instruction.";
cout << endl << endl;
system("pause");
return 0;
}
// Open file
bool openFile(ifstream &infile, string fileName){
infile.open(fileName);
if (infile)
return true;
return false;
}
void getInformationKeyBoard(int size, string Names[], int scores[]) // Information from keyboard
{
for (int i = 0; i < size; i++)
{
cout << i + 1 << ". Student First Name and Last Name: ";
cin.ignore();
getline(cin, Names[i]);
do
{
cout << i + 1 << ". Enter the score between 1 and 100: ";
cin >> scores[i];
} while (scores[i] > 100 || scores[i] < 0);
}
}
void read2Array(ifstream &infile, int size, string array[]){
int index = 0;
string line;
while (getline(infile, line)){
array[index] = line;
++index;
}
}
// Display array
void display(int size, string array[]){
for (int index = 0; index < size; ++index){
cout << array[index] << endl;
}
}
void printReport(string name[], int score[], int NumberOfStudent)
{
int lowest, highest, mean;
cout << "Enter lowest score: ";
cin >> lowest;
cout << "Enter highest score: ";
cin >> highest;
cout << "Enter mean score: ";
cin >> mean;
cout << "================================================================================";
cout << setw(10) << "Number of scores = " << NumberOfStudent << endl;
cout << setw(10) << "Lowest Score = " << lowest << endl;
cout << setw(10) << "Highest Score = " << highest << endl;
cout << setw(10) << "Mean Score = " << mean << endl;
cout << "Name" << setw(15) << "Score" << setw(15) << "IsLowest" << setw(15) << "IsHighest" << setw(15) << "Mean" << endl;
cout << "-----------------------------------------------------------------" << endl;
cout << name[NumberOfStudent] << endl;
cout << endl;
}
A header statistic section of number of scores, lowest, highest, and mean scores, followed by details for each student - one per line.
I stuck at making output to screen. I want my output look like this
Number of scores = 3
Lowest Score = 82
Highest Score = 92
Mean Score = 87
Name Score IsLowest IsHighest >=Mean
F1 L1 82 Y N N
F2 L2 87 N N Y
F3 L3 92 N Y Y
Perhaps you could pass in a ostream object as a parameter, then replace all occurences of cout in your function with the name of that argument. Then you could run the function twice
printReport(cout, other args);
printReport(outFile, other args);
(Or setup the function to call itself so you don't have to enter cout every time).
The only problem with this method is I see you are grabbing input while inside the function. If you want to use the above method, you'd have to move some things around. Instead, I would setup a different function that takes a string as input and inserts said string to both cout and your file. So rather than having to write
cout<<"hi";
file<<"hi";
You could do
...
functionName("hi", outfile);
...
void functionName(string str, ostream outfile)
{
cout<<str;
outfile<<str;
}
Hope this helps
In general, the following function will work to replicate a console output in a file.
#include <stdarg.h> /* va_list, va_start, va_arg, va_end */
void print(FILE *f, char const *fmt, ...) {
va_list ap;
//Normal console print
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
//Printing to file
if (f != NULL) {
va_start(ap, fmt);
vfprintf(f, fmt, ap);
va_end(ap);
}
}
If you want only console output, simply have
print(NULL, "%d\t%d\n", 1, 100);//include any needed C style formatting here
If you want the console output to be saved to a file, simply pass an appropriate file pointer as the first argument.
FILE *fp = fopen("logfile.txt","a");
print(fp, "%d\t%d\n, 1, 100);//logs the console output to logfile.txt
The console window formatting will be preserved in the text file as well.
I am working on a project using arrays and structures to further my poor programming skillz. I cannot figure out how to shift the array to the right. In the function editContact, I am trying to sort the contacts by last name after the name is changed. The plan is to shift the array right and put the edited contact in the appropriate alphabetized spot.
Do I need to put
"int numContacts=0;
Contact entries[500];"
into a structure?
This is the code I am struggling with specifically:
void shiftUp(int startIndex) {
entries = new int[entries.Length];
for (int i = startIndex; i < entries.Length - 1; i++)
{
entries[i] = entries[i + 1];
}
entries[entries.Length - 1] = entries[0];
}
This is the error message I receive from the compiler:
addressbook.cpp:311: error: request for member 'Length' in 'entries', which is of non-class type 'Contact [500]'
addressbook.cpp:311: error: incompatible types in assignment of 'int*' to 'Contact [500]'
addressbook.cpp:313: error: request for member 'Length' in 'entries', which is of non-class type 'Contact [500]'
addressbook.cpp:318: error: request for member 'Length' in 'entries', which is of non-class type 'Contact [500]'
This is the bulk of the program:
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
/*structures*/
struct Contact {
string firstName;
string lastName;
string middleInitial;
string phoneNumber;
string streetAddress;
string city;
string state;
string zipCode;
};
int numContacts=0;
Contact entries[500];
/*prototypes*/
int mainMenu();
int searchResults(string searchTerm);
void searchContacts();
void contactDetail(int contactIndex);
void editContact(int contactIndex);
bool deleteContact(int contactIndex);
void listContacts();
void addContact();
void shiftUp(int startIndex);
void shiftDown(int startIndex);
void saveData();
void loadData();
int findLocation(string lastName);
void saveContact(ofstream dataFile, Contact& newContact);
void loadContact(ifstream dataFile, Contact& newContact);
/*consts*/
const int SEARCH_CMD = 1;
const int LIST_CMD = 2;
const int ADD_CMD = 3;
const int EXIT_CMD = 4;
int main(){
loadData();
int selection;
do {
selection = mainMenu();
switch(selection) {
case SEARCH_CMD:
searchContacts();
break;
case LIST_CMD:
listContacts();
break;
case ADD_CMD:
addContact();
break;
}
} while (selection !=EXIT_CMD);
saveData();
}
int mainMenu(){
/*show the menu*/
cout << "**** Welcome to AddressBook ****" << endl << "1. Search for Contacts" << endl << "2. List Contacts" << endl << "3. Add New Contact" << endl << "4. Exit" << endl << "Enter Selection:";
/*input the selection*/
int selection;
while(1) {
cin >> selection;
/*validate the selection and reprompt if neccessary*/
if ((selection >4) || (selection < 1)) {
cout << "This is not a valid menu option. Please try again.";
break;
}
if ((selection <=4) && (selection >=1)) {
break;
}
}
/* return a valid selection */
return(selection);
}
void searchContacts() {
/*output "Enter search term: " */
cout << "Enter search term: ";
/*input the string searchTerm */
string searchTerm;
cin >> searchTerm;
/* call searchResults(searchTerm) */
searchResults(searchTerm);
}
int searchResults(string searchTerm){
/* output "Search Results:"*/
int noMatch =0;
cout << "Search Results: " << endl;
/*loop through every contact*/
int contactsIndex[500];
for (int i=0; i<=numContacts; i++) {
if (entries[i].lastName == searchTerm) {
noMatch++;
cout << noMatch << ". " << entries[i].firstName << " " << entries[i].lastName << " " << entries[i].phoneNumber << endl;
contactsIndex[noMatch] = i;
}
}
if (noMatch == 0) {
cout << "No match found\n";
return(1);
}
int selectContact;
cout << "Select a contact (or M for Main Menu): ";
cin >> selectContact;
if ((selectContact > 0) && (selectContact <= noMatch)) {
contactDetail(contactsIndex[selectContact]);
}
if ((selectContact=='m') || (selectContact=='M')) {
}
/* compare each field (using substr) to searchTerm*/
/* if the searchTerm is in any field, output the contact*/
/* save the index of the contact to contactsIndex array*/
/* output "Select a Contact (or M for Main Menu): "*/
/*input selection*/
/*if selection is a contact number, call contactDetail(contactsIndex[selection-1]);*/
}
void contactDetail(int contactsIndex){
/*show the indicated contact - addressBook.entries[contactIndex]*/
cout << entries[contactsIndex].firstName << " " << entries[contactsIndex].middleInitial << ". " << entries[contactsIndex].lastName << endl;
cout << entries[contactsIndex].streetAddress << endl << entries[contactsIndex].city << ", " << entries[contactsIndex].state << ", " << entries[contactsIndex].zipCode << endl;
cout << "Phone: " << entries[contactsIndex].phoneNumber << endl;
/* output "Select E for Edit, D to delete or M for Main Menu: "*/
cout << "Select E for Edit, D to delete, or M for Main Menu:" ;
/* read selection*/
char menuSelection;
cin >> menuSelection;
/*if selection is E*/
if (menuSelection == 'E') {
editContact(contactsIndex);
}
/* editContact(contactIndex)*/
/*if selection is D*/
if (menuSelection == 'D') {
bool retValue;
retValue = deleteContact(contactsIndex);
}
/* retValue = deleteContact(contactIndex)*/
/*else m, break*/
if (menuSelection == 'M') {
}
/* loop while retValue is false*/
}
void editContact(int contactsIndex){
/*output "**Press Enter to leave field unchanged. Enter a new value to change it.**"*/
cout << "Press Enter to leave field unchanged. Enter a new value to change it." << endl;
/*use addressBook.entries[contactIndex]*/
string editEntry;
cout << "First Name: ";
cin >> editEntry;
entries[contactsIndex].firstName = editEntry;
cout << "Last Name: ";
cin >> editEntry;
entries[contactsIndex].lastName = editEntry;
cout << "Middle Initial: ";
cin >> editEntry;
entries[contactsIndex].middleInitial = editEntry;
cout << "Phone Number: ";
cin >> editEntry;
entries[contactsIndex].phoneNumber = editEntry;
cout << "Street Address: ";
cin >> editEntry;
entries[contactsIndex].streetAddress = editEntry;
cout << "City: ";
cin >> editEntry;
entries[contactsIndex].city = editEntry;
cout << "State: ";
cin >> editEntry;
entries[contactsIndex].state = editEntry;
cout << "Zip Code: ";
cin >> editEntry;
entries[contactsIndex].zipCode = editEntry;
/* prompt for each field */
/* input fields*/
/* if input is not empty*/
/* set corresponding field with input*/
/* shiftUp(contactIndex)*/
shiftUp(contactsIndex);
int newIndex;
newIndex = findLocation (entries[contactsIndex].lastName);
/* newIndex = findLocation(lastName)
if (newIndex != numContacts) {
shiftDown(newIndex);
}*/
/* if newIndex != numContacts*/
/* shiftDown(newIndex)*/
/* add the new contact at [newindex]*/
/* output "Select E to Edit or M for Main Menu: "*/
/* if selection is Edit*/
/*loop*/
}
bool deleteContact(int contactIndex){
/*output "Are you sure you want to delete this contact? (Y/N): "*/
/*read selection*/
/*validate selection*/
/* if yes*/
/*shiftUp(contactIndex)*/
/* output "Contact deleted! Press any key to return to main menu."*/
/*return true - means contact was deleted*/
/*else if No*/
/*return false*/
return(false);
}
void listContacts(){
/*output "Contact List: "*/
cout << "Contact List: " << endl;
/* for all contacts:*/
for (int i=0; i < numContacts; i++) {
cout << entries[i].firstName << " " << entries[i].middleInitial << ". " << entries[i].lastName << endl;
cout << entries[i].streetAddress << endl << entries[i].city << ", " << entries[i].state << ", " << entries[i].zipCode << endl;
cout << "Phone: " << entries[i].phoneNumber << endl << endl;
/* output firstName, lastName, and phone (formatted)*/
/* output "Select a Contact (or M for Main Menu): "*/
/*input selection*/
/*validate selection*/
/*if selection is a contact number, call contactDetail(contactsIndex[selection-1]);*/
}
}
void addContact(){
cout << "Add A Contact! Please enter each value as prompted." << endl;
/*
string newEntry;
cout << "First Name: ";
cin >> newEntry;
entries[contactsIndex].firstName = newEntry;
cout << "Last Name: ";
cin >> newEntry;
entries[contactsIndex].lastName = newEntry;
cout << "Middle Initial: ";
cin >> newEntry;
entries[contactsIndex].middleInitial = newEntry;
cout << "Phone Number: ";
cin >> newEntry;
entries[contactsIndex].phoneNumber = newEntry;
cout << "Street Address: ";
cin >> newEntry;
entries[contactsIndex].streetAddress = newEntry;
cout << "City: ";
cin >> newEntry;
entries[contactsIndex].city = newEntry;
cout << "State: ";
cin >> newEntry;
entries[contactsIndex].state = newEntry;
cout << "Zip Code: ";
cin >> newEntry;
entries[contactsIndex].zipCode = newEntry;
*/
/*First Name:*/
/*Last Name:*/
/*Middle Initial:*/
/*Phone Number:*/
/*Street Address:*/
/*City: */
/*State:*/
/*Zip Code:*/
/* add the new contact to the addressBook*/
/* newIndex = findLocation(lastName)*/
/* if newIndex != numContacts*/
/* shiftDown(newIndex)*/
/* add the new contact at [newindex]*/
/* addressBook.numContacts++*/
/*set contactIndex to index of added contact*/
/*Enter 'E' for Edit Again, 'D' to Delete, or 'M' for Main Menu: M*/
/*if selection is E*/
/* editContact(contactIndex)*/
}
void shiftDown(int startIndex) {
/*shift the addressBook.entries up */
/*starting at startIndex+1 through the end of the array (loop should loop from bottom)*/
/*addressBook.numContacts++;*/
}
void shiftUp(int startIndex) {
entries = new int[entries.Length];
for (int i = startIndex; i < entries.Length - 1; i++)
{
entries[i] = entries[i + 1];
}
entries[entries.Length - 1] = entries[0];
/*shift the addressBook.entries down */
/*starting at startIndex through the end of the array (loop should loop from top)*/
/*addressBook.numContacts--;*/
}
int findLocation(string lastName) {
/*go through the addressBook and find the first lastName that is greater than the lastName passed to the function*/
int nameOrder;
for (int i=0; lastName < entries[i].lastName; i++) {
nameOrder++;
}
/* if you reach the end of the array, return the number of the next available slot*/
return(nameOrder);
}
void loadData(){
string newContact;
ifstream dataFile;
dataFile.open("addressBook.dat");
/*open addressBook.dat for input. call stream dataFile*/
/*for loop until end of file using i as loop counter*/
if (dataFile.is_open()) {
for (int i=0;!dataFile.eof();i++) {
getline (dataFile,newContact);
entries[i].firstName = newContact;
cout << entries[i].firstName << endl;
getline (dataFile,newContact);
entries[i].lastName = newContact;
cout << entries[i].lastName << endl;
getline (dataFile,newContact);
entries[i].middleInitial = newContact;
getline (dataFile,newContact);
entries[i].phoneNumber = newContact;
getline (dataFile,newContact);
entries[i].streetAddress = newContact;
getline (dataFile,newContact);
entries[i].city = newContact;
getline (dataFile,newContact);
entries[i].state = newContact;
getline (dataFile,newContact);
entries[i].zipCode = newContact;
numContacts++;
}
}
else cout << "Unable to open file";
/*loadContact(dataFile, addressBook.entries[i]);*/
/*close addressBook.dat*/
dataFile.close();
}
Thanks for your help, this is the solution I ended up using
void shiftUp(int startIndex) {
/*shift the addressBook.entries up to delete entries*/
/*starting at startIndex+1 through the end of the array (loop should loop from bottom)*/
for (int i = startIndex; i <= numContacts; ++i ){
entries[i] = entries[i+1];
Technically, instead of this:
void shiftUp(int startIndex) {
entries = new int[entries.Length];
for (int i = startIndex; i < entries.Length - 1; i++)
{
entries[i] = entries[i + 1];
}
entries[entries.Length - 1] = entries[0];
}
do:
void shiftUp( int startIndex )
{
int const n = sizeof( entries )/sizeof( *entries );
for( int i = n - 1; i > startIndex; --i )
{
entries[i] = entries[i - 1];
}
}
Examine the differences to learn some new C++ things.
Instead of raw arrays, consider using C++ standard library containers like vector and map.
Raw arrays has some problems, including how to safely find the size.
With C++11 and later, instead of the above C expression consider using std::end(a) - std::begin(a), expressed as a function template (e.g. called size).
Also, you may or will discover that resorting by shifting for each new item, gives O(n2) time. Things just get slower and slower the more items you have. Unproportionally so.
This is also a good reason to use standard library containers.
They employ far more efficient strategies for keeping things sorted.
I'm writing a program to store inventory data in a binary text file. One of the functions is to search for the name of an item (that was already entered) within the text file, and if found, read the information to a structure, update it, and send the structure back to the file.
The trouble is using seekp/seekg to overwrite the correct data.
I.E. The structure holds the item name, total stock, the Wholesale price, and the Retail price. But my current code will only overwrite the item name when sent back to the text file.
I have a feeling this is due to either using seek/read/write incorrectly.
In the following code I only use one struct to temporarily hold data when inputting/outputting to the file. (I hate to dump code like this but I'm not sure what else to do at this point.) Below is the function to modify a specific item that has already been entered:
The structure is
struct inventory
{
string itemname;
int stock;
double costWS,
costRE;
};
but i've only created one named "holder", to use when adding items to the text file or searching/modifying items.
void ModifyRecord()
{
fstream update ("Records.txt" , ios::in|ios::ate|ios::binary);
bool found = false;
long int whereAmI;
string tomodify;
cout << "Enter the name of the item to modify." << endl;
cin >> tomodify;
while ( !update.eof() || !found )
{
//holder is the structure containing inventory data
//this will read only one structure at a time, to send to holder
update.read(reinterpret_cast<char *> (&holder), sizeof(holder));
cout << "Reading new struct." << endl;
whereAmI = update.tellg();//save input position
//check this structure for the name entered
if (holder.itemname.find(tomodify) == 0)
{
found = true;//exit while loop
update.seekg( -( sizeof(holder) ), ios::cur);
//Update data
cout << "String found. \nYou have selected to modify: "
<< holder.itemname << endl;
cout << "Enter new name for the item: " << endl;
cin >> holder.itemname;
do
{
cout << "Enter amount stocked." << endl;
cin >> holder.stock;
}while(holder.stock < 0);
do
{
cout << "Enter wholesale cost." << endl;
cin >> holder.costWS;
}while(holder.costWS < 0);
do
{
cout << "Enter retail cost." << endl;
cin >> holder.costRE;
}while(holder.costRE < 0);
//send back to file
update.write(reinterpret_cast<char *> (&holder), sizeof(holder));
whereAmI = update.tellp();//save current output position
update.close();
break;
}
}
if ( !found )
cout << "Keyword not found." << endl;
}
So how do I overwrite the correct data using seekg/p? Am I using read/write correctly?
First: "binary text file" sounds like "cold hot water". You should decide: do you want to work with binary or text file.
Second: Your struct inventory contains a field of type string, that's why it cannot be used like a POD, but you're trying to do that:
update.seekg( -( sizeof(holder) ), ios::cur);
^^^^^^^^^^^^^^
and
update.write(reinterpret_cast<char *> (&holder), sizeof(holder));
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
Third: If you'll change your struct like this:
struct inventory {
enum { MAX_ITEM_LENGTH = 100 };
char itemname[ MAX_ITEM_LENGTH + 1 ]; // +1 for trailing '\0'
int stock;
double costWS,
costRE;
};
then the algorithm would be like this:
fstream update ("Records.txt" , ios::in|ios::ate|ios::binary);
bool found = false;
string tomodify;
cout << "Enter the name of the item to modify." << endl;
cin >> tomodify;
while ( !update.eof() )
{
update.read( reinterpret_cast<char *> (&holder), sizeof(holder) );
if ( tomodify == holder.itemname )
{
update.seekg( -( sizeof(holder) ), ios::cur);
cout << "String found. \nYou have selected to modify: "
<< holder.itemname << endl;
cout << "Enter new name for the item: " << endl;
string newItemName;
cin >> newItemName;
strncpy( holder.itemname, newItemName.c_str(), inventory::MAX_ITEM_LENGTH );
do
{
cout << "Enter amount stocked." << endl;
cin >> holder.stock;
} while(holder.stock < 0);
do
{
cout << "Enter wholesale cost." << endl;
cin >> holder.costWS;
} while(holder.costWS < 0);
do
{
cout << "Enter retail cost." << endl;
cin >> holder.costRE;
} while(holder.costRE < 0);
//send back to file
update.write(reinterpret_cast<char *> (&holder), sizeof(holder));
found = true;
break;
}
}
if ( !found )
cout << "Keyword not found." << endl;
}
i have a question regarding a assignment i have.
here i have 2 of the classes, employee class and gm class
void GM::addEmployee(fstream& afile, int noOfRecords)
{
afile.open("EmployeeInfo.dat", ios::in | ios::binary);
employee::eInfo e;
employee emp;
char name[80];
cout << "\nAdd Employee Info" << endl;
cout << "---------------------" << endl;
cout << "New Employee Username: ";
cin.clear();
cin.ignore(100, '\n');
cin.getline(name, 80);
//Check if there is already an entry inside the file with this name.
//If yes, add fail
bool flag = true;
if(noOfRecords > 0)
{
for(int i=1; i<=noOfRecords; i++)
{
afile.read (reinterpret_cast <char *>(&e), sizeof(e));
if(!strcmp(name, e.username))
{
cout << "Username is used, add GM failed" << endl;
flag = false;
}
}
}
afile.close();
if(flag)
{
//open in appending mode
afile.open("EmployeeInfo.dat", ios::out | ios::app | ios::binary);
strcpy(e.username, name);
cout << "Please Enter New Employee's Password: ";
cin.getline(e.password, 80);
cout << "\nPlease Enter New Employee's Appointment "
<< "\n(0 = GM / 1 = HM / "
<< "2= BS / 3 = FOS)\n : ";
cin >> e.eid;
cin.clear();
cin.ignore(100, '\n');
emp.dist = strlen(e.password);
emp.caesar_encrypt(e.password, 3, emp.dist);
afile.write(reinterpret_cast <const char *>(&e), sizeof(e));
afile.close();
cout << "\nEmployee Added" << endl;
}
}
The above is a function from my GM class, which is to add employees.
i have declared a structure in employee class as
struct eInfo
{
char username [80];
char password [80];
int eid;
};
The problem with this way of doing, is that when i try to add employee
my EmployeeInfo.dat data disappears. everything becomes blank after i used the add employee function.
can anyone guide me on what i did wrong?
This is the wrong way to read data into e:
afile.read(reinterpret_cast<char*>(&e), sizeof(e));
Likewise, this is the wrong way to write data from e:
afile.write(reinterpret_cast<const char*>(&e), sizeof(e));
If you need to print or read the data members of e, you need to do so one at a time. Moreover, using read/write in this context is unecessary because you simply use the extractor and inserter:
afile >> e.username;
// ...
afile << e.username << e.password;