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;
}
Related
So im trying to run a program that receives a set data from a file that updates each time the program is run and new data is added. But when i try to run it the program terminates after trying to receive input from user.The full code is as follow, im using devc++ if that matters
#include<iostream>
#include<fstream>
#include<string.h>
using namespace std;
struct Deets
{
string NameSite[];
string AddressName[];
int numVaccine[];
int numStall[];
string DateVax[];
string ContNum[];
};
void Outputmenu();
int AddData(int,struct Deets V);
void EditData(int,struct Deets V);
void ShowExisting(int,struct Deets V);
void ClearArr(int,struct Deets V);
int main()
{
int i;
ifstream r("Total.txt");
r>>i;
r.close();
Deets V;
ifstream a;
a.open("Data.txt");
for(int c=0;c<=i;c++)
while(a>>V.NameSite[c]>>V.AddressName[c]>>V.numVaccine[c]>>V.numStall[c]>>V.DateVax[c]>>V.ContNum[c]);
a.close();
int menuS;
do
{
Outputmenu();
cout<<"\nPlease choose from 1-4, press 0 to close menu"<<endl;
cin>>menuS;
if (menuS==1)
AddData(i,V);
else if (menuS==2)
EditData(i,V);
else if (menuS==3)
ShowExisting(i,V);
else if (menuS==0)
cout<<"Thank you for your cooperation, We hope to see you soon! \nClosing program..,";
else
cout<<"Error, not within selection"<<endl;
}
while (menuS!=0);
ofstream b("Data.txt");
for(int c=0;c<=i;c++)
while(b<<V.NameSite[c]<<" "<<V.AddressName[c]<<" "<<V.numVaccine[c]<<" "<<V.numStall[c]<<" "<<V.DateVax[c]<<" "<<V.ContNum[c]<<endl);
return 0;
}
void Outputmenu() //instruction about the command for the user
{
cout << " -hello there!- " << endl;
cout << "===================================================================" << endl;
cout << " ***PLEASE CHOOSE ONE OF THE OPTION BELOW*** " << endl;
cout << "===================================================================" << endl;
cout << "\t1. Add Data (about Vaccination Center)" << endl;
cout << "\t2. Edit Data" << endl;
cout << "\t3. Show Existing Data" << endl;
cout << "\t0. Close Program" << endl;
cout << "===================================================================" << endl;
}
int AddData(int c, struct Deets A)
{
bool rq;
int i = c;
cout<<"Enter your company name/ institute name : ";
cin.ignore();
getline(cin,A.NameSite[i]);
cout<<"\n\t\t Safety Measure"<<endl;
cout<<"-Maintain a distance of 1 meter between one other access to vaccine doses.\n"<<"-Have a dedicated toilets for patient\n"<<"-Ability to maintain room temperature between 19 – 25 degrees \n"<<"-Have an adequate place for patients to wait "<<"\n-Have adequate sharps disposal bins, appropriate for the volume of patients, and securely placed and spaced to mitigate the risk of needle stick injuries."<<endl;
cout<<"-Adequate handwashing facilities for staff, and antimicrobial hand sanitizers available.\n"<<"-Store and handle COVID-19 vaccines under proper conditions, including maintaining cold chain conditions and chain of custody at all times in accordance with a EUA or vaccine package insert, manufacturer guidance, and CDC guidance in the Vaccine Storage and Handling Toolkit."<<endl;
cout<<"-Appropriate security provisions to ensure no unauthorized access to vaccine doses."<<endl;
cout<<"\nAre all requirement met? \n1:Yes \n0:No"<<endl;
cin>>rq;
if(rq == 1)
{
cout<<"\nWhere is the location : "<<endl;
cin>>A.AddressName[i];
cout<<"How many vaccines required : "<<endl;
cin>>A.numVaccine[i];
cout<<"How many vaccine stall can a site hold : "<<endl;
cin>>A.numStall[i];
cin.ignore();
cout<<"Date for vaccine to be distributed"<<endl;
getline(cin,A.DateVax[i]);
cin.ignore();
cout<<"Enter your management contact number : "<<endl;
getline(cin,A.ContNum[i]);
cout<<"Certificate for "<<A.NameSite[i]<<endl;
i++;
}
else
{
cout<<"Thanks for the thought. We hope to cooperate with "<<(A.NameSite[i])<<" in the near future\n\n"<<endl;
if(i>0)
{
i = i-1;
}
else
{
i = 0;
}
}
return i;
}
void EditData(int i,struct Deets A)
{
int c,EN,edit=0;
for (int c=0;c<i;c++) //showing all Company/Institute name data
{
cout << c+1 << ". "<<A.NameSite[c]<<endl;
}
cout << "Enter number you would like to edit : "; //asking user to enter which data user want to edit
cin >> EN; //user enter which data they want to edit
c=EN-1;
cout << A.NameSite[c] << "\n" << "Do you want to edit this data? Yes:1 No:0"<<endl; //asking user whether they want to edit Company/Institute name
cin >> edit;
if(edit ==1) //if true, it will change the data
cin >> A.NameSite[c];
cout <<"Total stall : "<< A.numStall[c] << "\n" << "Do you want to edit this data? Yes:1 No:0"<<endl; //asking user whether they want to edit total Company/Institute vaccine stall
cin >> edit;
if(edit ==1) //if true, it will change the data
cin >> A.numStall[c];
cout <<"Adress : " << A.AddressName[c] << "\n" << "Do you want to edit this data? Yes:1 No:0"<<endl; //asking user whether they want to edit Company/Institute's address
cin >> edit;
if(edit ==1) //if true, it will change the data
cin >> A.AddressName[c];
cout << "Contact number : " << A.ContNum[c] << "\n" << "Do you want to edit this data? Yes:1 No:0"<<endl; //asking user whether they want to edit Company/Institute's contact number
cin >> edit;
if(edit ==1) //if true, it will change the data
cin >> A.ContNum[c];
cout << "Total Vaccine : "<< A.numVaccine[c] << "\n" << "Do you want to edit this data? Yes:1 No:0"<<endl; //asking user whether they want to edit total Company/Institute vaccine needed
cin >> edit;
if(edit ==1) //if true, it will change the data
cin >> A.numVaccine[c];
cout << "Date of vaccine : "<< A.DateVax[c]<< "\n" << "Do you want to edit this data? Yes:1 No:0"<<endl; //asking user whether they want to edit Company/Institute's receiving vaccine date
cin >> edit;
if(edit ==1) //if true, it will change the data
cin >> A.DateVax[c];
}
void ShowExisting(int i, struct Deets A) // void of ShowExisting that show the existing data stored in the program
{
for(int c=0; c<i; c++) //array to show all the existing data in the program so far
{
cout << (c+1) << ". "<< endl; //number that show the count of which set of data shown
cout << "Site Name: " << A.NameSite[c] << endl; //show the name of site in appropriate array of turn c
cout << "Address: " << A.AddressName[c] << endl; //show the address of site in appropriate array of turn c
cout << "Amount Vaccine: " << A.numVaccine[c]<< endl; //show the amount of vaccine needed in site in appropriate array of turn c
cout << "Amount Stall: " << A.numStall[c] << endl; //show the amount of stall needed in appropriate array of turn c
cout << "Vaccination Date: " << A.DateVax[c] << endl; //show the vaccination date in appropriate array of turn c
cout << "Contact Num.: " << A.ContNum[c] << "\n" << endl; //show the contact number of the reprsentative from the site in appropriate array of turn c
}
}
The program runs until input when there is no data in the file but when there is data, the program wont even go past
for(int c=0;c<=i;c++)
while(a>>V.NameSite[c]>>V.AddressName[c]>>V.numVaccine[c]>>V.numStall[c]>>V.DateVax[c]>>V.ContNum[c]);
please help as my caffeine brain is fried
*After considering everyone's response ive decided to rework the basis of the program with what everyone taught, Thank you for those who responded
IMHO, I would rewrite/redesign your code rather than debug it.
Let's start by differentiating a single Deet from a container of Deet:
struct Deet
{
string NameSite;
string AddressName;
int numVaccine;
int numStall;
string DateVax;
string ContNum;
};
You can then overload operator>>:
struct Deet
{
//...
friend std::istream& operator>>(std::istream& input, Deet& d);
};
std::istream& operator>>(std::istream& input, Deet& d)
{
std::getline(input, d.NameSite);
std::getline(input, d.AddressName);
input >> d.numVaccine;
input >> d.numStall;
std::getline(input, d.DateVax);
std::getline(input, d.ContNum);
return input;
}
You could declare a container and input the container like so:
std::vector<Deet> deet_container;
Deet d;
while (input_file >> d)
{
deet_container.push_back(d);
}
BTW, you should always put descriptive variables inside your function declarations. This gives people a better understanding of what the variables are and their positions.
Your function declarations could change:
typedef std::vector<Deet> Deet_Vector;
int AddData(int, Deet_Vector& V);
void EditData(int, Deet_Vector& V);
void ShowExisting(int, Deet_Vector& V);
void ClearArr(int, Deet_Vector& V);
By looking at AddData, the usage of the int first parameter is ambiguous.
Are you adding an int to the container?
Is the int the quantities of items to add to the container?
Likewise with the other functions.
Next, I would add one function at a time to the program, compile and debug, then add another, repeat.
BTW, you can simplify your Outputmenu function:
void Outputmenu()
{
static const char menu_text[] =
" -hello there!-\n"
"===========================================================\n"
" ***PLEASE CHOOSE ONE OF THE OPTION BELOW***\n"
"===========================================================\n"
"\t1. Add Data (about Vaccination Center)\n"
"\t2. Edit Data\n"
"\t3. Show Existing Data\n"
"\t0. Close Program\n"
"============================================================\n"
;
std::cout.write(menu_text, sizeof(menu_text);
}
By using the write method, the text is written as a block and is usually a lot faster than using a lot of operator<<.
I'm new to c++ and I'm trying to make a simple class roster program that accepts new students storing the student data in an array that then be sorted and display the contents of the array. However when running the program and entering the menu selection, two of the three functions do not work. Any help or guidance is much appreciated. My code is here.
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <iostream>
using namespace std;
//Create Students class
class Students
{
public:
char sFirstName[256];
char sLastName[256];
int sStudentID;
double sGrade;
double sGPA;
double nCreditHours;
};
//functions
Students addStudent();
//void displayRoster();
//void sortRoster();
void showMenu();
void showWelcome();
//Welcome function
void showWelcome()
{
cout << "Welcome to my class roster program. \n"
<< "This program can be used to add students to the roster, \n"
<< "which can then be sorted by either name or I.D. number. \n"
<< endl;
}
//Menu function
void showMenu()
{
cout << " Student Roster: \n"
<< "MAIN MENU PLEASE SELECT AN OPTION" << endl;
cout << "1) Add student to roster: " << endl;
cout << "2) Display current roster: " << endl;
cout << "3) Sort roster: " << endl;
cout << "4) Exit program: " << endl;
//cout << "5) Display roster sorted by 'student I.D.': " << endl;
//cout << "6) Display roster sorted by 'Grade': " << endl;
//cout << "7) Display roster sorted by 'GPA': \n" << endl;
cout << " Make your selection: \n" << endl;
}
//Add student function
Students addStudent()
{
Students student;
cout << "Add student to roster. \n"
<< "Enter first name: " << endl;
cin >> student.sFirstName;
cout << "Enter last name: " << endl;
cin >> student.sLastName;
cout << "Enter student I.D.: " << endl;
cin >> student.sStudentID;
return student;
}
void displayStudent(Students student)
{
cout << "Student name: " << student.sFirstName << " "
<< student.sLastName << endl;
cout << "I.D. # " << student.sStudentID << endl;
}
void displayRoster()
{
Students student[256];
int nCount;
for (int index = 0; index < nCount; index++)
{
displayStudent(student[index]);
}
}
int getStudents(Students student[], int nMaxSize)
{
int index;
for (index = 0; index < nMaxSize; index++)
{
char uInput;
cout << "Enter another student to the roster? (Y/N): ";
cin >> uInput;
if (uInput != 'y' && uInput != 'Y')
{
break;
}
student[index] = addStudent();
}
return index;
}
void sortRoster()
{
Students student[256];
int nCount;
//bubble swap
int nSwaps = 1;
while (nSwaps != 0)
{
nSwaps = 0;
for (int n = 0; n < (nCount - 1); n++)
{
if (student[n].sStudentID > student[n+1].sStudentID)
{
Students temp = student[n+1];
student[n+1] = student[n];
student[n] = temp;
nSwaps++;
}
}
}
}
int main()
{
int selection; //menu selection variable
//constants for menu selection
const int ADD_STUDENT = 1,
DISPLAY_ROSTER = 2,
SORT_ROSTER = 3,
QUIT_PROGRAM = 4;
Students student[256];
//int nCount = getStudents(student, 256);
do
{
showWelcome(); //Show welcome message
showMenu(); //Show menu options
cin >> selection;
while (selection < ADD_STUDENT || selection > QUIT_PROGRAM)
{
cout << "Enter a valid selection: ";
cin >> selection;
}
if (selection != QUIT_PROGRAM)
{
switch (selection)
{
case ADD_STUDENT:
addStudent();
break;
case DISPLAY_ROSTER:
displayRoster();
break;
case SORT_ROSTER:
sortRoster();
break;
}
}
}
while (selection != QUIT_PROGRAM);
return 0;
}
The problem is not in the switch.
The addStudent() is not adding the student into any list or array. Also since it return type is Students you should add it into the any array of Students. Since you have not stored any data display won't display anything.
The another problem is of nCount. You are using it in for comparison without initializing it. Also to keep nCount synchronized either make it global, use as pointer or handle it with return.
Also the problem is in displayRoster(). You are declaring Students array as Students student[256]; and you are using it without initializing. Also if initialized, it won't have the data which was given as input.
NOTE: Sit and read your code again, there are many more mistakes. Try visualizing how your data should be stored and how your code is to behave and then start writing code.
Your nCount is not initialised. Since this variable is used in those two functions (and assuming that it refers to the total count), you can declare it as a global variable:
nCount=0;
Everytime you add a new entry, you can increment the counter as:
nCount++;
Another suggestion to make your code actually work:
student[i++]=addStudent();
where i is a counter initialised to 0. Your addStudent() function returns an object, and you discard it. Store it in the array of objects you created:
Students student[256];
Also, since you use the above in almost all functions, it is best to declare it as global rather than redeclaring in each function.
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
Entire question :
Question 3
You are the owner of a hardware store and need to keep an inventory that can tell you what different tools you have, how many of each you have on hand and the cost of each one. Write a program that initializes the random-access file "hardware.dat" to 100 empty records, let you input the data concerning each tool, enables you to list all your tools, lets you delete a record for a tool that you no longer have and lets you update any information in the file. The tool identification number should be the record number. Use the following information to start your file.
My Code :
int question_3()
{
cout << "Question 3" << endl;
fstream hardware;
hardware.open("hardware.dat" , ios::binary | ios::out);
//Create 100 blank objects---------------------------------------------------------------
if (!hardware)
{
cerr << "File could not be opened." << endl;
exit(1);
}
HardwareData myHardwareData;
for (int counter = 1; counter <= 100; counter++)
{
hardware.write(reinterpret_cast< const char * >(&myHardwareData), sizeof(HardwareData));
}
cout << "Successfully create 100 blank objects and write them into the file." << endl;
hardware.close();
hardware.open("hardware.dat" , ios::binary | ios::out | ios::in);
//Write data-----------------------------------------------------------------------------
int record;
int quantity;
float cost;
string tool_name;
cout << endl;
cout << "Enter record number (1 to 100, 0 to end input) : ";
cin >> record;
while (record != 0)
{
cin.sync();
cout << "Enter tool name : "; getline(cin, tool_name);
cout << "Enter quantity : "; cin >> quantity;
cout << "Enter cost : "; cin >> cost;
myHardwareData.setRecord(record);
myHardwareData.setToolName(tool_name);
myHardwareData.setQuantity(quantity);
myHardwareData.setCost(cost);
hardware.seekp((myHardwareData.getRecord() - 1) * sizeof(HardwareData));
hardware.write(reinterpret_cast<const char *>(&myHardwareData), sizeof(HardwareData));
cout << endl
<< "Enter record number (1 to 100, 0 to end input) : ";
cin >> record;
}
cout << "Successfully write all input data into the file." << endl;
//Read data----------------------------------------------------------------------------
cout << endl;
outputDataLineHead();
hardware.read(reinterpret_cast<char *>(&myHardwareData), sizeof(HardwareData));
int counter = 0;
cout << setprecision(2) << fixed;
while (hardware && !hardware.eof())
{
if (myHardwareData.getRecord() != 0)
outputDataLine(cout, myHardwareData);
hardware.seekp(counter++ * sizeof(HardwareData));
hardware.read(reinterpret_cast<char *>(&myHardwareData), sizeof(HardwareData));
}
return 0;
}
//Function for showing data in line form.-----------------------------------------------
void outputDataLineHead()
{
cout << left << setw(17) << "Record No."
<< left << setw(17) << "Tool Name"
<< left << setw(17) << "Quantity"
<< left << setw(17) << "Cost" << endl;
}
void outputDataLine(ostream &output, const HardwareData &Object_in_file)
{
output << left << setw(17) << Object_in_file.getRecord()
<< left << setw(17) << Object_in_file.getToolName()
<< left << setw(17) << Object_in_file.getQuantity()
<< left << setw(17) << Object_in_file.getCost() << endl;
}
HardwareData.h :
#ifndef HAREWAREDATA_H
#define HAREWAREDATA_H
#include <iostream>
using std::string;
class HardwareData
{
public :
HardwareData(string name = "", int recd = 0, int qutity = 0, float cot = 0.0)
{
setToolName(name);
setRecord(recd);
setQuantity(qutity);
setCost(cot);
}
void setToolName(string name)
{
const char *nameValue = name.data();
int length = 0;
length = (length < 15 ? length : 14);
strncpy(tool_name, nameValue, length);
tool_name[length] = '\n';
}
string getToolName() const
{
return tool_name;
}
void setRecord(int recd)
{
record = recd;
}
int getRecord() const
{
return record;
}
void setQuantity(int qutity)
{
quantity = qutity;
}
int getQuantity() const
{
return quantity;
}
void setCost(float cot)
{
cost = cot;
}
float getCost() const
{
return cost;
}
private :
char tool_name[15];
int record;
int quantity;
float cost;
};
#endif
I want to show the data like the following :
Record No. Tool Name Quantity Cost
4 electric hammer 3 34.32
How to achieve this?
Thank you for your attention.
I think your problem is while reading data.. Please check your variables if they get correct data or not.. You can check this with counting characters or try to printf them.
If they are not correct. You can use such an example which i used in below.
First of all i prefer you to read your line like this example ;
In this example i get coordinates of faces. You should change parameters.. In order not to read no need data
std::string str;
while(std::getline(in, str))
{
sscanf(str.c_str(), "%d %f %f", &fiducial.number, &fiducial.x, &fiducial.y);
coord_Num[fiducial.number] = fiducial.get_number();
coord_X[fiducial.number] = fiducial.get_x();
coord_Y[fiducial.number] = fiducial.get_y();
}
If everything looks fine. You should check
void outputDataLine(ostream &output, const HardwareData &Object_in_file)
The core issue here is that you're reading and writing bytes to/from objects of type HardwareData when rather you should be creating inserters/extractors so you can implement correct I/O semantics. For example:
// Inside HardwareData class
friend std::ostream& operator<<(std::ostream&, const HardwareData&);
friend std::istream& operator>>(std::istream&, HardwareData&);
These two declarations are for the inserter and extractor respectively. Input should consist of extracting into the record, tool_name, quantity and cost data members; and output should simply be an stream insertion which is trivial to implement.
It is often the problem when mixing formatted input with unformatted input that the residual newline inhibits further input. That seems to be the case here:
cin >> record; /*
^^^^^^^^^^^^^^ */
while (record != 0)
{
cin.sync();
cout << "Enter tool name : "; getline(cin, tool_name);
// ^^^^^^^^^^^^^^^^^^^^^^^^
// ...
}
After cin >> record; finishes, there will be a newline left inside the stream. That newline will stop std::getline() from working correctly because std::getline() only reads until the newline.
The fix here is to ignore this new line by using the std::ws manipulator:
std::getline(std::cin >> std::ws, tool_name);
// ^^^^^^^^^^^^^^^^^^^
Note: I talk about this in more detail here.
But this manual extraction isn't needed as we've already defined the inserter and extractor for our class. So all that's really needed is the following:
while (std::cin >> myHardwareData)
{
hardware << myHardwareData;
}
or
std::copy(std::istream_iterator<HardwareData>(std::cin),
std::istream_iterator<HardwareData>(),
std::ostream_iterator<HardwareData>(hardware));
Noticed how I've also taken out the check for a 0 value of record in the while loop. That's because the extractor takes care of it by reflecting a 0 value of record as invalid input. It sets the stream state of the stream if this occurs, thus allowing ourselves to be ejected from the while if that happens:
std::istream& operator>>(std::istream& is, HardwareData& hd)
{
cout << "Enter record number (1 to 100, 0 to end input) : ";
if ((is >> record) && record != 0)
{
// ...
} else
{
is.setstate(std::ios_base::failbit);
}
// ...
}
And the rest of your code be changed to:
std::cout << myHardwareData;
hardware >> myHardwareData;
std::cout << std::setprecision(2) << std::fixed;
while (hardware >> myHardwareData)
{
if (myHardwareData.getRecord() != 0)
std::cout << myHardwareData;
}
I don't really know what the seekps are for. If you elaborate on that, that would really help me adapt my code more accurately to your needs.
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;